diff --git a/.github/workflows/android.yaml b/.github/workflows/android.yaml index 9b4c27c8e3d887..093ce6b606a72d 100644 --- a/.github/workflows/android.yaml +++ b/.github/workflows/android.yaml @@ -34,7 +34,7 @@ jobs: runs-on: ubuntu-latest container: - image: connectedhomeip/chip-build-android:0.4.16 + image: connectedhomeip/chip-build-android:0.4.18 volumes: - "/tmp/log_output:/tmp/test_logs" diff --git a/.github/workflows/bloat_check.yaml b/.github/workflows/bloat_check.yaml index a52a77fa04c5f5..fb32f3482f13a1 100644 --- a/.github/workflows/bloat_check.yaml +++ b/.github/workflows/bloat_check.yaml @@ -24,7 +24,7 @@ jobs: runs-on: ubuntu-latest container: - image: connectedhomeip/chip-build:0.4.16 + image: connectedhomeip/chip-build:0.4.18 steps: - name: Checkout diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 1870296624133d..8d96f11137a162 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -34,7 +34,7 @@ jobs: runs-on: ubuntu-latest container: - image: connectedhomeip/chip-build:0.4.16 + image: connectedhomeip/chip-build:0.4.18 volumes: - "/tmp/log_output:/tmp/test_logs" options: diff --git a/.github/workflows/examples-efr32.yaml b/.github/workflows/examples-efr32.yaml index 398b6b4d6b1b82..1f052131828641 100644 --- a/.github/workflows/examples-efr32.yaml +++ b/.github/workflows/examples-efr32.yaml @@ -29,7 +29,7 @@ jobs: runs-on: ubuntu-latest container: - image: connectedhomeip/chip-build-efr32:0.4.16 + image: connectedhomeip/chip-build-efr32:0.4.18 volumes: - "/tmp/bloat_reports:/tmp/bloat_reports" - "/tmp/output_binaries:/tmp/output_binaries" diff --git a/.github/workflows/examples-esp32.yaml b/.github/workflows/examples-esp32.yaml index 5acba3a8db52f1..e12ed6f6d79851 100644 --- a/.github/workflows/examples-esp32.yaml +++ b/.github/workflows/examples-esp32.yaml @@ -29,7 +29,7 @@ jobs: runs-on: ubuntu-latest container: - image: connectedhomeip/chip-build-esp32:0.4.16 + image: connectedhomeip/chip-build-esp32:0.4.18 volumes: - "/tmp/bloat_reports:/tmp/bloat_reports" - "/tmp/output_binaries:/tmp/output_binaries" diff --git a/.github/workflows/examples-linux-standalone.yaml b/.github/workflows/examples-linux-standalone.yaml index 5fe57bbf8882d3..579d82f95d432d 100644 --- a/.github/workflows/examples-linux-standalone.yaml +++ b/.github/workflows/examples-linux-standalone.yaml @@ -31,7 +31,7 @@ jobs: runs-on: ubuntu-latest container: - image: connectedhomeip/chip-build:0.4.16 + image: connectedhomeip/chip-build:0.4.18 volumes: - "/tmp/bloat_reports:/tmp/bloat_reports" - "/tmp/output_binaries:/tmp/output_binaries" diff --git a/.github/workflows/examples-nrfconnect.yaml b/.github/workflows/examples-nrfconnect.yaml index e18ee6bd9cb54e..263b9d2a855bab 100644 --- a/.github/workflows/examples-nrfconnect.yaml +++ b/.github/workflows/examples-nrfconnect.yaml @@ -27,7 +27,7 @@ jobs: runs-on: ubuntu-latest container: - image: connectedhomeip/chip-build-nrf-platform:0.4.16 + image: connectedhomeip/chip-build-nrf-platform:0.4.18 volumes: - "/tmp/bloat_reports:/tmp/bloat_reports" - "/tmp/output_binaries:/tmp/output_binaries" diff --git a/.github/workflows/examples-qpg6100.yaml b/.github/workflows/examples-qpg6100.yaml index 7f0fc0e3de0c26..d611ec95d2aa9e 100644 --- a/.github/workflows/examples-qpg6100.yaml +++ b/.github/workflows/examples-qpg6100.yaml @@ -27,7 +27,7 @@ jobs: runs-on: ubuntu-latest container: - image: connectedhomeip/chip-build:0.4.16 + image: connectedhomeip/chip-build:0.4.18 volumes: - "/tmp/bloat_reports:/tmp/bloat_reports" - "/tmp/output_binaries:/tmp/output_binaries" diff --git a/.github/workflows/qemu.yaml b/.github/workflows/qemu.yaml index b320f618544df2..7af7ba7ac944cf 100644 --- a/.github/workflows/qemu.yaml +++ b/.github/workflows/qemu.yaml @@ -28,7 +28,7 @@ jobs: runs-on: ubuntu-latest container: - image: connectedhomeip/chip-build-esp32-qemu:0.4.16 + image: connectedhomeip/chip-build-esp32-qemu:0.4.18 volumes: - "/tmp/log_output:/tmp/test_logs" diff --git a/.github/workflows/unit_integration_test.yaml b/.github/workflows/unit_integration_test.yaml index 020fe8fba5e6c4..8f63293f3a68b4 100644 --- a/.github/workflows/unit_integration_test.yaml +++ b/.github/workflows/unit_integration_test.yaml @@ -34,7 +34,7 @@ jobs: runs-on: ubuntu-latest container: - image: connectedhomeip/chip-build:0.4.16 + image: connectedhomeip/chip-build:0.4.18 volumes: - "/tmp/log_output:/tmp/test_logs" - "/tmp/happy_test_logs:/tmp/happy_test_logs" diff --git a/.github/workflows/zap_templates.yaml b/.github/workflows/zap_templates.yaml new file mode 100644 index 00000000000000..507c9418b1f2a5 --- /dev/null +++ b/.github/workflows/zap_templates.yaml @@ -0,0 +1,47 @@ +# 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. + +name: ZAP + +on: + push: + pull_request: + +jobs: + templates: + name: ZAP templates generation + + runs-on: ubuntu-18.04 + + steps: + - name: Checkout + uses: actions/checkout@v2 + with: + submodules: true + - name: Use Node.js 12.x + uses: actions/setup-node@v1 + with: + node-version: '12.x' + + - run: sudo apt-get update + - run: sudo apt-get install --fix-missing libpixman-1-dev libcairo-dev libsdl-pango-dev libjpeg-dev libgif-dev + - name: Setup ZAP + run: | + cd third_party/zap/repo/ + npm ci + npm run version-stamp + npm rebuild canvas --update-binary + npm run build-spa + - name: Generate + run: scripts/tools/zap_generate.sh examples/all-clusters-app/all-clusters-common/all-clusters-app.zap diff --git a/.gitmodules b/.gitmodules index 2859972f4a287b..55f495a9b753ff 100644 --- a/.gitmodules +++ b/.gitmodules @@ -66,3 +66,7 @@ path = third_party/zap/repo url = https://github.com/project-chip/zap.git branch = master +[submodule "freertos"] + path = third_party/freertos/repo + url = https://github.com/FreeRTOS/FreeRTOS-Kernel.git + branch = V10.3.1-kernel-only diff --git a/BUILD.gn b/BUILD.gn index 22ff9f3939cce9..9a1320b2e9ac8e 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -18,6 +18,7 @@ import("//build_overrides/nlassert.gni") import("//build_overrides/nlio.gni") import("//build_overrides/nlunit_test.gni") import("//build_overrides/pigweed.gni") +import("//src/platform/device.gni") import("$dir_pw_build/python.gni") # This build file should not be used in superproject builds. @@ -47,6 +48,7 @@ if (current_toolchain != "${dir_pw_toolchain}/dummy:dummy") { "${chip_root}/src/app", "${chip_root}/src/ble", "${chip_root}/src/controller", + "${chip_root}/src/credentials", "${chip_root}/src/crypto", "${chip_root}/src/inet", "${chip_root}/src/lib", @@ -66,6 +68,10 @@ if (current_toolchain != "${dir_pw_toolchain}/dummy:dummy") { "${nlunit_test_root}:nlunit-test", ] + if (chip_device_platform != "none") { + deps += [ "${chip_root}/src/app/server" ] + } + if (chip_build_tests) { deps += [ "//src:tests" ] } @@ -73,6 +79,8 @@ if (current_toolchain != "${dir_pw_toolchain}/dummy:dummy") { if (chip_build_tools) { deps += [ "${chip_root}/examples/shell/standalone:chip-shell", + "${chip_root}/src/app/tests/integration:chip-im-initiator", + "${chip_root}/src/app/tests/integration:chip-im-responder", "${chip_root}/src/messaging/tests/echo:chip-echo-requester", "${chip_root}/src/messaging/tests/echo:chip-echo-responder", "${chip_root}/src/qrcodetool", @@ -115,6 +123,9 @@ if (current_toolchain != "${dir_pw_toolchain}/dummy:dummy") { # Enable building for Android. enable_android_builds = false + # Set this to true to enable TI builds by default. + enable_cc13x2_26x2_builds = false + # Set this to true to enable efr32 builds by default. enable_efr32_builds = false @@ -149,6 +160,9 @@ if (current_toolchain != "${dir_pw_toolchain}/dummy:dummy") { enable_linux_lighting_app_build = enable_default_builds && (host_os == "linux" || host_os == "mac") + # Build the cc13x2_26x2 lock app example. + enable_cc13x2_26x2_lock_app_build = enable_cc13x2_26x2_builds + # Build the efr32 lock app example. enable_efr32_lock_app_build = enable_efr32_builds @@ -199,6 +213,7 @@ if (current_toolchain != "${dir_pw_toolchain}/dummy:dummy") { } standalone_toolchain = "${chip_root}/config/standalone/toolchain:standalone" + not_needed([ "standalone_toolchain" ]) # Might not be needed. if (enable_standalone_chip_tool_build) { group("standalone_chip_tool") { @@ -206,6 +221,12 @@ if (current_toolchain != "${dir_pw_toolchain}/dummy:dummy") { } } + if (enable_cc13x2_26x2_lock_app_build) { + group("cc13x2_26x2_lock_app") { + deps = [ "${chip_root}/examples/lock-app/cc13x2_26x2(${chip_root}/config/cc13x2_26x2/toolchain:cc13x2_26x2_lock_app)" ] + } + } + if (enable_standalone_shell_build) { group("standalone_shell") { deps = diff --git a/config/nrfconnect/README.md b/config/nrfconnect/README.md new file mode 100644 index 00000000000000..34eafc9ddab930 --- /dev/null +++ b/config/nrfconnect/README.md @@ -0,0 +1,11 @@ +# nRF Connect build and configuration files + +This directory contains build scripts and common configuration files used by +CHIP nRF Connect applications. It is structured as follows: + +| File/Folder | Contents | +| ------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| chip-gn | GN project used to build selected CHIP libraries with the _nrfconnect_ platform integration layer | +| chip-module | CMake wrapper for the GN project defined in `chip-gn` directory, and other components that allow one to use CHIP as a Zephyr module | +| app/app.cmake | Helper CMake module to be used by nRF Connect applications in this repository to inject `chip-module` into the Zephyr module list and load Zephyr build system | +| app/\*.conf | Common and optional Kconfig configuration files that can be used in nRF Connect applications | diff --git a/config/nrfconnect/app/app.cmake b/config/nrfconnect/app/app.cmake new file mode 100644 index 00000000000000..1e01e1a468b927 --- /dev/null +++ b/config/nrfconnect/app/app.cmake @@ -0,0 +1,39 @@ +# +# 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 +# CMake module for incorporating CHIP into an nRF Connect SDK +# application as an out-of-tree Zephyr module. +# + +# Use Device Tree overlay if exists in the application directory + +if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/dts.overlay") + set(DTC_OVERLAY_FILE "${CMAKE_CURRENT_SOURCE_DIR}/dts.overlay") +endif() + +# Add CHIP to the list of Zephyr modules + +list(APPEND ZEPHYR_EXTRA_MODULES ${CMAKE_CURRENT_LIST_DIR}/../chip-module) + +# Load NCS/Zephyr build system + +find_package(Zephyr HINTS $ENV{ZEPHYR_BASE}) + +# Configure the application + +target_link_libraries(app PUBLIC chip) diff --git a/config/nrfconnect/overlay-usb_support.conf b/config/nrfconnect/app/overlay-usb_support.conf similarity index 100% rename from config/nrfconnect/overlay-usb_support.conf rename to config/nrfconnect/app/overlay-usb_support.conf diff --git a/config/nrfconnect/release.conf b/config/nrfconnect/app/release.conf similarity index 100% rename from config/nrfconnect/release.conf rename to config/nrfconnect/app/release.conf diff --git a/config/nrfconnect/sample-defaults.conf b/config/nrfconnect/app/sample-defaults.conf similarity index 93% rename from config/nrfconnect/sample-defaults.conf rename to config/nrfconnect/app/sample-defaults.conf index 9e90bae62fbaee..21f979cc9f82e3 100644 --- a/config/nrfconnect/sample-defaults.conf +++ b/config/nrfconnect/app/sample-defaults.conf @@ -16,12 +16,7 @@ CONFIG_CHIP=y -CONFIG_NEWLIB_LIBC=y - -# Export POSIX names for functions implementing a subset of POSIX standard in Zephyr -CONFIG_POSIX_API=y -CONFIG_PTHREAD_IPC=y -CONFIG_EVENTFD=y +CONFIG_STD_CPP14=y CONFIG_LOG=y CONFIG_LOG_MINIMAL=y diff --git a/config/nrfconnect/build_overrides b/config/nrfconnect/build_overrides deleted file mode 120000 index aea3e8d3b72a17..00000000000000 --- a/config/nrfconnect/build_overrides +++ /dev/null @@ -1 +0,0 @@ -../../examples/build_overrides \ No newline at end of file diff --git a/config/nrfconnect/.gn b/config/nrfconnect/chip-gn/.gn similarity index 100% rename from config/nrfconnect/.gn rename to config/nrfconnect/chip-gn/.gn diff --git a/config/nrfconnect/BUILD.gn b/config/nrfconnect/chip-gn/BUILD.gn similarity index 95% rename from config/nrfconnect/BUILD.gn rename to config/nrfconnect/chip-gn/BUILD.gn index 08db1477a1a4d1..bf1d8d3d528821 100644 --- a/config/nrfconnect/BUILD.gn +++ b/config/nrfconnect/chip-gn/BUILD.gn @@ -29,6 +29,10 @@ group("dummy") { group("nrfconnect") { deps = [ "${chip_root}/src/lib" ] + if (chip_build_tests) { + deps += [ "${chip_root}/src:tests" ] + } + if (chip_build_libshell) { deps += [ "${chip_root}/src/lib/shell" ] } @@ -36,14 +40,10 @@ group("nrfconnect") { # Building PW_RPC lib with GN may go obsolete after getting full CMake # support in Pigweed. if (chip_build_pw_rpc_lib) { - deps += [ "${chip_root}/config/nrfconnect/lib/pw_rpc" ] + deps += [ "//lib/pw_rpc" ] } } group("default") { deps = [ ":nrfconnect" ] - - if (chip_build_tests) { - deps += [ "${chip_root}/src:tests" ] - } } diff --git a/config/nrfconnect/args.gni b/config/nrfconnect/chip-gn/args.gni similarity index 85% rename from config/nrfconnect/args.gni rename to config/nrfconnect/chip-gn/args.gni index e19a2186731655..ccee7feb52575e 100644 --- a/config/nrfconnect/args.gni +++ b/config/nrfconnect/chip-gn/args.gni @@ -15,17 +15,13 @@ import("//build_overrides/chip.gni") import("//lib/pw_rpc/pw_rpc.gni") -nrfconnect_target = get_label_info(":nrfconnect", "label_no_toolchain") - chip_device_platform = "nrfconnect" -chip_logging_style = "external" - -chip_config_network_layer_ble = true chip_build_tests = false chip_project_config_include = "" chip_system_project_config_include = "" +chip_ble_project_config_include = "" custom_toolchain = "//toolchain:zephyr" mbedtls_target = "//:dummy" diff --git a/config/nrfconnect/build b/config/nrfconnect/chip-gn/build similarity index 100% rename from config/nrfconnect/build rename to config/nrfconnect/chip-gn/build diff --git a/config/nrfconnect/chip-gn/build_overrides b/config/nrfconnect/chip-gn/build_overrides new file mode 120000 index 00000000000000..5140c246d723bf --- /dev/null +++ b/config/nrfconnect/chip-gn/build_overrides @@ -0,0 +1 @@ +../../../examples/build_overrides/ \ No newline at end of file diff --git a/config/nrfconnect/lib/pw_rpc/BUILD.gn b/config/nrfconnect/chip-gn/lib/pw_rpc/BUILD.gn similarity index 97% rename from config/nrfconnect/lib/pw_rpc/BUILD.gn rename to config/nrfconnect/chip-gn/lib/pw_rpc/BUILD.gn index b9870de9edbed4..48abf29e619e3d 100644 --- a/config/nrfconnect/lib/pw_rpc/BUILD.gn +++ b/config/nrfconnect/chip-gn/lib/pw_rpc/BUILD.gn @@ -24,6 +24,7 @@ static_library("pw_rpc") { deps = [ "$dir_pw_rpc:server", "$dir_pw_rpc/nanopb:echo_service", + "$dir_pw_rpc/system_server", "${chip_root}/examples/platform/nrfconnect/pw_sys_io:pw_sys_io_nrfconnect", "${dir_pigweed}/pw_hdlc_lite:pw_rpc", dir_pw_assert, diff --git a/config/nrfconnect/lib/pw_rpc/pw_rpc.gni b/config/nrfconnect/chip-gn/lib/pw_rpc/pw_rpc.gni similarity index 85% rename from config/nrfconnect/lib/pw_rpc/pw_rpc.gni rename to config/nrfconnect/chip-gn/lib/pw_rpc/pw_rpc.gni index ce3a90879f6f9e..b1af418d991fc4 100644 --- a/config/nrfconnect/lib/pw_rpc/pw_rpc.gni +++ b/config/nrfconnect/chip-gn/lib/pw_rpc/pw_rpc.gni @@ -5,6 +5,7 @@ pw_log_BACKEND = "$dir_pw_log_basic" pw_assert_BACKEND = "$dir_pw_assert_log" pw_sys_io_BACKEND = "${chip_root}/examples/platform/nrfconnect/pw_sys_io:pw_sys_io_nrfconnect" +pw_rpc_system_server_BACKEND = "$dir_pw_rpc/system_server:sys_io" dir_pw_third_party_nanopb = "${chip_root}/third_party/nanopb/repo" pw_protobuf_GENERATORS = [ diff --git a/config/nrfconnect/chip-gn/third_party/connectedhomeip b/config/nrfconnect/chip-gn/third_party/connectedhomeip new file mode 120000 index 00000000000000..11a54ed360106c --- /dev/null +++ b/config/nrfconnect/chip-gn/third_party/connectedhomeip @@ -0,0 +1 @@ +../../../../ \ No newline at end of file diff --git a/config/nrfconnect/toolchain/BUILD.gn b/config/nrfconnect/chip-gn/toolchain/BUILD.gn similarity index 100% rename from config/nrfconnect/toolchain/BUILD.gn rename to config/nrfconnect/chip-gn/toolchain/BUILD.gn diff --git a/config/nrfconnect/chip-lib.cmake b/config/nrfconnect/chip-lib.cmake deleted file mode 100644 index 8d04beec199e33..00000000000000 --- a/config/nrfconnect/chip-lib.cmake +++ /dev/null @@ -1,210 +0,0 @@ -# -# 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 -# CMake module for configuring and building CHIP libraries to be used -# in Zephyr applications. -# -# It is assumed that at this point: -# - CHIP_ROOT is defined -# - find_package(Zephyr) has been called -# - -# ================================================== -# Helpers & settings -# ================================================== - -include(ExternalProject) - -# Directory for CHIP build artifacts -set(CHIP_OUTPUT_DIR "${CMAKE_CURRENT_BINARY_DIR}/chip") - -# Define Zephyr C/C++ compiler flags which should not be forwarded to CHIP -# build system (e.g. because CHIP configures them on its own). -set(CHIP_CFLAG_EXCLUDES - "-fno-asynchronous-unwind-tables" - "-fno-common" - "-fno-defer-pop" - "-fno-reorder-functions" - "-ffunction-sections" - "-fdata-sections" - "-g*" - "-O*" - "-W*" -) - -macro(chip_gn_arg_bool_if CONDITION ARGSTRING GN_VARNAME) - if (${CONDITION}) - string(APPEND ${ARGSTRING} "${GN_VARNAME} = true\n") - else () - string(APPEND ${ARGSTRING} "${GN_VARNAME} = false\n") - endif() -endmacro() - -macro(chip_gn_arg_string ARGSTRING GN_STRING) - string(APPEND ${ARGSTRING} "${GN_STRING}\n") -endmacro() - -macro(chip_gn_arg_cflags ARGSTRING ARG CFLAGS) - set(CFLAG_EXCLUDES "[") - foreach(cflag ${CHIP_CFLAG_EXCLUDES}) - string(APPEND CFLAG_EXCLUDES "\"${cflag}\", ") - endforeach() - string(APPEND CFLAG_EXCLUDES "]") - string(APPEND ${ARGSTRING} "${ARG} = filter_exclude(string_split(\"${CFLAGS}\"), ${CFLAG_EXCLUDES})\n") -endmacro() - -# Function to retrieve Zephyr compilation flags for the given language (C or CXX) -function(zephyr_get_compile_flags VAR LANG) - # We want to treat all zephyr-provided headers as system headers, so - # warnings in them don't trigger -Werror. That means that for the headers - # zephyr returns as "non-system" headers (the ones from - # zephyr_get_include_directories_for_lang) we need to manually replace "-I" - # with "-isystem" before adding them to INCLUDES. - set(temp_includes "") - zephyr_get_include_directories_for_lang(${LANG} temp_includes) - foreach(include ${temp_includes}) - string(REPLACE "-I" "-isystem" include ${include}) - list(APPEND INCLUDES ${include}) - endforeach() - - zephyr_get_system_include_directories_for_lang(${LANG} SYSTEM_INCLUDES) - zephyr_get_compile_definitions_for_lang(${LANG} DEFINES) - zephyr_get_compile_options_for_lang(${LANG} FLAGS) - set(${VAR} ${INCLUDES} ${SYSTEM_INCLUDES} ${DEFINES} ${FLAGS} ${${VAR}} PARENT_SCOPE) -endfunction() - -function(chip_select_cpp_standard VAR) - if (CONFIG_STD_CPP11) - set(${VAR} -std=gnu++11 PARENT_SCOPE) - elseif (CONFIG_STD_CPP14) - set(${VAR} -std=gnu++14 PARENT_SCOPE) - elseif (CONFIG_STD_CPP17) - set(${VAR} -std=gnu++17 PARENT_SCOPE) - elseif (CONFIG_STD_CPP2A) - set(${VAR} -std=gnu++20 PARENT_SCOPE) - else() - message(FATAL_ERROR "Building with unsupported C++ standard") - endif() -endfunction() - -# ================================================== -# Define chip configuration target -# ================================================== - -function(chip_configure TARGET_NAME) - cmake_parse_arguments(CHIP - "BUILD_TESTS" - "PROJECT_CONFIG" - "CFLAGS;CXXFLAGS" - ${ARGN}) - - # Prepare CFLAGS & CXXFLAGS - zephyr_get_compile_flags(CHIP_CFLAGS C) - convert_list_of_flags_to_string_of_flags(CHIP_CFLAGS CHIP_CFLAGS) - - zephyr_get_compile_flags(CHIP_CXXFLAGS CXX) - list(FILTER CHIP_CXXFLAGS EXCLUDE REGEX -std.*) - chip_select_cpp_standard(CHIP_CXX_STANDARD) - list(APPEND CHIP_CXXFLAGS ${CHIP_CXX_STANDARD}) - convert_list_of_flags_to_string_of_flags(CHIP_CXXFLAGS CHIP_CXXFLAGS) - - set(GN_ARGS "") - chip_gn_arg_cflags(GN_ARGS "target_cflags_c" ${CHIP_CFLAGS}) - chip_gn_arg_cflags(GN_ARGS "target_cflags_cc" ${CHIP_CXXFLAGS}) - chip_gn_arg_string(GN_ARGS "zephyr_ar = \"${CMAKE_AR}\"") - chip_gn_arg_string(GN_ARGS "zephyr_cc = \"${CMAKE_C_COMPILER}\"") - chip_gn_arg_string(GN_ARGS "zephyr_cxx = \"${CMAKE_CXX_COMPILER}\"") - - if (CHIP_PROJECT_CONFIG) - chip_gn_arg_string(GN_ARGS "chip_project_config_include = \"<${CHIP_PROJECT_CONFIG}>\"") - chip_gn_arg_string(GN_ARGS "chip_system_project_config_include = \"<${CHIP_PROJECT_CONFIG}>\"") - endif () - - if (BOARD STREQUAL "native_posix") - chip_gn_arg_string(GN_ARGS "target_cpu = \"x86\"") - elseif (BOARD STREQUAL "native_posix_64") - chip_gn_arg_string(GN_ARGS "target_cpu = \"x64\"") - endif () - - chip_gn_arg_bool_if(CONFIG_NET_L2_OPENTHREAD GN_ARGS "chip_enable_openthread") - chip_gn_arg_bool_if(CONFIG_NET_IPV4 GN_ARGS "chip_inet_config_enable_ipv4") - chip_gn_arg_bool_if(CHIP_BUILD_TESTS GN_ARGS "chip_build_tests") - chip_gn_arg_bool_if(CONFIG_DEBUG GN_ARGS "is_debug") - chip_gn_arg_bool_if(CHIP_BUILD_TESTS GN_ARGS "chip_inet_config_enable_raw_endpoint") - chip_gn_arg_bool_if(CHIP_BUILD_TESTS GN_ARGS "chip_inet_config_enable_tcp_endpoint") - chip_gn_arg_bool_if(CHIP_BUILD_TESTS GN_ARGS "chip_inet_config_enable_dns_resolver") - chip_gn_arg_bool_if(CONFIG_CHIP_LIB_SHELL GN_ARGS "chip_build_libshell") - chip_gn_arg_bool_if(CONFIG_CHIP_PW_RPC GN_ARGS "chip_build_pw_rpc_lib") - - file(GENERATE OUTPUT ${CHIP_OUTPUT_DIR}/args.gn CONTENT "${GN_ARGS}") - - # Define target - ExternalProject_Add( - ${TARGET_NAME} - PREFIX ${CHIP_OUTPUT_DIR} - SOURCE_DIR ${CHIP_ROOT} - BINARY_DIR ${CHIP_OUTPUT_DIR} - CONFIGURE_COMMAND gn --root=${CHIP_ROOT}/config/nrfconnect gen --check --fail-on-unused-args ${CHIP_OUTPUT_DIR} - BUILD_COMMAND "" - INSTALL_COMMAND "" - BUILD_ALWAYS TRUE - USES_TERMINAL_CONFIGURE TRUE - ) -endfunction() - -# ================================================== -# Define chip build target -# ================================================== - -function(chip_build TARGET_NAME BASE_TARGET_NAME) - cmake_parse_arguments(CHIP "" "" "BUILD_COMMAND;BUILD_ARTIFACTS" ${ARGN}) - - # Define build target - ExternalProject_Add( - ${TARGET_NAME}Build - PREFIX ${CHIP_OUTPUT_DIR} - SOURCE_DIR ${CHIP_ROOT} - BINARY_DIR ${CHIP_OUTPUT_DIR} - CONFIGURE_COMMAND "" - BUILD_COMMAND ${CHIP_BUILD_COMMAND} - INSTALL_COMMAND "" - BUILD_BYPRODUCTS ${CHIP_BUILD_ARTIFACTS} - BUILD_ALWAYS TRUE - USES_TERMINAL_BUILD TRUE - ) - - # Define interface library containing desired CHIP byproducts - add_library(${TARGET_NAME} INTERFACE) - target_include_directories(${TARGET_NAME} INTERFACE - ${CHIP_ROOT}/src - ${CHIP_ROOT}/src/app/util - ${CHIP_ROOT}/src/lib - ${CHIP_ROOT}/src/lib/core - ${CHIP_ROOT}/src/include - ${CHIP_ROOT}/third_party/nlassert/repo/include - ${CHIP_OUTPUT_DIR}/gen/include - ${CHIP_OUTPUT_DIR}/gen/third_party/connectedhomeip/src/lib/support/include - ${CHIP_OUTPUT_DIR}/gen/third_party/connectedhomeip/src/app/include - ) - target_link_directories(${TARGET_NAME} INTERFACE ${CHIP_OUTPUT_DIR}/lib) - target_link_libraries(${TARGET_NAME} INTERFACE -Wl,--start-group ${CHIP_BUILD_ARTIFACTS} -Wl,--end-group) - - add_dependencies(${TARGET_NAME}Build ${BASE_TARGET_NAME}) - add_dependencies(${TARGET_NAME} ${TARGET_NAME}Build) - add_dependencies(${TARGET_NAME}Build kernel) -endfunction() diff --git a/config/nrfconnect/chip-module/CMakeLists.txt b/config/nrfconnect/chip-module/CMakeLists.txt new file mode 100644 index 00000000000000..91dfe155ab1057 --- /dev/null +++ b/config/nrfconnect/chip-module/CMakeLists.txt @@ -0,0 +1,243 @@ +# +# 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 +# CMake sub-project defining 'chip' target which represents CHIP library +# and other optional libraries like unit tests, built with 'nrfconnect' +# platform. +# Since CHIP doesn't provide native CMake support, ExternalProject +# module is used to build the required artifacts with GN meta-build +# system. It is assumed that find_package(Zephyr) has been called before +# including this file. +# + +if (CONFIG_CHIP) + +include(ExternalProject) +include(zephyr-util.cmake) + +# ============================================================================== +# Declare configuration variables and define constants +# ============================================================================== + +# C/C++ compiler flags passed to CHIP build system +list(APPEND CHIP_CFLAGS) + +# C compiler flags passed to CHIP build system +list(APPEND CHIP_CFLAGS_C) + +# C++ compiler flags passed to CHIP build system +list(APPEND CHIP_CFLAGS_CC) + +# CHIP libraries that the application should be linked with +list(APPEND CHIP_LIBRARIES) + +# GN meta-build system arguments in the form of 'key1 = value1\nkey2 = value2...' string +string(APPEND CHIP_GN_ARGS) + +# C/C++ compiler flags which should not be forwarded to CHIP +# build system (e.g. because CHIP configures them on its own) +set(CHIP_CFLAG_EXCLUDES + "-fno-asynchronous-unwind-tables" + "-fno-common" + "-fno-defer-pop" + "-fno-reorder-functions" + "-ffunction-sections" + "-fdata-sections" + "-g*" + "-O*" + "-W*" +) + +# ============================================================================== +# Helper macros +# ============================================================================== + +macro(chip_gn_arg_string ARG STRING) + string(APPEND CHIP_GN_ARGS "${ARG} = \"${STRING}\"\n") +endmacro() + +macro(chip_gn_arg_bool ARG BOOLEAN) + if (${BOOLEAN}) + string(APPEND CHIP_GN_ARGS "${ARG} = true\n") + else() + string(APPEND CHIP_GN_ARGS "${ARG} = false\n") + endif() +endmacro() + +macro(chip_gn_arg_cflags ARG CFLAGS) + set(CFLAG_EXCLUDES "[") + foreach(cflag ${CHIP_CFLAG_EXCLUDES}) + string(APPEND CFLAG_EXCLUDES "\"${cflag}\", ") + endforeach() + string(APPEND CFLAG_EXCLUDES "]") + string(APPEND CHIP_GN_ARGS "${ARG} = filter_exclude(string_split(\"${CFLAGS}\"), ${CFLAG_EXCLUDES})\n") +endmacro() + +# ============================================================================== +# Prepare CHIP configuration based on the project Kconfig configuration +# ============================================================================== + +if (NOT CHIP_ROOT) + get_filename_component(CHIP_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/../../.. REALPATH) +endif() + +# Prepare compiler flags + +if (CONFIG_ARM) + list(APPEND CHIP_CFLAGS_C + --specs=nosys.specs + ) +endif() + +if (CONFIG_POSIX_API) + list(APPEND CHIP_CFLAGS + -D_USE_LONG_TIME_T # TODO: Remove when #3822 is resolved + -D_SYS__PTHREADTYPES_H_ + -isystem${ZEPHYR_BASE}/include/posix + ) +endif() + +if (CONFIG_NORDIC_SECURITY_BACKEND) + # TODO: Remove when the missing dependency is fixed in nRF Connect SDK + zephyr_include_directories(${ZEPHYR_BASE}/../nrfxlib/crypto/nrf_cc310_platform/include) + + list(APPEND CHIP_CFLAGS + -DMBEDTLS_CONFIG_FILE= + -DMBEDTLS_PK_WRITE_C + -DMBEDTLS_X509_CREATE_C + -DMBEDTLS_X509_CSR_WRITE_C + ) +endif() + +zephyr_get_compile_flags(CHIP_CFLAGS_C C) +zephyr_get_compile_flags(CHIP_CFLAGS_CC CXX) +zephyr_get_gnu_cpp_standard(CHIP_CFLAGS_CC) + +convert_list_of_flags_to_string_of_flags(CHIP_CFLAGS CHIP_CFLAGS) +convert_list_of_flags_to_string_of_flags(CHIP_CFLAGS_C CHIP_CFLAGS_C) +convert_list_of_flags_to_string_of_flags(CHIP_CFLAGS_CC CHIP_CFLAGS_CC) + +# Prepare CHIP libraries that the application should be linked with + +if (NOT CHIP_LIBRARIES) + set(CHIP_LIBRARIES -lCHIP) +endif() + +if (CONFIG_CHIP_LIB_SHELL) + list(APPEND CHIP_LIBRARIES ${CMAKE_CURRENT_BINARY_DIR}/obj/third_party/connectedhomeip/src/lib/shell/lib/libCHIPShell.a) +endif() + +if (CONFIG_CHIP_PW_RPC) + list(APPEND CHIP_LIBRARIES -lPwRpc) +endif() + +# Set up CHIP project configuration file + +if (CONFIG_CHIP_PROJECT_CONFIG) + get_filename_component(CHIP_PROJECT_CONFIG + ${CONFIG_CHIP_PROJECT_CONFIG} + REALPATH + BASE_DIR ${CMAKE_SOURCE_DIR} + ) + set(CHIP_PROJECT_CONFIG "<${CHIP_PROJECT_CONFIG}>") +else() + set(CHIP_PROJECT_CONFIG "") +endif() + +# Set up custom OpenThread configuration + +if (CONFIG_CHIP_OPENTHREAD_CONFIG) + get_filename_component(CHIP_OPENTHREAD_CONFIG + ${CONFIG_CHIP_OPENTHREAD_CONFIG} + REALPATH + BASE_DIR ${CMAKE_SOURCE_DIR} + ) + zephyr_set_openthread_config(${CHIP_OPENTHREAD_CONFIG}) +endif() + +# ============================================================================== +# Generate configuration for CHIP GN build system +# ============================================================================== + +chip_gn_arg_cflags("target_cflags" ${CHIP_CFLAGS}) +chip_gn_arg_cflags("target_cflags_c" ${CHIP_CFLAGS_C}) +chip_gn_arg_cflags("target_cflags_cc" ${CHIP_CFLAGS_CC}) +chip_gn_arg_string("zephyr_ar" ${CMAKE_AR}) +chip_gn_arg_string("zephyr_cc" ${CMAKE_C_COMPILER}) +chip_gn_arg_string("zephyr_cxx" ${CMAKE_CXX_COMPILER}) +chip_gn_arg_string("chip_project_config_include" "${CHIP_PROJECT_CONFIG}") +chip_gn_arg_string("chip_system_project_config_include" "${CHIP_PROJECT_CONFIG}") +chip_gn_arg_bool ("is_debug" CONFIG_DEBUG) +chip_gn_arg_bool ("chip_enable_openthread" CONFIG_NET_L2_OPENTHREAD) +chip_gn_arg_bool ("chip_inet_config_enable_ipv4" CONFIG_NET_IPV4) +chip_gn_arg_bool ("chip_build_tests" CONFIG_CHIP_BUILD_TESTS) +chip_gn_arg_bool ("chip_inet_config_enable_raw_endpoint" CONFIG_CHIP_BUILD_TESTS) +chip_gn_arg_bool ("chip_inet_config_enable_tcp_endpoint" CONFIG_CHIP_BUILD_TESTS) +chip_gn_arg_bool ("chip_inet_config_enable_dns_resolver" CONFIG_CHIP_BUILD_TESTS) +chip_gn_arg_bool ("chip_build_libshell" CONFIG_CHIP_LIB_SHELL) +chip_gn_arg_bool ("chip_build_pw_rpc_lib" CONFIG_CHIP_PW_RPC) + +if (BOARD STREQUAL "native_posix") + chip_gn_arg_string("target_cpu" "x86") +elseif (BOARD STREQUAL "native_posix_64") + chip_gn_arg_string("target_cpu" "x64") +endif() + +file(GENERATE OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/args.gn CONTENT ${CHIP_GN_ARGS}) + +# ============================================================================== +# Define 'chip-gn' target that builds CHIP library(ies) with GN build system +# ============================================================================== + +ExternalProject_Add( + chip-gn + PREFIX ${CMAKE_CURRENT_BINARY_DIR} + SOURCE_DIR ${CHIP_ROOT} + BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR} + CONFIGURE_COMMAND gn --root=${CHIP_ROOT}/config/nrfconnect/chip-gn gen --check --fail-on-unused-args ${CMAKE_CURRENT_BINARY_DIR} + BUILD_COMMAND ninja + INSTALL_COMMAND "" + BUILD_BYPRODUCTS ${CHIP_LIBRARIES} + BUILD_ALWAYS TRUE + USES_TERMINAL_CONFIGURE TRUE + USES_TERMINAL_BUILD TRUE +) +add_dependencies(chip-gn kernel) + +# ============================================================================== +# Define 'chip' target that exposes CHIP headers & libraries to the application +# ============================================================================== + +zephyr_interface_library_named(chip) +target_compile_definitions(chip INTERFACE CHIP_HAVE_CONFIG_H) +target_include_directories(chip INTERFACE + ${CHIP_ROOT}/src + ${CHIP_ROOT}/src/app/server + ${CHIP_ROOT}/src/app/util + ${CHIP_ROOT}/src/include + ${CHIP_ROOT}/src/lib + ${CHIP_ROOT}/src/lib/core + ${CHIP_ROOT}/third_party/nlassert/repo/include + ${CMAKE_CURRENT_BINARY_DIR}/gen/include + ${CMAKE_CURRENT_BINARY_DIR}/gen/third_party/connectedhomeip/src/app/include +) +target_link_directories(chip INTERFACE ${CMAKE_CURRENT_BINARY_DIR}/lib) +target_link_libraries(chip INTERFACE -Wl,--start-group ${CHIP_LIBRARIES} -Wl,--end-group) +add_dependencies(chip chip-gn) + +endif() # CONFIG_CHIP diff --git a/config/nrfconnect/Kconfig b/config/nrfconnect/chip-module/Kconfig similarity index 58% rename from config/nrfconnect/Kconfig rename to config/nrfconnect/chip-module/Kconfig index ed969940d22e78..59d7be4efda4ef 100644 --- a/config/nrfconnect/Kconfig +++ b/config/nrfconnect/chip-module/Kconfig @@ -14,53 +14,67 @@ # limitations under the License. # -mainmenu "CHIP application" - -source "Kconfig.zephyr" - -config CHIP - bool "Enable CHIP" +menuconfig CHIP + bool "Connected Home over IP protocol stack" default n select CPLUSPLUS imply LIB_CPLUSPLUS + imply REQUIRES_FULL_LIBC + imply POSIX_API if !ARCH_POSIX + imply EVENTFD if !ARCH_POSIX imply REBOOT - select ENTROPY_GENERATOR + imply ENTROPY_GENERATOR imply NET_UDP imply NET_IPV6 imply NET_CONFIG_NEED_IPV6 imply NET_SOCKETS - imply MULTIPROTOCOL help - Use the CHIP protocol. + This option enables Connected Home over IP libraries. + +if CHIP + +config CHIP_PROJECT_CONFIG + string "Project configuration file for CHIP" + help + Project configuration file for CHIP. If specified, CHIP generic + configuration files will include the project configuration file which can + be used to override any CHIP default or platform-specific settings. + +config CHIP_OPENTHREAD_CONFIG + string "Custom OpenThread configuration file" + help + This option can be used to replace Zephyr-supplied OpenThread + configuration file with a custom one. config CHIP_LIB_SHELL - bool "Enable CHIP's shell library" + bool "Enable CHIP shell library" + default n help - Link the application with the library containing CHIP shell commands + Link the application with the library containing CHIP shell commands. config CHIP_PW_RPC bool "Enable Pigweed RPC library" + default n help - Link the application with the library containing Pigweed RPC functionalities + Link the application with the library containing Pigweed RPC functionalities. -config MULTIPROTOCOL - bool "Enable multiprotocol support" - select NRF_802154_MULTIPROTOCOL_SUPPORT - depends on BT && NET_L2_OPENTHREAD +config CHIP_BUILD_TESTS + bool "Build CHIP unit tests" + default n help - Enable multiprotocol in the nRF 802.15.4 radio driver + This option enables building CHIP unit tests. config CHIP_DISABLE_CHIPOBLE_ADVERTISING_WHEN_PROVISIONED bool "Disable CHIPoBLE advertising when device is fully provisioned" default y help - Enables CHIPoBLE advertising disabling when the device achieves a fully provisioned state. + Disable CHIPoBLE advertising when the device achieves a fully provisioned state. config CHIP_ENABLE_CHIPOBLE_ADVERTISING_AUTOSTART bool "Enable CHIPoBLE advertising autostart" default n help - Enables starting CHIPoBLE advertising automatically after application boot. + Start CHIPoBLE advertising automatically at application boot time. config CHIP_NFC_COMMISSIONING bool "Enable NFC commissioning support" @@ -73,3 +87,5 @@ config CHIP_NFC_COMMISSIONING imply NFC_NDEF_URI_MSG help Enables NFC commissioning by sharing onboarding payload in NFC tag. + +endif diff --git a/config/nrfconnect/chip-module/zephyr-util.cmake b/config/nrfconnect/chip-module/zephyr-util.cmake new file mode 100644 index 00000000000000..3fdadb9727b75e --- /dev/null +++ b/config/nrfconnect/chip-module/zephyr-util.cmake @@ -0,0 +1,73 @@ +# +# 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 +# CMake utilities for managing and retrieving Zephyr build configuration +# + +# Retrieve Zephyr compiler flags for the given language (C or CXX) +function(zephyr_get_compile_flags VAR LANG) + # We want to treat all zephyr-provided headers as system headers, so + # warnings in them don't trigger -Werror. That means that for the headers + # zephyr returns as "non-system" headers (the ones from + # zephyr_get_include_directories_for_lang) we need to manually replace "-I" + # with "-isystem". + zephyr_get_include_directories_for_lang(${LANG} INCLUDES) + list(TRANSFORM INCLUDES REPLACE "-I" "-isystem") + zephyr_get_system_include_directories_for_lang(${LANG} SYSTEM_INCLUDES) + zephyr_get_compile_definitions_for_lang(${LANG} DEFINES) + zephyr_get_compile_options_for_lang(${LANG} FLAGS) + set(${VAR} ${INCLUDES} ${SYSTEM_INCLUDES} ${DEFINES} ${FLAGS} ${${VAR}} PARENT_SCOPE) +endfunction() + +# Select gnu++ standard based on Kconfig configuration +macro(zephyr_get_gnu_cpp_standard VAR) + if (CONFIG_STD_CPP11) + list(APPEND ${VAR} -std=gnu++11) + elseif (CONFIG_STD_CPP14) + list(APPEND ${VAR} -std=gnu++14) + elseif (CONFIG_STD_CPP17) + list(APPEND ${VAR} -std=gnu++17) + elseif (CONFIG_STD_CPP2A) + list(APPEND ${VAR} -std=gnu++20) + else() + message(FATAL_ERROR "Building with unsupported C++ standard") + endif() +endmacro() + +function(zephyr_set_openthread_config_impl OT_DIR CONFIG_FILE) + get_property(DEFINES DIRECTORY ${OT_DIR} PROPERTY COMPILE_DEFINITIONS) + get_property(SUBDIRS DIRECTORY ${OT_DIR} PROPERTY SUBDIRECTORIES) + + list(TRANSFORM DEFINES REPLACE + OPENTHREAD_PROJECT_CORE_CONFIG_FILE=.* + OPENTHREAD_PROJECT_CORE_CONFIG_FILE="${CONFIG_FILE}") + + set_property(DIRECTORY ${OT_DIR} PROPERTY COMPILE_DEFINITIONS ${DEFINES}) + + foreach(SUBDIR ${SUBDIRS}) + zephyr_set_openthread_config_impl(${SUBDIR} ${CONFIG_FILE}) + endforeach() +endfunction() + +# Replace Zephyr-supplied configuration file with a custom one +function(zephyr_set_openthread_config CONFIG_PATH) + get_filename_component(CONFIG_DIR ${CONFIG_PATH} DIRECTORY) + get_filename_component(CONFIG_FILE ${CONFIG_PATH} NAME) + target_include_directories(ot-config INTERFACE ${CONFIG_DIR}) + zephyr_set_openthread_config_impl(${ZEPHYR_OPENTHREAD_MODULE_DIR} ${CONFIG_FILE}) +endfunction() diff --git a/config/nrfconnect/chip-module/zephyr/module.yml b/config/nrfconnect/chip-module/zephyr/module.yml new file mode 100644 index 00000000000000..3ab57aa7ec540a --- /dev/null +++ b/config/nrfconnect/chip-module/zephyr/module.yml @@ -0,0 +1,19 @@ +# +# 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. +# + +build: + cmake: . + kconfig: Kconfig diff --git a/config/nrfconnect/nrfconnect-app.cmake b/config/nrfconnect/nrfconnect-app.cmake deleted file mode 100644 index 9f3f1d00cda7d5..00000000000000 --- a/config/nrfconnect/nrfconnect-app.cmake +++ /dev/null @@ -1,143 +0,0 @@ -# -# 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 -# CMake module for incorporating CHIP into an nRF Connect SDK -# application for Nordic platforms. -# - -# -# The top-level CMakeLists.txt of an application should define CHIP_ROOT variable, -# include this module and configure `app` build target properly. E.g.: -# -# cmake_minimum_required(VERSION 3.13.1) -# -# set(CHIP_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/third_party/connectedhomeip) -# get_filename_component(CHIP_ROOT ${CHIP_ROOT} REALPATH) -# set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CHIP_ROOT}/config/nrfconnect/) -# -# include(nrfconnect-app) -# -# project(chip-nrf52840-lock-example) -# target_sources(app PRIVATE main/main.cpp ...) -# - -# Set DTC overlay before finding the Zephyr package. -if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/dts.overlay") - set(DTC_OVERLAY_FILE "${CMAKE_CURRENT_SOURCE_DIR}/dts.overlay") -endif() - -# Set Kconfig root -if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/Kconfig) - set(KCONFIG_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/Kconfig) -else() - set(KCONFIG_ROOT ${CHIP_ROOT}/config/nrfconnect/Kconfig) -endif() - -# ================================================== -# Load NCS/Zephyr build system -# ================================================== -find_package(Zephyr HINTS $ENV{ZEPHYR_BASE}) - -# TODO: temporary fix forcing time_t size to be equal long size - remove it after merging fix from Zephyr project. -zephyr_compile_definitions(_USE_LONG_TIME_T) - -# ================================================== -# General settings -# ================================================== - -include(chip-lib) - -set(CHIP_COMMON_FLAGS - -D_SYS__PTHREADTYPES_H_ - -DMBEDTLS_CONFIG_FILE= - -DMBEDTLS_PK_WRITE_C - -DMBEDTLS_X509_CREATE_C - -DMBEDTLS_X509_CSR_WRITE_C - -isystem${ZEPHYR_BASE}/include/posix - -isystem${ZEPHYR_BASE}/../mbedtls/include - -I${CMAKE_CURRENT_SOURCE_DIR} - -I${CMAKE_CURRENT_SOURCE_DIR}/main/include -) - -set(CHIP_LIBRARIES ${CHIP_OUTPUT_DIR}/lib/libCHIP.a) -if (CONFIG_CHIP_LIB_SHELL) - list(APPEND CHIP_LIBRARIES ${CHIP_OUTPUT_DIR}/obj/third_party/connectedhomeip/src/lib/shell/lib/libCHIPShell.a) -endif() -if (CONFIG_CHIP_PW_RPC) - list(APPEND CHIP_LIBRARIES ${CHIP_OUTPUT_DIR}/lib/libPwRpc.a) -endif() - -find_file(CHIP_PROJECT_CONFIG - CHIPProjectConfig.h - PATHS ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/main/include - NO_DEFAULT_PATH -) - -# ================================================== -# Configure Zephyr -# ================================================== - -function(set_openthread_config OT_DIR CONFIG_FILE) - get_property(DEFINES DIRECTORY ${OT_DIR} PROPERTY COMPILE_DEFINITIONS) - get_property(SUBDIRS DIRECTORY ${OT_DIR} PROPERTY SUBDIRECTORIES) - - list(TRANSFORM DEFINES REPLACE - OPENTHREAD_PROJECT_CORE_CONFIG_FILE=.* - OPENTHREAD_PROJECT_CORE_CONFIG_FILE="${CONFIG_FILE}") - - set_property(DIRECTORY ${OT_DIR} PROPERTY COMPILE_DEFINITIONS ${DEFINES}) - - foreach(SUBDIR ${SUBDIRS}) - set_openthread_config(${SUBDIR} ${CONFIG_FILE}) - endforeach() -endfunction() - -# Add dependency on nRF crypto library. -# This is temporary solution and should be removed after fixing it in nRF Connect SDK. -zephyr_include_directories(${ZEPHYR_BASE}/../nrfxlib/crypto/nrf_cc310_platform/include) - -# Override Zephyr-supplied OpenThread configuration -if (CHIP_OPENTHREAD_CONFIG) - get_filename_component(CONFIG_DIR ${CHIP_OPENTHREAD_CONFIG} DIRECTORY) - get_filename_component(CONFIG_FILE ${CHIP_OPENTHREAD_CONFIG} NAME) - target_include_directories(ot-config INTERFACE ${CONFIG_DIR}) - set_openthread_config(${ZEPHYR_BASE}/../modules/lib/openthread ${CONFIG_FILE}) -endif() - -# ================================================== -# Setup CHIP build -# ================================================== - -chip_configure(ChipConfig - ARCH arm-none-eabi - CFLAGS ${CHIP_COMMON_FLAGS} --specs=nosys.specs - CXXFLAGS ${CHIP_COMMON_FLAGS} - PROJECT_CONFIG ${CHIP_PROJECT_CONFIG} -) - -chip_build(ChipLib ChipConfig - BUILD_COMMAND ninja - BUILD_ARTIFACTS ${CHIP_LIBRARIES} -) - -# ================================================== -# Configure application -# ================================================== - -target_link_libraries(app PUBLIC ChipLib) -target_compile_definitions(app PRIVATE CHIP_HAVE_CONFIG_H) diff --git a/config/nrfconnect/third_party/connectedhomeip b/config/nrfconnect/third_party/connectedhomeip deleted file mode 120000 index a8a4f8c2127bf7..00000000000000 --- a/config/nrfconnect/third_party/connectedhomeip +++ /dev/null @@ -1 +0,0 @@ -../../.. \ No newline at end of file diff --git a/config/standalone/CHIPProjectConfig.h b/config/standalone/CHIPProjectConfig.h index 148cb2cf59f54d..feb00ce7cf7e6d 100644 --- a/config/standalone/CHIPProjectConfig.h +++ b/config/standalone/CHIPProjectConfig.h @@ -38,6 +38,10 @@ // Enable support functions for parsing command-line arguments #define CHIP_CONFIG_ENABLE_ARG_PARSER 1 +// Use a default pairing code if one hasn't been provisioned in flash. +#define CHIP_DEVICE_CONFIG_USE_TEST_SETUP_PIN_CODE 12345678 +#define CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR 0xF00 + // Enable reading DRBG seed data from /dev/(u)random. // This is needed for test applications and the CHIP device manager to function // properly when CHIP_CONFIG_RNG_IMPLEMENTATION_CHIPDRBG is enabled. diff --git a/docs/BUILDING.md b/docs/BUILDING.md index 2ab5baa3bd631d..f00489f308bd4a 100644 --- a/docs/BUILDING.md +++ b/docs/BUILDING.md @@ -83,6 +83,8 @@ Finally, install some Raspberry Pi specific dependencies: sudo apt-get install pi-bluetooth ``` +You need to reboot your RPi after install `pi-bluetooth`. + ### Build Preparation Before running any other build command, the `scripts/activate.sh` environment diff --git a/docs/Doxyfile b/docs/Doxyfile index 461d499209b31c..9230cc1ac11170 100644 --- a/docs/Doxyfile +++ b/docs/Doxyfile @@ -843,7 +843,8 @@ INPUT = README.md \ src/platform \ src/setup_payload \ src/system \ - src/transport + src/transport \ + src/test_driver/linux-cirque/README.md USE_MDFILE_AS_MAINPAGE = README.md diff --git a/docs/README.md b/docs/README.md index 922369481ab7bf..ef6e6223b99a30 100644 --- a/docs/README.md +++ b/docs/README.md @@ -4,6 +4,9 @@ - Documentation about building from the command line can be found in [the build guide](./BUILDING.md) +- Documentation about running [cirque](https://github.com/openweave/cirque) + tests can be found in + [the cirque test guide](src/test_driver/linux-cirque/README.md) - Documentation about standard build & development flows using [Visual Studio Code](https://code.visualstudio.com/) can be found in [the development guide](./VSCODE_DEVELOPMENT.md) diff --git a/docs/specs/chip-tlv-format.adoc b/docs/specs/chip-tlv-format.adoc deleted file mode 100644 index aa9e3c1b783639..00000000000000 --- a/docs/specs/chip-tlv-format.adoc +++ /dev/null @@ -1,509 +0,0 @@ -= Project Connected Home over IP -:toc: macro -:toclevels: 7 - -[discrete] -[.text-center] -== TLV Format - -[.text-center] -_Revision 6_ + -_2020-05-08_ - -[.text-center] -*Status:* [red]*Final* / [red]*Active* - -toc::[] - -== Introduction - -This document describes the CHIP TLV (_Tag-Length-Value_) format. CHIP -TLV is a generalized encoding method for simple structured data. It -shares many properties with the commonly used JSON serialization format -while being considerably more compact over the wire. - -== TLV Elements and Encodings - -Values in the CHIP TLV format are encoded as _TLV elements_. Each TLV -element has a type. Element types fall into two categories: _primitive -types_ and _container types_. Primitive types convey fundamental data -values such as integers and strings. Container types convey collections -of elements that themselves are either primitives or containers. The -CHIP TLV format supports three different container types: structures, -arrays and lists. - -All valid _TLV encodings_ consist of a single top-level element. This -value can be either a primitive type or a container type. - -== Tags - -A TLV element includes an optional numeric tag that identifies its -purpose. Two categories of tags are defined: _profile-specific _and -_context-specific_. A TLV element without a tag is called an _anonymous_ -element. - -=== Profile-Specific Tags - -Profile-specific tags identify elements globally. A profile-specific tag -is a 64-bit number composed of the following fields: - -* 16-bit vendor id -* 16-bit profile number -* 32-bit tag number - -Profile-specific tags are defined either by CHIP or by external vendors. -Additionally the CHIP Common Profile includes a set of predefined -profile-specific tags that can be used across organizations. - -=== Context-Specific Tags - -Context-specific tags identify elements within the context of a -containing structure element. A context-specific tag consists of a -single 8-bit tag number. The meaning of a context specific tag derives -from the structure it resides in, implying that the same tag number may -have different meanings in the context of different structures. -Effectively, the interpretation of a context specific tag depends on the -tag attached to the containing element. Because structures themselves -can be assigned context-specific tags, the interpretation of a -context-specific tag may ultimately depend on a nested chain of such -tags. - -Context-specific tags can only be assigned to elements that are -immediately within a structure. This implies that an element with a -context-specific tag cannot appear as the outermost element of a TLV -encoding. - -=== Anonymous Tags - -A special anonymous tag is used to denote TLV elements that lack a tag -value. Such a TLV element is referred to as an anonymous element. - -=== Canonical Ordering of Tags - -Where a distinguished ordering of tags is required (e.g. for the purposes -of generating a hash or cryptographic signature of elements within a -structure), the following ordering rules shall be used: - -* Anonymous tags shall be ordered before all other tags. -* Context specific tags shall be ordered before profile specific tags. -* Context specific tags with numerically lesser tag values shall be ordered -before those with higher tag values. -* Profile specific tags with numerically lesser vendor ids shall be ordered -before those with higher vendor ids. -* Profile specific tags with the same vendor id, but numerically lesser -profile numbers shall be ordered before those with higher numbers. - -== Lengths - -Depending on its type, a TLV element may contain a length field that -gives the length, in bytes, of the element’s value field. A length field -is only present for string types (character and byte strings). Other -element types either have a predetermined length or are encoded with a -marker that identifies their end. - -== Primitive Types - -The CHIP TLV format supports the following primitive types: - -* Signed integers -* Unsigned integers -* UTF-8 Strings -* Byte Strings -* Single or double-precision floating point numbers (IEEE 754-1985 -format) -* Booleans -* Nulls - -Of the primitive types, integers, floating point numbers, booleans and -nulls have a predetermined length specified by their type. Byte strings -and UTF-8 strings include a length field that gives their lengths in -bytes. - -== Container Types - -The CHIP TLV format supports the following container types: - -* Structures -* Arrays -* Lists - -Each of the container types is a form of element collection that can -contain primitive types and/or other container types. The elements -appearing immediately within a container type are called its _members_. -A container type can contain any number of member elements, including -none. Container types can be nested to any depth and in any combination. -The end of a container type is denoted by a special element called the -‘end-of-container’ element. Although encoded as a member, conceptually -the end-of-container element is not included in the members of the -containing type. - -=== Structures - -A structure is a collection of member elements that each have a distinct -meaning. All member elements within a structure must have a unique tag -as compared to the other members of the structure. Member elements -without tags (anonymous elements) are not allowed in structures. The -encoded ordering of members in a structure may or may not be important -depending on the intent of the sender or the expectations of the -receiver. For example, in some situations, senders and receivers may -agree on a particular ordering of elements to make encoding and decoding -easier. - -Where a distinguished ordering of members is required (for example, for -the purposes of generating a hash or cryptographic signature of the -structure), the members of the structure shall be encoded in order of -their tag values, according to the rules for the canonical ordering of tags. - -=== Arrays - -An array is an ordered collection of member elements that either do not -have distinct meanings, or whose meanings are implied by their encoded -positions in the array. An array can contain any type of element, -including other arrays. All member elements of an array must be anonymous -elements–that is, they must be encoded with an anonymous tag. - -=== Lists - -A list is an ordered collection of member elements, each of which may be -encoded with a tag. The meanings of member elements in a list are denoted -by their position within the list in conjunction with any associated tag -value they may have. - -A list can contain any type of element, including other lists. The members -of a list may be encoded with any form of tag, including an anonymous tag. -The tags within a list needn’t be unique with respect to other members of -the list. - -|=== -**Note:** In a previous version of this specification, the list type was -referred to as a “path”. It was subsequently renamed to better reflect its -use in practice. -|=== - -== Element Encoding - -A TLV element is encoded a single control byte, followed by a sequence -of tag, length and value bytes. Depending on the nature of the element, -any of the tag, length or value fields may be omitted. - -[options="header"] -|=== -|Control Byte|Tag|Length|Value -|1 byte|0 to 8 bytes|0 to 8 bytes|Variable -|=== - -== Control Byte Encoding - -The control byte specifies the type of a TLV element and how its tag, -length and value fields are encoded. The control byte consists of two -subfields: an _element type field_ which occupies the lower 5 bits, and -a _tag control field_ which occupies the upper 3 bits. - -=== Element Type Field - -The element type field encodes the element’s type as well as how the -corresponding length and value fields are encoded. In the case of -Booleans and the null value, the element type field also encodes the -value itself. - -[cols="^1,^1,^1,^1,^1,^1,^1,^1,<8",options="header"] -|=== -8+h|Control Byte -.3+h|Description -3+h|Tag Control -5+h|Element Type -h|7 -h|6 -h|5 -h|4 -h|3 -h|2 -h|1 -h|0 -|x|x|x|0|0|0|0|0|Signed Integer, 1-byte value -|x|x|x|0|0|0|0|1|Signed Integer, 2-byte value -|x|x|x|0|0|0|1|0|Signed Integer, 4-byte value -|x|x|x|0|0|0|1|1|Signed Integer, 8-byte value -|x|x|x|0|0|1|0|0|Unsigned Integer, 1-byte value -|x|x|x|0|0|1|0|1|Unsigned Integer, 2-byte value -|x|x|x|0|0|1|1|0|Unsigned Integer, 4-byte value -|x|x|x|0|0|1|1|1|Unsigned Integer, 8-byte value -|x|x|x|0|1|0|0|0|Boolean False -|x|x|x|0|1|0|0|1|Boolean True -|x|x|x|0|1|0|1|0|Floating Point Number, 4-byte value -|x|x|x|0|1|0|1|1|Floating Point Number, 8-byte value -|x|x|x|0|1|1|0|0|UTF-8 String, 1-byte length -|x|x|x|0|1|1|0|1|UTF-8 String, 2-byte length -|x|x|x|0|1|1|1|0|UTF-8 String, 4-byte length -|x|x|x|0|1|1|1|1|UTF-8 String, 8-byte length -|x|x|x|1|0|0|0|0|Byte String, 1-byte length -|x|x|x|1|0|0|0|1|Byte String, 2-byte length -|x|x|x|1|0|0|1|0|Byte String, 4-byte length -|x|x|x|1|0|0|1|1|Byte String, 8-byte length -|x|x|x|1|0|1|0|0|Null -|x|x|x|1|0|1|0|1|Structure -|x|x|x|1|0|1|1|0|Array -|x|x|x|1|0|1|1|1|List -|x|x|x|1|1|0|0|0|End of Container -|x|x|x|1|1|0|0|1|Reserved -|x|x|x|1|1|0|1|0|Reserved -|x|x|x|1|1|0|1|1|Reserved -|x|x|x|1|1|1|0|0|Reserved -|x|x|x|1|1|1|0|1|Reserved -|x|x|x|1|1|1|1|0|Reserved -|x|x|x|1|1|1|1|1|Reserved -|=== - -For types that have varying length or value fields, the bottom two bits -of the element type field signal the width of the corresponding field as -follows: - -* 00 -- 1 byte -* 01 -- 2 bytes -* 10 -- 4 bytes -* 11 -- 8 bytes - -=== Tag Control Field - -The tag control field identifies the form of tag assigned to the element -(including none) as well as the encoding of the tag bytes. - -[cols="^1,^1,^1,^1,^1,^1,^1,^1,<8",options="header"] -|=== -8+h|Control Byte -.3+h|Description -3+h|Tag Control -5+h|Element Type -h|7 -h|6 -h|5 -h|4 -h|3 -h|2 -h|1 -h|0 -|0|0|0|x|x|x|x|x|Anonymous, 0 bytes -|0|0|1|x|x|x|x|x|Context-specific Tag, 1 byte -|0|1|0|x|x|x|x|x|Common Profile Tag, 2 bytes -|0|1|1|x|x|x|x|x|Common Profile Tag, 4 bytes -|1|0|0|x|x|x|x|x|Implicit Profile Tag, 2 bytes -|1|0|1|x|x|x|x|x|Implicit Profile Tag, 4 bytes -|1|1|0|x|x|x|x|x|Fully-qualified Tag, 6 bytes -|1|1|1|x|x|x|x|x|Fully-qualified Tag, 8 bytes -|=== - -== Tag Encoding - -Tags are encoded in 0, 1, 2, 4, 6 or 8 byte widths as specified by the -tag control field. Tags consist of up to three numeric fields: a _vendor -id field_, a _profile number field_, and a _tag number field_. All -fields are encoded in little-endian order. - -=== Fully-Qualified Form - -A profile-specific tag can be encoded in _fully-qualified form_, where -the encoding includes all three tag components (vendor id, profile -number and tag number). Two variants of this form are supported, one -with a 16-bit tag number and one with a 32-bit tag number. The 16-bit -variant must be used with tag numbers < 65536, while the 32-bit variant -must be used with tag numbers >= 65536. - -[options="header"] -|=== -|Tag Control|Vendor Id Size|Profile Number Size|Tag Number Size| -|C0h|2 bytes|2 bytes|2 bytes|For tag numbers < 65536 -|E0h|2 bytes|2 bytes|4 bytes|For tag numbers >= 65535 -|=== - -=== Implicit Form - -A profile-specific tag can also be encoded in _implicit form_, where the -encoding includes only the tag number, and the vendor id and profile -number are inferred from the protocol context in which the TLV encoding -is communicated. This form also has two variants based on the magnitude -of the tag number. - -[options="header"] -|=== -|Tag Control|Tag Number Size| -|80h|2 bytes|For tag numbers < 65536 -|A0h|4 bytes|For tag numbers >= 65535 -|=== - -=== Common Profile Form - -A special encoding exists for profile-specific tags that are defined by -the CHIP Common Profile. These are encoded in the same manner as -implicit tags except that they are identified as common profile tags, -rather than implicit profile tags in the tag control field. - -[options="header"] -|=== -|Tag Control|Tag Number Size| -|40h|2 bytes|For tag numbers < 65536 -|60h|4 bytes|For tag numbers >= 65535 -|=== - -=== Context-Specific Form - -Context-specific tags are encoded as a single byte conveying the tag -number. - -[options="header"] -|=== -|Tag Control|Tag Number Size| -|20h|1 bytes|All tag numbers 0 - 255 -|=== - -=== Anonymous - -Anonymous elements do not encode any tag bytes. - -[options="header"] -|=== -|Tag Control|Tag Size| -|00h|0 bytes|No data encoded. -|=== - -== Length Encoding - -Length fields are encoded in 0, 1, 2 or 4 byte widths, as specified by -the element type field. Length fields of more than one byte are encoded -in little-endian order. The choice of width for the length field is up -to the discretion of the sender, implying that a sender can choose to -send more length bytes than strictly necessary to encode the value. - -== End of Container Encoding - -The end of a container type is marked with a special element called the -end-of-container element. The end-of-container element is encoded as a -single control byte with the value 18h. The tag control bits within the -control byte must be set to zero, implying that end-of-container element -can never have a tag. - -[options="header"] -|=== -|Control Byte -|1 byte -|=== - -== Value Encodings - -=== Integers - -An integer element is encoded as follows: - -[options="header"] -|=== -|Control Byte|Tag|Value -|1 byte|0 to 8 bytes|1, 2, 4 or 8 bytes -|=== - -The number of bytes in the value field is indicated by the element type -field within the control byte. The choice of value byte count is at the -sender’s discretion, implying that a sender is free to send more bytes -than strictly necessary to encode the value. Within the value bytes, the -integer value is encoded in little-endian two’s complement format. - -=== UTF-8 and Byte Strings - -UTF-8 and byte strings are encoded as follows: - -[options="header"] -|=== -|Control Byte|Tag|Length|Value -|1 byte|0 to 8 bytes|1 to 4 bytes|0 to 2^32^-1 bytes -|=== - -The length field of a UTF-8 or byte string encodes the number of bytes -(not characters) present in the value field. The number of bytes in the -length field is implied by the type specified in the element type field -(within the control byte). - -For UTF-8 strings, the value bytes must encode a valid UTF-8 character -sequence. Senders *should not* include a terminating null character to -mark the end of a string. For byte strings, the value can be any -arbitrary sequence of bytes. - -=== Booleans - -Boolean elements are encoded as follows: - -[options="header"] -|=== -|Control Byte|Tag -|1 byte|0 to 8 bytes -|=== - -The value of a Boolean element (true or false) is implied by the type -indicated in the element type field. - -=== Arrays, Structures and Lists - -Array, structure and list elements are encoded as follows: - -[options="header"] -|=== -|Control Byte|Tag|Value|End-of-Container -|1 byte|0 to 8 bytes|_Variable_|1-byte -|=== - -The value field of an array/structure/list element is a sequence of -encoded TLV elements that constitute the members of the element, -followed by an end-of-container element. The end-of-container element -must always be present, even in cases where the end of the -array/structure/list element could be inferred by other means (e.g. the -length of the packet containing the TLV encoding). - -=== Floating Point Numbers - -A floating point number is encoded as follows: - -[options="header"] -|=== -|Control Byte|Tag|Value -|1 byte|0 to 8 bytes|4 or 8 bytes -|=== - -The value field of a floating point element contains an IEEE 754-1985 -single or double precision floating point number encoded in -little-endian format (specifically, the reverse of the order described -in External Data Representation, RFC 4506). The choice of precision is -implied by the type specified in the element type field (within the -control byte). The sender is free to choose either precision at their -discretion. - -=== Nulls - -A null value is encoded as follows: - -[options="header"] -|=== -|Control Byte|Tag -|1 byte|0 to 8 bytes -|=== - -[discrete] -== Revision History - -[cols="^1,^1,<1,<4",options="header"] -|=== -|Revision |Date |Modified By |Description -|6|2020-05-08|Jay Logue|Renamed path type to list and clarified text in corresponding section. - -Added section on canonical ordering of tags. - -Added section describing anonymous tags. - -Clarified descriptions of structure and array types. - -Clarified encoding of floating point values with reference to RFC-4506. -|5|2020-04-23|Grant Erickson|Import into Project Connected Home over IP. -|4|2013-05-20|Jay Logue|Fixed incorrect control byte value for end of container encoding. -|3|2013-04-22|Jay Logue|Renamed dictionary to structure. -|2|2013-04-17|Jay Logue|Normalized the naming for ‘container’ types. -|1|2013-04-15|Jay Logue|Initial revision. -|=== - -[.text-center] -_Project Connect Home over IP Public Information_ diff --git a/examples/all-clusters-app/all-clusters-common/BUILD.gn b/examples/all-clusters-app/all-clusters-common/BUILD.gn index 556d8ffbda1fd0..16d62bf5ccc183 100644 --- a/examples/all-clusters-app/all-clusters-common/BUILD.gn +++ b/examples/all-clusters-app/all-clusters-common/BUILD.gn @@ -23,9 +23,9 @@ config("includes") { source_set("all-clusters-common") { sources = [ - "${chip_root}/examples/common/chip-app-server/DataModelHandler.cpp", "${chip_root}/src/app/clusters/barrier-control-server/barrier-control-server.cpp", "${chip_root}/src/app/clusters/basic/basic.cpp", + "${chip_root}/src/app/clusters/bindings/bindings.cpp", "${chip_root}/src/app/clusters/color-control-server/color-control-server.cpp", "${chip_root}/src/app/clusters/door-lock-client/door-lock-client.cpp", "${chip_root}/src/app/clusters/door-lock-server/door-lock-server-core.cpp", @@ -44,6 +44,7 @@ source_set("all-clusters-common") { "${chip_root}/src/app/clusters/temperature-measurement-server/temperature-measurement-server.cpp", "${chip_root}/src/app/reporting/reporting-default-configuration.cpp", "${chip_root}/src/app/reporting/reporting.cpp", + "${chip_root}/src/app/server/DataModelHandler.cpp", "${chip_root}/src/app/util/af-event.cpp", "${chip_root}/src/app/util/af-main-common.cpp", "${chip_root}/src/app/util/attribute-size.cpp", @@ -61,10 +62,7 @@ source_set("all-clusters-common") { "gen/callback-stub.cpp", ] - deps = [ - "${chip_root}/examples/common/chip-app-server:chip-app-server", - "${chip_root}/src/lib", - ] + deps = [ "${chip_root}/src/lib" ] public_configs = [ ":includes" ] } diff --git a/examples/all-clusters-app/all-clusters-common/all-clusters-app.zap b/examples/all-clusters-app/all-clusters-common/all-clusters-app.zap index 204240cdfae12c..83302f415b85bb 100644 --- a/examples/all-clusters-app/all-clusters-common/all-clusters-app.zap +++ b/examples/all-clusters-app/all-clusters-common/all-clusters-app.zap @@ -1,6 +1,6 @@ { - "writeTime": "Wed Nov 18 2020 10:23:41 GMT+0100 (Central European Standard Time)", - "featureLevel": 4, + "writeTime": "Fri Dec 11 2020 17:43:28 GMT+0100 (Central European Standard Time)", + "featureLevel": 5, "creator": "zap", "keyValuePairs": [ { @@ -33,9 +33,9 @@ "endpointTypes": [ { "name": "Anonymous Endpoint Type", - "deviceTypeName": null, - "deviceTypeCode": null, - "deviceTypeProfileId": null, + "deviceTypeName": "CHIP-All-Clusters-Server", + "deviceTypeCode": "0x0000", + "deviceTypeProfileId": "0x0103", "clusters": [ { "name": "Basic", @@ -52,8 +52,2787 @@ "source": "client", "incoming": 1, "outgoing": 1 + }, + { + "name": "MfgSpecificPing", + "code": 0, + "mfgCode": "0x1002", + "source": "client", + "incoming": 1, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "cluster revision", + "code": 65533, + "mfgCode": null, + "side": "client", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "3", + "reportable": 0, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Basic", + "code": 0, + "mfgCode": null, + "define": "BASIC_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [], + "attributes": [ + { + "name": "cluster revision", + "code": 65533, + "mfgCode": null, + "side": "server", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "3", + "reportable": 0, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ZCL version", + "code": 0, + "mfgCode": null, + "side": "server", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x08", + "reportable": 0, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "power source", + "code": 7, + "mfgCode": null, + "side": "server", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 0, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Identify", + "code": 3, + "mfgCode": null, + "define": "IDENTIFY_CLUSTER", + "side": "client", + "enabled": 1, + "commands": [ + { + "name": "Identify", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "IdentifyQuery", + "code": 1, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "cluster revision", + "code": 65533, + "mfgCode": null, + "side": "client", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "2", + "reportable": 0, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Identify", + "code": 3, + "mfgCode": null, + "define": "IDENTIFY_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [ + { + "name": "IdentifyQueryResponse", + "code": 0, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "cluster revision", + "code": 65533, + "mfgCode": null, + "side": "server", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "2", + "reportable": 0, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "identify time", + "code": 0, + "mfgCode": null, + "side": "server", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 0, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Groups", + "code": 4, + "mfgCode": null, + "define": "GROUPS_CLUSTER", + "side": "client", + "enabled": 1, + "attributes": [ + { + "name": "cluster revision", + "code": 65533, + "mfgCode": null, + "side": "client", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "3", + "reportable": 0, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ], + "commands": [ + { + "name": "AddGroup", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "ViewGroup", + "code": 1, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "GetGroupMembership", + "code": 2, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "RemoveGroup", + "code": 3, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "RemoveAllGroups", + "code": 4, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "AddGroupIfIdentifying", + "code": 5, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + } + ] + }, + { + "name": "Groups", + "code": 4, + "mfgCode": null, + "define": "GROUPS_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [ + { + "name": "AddGroupResponse", + "code": 0, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "ViewGroupResponse", + "code": 1, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "GetGroupMembershipResponse", + "code": 2, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "RemoveGroupResponse", + "code": 3, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "cluster revision", + "code": 65533, + "mfgCode": null, + "side": "server", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "3", + "reportable": 0, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "name support", + "code": 0, + "mfgCode": null, + "side": "server", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 0, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Scenes", + "code": 5, + "mfgCode": null, + "define": "SCENES_CLUSTER", + "side": "client", + "enabled": 1, + "attributes": [ + { + "name": "cluster revision", + "code": 65533, + "mfgCode": null, + "side": "client", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "3", + "reportable": 0, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ], + "commands": [ + { + "name": "AddScene", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "ViewScene", + "code": 1, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "RemoveScene", + "code": 2, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "RemoveAllScenes", + "code": 3, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "StoreScene", + "code": 4, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "RecallScene", + "code": 5, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "GetSceneMembership", + "code": 6, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + } + ] + }, + { + "name": "Scenes", + "code": 5, + "mfgCode": null, + "define": "SCENES_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [ + { + "name": "AddSceneResponse", + "code": 0, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "ViewSceneResponse", + "code": 1, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "RemoveSceneResponse", + "code": 2, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "RemoveAllScenesResponse", + "code": 3, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "StoreSceneResponse", + "code": 4, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "GetSceneMembershipResponse", + "code": 6, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "cluster revision", + "code": 65533, + "mfgCode": null, + "side": "server", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "3", + "reportable": 0, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "scene count", + "code": 0, + "mfgCode": null, + "side": "server", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 0, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "current scene", + "code": 1, + "mfgCode": null, + "side": "server", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 0, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "current group", + "code": 2, + "mfgCode": null, + "side": "server", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 0, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "scene valid", + "code": 3, + "mfgCode": null, + "side": "server", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 0, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "name support", + "code": 4, + "mfgCode": null, + "side": "server", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 0, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "On/off", + "code": 6, + "mfgCode": null, + "define": "ON_OFF_CLUSTER", + "side": "client", + "enabled": 1, + "attributes": [ + { + "name": "cluster revision", + "code": 65533, + "mfgCode": null, + "side": "client", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "2", + "reportable": 0, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ], + "commands": [ + { + "name": "Off", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "On", + "code": 1, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "Toggle", + "code": 2, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + } + ] + }, + { + "name": "On/off", + "code": 6, + "mfgCode": null, + "define": "ON_OFF_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "cluster revision", + "code": 65533, + "mfgCode": null, + "side": "server", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "2", + "reportable": 0, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "on/off", + "code": 0, + "mfgCode": null, + "side": "server", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 0, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ], + "commands": [] + }, + { + "name": "Level Control", + "code": 8, + "mfgCode": null, + "define": "LEVEL_CONTROL_CLUSTER", + "side": "client", + "enabled": 1, + "attributes": [ + { + "name": "cluster revision", + "code": 65533, + "mfgCode": null, + "side": "client", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "3", + "reportable": 0, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ], + "commands": [ + { + "name": "MoveToLevel", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "Move", + "code": 1, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "Step", + "code": 2, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "Stop", + "code": 3, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "MoveToLevelWithOnOff", + "code": 4, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "MoveWithOnOff", + "code": 5, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "StepWithOnOff", + "code": 6, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "StopWithOnOff", + "code": 7, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + } + ] + }, + { + "name": "Level Control", + "code": 8, + "mfgCode": null, + "define": "LEVEL_CONTROL_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "cluster revision", + "code": 65533, + "mfgCode": null, + "side": "server", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "3", + "reportable": 0, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "current level", + "code": 0, + "mfgCode": null, + "side": "server", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 0, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ], + "commands": [] + }, + { + "name": "Door Lock", + "code": 257, + "mfgCode": null, + "define": "DOOR_LOCK_CLUSTER", + "side": "client", + "enabled": 1, + "attributes": [ + { + "name": "cluster revision", + "code": 65533, + "mfgCode": null, + "side": "client", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "3", + "reportable": 0, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ], + "commands": [ + { + "name": "LockDoor", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "UnlockDoor", + "code": 1, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "UnlockWithTimeout", + "code": 3, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "GetLogRecord", + "code": 4, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "SetPin", + "code": 5, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "GetPin", + "code": 6, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "ClearPin", + "code": 7, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "ClearAllPins", + "code": 8, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "SetWeekdaySchedule", + "code": 11, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "GetWeekdaySchedule", + "code": 12, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "ClearWeekdaySchedule", + "code": 13, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "SetYeardaySchedule", + "code": 14, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "GetYeardaySchedule", + "code": 15, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "ClearYeardaySchedule", + "code": 16, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "SetHolidaySchedule", + "code": 17, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "GetHolidaySchedule", + "code": 18, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "ClearHolidaySchedule", + "code": 19, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "SetUserType", + "code": 20, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "GetUserType", + "code": 21, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "SetRfid", + "code": 22, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "GetRfid", + "code": 23, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "ClearRfid", + "code": 24, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "ClearAllRfids", + "code": 25, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + } + ] + }, + { + "name": "Door Lock", + "code": 257, + "mfgCode": null, + "define": "DOOR_LOCK_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "cluster revision", + "code": 65533, + "mfgCode": null, + "side": "server", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "3", + "reportable": 0, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "lock state", + "code": 0, + "mfgCode": null, + "side": "server", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "lock type", + "code": 1, + "mfgCode": null, + "side": "server", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 0, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "actuator enabled", + "code": 2, + "mfgCode": null, + "side": "server", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 0, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "door state", + "code": 3, + "mfgCode": null, + "side": "server", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "enable logging", + "code": 32, + "mfgCode": null, + "side": "server", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "language", + "code": 33, + "mfgCode": null, + "side": "server", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "led settings", + "code": 34, + "mfgCode": null, + "side": "server", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "auto relock time", + "code": 35, + "mfgCode": null, + "side": "server", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "sound volume", + "code": 36, + "mfgCode": null, + "side": "server", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "operating mode", + "code": 37, + "mfgCode": null, + "side": "server", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "default configuration register", + "code": 39, + "mfgCode": null, + "side": "server", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "enable local programming", + "code": 40, + "mfgCode": null, + "side": "server", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x01", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "enable one touch locking", + "code": 41, + "mfgCode": null, + "side": "server", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "enable inside status led", + "code": 42, + "mfgCode": null, + "side": "server", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "enable privacy mode button", + "code": 43, + "mfgCode": null, + "side": "server", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "wrong code entry limit", + "code": 48, + "mfgCode": null, + "side": "server", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "user code temporary disable time", + "code": 49, + "mfgCode": null, + "side": "server", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "send pin over the air", + "code": 50, + "mfgCode": null, + "side": "server", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "require pin for rf operation", + "code": 51, + "mfgCode": null, + "side": "server", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "zigbee security level", + "code": 52, + "mfgCode": null, + "side": "server", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "alarm mask", + "code": 64, + "mfgCode": null, + "side": "server", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "keypad operation event mask", + "code": 65, + "mfgCode": null, + "side": "server", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RF operation event mask", + "code": 66, + "mfgCode": null, + "side": "server", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "manual operation event mask", + "code": 67, + "mfgCode": null, + "side": "server", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "rfid operation event mask", + "code": 68, + "mfgCode": null, + "side": "server", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "keypad programming event mask", + "code": 69, + "mfgCode": null, + "side": "server", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "rf programming event mask", + "code": 70, + "mfgCode": null, + "side": "server", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "rfid programming event mask", + "code": 71, + "mfgCode": null, + "side": "server", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ], + "commands": [ + { + "name": "LockDoorResponse", + "code": 0, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "UnlockDoorResponse", + "code": 1, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 1 + } + ] + }, + { + "name": "Barrier Control", + "code": 259, + "mfgCode": null, + "define": "BARRIER_CONTROL_CLUSTER", + "side": "client", + "enabled": 1, + "commands": [ + { + "name": "BarrierControlGoToPercent", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "BarrierControlStop", + "code": 1, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "cluster revision", + "code": 65533, + "mfgCode": null, + "side": "client", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0001", + "reportable": 0, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Barrier Control", + "code": 259, + "mfgCode": null, + "define": "BARRIER_CONTROL_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [], + "attributes": [ + { + "name": "cluster revision", + "code": 65533, + "mfgCode": null, + "side": "server", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0001", + "reportable": 0, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "barrier moving state", + "code": 1, + "mfgCode": null, + "side": "server", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 0, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "barrier safety status", + "code": 2, + "mfgCode": null, + "side": "server", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 0, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "barrier capabilities", + "code": 3, + "mfgCode": null, + "side": "server", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 0, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "barrier position", + "code": 10, + "mfgCode": null, + "side": "server", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 0, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Color Control", + "code": 768, + "mfgCode": null, + "define": "COLOR_CONTROL_CLUSTER", + "side": "client", + "enabled": 1, + "commands": [ + { + "name": "MoveToHue", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "MoveHue", + "code": 1, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "StepHue", + "code": 2, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "MoveToSaturation", + "code": 3, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "MoveSaturation", + "code": 4, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "StepSaturation", + "code": 5, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "MoveToHueAndSaturation", + "code": 6, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "MoveToColor", + "code": 7, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "MoveColor", + "code": 8, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "StepColor", + "code": 9, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "MoveToColorTemperature", + "code": 10, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "StopMoveStep", + "code": 71, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "MoveColorTemperature", + "code": 75, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "StepColorTemperature", + "code": 76, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "cluster revision", + "code": 65533, + "mfgCode": null, + "side": "client", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "3", + "reportable": 0, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Color Control", + "code": 768, + "mfgCode": null, + "define": "COLOR_CONTROL_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [], + "attributes": [ + { + "name": "cluster revision", + "code": 65533, + "mfgCode": null, + "side": "server", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "3", + "reportable": 0, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "current hue", + "code": 0, + "mfgCode": null, + "side": "server", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 0, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "current saturation", + "code": 1, + "mfgCode": null, + "side": "server", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 0, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "remaining time", + "code": 2, + "mfgCode": null, + "side": "server", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 0, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "current x", + "code": 3, + "mfgCode": null, + "side": "server", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x616B", + "reportable": 0, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "current y", + "code": 4, + "mfgCode": null, + "side": "server", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x607D", + "reportable": 0, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "drift compensation", + "code": 5, + "mfgCode": null, + "side": "server", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 0, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "compensation text", + "code": 6, + "mfgCode": null, + "side": "server", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 0, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "color temperature", + "code": 7, + "mfgCode": null, + "side": "server", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00FA", + "reportable": 0, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "color mode", + "code": 8, + "mfgCode": null, + "side": "server", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x01", + "reportable": 0, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "color control options", + "code": 15, + "mfgCode": null, + "side": "server", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 0, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "number of primaries", + "code": 16, + "mfgCode": null, + "side": "server", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 0, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "primary 1 x", + "code": 17, + "mfgCode": null, + "side": "server", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 0, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "primary 1 y", + "code": 18, + "mfgCode": null, + "side": "server", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 0, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "primary 1 intensity", + "code": 19, + "mfgCode": null, + "side": "server", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 0, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "primary 2 x", + "code": 21, + "mfgCode": null, + "side": "server", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 0, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "primary 2 y", + "code": 22, + "mfgCode": null, + "side": "server", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 0, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "primary 2 intensity", + "code": 23, + "mfgCode": null, + "side": "server", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 0, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "primary 3 x", + "code": 25, + "mfgCode": null, + "side": "server", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 0, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "primary 3 y", + "code": 26, + "mfgCode": null, + "side": "server", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 0, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "primary 3 intensity", + "code": 27, + "mfgCode": null, + "side": "server", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 0, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "primary 4 x", + "code": 32, + "mfgCode": null, + "side": "server", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 0, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "primary 4 y", + "code": 33, + "mfgCode": null, + "side": "server", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 0, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "primary 4 intensity", + "code": 34, + "mfgCode": null, + "side": "server", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 0, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "primary 5 x", + "code": 36, + "mfgCode": null, + "side": "server", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 0, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "primary 5 y", + "code": 37, + "mfgCode": null, + "side": "server", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 0, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "primary 5 intensity", + "code": 38, + "mfgCode": null, + "side": "server", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 0, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "primary 6 x", + "code": 40, + "mfgCode": null, + "side": "server", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 0, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "primary 6 y", + "code": 41, + "mfgCode": null, + "side": "server", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 0, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "primary 6 intensity", + "code": 42, + "mfgCode": null, + "side": "server", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 0, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "white point x", + "code": 48, + "mfgCode": null, + "side": "server", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 0, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "white point y", + "code": 49, + "mfgCode": null, + "side": "server", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 0, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "color point r x", + "code": 50, + "mfgCode": null, + "side": "server", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 0, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "color point r y", + "code": 51, + "mfgCode": null, + "side": "server", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 0, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "color point r intensity", + "code": 52, + "mfgCode": null, + "side": "server", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 0, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "color point g x", + "code": 54, + "mfgCode": null, + "side": "server", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 0, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "color point g y", + "code": 55, + "mfgCode": null, + "side": "server", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 0, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "color point g intensity", + "code": 56, + "mfgCode": null, + "side": "server", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 0, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "color point b x", + "code": 58, + "mfgCode": null, + "side": "server", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 0, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "color point b y", + "code": 59, + "mfgCode": null, + "side": "server", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 0, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "color point b intensity", + "code": 60, + "mfgCode": null, + "side": "server", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 0, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "couple color temp to level min-mireds", + "code": 16397, + "mfgCode": null, + "side": "server", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 0, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "start up color temperature mireds", + "code": 16400, + "mfgCode": null, + "side": "server", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 0, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "enhanced current hue", + "code": 16384, + "mfgCode": null, + "side": "server", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 0, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "enhanced color mode", + "code": 16385, + "mfgCode": null, + "side": "server", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x01", + "reportable": 0, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "color loop active", + "code": 16386, + "mfgCode": null, + "side": "server", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 0, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "color loop direction", + "code": 16387, + "mfgCode": null, + "side": "server", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 0, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "color loop time", + "code": 16388, + "mfgCode": null, + "side": "server", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0019", + "reportable": 0, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "color capabilities", + "code": 16394, + "mfgCode": null, + "side": "server", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 0, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "color temp physical min", + "code": 16395, + "mfgCode": null, + "side": "server", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 0, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "color temp physical max", + "code": 16396, + "mfgCode": null, + "side": "server", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0xFEFF", + "reportable": 0, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Temperature Measurement", + "code": 1026, + "mfgCode": null, + "define": "TEMP_MEASUREMENT_CLUSTER", + "side": "client", + "enabled": 0, + "attributes": [ + { + "name": "cluster revision", + "code": 65533, + "mfgCode": null, + "side": "client", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "3", + "reportable": 0, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ], + "commands": [] + }, + { + "name": "Temperature Measurement", + "code": 1026, + "mfgCode": null, + "define": "TEMP_MEASUREMENT_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "cluster revision", + "code": 65533, + "mfgCode": null, + "side": "server", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "3", + "reportable": 0, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "measured value", + "code": 0, + "mfgCode": null, + "side": "server", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x8000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "min measured value", + "code": 1, + "mfgCode": null, + "side": "server", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x8000", + "reportable": 0, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "max measured value", + "code": 2, + "mfgCode": null, + "side": "server", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x8000", + "reportable": 0, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "tolerance", + "code": 3, + "mfgCode": null, + "side": "server", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ], + "commands": [] + }, + { + "name": "IAS Zone", + "code": 1280, + "mfgCode": null, + "define": "IAS_ZONE_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "ZoneEnrollResponse", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "cluster revision", + "code": 65533, + "mfgCode": null, + "side": "client", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "2", + "reportable": 0, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "IAS Zone", + "code": 1280, + "mfgCode": null, + "define": "IAS_ZONE_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [ + { + "name": "ZoneStatusChangeNotification", + "code": 0, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "ZoneEnrollRequest", + "code": 1, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "cluster revision", + "code": 65533, + "mfgCode": null, + "side": "server", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "2", + "reportable": 0, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "zone state", + "code": 0, + "mfgCode": null, + "side": "server", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 0, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "zone type", + "code": 1, + "mfgCode": null, + "side": "server", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 0, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "zone status", + "code": 2, + "mfgCode": null, + "side": "server", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 0, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "IAS CIE address", + "code": 16, + "mfgCode": null, + "side": "server", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 0, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Zone ID", + "code": 17, + "mfgCode": null, + "side": "server", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0xff", + "reportable": 0, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 } - ], + ] + } + ] + }, + { + "name": "Anonymous Endpoint Type", + "deviceTypeName": "CHIP-All-Clusters-Server", + "deviceTypeCode": "0x0000", + "deviceTypeProfileId": "0x0103", + "clusters": [ + { + "name": "Basic", + "code": 0, + "mfgCode": null, + "define": "BASIC_CLUSTER", + "side": "client", + "enabled": 0, "attributes": [ { "name": "cluster revision", @@ -70,6 +2849,16 @@ "maxInterval": 65344, "reportableChange": 0 } + ], + "commands": [ + { + "name": "ResetToFactoryDefaults", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + } ] }, { @@ -134,7 +2923,24 @@ "mfgCode": null, "define": "IDENTIFY_CLUSTER", "side": "client", - "enabled": 1, + "enabled": 0, + "attributes": [ + { + "name": "cluster revision", + "code": 65533, + "mfgCode": null, + "side": "client", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "2", + "reportable": 0, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ], "commands": [ { "name": "Identify", @@ -152,23 +2958,6 @@ "incoming": 1, "outgoing": 1 } - ], - "attributes": [ - { - "name": "cluster revision", - "code": 65533, - "mfgCode": null, - "side": "client", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "2", - "reportable": 0, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 - } ] }, { @@ -177,7 +2966,7 @@ "mfgCode": null, "define": "IDENTIFY_CLUSTER", "side": "server", - "enabled": 1, + "enabled": 0, "commands": [ { "name": "IdentifyQueryResponse", @@ -227,7 +3016,7 @@ "mfgCode": null, "define": "GROUPS_CLUSTER", "side": "client", - "enabled": 1, + "enabled": 0, "commands": [ { "name": "AddGroup", @@ -302,7 +3091,7 @@ "mfgCode": null, "define": "GROUPS_CLUSTER", "side": "server", - "enabled": 1, + "enabled": 0, "commands": [ { "name": "AddGroupResponse", @@ -376,7 +3165,7 @@ "mfgCode": null, "define": "SCENES_CLUSTER", "side": "client", - "enabled": 1, + "enabled": 0, "commands": [ { "name": "AddScene", @@ -459,57 +3248,7 @@ "mfgCode": null, "define": "SCENES_CLUSTER", "side": "server", - "enabled": 1, - "commands": [ - { - "name": "AddSceneResponse", - "code": 0, - "mfgCode": null, - "source": "server", - "incoming": 1, - "outgoing": 1 - }, - { - "name": "ViewSceneResponse", - "code": 1, - "mfgCode": null, - "source": "server", - "incoming": 1, - "outgoing": 1 - }, - { - "name": "RemoveSceneResponse", - "code": 2, - "mfgCode": null, - "source": "server", - "incoming": 1, - "outgoing": 1 - }, - { - "name": "RemoveAllScenesResponse", - "code": 3, - "mfgCode": null, - "source": "server", - "incoming": 1, - "outgoing": 1 - }, - { - "name": "StoreSceneResponse", - "code": 4, - "mfgCode": null, - "source": "server", - "incoming": 1, - "outgoing": 1 - }, - { - "name": "GetSceneMembershipResponse", - "code": 6, - "mfgCode": null, - "source": "server", - "incoming": 1, - "outgoing": 1 - } - ], + "enabled": 0, "attributes": [ { "name": "cluster revision", @@ -601,6 +3340,56 @@ "maxInterval": 65344, "reportableChange": 0 } + ], + "commands": [ + { + "name": "AddSceneResponse", + "code": 0, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "ViewSceneResponse", + "code": 1, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "RemoveSceneResponse", + "code": 2, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "RemoveAllScenesResponse", + "code": 3, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "StoreSceneResponse", + "code": 4, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "GetSceneMembershipResponse", + "code": 6, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 1 + } ] }, { @@ -609,7 +3398,7 @@ "mfgCode": null, "define": "ON_OFF_CLUSTER", "side": "client", - "enabled": 1, + "enabled": 0, "commands": [ { "name": "Off", @@ -701,7 +3490,7 @@ "mfgCode": null, "define": "LEVEL_CONTROL_CLUSTER", "side": "client", - "enabled": 1, + "enabled": 0, "commands": [ { "name": "MoveToLevel", @@ -792,7 +3581,7 @@ "mfgCode": null, "define": "LEVEL_CONTROL_CLUSTER", "side": "server", - "enabled": 1, + "enabled": 0, "commands": [], "attributes": [ { @@ -833,7 +3622,7 @@ "mfgCode": null, "define": "DOOR_LOCK_CLUSTER", "side": "client", - "enabled": 1, + "enabled": 0, "commands": [ { "name": "LockDoor", @@ -1044,25 +3833,7 @@ "mfgCode": null, "define": "DOOR_LOCK_CLUSTER", "side": "server", - "enabled": 1, - "commands": [ - { - "name": "LockDoorResponse", - "code": 0, - "mfgCode": null, - "source": "server", - "incoming": 1, - "outgoing": 1 - }, - { - "name": "UnlockDoorResponse", - "code": 1, - "mfgCode": null, - "source": "server", - "incoming": 1, - "outgoing": 1 - } - ], + "enabled": 0, "attributes": [ { "name": "cluster revision", @@ -1499,6 +4270,24 @@ "maxInterval": 65344, "reportableChange": 0 } + ], + "commands": [ + { + "name": "LockDoorResponse", + "code": 0, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "UnlockDoorResponse", + "code": 1, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 1 + } ] }, { @@ -1507,7 +4296,7 @@ "mfgCode": null, "define": "BARRIER_CONTROL_CLUSTER", "side": "client", - "enabled": 1, + "enabled": 0, "commands": [ { "name": "BarrierControlGoToPercent", @@ -1550,8 +4339,7 @@ "mfgCode": null, "define": "BARRIER_CONTROL_CLUSTER", "side": "server", - "enabled": 1, - "commands": [], + "enabled": 0, "attributes": [ { "name": "cluster revision", @@ -1628,7 +4416,8 @@ "maxInterval": 65344, "reportableChange": 0 } - ] + ], + "commands": [] }, { "name": "Color Control", @@ -1636,7 +4425,7 @@ "mfgCode": null, "define": "COLOR_CONTROL_CLUSTER", "side": "client", - "enabled": 1, + "enabled": 0, "commands": [ { "name": "MoveToHue", @@ -1775,7 +4564,8 @@ "mfgCode": null, "define": "COLOR_CONTROL_CLUSTER", "side": "server", - "enabled": 1, + "enabled": 0, + "commands": [], "attributes": [ { "name": "cluster revision", @@ -2542,8 +5332,7 @@ "maxInterval": 65344, "reportableChange": 0 } - ], - "commands": [] + ] }, { "name": "Temperature Measurement", @@ -2577,8 +5366,7 @@ "mfgCode": null, "define": "TEMP_MEASUREMENT_CLUSTER", "side": "server", - "enabled": 1, - "commands": [], + "enabled": 0, "attributes": [ { "name": "cluster revision", @@ -2655,7 +5443,8 @@ "maxInterval": 65344, "reportableChange": 0 } - ] + ], + "commands": [] }, { "name": "IAS Zone", @@ -2698,7 +5487,7 @@ "mfgCode": null, "define": "IAS_ZONE_CLUSTER", "side": "server", - "enabled": 1, + "enabled": 0, "commands": [ { "name": "ZoneStatusChangeNotification", @@ -2820,6 +5609,13 @@ "profileId": "0x0103", "endpointId": 1, "networkId": 1 + }, + { + "endpointTypeName": "Anonymous Endpoint Type", + "endpointTypeIndex": 1, + "profileId": "0x0103", + "endpointId": 1, + "networkId": 1 } ] -} +} \ No newline at end of file diff --git a/examples/all-clusters-app/all-clusters-common/gen/af-structs.h b/examples/all-clusters-app/all-clusters-common/gen/af-structs.h index 6d04f3faa8e82d..02960bec60ddfb 100644 --- a/examples/all-clusters-app/all-clusters-common/gen/af-structs.h +++ b/examples/all-clusters-app/all-clusters-common/gen/af-structs.h @@ -1,4 +1,3 @@ - /* * * Copyright (c) 2020 Project CHIP Authors diff --git a/examples/all-clusters-app/all-clusters-common/gen/att-storage.h b/examples/all-clusters-app/all-clusters-common/gen/att-storage.h index 7572c8cbc338fb..74b44d6111b3e4 100644 --- a/examples/all-clusters-app/all-clusters-common/gen/att-storage.h +++ b/examples/all-clusters-app/all-clusters-common/gen/att-storage.h @@ -1,4 +1,3 @@ - /* * * Copyright (c) 2020 Project CHIP Authors diff --git a/examples/all-clusters-app/all-clusters-common/gen/attribute-id.h b/examples/all-clusters-app/all-clusters-common/gen/attribute-id.h index 648809ca67cd83..901653b7d8f3b6 100644 --- a/examples/all-clusters-app/all-clusters-common/gen/attribute-id.h +++ b/examples/all-clusters-app/all-clusters-common/gen/attribute-id.h @@ -1,4 +1,3 @@ - /* * * Copyright (c) 2020 Project CHIP Authors @@ -19,11 +18,15 @@ // Prevent multiple inclusion #pragma once +// Global cluster attribute ids +#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) +#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) +#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) +#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) + // Attribute ids for cluster: Basic // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_VERSION_ATTRIBUTE_ID (0x0000) @@ -44,14 +47,10 @@ #define ZCL_ALARM_MASK_ATTRIBUTE_ID (0x0013) #define ZCL_DISABLE_LOCAL_CONFIG_ATTRIBUTE_ID (0x0014) #define ZCL_SW_BUILD_ID_ATTRIBUTE_ID (0x4000) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Power Configuration // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_MAINS_VOLTAGE_ATTRIBUTE_ID (0x0000) @@ -111,14 +110,10 @@ #define ZCL_BATTERY_3_PERCENTAGE_THRESHOLD_2_ATTRIBUTE_ID (0x007C) #define ZCL_BATTERY_3_PERCENTAGE_THRESHOLD_3_ATTRIBUTE_ID (0x007D) #define ZCL_BATTERY_3_ALARM_STATE_ATTRIBUTE_ID (0x007E) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Device Temperature Configuration // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_CURRENT_TEMPERATURE_ATTRIBUTE_ID (0x0000) @@ -130,37 +125,25 @@ #define ZCL_HIGH_TEMP_THRESHOLD_ATTRIBUTE_ID (0x0012) #define ZCL_LOW_TEMP_DWELL_TRIP_POINT_ATTRIBUTE_ID (0x0013) #define ZCL_HIGH_TEMP_DWELL_TRIP_POINT_ATTRIBUTE_ID (0x0014) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Identify // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_IDENTIFY_TIME_ATTRIBUTE_ID (0x0000) #define ZCL_COMMISSION_STATE_ATTRIBUTE_ID (0x0001) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Groups // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_GROUP_NAME_SUPPORT_ATTRIBUTE_ID (0x0000) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Scenes // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_SCENE_COUNT_ATTRIBUTE_ID (0x0000) @@ -169,14 +152,10 @@ #define ZCL_SCENE_VALID_ATTRIBUTE_ID (0x0003) #define ZCL_SCENE_NAME_SUPPORT_ATTRIBUTE_ID (0x0004) #define ZCL_LAST_CONFIGURED_BY_ATTRIBUTE_ID (0x0005) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: On/off // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_ON_OFF_ATTRIBUTE_ID (0x0000) @@ -188,26 +167,18 @@ #define ZCL_ON_TIME_ATTRIBUTE_ID (0x4001) #define ZCL_OFF_WAIT_TIME_ATTRIBUTE_ID (0x4002) #define ZCL_START_UP_ON_OFF_ATTRIBUTE_ID (0x4003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: On/off Switch Configuration // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_SWITCH_TYPE_ATTRIBUTE_ID (0x0000) #define ZCL_SWITCH_ACTIONS_ATTRIBUTE_ID (0x0010) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Level Control // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_CURRENT_LEVEL_ATTRIBUTE_ID (0x0000) @@ -219,25 +190,17 @@ #define ZCL_OFF_TRANSITION_TIME_ATTRIBUTE_ID (0x0013) #define ZCL_DEFAULT_MOVE_RATE_ATTRIBUTE_ID (0x0014) #define ZCL_START_UP_CURRENT_LEVEL_ATTRIBUTE_ID (0x4000) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Alarms // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_ALARM_COUNT_ATTRIBUTE_ID (0x0000) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Time // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_TIME_ATTRIBUTE_ID (0x0000) @@ -250,14 +213,10 @@ #define ZCL_LOCAL_TIME_ATTRIBUTE_ID (0x0007) #define ZCL_LAST_SET_TIME_ATTRIBUTE_ID (0x0008) #define ZCL_VALID_UNTIL_TIME_ATTRIBUTE_ID (0x0009) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: RSSI Location // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_LOCATION_TYPE_ATTRIBUTE_ID (0x0000) @@ -273,14 +232,10 @@ #define ZCL_REPORTING_PERIOD_ATTRIBUTE_ID (0x0015) #define ZCL_CALCULATION_PERIOD_ATTRIBUTE_ID (0x0016) #define ZCL_NUMBER_RSSI_MEASUREMENTS_ATTRIBUTE_ID (0x0017) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Binary Input (Basic) // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_ACTIVE_TEXT_ATTRIBUTE_ID (0x0004) @@ -292,14 +247,10 @@ #define ZCL_RELIABILITY_ATTRIBUTE_ID (0x0067) #define ZCL_STATUS_FLAGS_ATTRIBUTE_ID (0x006F) #define ZCL_APPLICATION_TYPE_ATTRIBUTE_ID (0x0100) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Commissioning // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_SHORT_ADDRESS_ATTRIBUTE_ID (0x0000) @@ -326,14 +277,10 @@ #define ZCL_CONCENTRATOR_FLAG_ATTRIBUTE_ID (0x0040) #define ZCL_CONCENTRATOR_RADIUS_ATTRIBUTE_ID (0x0041) #define ZCL_CONCENTRATOR_DISCOVERY_TIME_ATTRIBUTE_ID (0x0042) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Partition // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_PARTITION_MAXIMUM_INCOMING_TRANSFER_SIZE_ATTRIBUTE_ID (0x0000) @@ -346,8 +293,6 @@ #define ZCL_NUMBER_OF_SEND_RETRIES_ATTRIBUTE_ID (0x0007) #define ZCL_SENDER_TIMEOUT_ATTRIBUTE_ID (0x0008) #define ZCL_RECEIVER_TIMEOUT_ATTRIBUTE_ID (0x0009) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Over the Air Bootloading @@ -365,18 +310,12 @@ #define ZCL_IMAGE_STAMP_ATTRIBUTE_ID (0x000A) #define ZCL_UPGRADE_ACTIVATION_POLICY_ATTRIBUTE_ID (0x000B) #define ZCL_UPGRADE_TIMEOUT_POLICY_ATTRIBUTE_ID (0x000C) -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Power Profile // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_TOTAL_PROFILE_NUM_ATTRIBUTE_ID (0x0000) @@ -384,27 +323,19 @@ #define ZCL_ENERGY_FORMATTING_ATTRIBUTE_ID (0x0002) #define ZCL_ENERGY_REMOTE_ATTRIBUTE_ID (0x0003) #define ZCL_SCHEDULE_MODE_ATTRIBUTE_ID (0x0004) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Appliance Control // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_START_TIME_ATTRIBUTE_ID (0x0000) #define ZCL_FINISH_TIME_ATTRIBUTE_ID (0x0001) #define ZCL_REMAINING_TIME_ATTRIBUTE_ID (0x0002) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Poll Control // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_CHECK_IN_INTERVAL_ATTRIBUTE_ID (0x0000) @@ -414,8 +345,6 @@ #define ZCL_CHECK_IN_INTERVAL_MIN_ATTRIBUTE_ID (0x0004) #define ZCL_LONG_POLL_INTERVAL_MIN_ATTRIBUTE_ID (0x0005) #define ZCL_FAST_POLL_TIMEOUT_MAX_ATTRIBUTE_ID (0x0006) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Green Power @@ -431,8 +360,6 @@ #define ZCL_GP_CLIENT_GP_SHARED_SECURITY_KEY_TYPE_ATTRIBUTE_ID (0x0020) #define ZCL_GP_CLIENT_GP_SHARED_SECURITY_KEY_ATTRIBUTE_ID (0x0021) #define ZCL_GP_CLIENT_GP_LINK_KEY_ATTRIBUTE_ID (0x0022) -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_GP_SERVER_GPS_MAX_SINK_TABLE_ENTRIES_ATTRIBUTE_ID (0x0000) @@ -446,26 +373,18 @@ #define ZCL_GP_SERVER_GP_SHARED_SECURITY_KEY_TYPE_ATTRIBUTE_ID (0x0020) #define ZCL_GP_SERVER_GP_SHARED_SECURITY_KEY_ATTRIBUTE_ID (0x0021) #define ZCL_GP_SERVER_GP_LINK_KEY_ATTRIBUTE_ID (0x0022) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Keep-Alive // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_KEEPALIVE_BASE_ATTRIBUTE_ID (0x0000) #define ZCL_KEEPALIVE_JITTER_ATTRIBUTE_ID (0x0001) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Shade Configuration // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_SHADE_CONFIG_PHYSICAL_CLOSED_LIMIT_ATTRIBUTE_ID (0x0000) @@ -473,14 +392,10 @@ #define ZCL_SHADE_CONFIG_STATUS_ATTRIBUTE_ID (0x0002) #define ZCL_SHADE_CONFIG_CLOSED_LIMIT_ATTRIBUTE_ID (0x0010) #define ZCL_SHADE_CONFIG_MODE_ATTRIBUTE_ID (0x0011) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Door Lock // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_LOCK_STATE_ATTRIBUTE_ID (0x0000) @@ -526,14 +441,10 @@ #define ZCL_KEYPAD_PROGRAMMING_EVENT_MASK_ATTRIBUTE_ID (0x0045) #define ZCL_RF_PROGRAMMING_EVENT_MASK_ATTRIBUTE_ID (0x0046) #define ZCL_RFID_PROGRAMMING_EVENT_MASK_ATTRIBUTE_ID (0x0047) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Window Covering // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_COVERING_TYPE_ATTRIBUTE_ID (0x0000) @@ -556,14 +467,10 @@ #define ZCL_MODE_ATTRIBUTE_ID (0x0017) #define ZCL_SETPOINTS_LIFT_ATTRIBUTE_ID (0x0018) #define ZCL_SETPOINTS_TILT_ATTRIBUTE_ID (0x0019) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Barrier Control // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_BARRIER_MOVING_STATE_ATTRIBUTE_ID (0x0001) @@ -576,14 +483,10 @@ #define ZCL_BARRIER_OPEN_PERIOD_ATTRIBUTE_ID (0x0008) #define ZCL_BARRIER_CLOSE_PERIOD_ATTRIBUTE_ID (0x0009) #define ZCL_BARRIER_POSITION_ATTRIBUTE_ID (0x000A) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Pump Configuration and Control // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_MAX_PRESSURE_ATTRIBUTE_ID (0x0000) @@ -610,14 +513,10 @@ #define ZCL_OPERATION_MODE_ATTRIBUTE_ID (0x0020) #define ZCL_CONTROL_MODE_ATTRIBUTE_ID (0x0021) #define ZCL_PUMP_ALARM_MASK_ATTRIBUTE_ID (0x0022) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Thermostat // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_LOCAL_TEMPERATURE_ATTRIBUTE_ID (0x0000) @@ -663,26 +562,18 @@ #define ZCL_AC_LOUVER_POSITION_ATTRIBUTE_ID (0x0045) #define ZCL_AC_COIL_TEMPERATURE_ATTRIBUTE_ID (0x0046) #define ZCL_AC_CAPACITY_FORMAT_ATTRIBUTE_ID (0x0047) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Fan Control // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_FAN_CONTROL_FAN_MODE_ATTRIBUTE_ID (0x0000) #define ZCL_FAN_CONTROL_FAN_MODE_SEQUENCE_ATTRIBUTE_ID (0x0001) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Dehumidification Control // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_RELATIVE_HUMIDITY_ATTRIBUTE_ID (0x0000) @@ -693,27 +584,19 @@ #define ZCL_DEHUMIDIFICATION_HYSTERESIS_ATTRIBUTE_ID (0x0013) #define ZCL_DEHUMIDIFICATION_MAX_COOL_ATTRIBUTE_ID (0x0014) #define ZCL_RELATIVE_HUMIDITY_DISPLAY_ATTRIBUTE_ID (0x0015) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Thermostat User Interface Configuration // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_TEMPERATURE_DISPLAY_MODE_ATTRIBUTE_ID (0x0000) #define ZCL_KEYPAD_LOCKOUT_ATTRIBUTE_ID (0x0001) #define ZCL_SCHEDULE_PROGRAMMING_VISIBILITY_ATTRIBUTE_ID (0x0002) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Color Control // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_COLOR_CONTROL_CURRENT_HUE_ATTRIBUTE_ID (0x0000) @@ -768,14 +651,10 @@ #define ZCL_COLOR_CONTROL_COLOR_TEMP_PHYSICAL_MAX_ATTRIBUTE_ID (0x400C) #define ZCL_COLOR_CONTROL_TEMPERATURE_LEVEL_MIN_MIREDS_ATTRIBUTE_ID (0x400D) #define ZCL_START_UP_COLOR_TEMPERATURE_MIREDS_ATTRIBUTE_ID (0x4010) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Ballast Configuration // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_PHYSICAL_MIN_LEVEL_ATTRIBUTE_ID (0x0000) @@ -794,14 +673,10 @@ #define ZCL_LAMP_BURN_HOURS_ATTRIBUTE_ID (0x0033) #define ZCL_LAMP_ALARM_MODE_ATTRIBUTE_ID (0x0034) #define ZCL_LAMP_BURN_HOURS_TRIP_POINT_ATTRIBUTE_ID (0x0035) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Illuminance Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_ILLUM_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) @@ -809,41 +684,29 @@ #define ZCL_ILLUM_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_ILLUM_TOLERANCE_ATTRIBUTE_ID (0x0003) #define ZCL_MEASUREMENT_LIGHT_SENSOR_TYPE_ATTRIBUTE_ID (0x0004) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Illuminance Level Sensing // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_LEVEL_STATUS_ATTRIBUTE_ID (0x0000) #define ZCL_SENSING_LIGHT_SENSOR_TYPE_ATTRIBUTE_ID (0x0001) #define ZCL_ILLUMINANCE_TARGET_LEVEL_ATTRIBUTE_ID (0x0010) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Temperature Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_TEMP_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_TEMP_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_TEMP_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_TEMP_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Pressure Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_PRESSURE_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) @@ -855,42 +718,30 @@ #define ZCL_PRESSURE_MAX_SCALED_VALUE_ATTRIBUTE_ID (0x0012) #define ZCL_PRESSURE_SCALED_TOLERANCE_ATTRIBUTE_ID (0x0013) #define ZCL_PRESSURE_SCALE_ATTRIBUTE_ID (0x0014) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Flow Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_FLOW_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_FLOW_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_FLOW_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_FLOW_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Relative Humidity Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_RELATIVE_HUMIDITY_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_RELATIVE_HUMIDITY_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_RELATIVE_HUMIDITY_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_RELATIVE_HUMIDITY_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Occupancy Sensing // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_OCCUPANCY_ATTRIBUTE_ID (0x0000) @@ -905,434 +756,310 @@ #define ZCL_PHYSICAL_CONTACT_OCCUPIED_TO_UNOCCUPIED_DELAY_ATTRIBUTE_ID (0x0030) #define ZCL_PHYSICAL_CONTACT_UNOCCUPIED_TO_OCCUPIED_DELAY_ATTRIBUTE_ID (0x0031) #define ZCL_PHYSICAL_CONTACT_UNOCCUPIED_TO_OCCUPIED_THRESHOLD_ATTRIBUTE_ID (0x0032) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Carbon Monoxide Concentration Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_CARBON_MONOXIDE_CONCENTRATION_MEASUREMENT_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_CARBON_MONOXIDE_CONCENTRATION_MEASUREMENT_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_CARBON_MONOXIDE_CONCENTRATION_MEASUREMENT_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_CARBON_MONOXIDE_CONCENTRATION_MEASUREMENT_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Carbon Dioxide Concentration Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_CARBON_DIOXIDE_CONCENTRATION_MEASUREMENT_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_CARBON_DIOXIDE_CONCENTRATION_MEASUREMENT_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_CARBON_DIOXIDE_CONCENTRATION_MEASUREMENT_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_CARBON_DIOXIDE_CONCENTRATION_MEASUREMENT_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Ethylene Concentration Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_ETHYLENE_CONCENTRATION_MEASUREMENT_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_ETHYLENE_CONCENTRATION_MEASUREMENT_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_ETHYLENE_CONCENTRATION_MEASUREMENT_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_ETHYLENE_CONCENTRATION_MEASUREMENT_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Ethylene Oxide Concentration Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_ETHYLENE_OXIDE_CONCENTRATION_MEASUREMENT_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_ETHYLENE_OXIDE_CONCENTRATION_MEASUREMENT_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_ETHYLENE_OXIDE_CONCENTRATION_MEASUREMENT_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_ETHYLENE_OXIDE_CONCENTRATION_MEASUREMENT_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Hydrogen Concentration Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_HYDROGEN_CONCENTRATION_MEASUREMENT_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_HYDROGEN_CONCENTRATION_MEASUREMENT_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_HYDROGEN_CONCENTRATION_MEASUREMENT_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_HYDROGEN_CONCENTRATION_MEASUREMENT_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Hydrogen Sulphide Concentration Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_HYDROGEN_SULPHIDE_CONCENTRATION_MEASUREMENT_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_HYDROGEN_SULPHIDE_CONCENTRATION_MEASUREMENT_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_HYDROGEN_SULPHIDE_CONCENTRATION_MEASUREMENT_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_HYDROGEN_SULPHIDE_CONCENTRATION_MEASUREMENT_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Nitric Oxide Concentration Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_NITRIC_OXIDE_CONCENTRATION_MEASUREMENT_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_NITRIC_OXIDE_CONCENTRATION_MEASUREMENT_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_NITRIC_OXIDE_CONCENTRATION_MEASUREMENT_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_NITRIC_OXIDE_CONCENTRATION_MEASUREMENT_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Nitrogen Dioxide Concentration Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_NITROGEN_DIOXIDE_CONCENTRATION_MEASUREMENT_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_NITROGEN_DIOXIDE_CONCENTRATION_MEASUREMENT_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_NITROGEN_DIOXIDE_CONCENTRATION_MEASUREMENT_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_NITROGEN_DIOXIDE_CONCENTRATION_MEASUREMENT_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Oxygen Concentration Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_OXYGEN_CONCENTRATION_MEASUREMENT_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_OXYGEN_CONCENTRATION_MEASUREMENT_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_OXYGEN_CONCENTRATION_MEASUREMENT_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_OXYGEN_CONCENTRATION_MEASUREMENT_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Ozone Concentration Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_OZONE_CONCENTRATION_MEASUREMENT_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_OZONE_CONCENTRATION_MEASUREMENT_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_OZONE_CONCENTRATION_MEASUREMENT_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_OZONE_CONCENTRATION_MEASUREMENT_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Sulfur Dioxide Concentration Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_SULFUR_DIOXIDE_CONCENTRATION_MEASUREMENT_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_SULFUR_DIOXIDE_CONCENTRATION_MEASUREMENT_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_SULFUR_DIOXIDE_CONCENTRATION_MEASUREMENT_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_SULFUR_DIOXIDE_CONCENTRATION_MEASUREMENT_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Dissolved Oxygen Concentration Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_DISSOLVED_OXYGEN_CONCENTRATION_MEASUREMENT_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_DISSOLVED_OXYGEN_CONCENTRATION_MEASUREMENT_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_DISSOLVED_OXYGEN_CONCENTRATION_MEASUREMENT_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_DISSOLVED_OXYGEN_CONCENTRATION_MEASUREMENT_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Bromate Concentration Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_BROMATE_CONCENTRATION_MEASUREMENT_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_BROMATE_CONCENTRATION_MEASUREMENT_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_BROMATE_CONCENTRATION_MEASUREMENT_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_BROMATE_CONCENTRATION_MEASUREMENT_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Chloramines Concentration Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_CHLORAMINES_CONCENTRATION_MEASUREMENT_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_CHLORAMINES_CONCENTRATION_MEASUREMENT_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_CHLORAMINES_CONCENTRATION_MEASUREMENT_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_CHLORAMINES_CONCENTRATION_MEASUREMENT_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Chlorine Concentration Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_CHLORINE_CONCENTRATION_MEASUREMENT_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_CHLORINE_CONCENTRATION_MEASUREMENT_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_CHLORINE_CONCENTRATION_MEASUREMENT_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_CHLORINE_CONCENTRATION_MEASUREMENT_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Fecal coliform and E. Coli Concentration Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_FECAL_COLIFORM_AND_E_COLI_CONCENTRATION_MEASUREMENT_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_FECAL_COLIFORM_AND_E_COLI_CONCENTRATION_MEASUREMENT_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_FECAL_COLIFORM_AND_E_COLI_CONCENTRATION_MEASUREMENT_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_FECAL_COLIFORM_AND_E_COLI_CONCENTRATION_MEASUREMENT_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Fluoride Concentration Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_FLUORIDE_CONCENTRATION_MEASUREMENT_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_FLUORIDE_CONCENTRATION_MEASUREMENT_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_FLUORIDE_CONCENTRATION_MEASUREMENT_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_FLUORIDE_CONCENTRATION_MEASUREMENT_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Haloacetic Acids Concentration Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_HALOACETIC_ACIDS_CONCENTRATION_MEASUREMENT_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_HALOACETIC_ACIDS_CONCENTRATION_MEASUREMENT_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_HALOACETIC_ACIDS_CONCENTRATION_MEASUREMENT_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_HALOACETIC_ACIDS_CONCENTRATION_MEASUREMENT_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Total Trihalomethanes Concentration Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_TOTAL_TRIHALOMETHANES_CONCENTRATION_MEASUREMENT_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_TOTAL_TRIHALOMETHANES_CONCENTRATION_MEASUREMENT_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_TOTAL_TRIHALOMETHANES_CONCENTRATION_MEASUREMENT_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_TOTAL_TRIHALOMETHANES_CONCENTRATION_MEASUREMENT_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Total Coliform Bacteria Concentration Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_TOTAL_COLIFORM_BACTERIA_CONCENTRATION_MEASUREMENT_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_TOTAL_COLIFORM_BACTERIA_CONCENTRATION_MEASUREMENT_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_TOTAL_COLIFORM_BACTERIA_CONCENTRATION_MEASUREMENT_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_TOTAL_COLIFORM_BACTERIA_CONCENTRATION_MEASUREMENT_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Turbidity Concentration Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_TURBIDITY_CONCENTRATION_MEASUREMENT_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_TURBIDITY_CONCENTRATION_MEASUREMENT_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_TURBIDITY_CONCENTRATION_MEASUREMENT_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_TURBIDITY_CONCENTRATION_MEASUREMENT_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Copper Concentration Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_COPPER_CONCENTRATION_MEASUREMENT_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_COPPER_CONCENTRATION_MEASUREMENT_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_COPPER_CONCENTRATION_MEASUREMENT_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_COPPER_CONCENTRATION_MEASUREMENT_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Lead Concentration Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_LEAD_CONCENTRATION_MEASUREMENT_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_LEAD_CONCENTRATION_MEASUREMENT_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_LEAD_CONCENTRATION_MEASUREMENT_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_LEAD_CONCENTRATION_MEASUREMENT_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Manganese Concentration Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_MANGANESE_CONCENTRATION_MEASUREMENT_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_MANGANESE_CONCENTRATION_MEASUREMENT_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_MANGANESE_CONCENTRATION_MEASUREMENT_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_MANGANESE_CONCENTRATION_MEASUREMENT_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Sulfate Concentration Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_SULFATE_CONCENTRATION_MEASUREMENT_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_SULFATE_CONCENTRATION_MEASUREMENT_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_SULFATE_CONCENTRATION_MEASUREMENT_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_SULFATE_CONCENTRATION_MEASUREMENT_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Bromodichloromethane Concentration Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_BROMODICHLOROMETHANE_CONCENTRATION_MEASUREMENT_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_BROMODICHLOROMETHANE_CONCENTRATION_MEASUREMENT_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_BROMODICHLOROMETHANE_CONCENTRATION_MEASUREMENT_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_BROMODICHLOROMETHANE_CONCENTRATION_MEASUREMENT_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Bromoform Concentration Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_BROMOFORM_CONCENTRATION_MEASUREMENT_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_BROMOFORM_CONCENTRATION_MEASUREMENT_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_BROMOFORM_CONCENTRATION_MEASUREMENT_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_BROMOFORM_CONCENTRATION_MEASUREMENT_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Chlorodibromomethane Concentration Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_CHLORODIBROMOMETHANE_CONCENTRATION_MEASUREMENT_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_CHLORODIBROMOMETHANE_CONCENTRATION_MEASUREMENT_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_CHLORODIBROMOMETHANE_CONCENTRATION_MEASUREMENT_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_CHLORODIBROMOMETHANE_CONCENTRATION_MEASUREMENT_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Chloroform Concentration Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_CHLOROFORM_CONCENTRATION_MEASUREMENT_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_CHLOROFORM_CONCENTRATION_MEASUREMENT_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_CHLOROFORM_CONCENTRATION_MEASUREMENT_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_CHLOROFORM_CONCENTRATION_MEASUREMENT_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Sodium Concentration Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_SODIUM_CONCENTRATION_MEASUREMENT_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_SODIUM_CONCENTRATION_MEASUREMENT_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_SODIUM_CONCENTRATION_MEASUREMENT_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_SODIUM_CONCENTRATION_MEASUREMENT_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: IAS Zone // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_ZONE_STATE_ATTRIBUTE_ID (0x0000) @@ -1342,58 +1069,38 @@ #define ZCL_ZONE_ID_ATTRIBUTE_ID (0x0011) #define ZCL_NUMBER_OF_ZONE_SENSITIVITY_LEVELS_SUPPORTED_ATTRIBUTE_ID (0x0012) #define ZCL_CURRENT_ZONE_SENSITIVITY_LEVEL_ATTRIBUTE_ID (0x0013) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: IAS ACE // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: IAS WD // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_MAX_DURATION_ATTRIBUTE_ID (0x0000) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Generic Tunnel // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_MAXIMUM_INCOMING_TRANSFER_SIZE_ATTRIBUTE_ID (0x0001) #define ZCL_MAXIMUM_OUTGOING_TRANSFER_SIZE_ATTRIBUTE_ID (0x0002) #define ZCL_PROTOCOL_ADDRESS_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: BACnet Protocol Tunnel // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: 11073 Protocol Tunnel // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_DEVICE_ID_LIST_ATTRIBUTE_ID (0x0000) @@ -1402,19 +1109,13 @@ #define ZCL_CONNECTED_ATTRIBUTE_ID (0x0003) #define ZCL_PREEMPTIBLE_ATTRIBUTE_ID (0x0004) #define ZCL_IDLE_TIMEOUT_ATTRIBUTE_ID (0x0005) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: ISO 7816 Protocol Tunnel // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_ISO7816_PROTOCOL_TUNNEL_STATUS_ATTRIBUTE_ID (0x0000) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Price @@ -1422,8 +1123,6 @@ #define ZCL_PRICE_INCREASE_RANDOMIZE_MINUTES_ATTRIBUTE_ID (0x0000) #define ZCL_PRICE_DECREASE_RANDOMIZE_MINUTES_ATTRIBUTE_ID (0x0001) #define ZCL_COMMODITY_TYPE_CLIENT_ATTRIBUTE_ID (0x0002) -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_TIER1_PRICE_LABEL_ATTRIBUTE_ID (0x0000) @@ -2438,8 +2137,6 @@ #define ZCL_RX_LAST_BILLING_PERIOD_START_ATTRIBUTE_ID (0x8702) #define ZCL_RX_LAST_BILLING_PERIOD_DURATION_ATTRIBUTE_ID (0x8703) #define ZCL_RX_LAST_BILLING_PERIOD_CONSOLIDATED_BILL_ATTRIBUTE_ID (0x8704) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Demand Response and Load Control @@ -2448,12 +2145,8 @@ #define ZCL_START_RANDOMIZATION_MINUTES_ATTRIBUTE_ID (0x0001) #define ZCL_DURATION_RANDOMIZATION_MINUTES_ATTRIBUTE_ID (0x0002) #define ZCL_DEVICE_CLASS_VALUE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Simple Metering @@ -2466,8 +2159,6 @@ #define ZCL_NOTIFICATION_FLAGS_6_ATTRIBUTE_ID (0x0005) #define ZCL_NOTIFICATION_FLAGS_7_ATTRIBUTE_ID (0x0006) #define ZCL_NOTIFICATION_FLAGS_8_ATTRIBUTE_ID (0x0007) -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_CURRENT_SUMMATION_DELIVERED_ATTRIBUTE_ID (0x0000) @@ -3354,35 +3045,23 @@ #define ZCL_CURRENT_REACTIVE_SUMMATION_Q2_ATTRIBUTE_ID (0x0D06) #define ZCL_CURRENT_REACTIVE_SUMMATION_Q3_ATTRIBUTE_ID (0x0D07) #define ZCL_CURRENT_REACTIVE_SUMMATION_Q4_ATTRIBUTE_ID (0x0D08) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Messaging // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Tunneling // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_CLOSE_TUNNEL_TIMEOUT_ATTRIBUTE_ID (0x0000) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Prepayment // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_PAYMENT_CONTROL_CONFIGURATION_ATTRIBUTE_ID (0x0000) @@ -3516,14 +3195,10 @@ #define ZCL_PREVIOUS_MONTH_13_COST_CONSUMPTION_DELIVERED_ATTRIBUTE_ID (0x055A) #define ZCL_PREVIOUS_MONTH_13_COST_CONSUMPTION_RECEIVED_ATTRIBUTE_ID (0x055B) #define ZCL_PREPAYMENT_HISTORICAL_FREEZE_TIME_ATTRIBUTE_ID (0x055C) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Energy Management // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_LOAD_CONTROL_STATE_ATTRIBUTE_ID (0x0000) @@ -3533,14 +3208,10 @@ #define ZCL_MINIMUM_OFF_TIME_ATTRIBUTE_ID (0x0004) #define ZCL_MINIMUM_ON_TIME_ATTRIBUTE_ID (0x0005) #define ZCL_MINIMUM_CYCLE_PERIOD_ATTRIBUTE_ID (0x0006) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Calendar // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_AUXILIARY_SWITCH_1_LABEL_ATTRIBUTE_ID (0x0000) @@ -3551,8 +3222,6 @@ #define ZCL_AUXILIARY_SWITCH_6_LABEL_ATTRIBUTE_ID (0x0005) #define ZCL_AUXILIARY_SWITCH_7_LABEL_ATTRIBUTE_ID (0x0006) #define ZCL_AUXILIARY_SWITCH_8_LABEL_ATTRIBUTE_ID (0x0007) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Device Management @@ -3991,8 +3660,6 @@ #define ZCL_QUERY_SPECIFIC_FILE_REQUEST_GENERATED_ATTRIBUTE_ID (0x08CC) #define ZCL_QUERY_SPECIFIC_FILE_RESPONSE_RECEIVED_ATTRIBUTE_ID (0x08CD) #define ZCL_QUERY_SPECIFIC_FILE_RESPONSE_REJECTED_ATTRIBUTE_ID (0x08CE) -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_PROVIDER_ID_SERVER_ATTRIBUTE_ID (0x0100) @@ -4014,34 +3681,22 @@ #define ZCL_WAN_STATUS_ATTRIBUTE_ID (0x0300) #define ZCL_LOW_MEDIUM_THRESHOLD_ATTRIBUTE_ID (0x0400) #define ZCL_MEDIUM_HIGH_THRESHOLD_ATTRIBUTE_ID (0x0401) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Events // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: MDU Pairing // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Sub-GHz // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_SUB_GHZ_CLUSTER_CHANNEL_CHANGE_ATTRIBUTE_ID (0x0000) @@ -4049,26 +3704,18 @@ #define ZCL_SUB_GHZ_CLUSTER_PAGE_29_CHANNEL_MASK_ATTRIBUTE_ID (0x0002) #define ZCL_SUB_GHZ_CLUSTER_PAGE_30_CHANNEL_MASK_ATTRIBUTE_ID (0x0003) #define ZCL_SUB_GHZ_CLUSTER_PAGE_31_CHANNEL_MASK_ATTRIBUTE_ID (0x0004) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Key Establishment // Client attributes #define ZCL_KEY_ESTABLISHMENT_SUITE_CLIENT_ATTRIBUTE_ID (0x0000) -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_KEY_ESTABLISHMENT_SUITE_SERVER_ATTRIBUTE_ID (0x0000) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Information // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_NODE_DESCRIPTION_ATTRIBUTE_ID (0x0000) @@ -4077,26 +3724,18 @@ #define ZCL_ENABLE_SECURE_CONFIGURATION_ATTRIBUTE_ID (0x0003) #define ZCL_NUMBER_OF_CONTENTS_ATTRIBUTE_ID (0x0010) #define ZCL_CONTENT_ROOT_ID_ATTRIBUTE_ID (0x0011) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Data Sharing // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_DEVICE_NAME_ATTRIBUTE_ID (0x0000) #define ZCL_DEVICE_DESCRIPTION_ATTRIBUTE_ID (0x0001) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Gaming // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_PLAYER_NAME_ATTRIBUTE_ID (0x0000) @@ -4119,27 +3758,19 @@ #define ZCL_COUNTER1_ATTRIBUTE_ID (0x001D) #define ZCL_COUNTER2_ATTRIBUTE_ID (0x001E) #define ZCL_DOWNLOADABLE_ATTRIBUTE_ID (0x001F) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Data Rate Control // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_AVERAGE_LATENCY_REQUIREMENT_ATTRIBUTE_ID (0x0000) #define ZCL_MAX_LATENCY_REQUIREMENT_ATTRIBUTE_ID (0x0001) #define ZCL_BANDWIDTH_REQUIREMENT_ATTRIBUTE_ID (0x0002) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Voice over ZigBee // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_CODEC_TYPE_ATTRIBUTE_ID (0x0000) @@ -4153,14 +3784,10 @@ #define ZCL_COMPRESSION_RATE_ATTRIBUTE_ID (0x0008) #define ZCL_OPTION_FLAGS_ATTRIBUTE_ID (0x0009) #define ZCL_THRESHOLD_ATTRIBUTE_ID (0x000A) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Chatting // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_U_ID_ATTRIBUTE_ID (0x0000) @@ -4168,14 +3795,10 @@ #define ZCL_C_ID_ATTRIBUTE_ID (0x0010) #define ZCL_NAME_ATTRIBUTE_ID (0x0011) #define ZCL_ENABLE_ADD_CHAT_ATTRIBUTE_ID (0x0020) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Payment // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_PAYMENT_USER_ID_ATTRIBUTE_ID (0x0000) @@ -4192,14 +3815,10 @@ #define ZCL_TRANS_ID_ATTRIBUTE_ID (0x0033) #define ZCL_TRANS_STATUS_ATTRIBUTE_ID (0x0034) #define ZCL_PAYMENT_STATUS_ATTRIBUTE_ID (0x0035) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Billing // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_USER_ID_ATTRIBUTE_ID (0x0000) @@ -4208,14 +3827,10 @@ #define ZCL_SESSION_INTERVAL_ATTRIBUTE_ID (0x0012) #define ZCL_TIMESTAMP_ATTRIBUTE_ID (0x0020) #define ZCL_DURATION_ATTRIBUTE_ID (0x0021) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Appliance Identification // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_BASIC_IDENTIFICATION_ATTRIBUTE_ID (0x0000) @@ -4230,14 +3845,10 @@ #define ZCL_PRODUCT_TYPE_NAME_ATTRIBUTE_ID (0x0018) #define ZCL_PRODUCT_TYPE_ID_ATTRIBUTE_ID (0x0019) #define ZCL_CECED_SPECIFICATION_VERSION_ATTRIBUTE_ID (0x001A) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Meter Identification // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_METER_COMPANY_NAME_ATTRIBUTE_ID (0x0000) @@ -4252,36 +3863,24 @@ #define ZCL_POD_ATTRIBUTE_ID (0x000C) #define ZCL_AVAILABLE_POWER_ATTRIBUTE_ID (0x000D) #define ZCL_POWER_THRESHOLD_ATTRIBUTE_ID (0x000E) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Appliance Events and Alert // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Appliance Statistics // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_LOG_MAX_SIZE_ATTRIBUTE_ID (0x0000) #define ZCL_LOG_QUEUE_MAX_SIZE_ATTRIBUTE_ID (0x0001) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Electrical Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_MEASUREMENT_TYPE_ATTRIBUTE_ID (0x0000) @@ -4412,14 +4011,10 @@ #define ZCL_RMS_EXTREME_UNDER_VOLTAGE_PERIOD_PHASE_C_ATTRIBUTE_ID (0x0A15) #define ZCL_RMS_VOLTAGE_SAG_PERIOD_PHASE_C_ATTRIBUTE_ID (0x0A16) #define ZCL_RMS_VOLTAGE_SWELL_PERIOD_PHASE_C_ATTRIBUTE_ID (0x0A17) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Diagnostics // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_NUMBER_OF_RESETS_ATTRIBUTE_ID (0x0000) @@ -4454,72 +4049,54 @@ #define ZCL_AVERAGE_MAC_RETRY_PER_APS_MSG_SENT_ATTRIBUTE_ID (0x011B) #define ZCL_LAST_MESSAGE_LQI_ATTRIBUTE_ID (0x011C) #define ZCL_LAST_MESSAGE_RSSI_ATTRIBUTE_ID (0x011D) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: ZLL Commissioning // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) + +// Attribute ids for cluster: Binding + +// Client attributes + +// Server attributes // Attribute ids for cluster: Sample Mfg Specific Cluster // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_ATTRIBUTE_ONE_ATTRIBUTE_ID (0x0000) #define ZCL_ATTRIBUTE_TWO_ATTRIBUTE_ID (0x0001) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Sample Mfg Specific Cluster 2 // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_ATTRIBUTE_THREE_ATTRIBUTE_ID (0x0000) #define ZCL_ATTRIBUTE_FOUR_ATTRIBUTE_ID (0x0001) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Configuration Cluster // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_TOKENS_LOCKED_ATTRIBUTE_ID (0x0000) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: MFGLIB Cluster // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_PACKETS_RECEIVED_ATTRIBUTE_ID (0x0000) #define ZCL_SAVED_RSSI_ATTRIBUTE_ID (0x0001) #define ZCL_SAVED_LQI_ATTRIBUTE_ID (0x0002) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: SL Works With All Hubs // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_SL_DISABLE_OTA_DOWNGRADES_ATTRIBUTE_ID (0x0002) @@ -4540,5 +4117,3 @@ #define ZCL_SL_PENDING_NETWORK_UPDATE_CHANNEL_ATTRIBUTE_ID (0x0011) #define ZCL_SL_PENDING_NETWORK_UPDATE_PANID_ATTRIBUTE_ID (0x0012) #define ZCL_SL_OTA_MAX_OFFLINE_DURATION_ATTRIBUTE_ID (0x0013) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) diff --git a/examples/all-clusters-app/all-clusters-common/gen/attribute-size.h b/examples/all-clusters-app/all-clusters-common/gen/attribute-size.h index 8d8659ee7ece2e..f9ef9212244eca 100644 --- a/examples/all-clusters-app/all-clusters-common/gen/attribute-size.h +++ b/examples/all-clusters-app/all-clusters-common/gen/attribute-size.h @@ -1,4 +1,3 @@ - /* * * Copyright (c) 2020 Project CHIP Authors @@ -32,3 +31,5 @@ ZCL_DATA8_ATTRIBUTE_TYPE, 1, ZCL_DATA16_ATTRIBUTE_TYPE, 2, ZCL_DATA24_ATTRIBUTE_ ZCL_FLOAT_SINGLE_ATTRIBUTE_TYPE, 4, ZCL_FLOAT_DOUBLE_ATTRIBUTE_TYPE, 8, ZCL_TIME_OF_DAY_ATTRIBUTE_TYPE, 4, ZCL_DATE_ATTRIBUTE_TYPE, 4, ZCL_UTC_TIME_ATTRIBUTE_TYPE, 4, ZCL_CLUSTER_ID_ATTRIBUTE_TYPE, 2, ZCL_ATTRIBUTE_ID_ATTRIBUTE_TYPE, 2, ZCL_BACNET_OID_ATTRIBUTE_TYPE, 4, ZCL_IEEE_ADDRESS_ATTRIBUTE_TYPE, 8, ZCL_SECURITY_KEY_ATTRIBUTE_TYPE, 16, + ZCL_ENDPOINT_ID_ATTRIBUTE_TYPE, 1, ZCL_GROUP_ID_ATTRIBUTE_TYPE, 2, ZCL_COMMAND_ID_ATTRIBUTE_TYPE, 1, ZCL_NODE_ID_ATTRIBUTE_TYPE, + 8, diff --git a/examples/all-clusters-app/all-clusters-common/gen/attribute-type.h b/examples/all-clusters-app/all-clusters-common/gen/attribute-type.h index bc5d1bae34b365..225cbc68be49c2 100644 --- a/examples/all-clusters-app/all-clusters-common/gen/attribute-type.h +++ b/examples/all-clusters-app/all-clusters-common/gen/attribute-type.h @@ -1,4 +1,3 @@ - /* * * Copyright (c) 2020 Project CHIP Authors @@ -77,5 +76,9 @@ enum ZCL_BACNET_OID_ATTRIBUTE_TYPE = 0xEA, // BACnet OID ZCL_IEEE_ADDRESS_ATTRIBUTE_TYPE = 0xF0, // IEEE address ZCL_SECURITY_KEY_ATTRIBUTE_TYPE = 0xF1, // 128-bit security key + ZCL_ENDPOINT_ID_ATTRIBUTE_TYPE = 0xF2, // Endpoint Id + ZCL_GROUP_ID_ATTRIBUTE_TYPE = 0xF3, // Group Id + ZCL_COMMAND_ID_ATTRIBUTE_TYPE = 0xF4, // Command Id + ZCL_NODE_ID_ATTRIBUTE_TYPE = 0xF5, // Node Id ZCL_UNKNOWN_ATTRIBUTE_TYPE = 0xFF, // Unknown }; diff --git a/examples/all-clusters-app/all-clusters-common/gen/call-command-handler.cpp b/examples/all-clusters-app/all-clusters-common/gen/call-command-handler.cpp index 9db10b94ef3350..985eb196a6ad60 100644 --- a/examples/all-clusters-app/all-clusters-common/gen/call-command-handler.cpp +++ b/examples/all-clusters-app/all-clusters-common/gen/call-command-handler.cpp @@ -1,4 +1,3 @@ - /* * * Copyright (c) 2020 Project CHIP Authors @@ -199,7 +198,14 @@ EmberAfStatus emberAfBasicClusterServerCommandParse(EmberAfClusterCommand * cmd) { bool wasHandled = false; - if (!cmd->mfgSpecific) + if (cmd->mfgSpecific) + { + if (cmd->mfgCode == 0x1002 && cmd->commandId == ZCL_MFG_SPECIFIC_PING_COMMAND_ID) + { + wasHandled = emberAfBasicClusterMfgSpecificPingCallback(); + } + } + else { switch (cmd->commandId) { diff --git a/examples/all-clusters-app/all-clusters-common/gen/call-command-handler.h b/examples/all-clusters-app/all-clusters-common/gen/call-command-handler.h index c1b06642f07ac9..43164ad576bfa8 100644 --- a/examples/all-clusters-app/all-clusters-common/gen/call-command-handler.h +++ b/examples/all-clusters-app/all-clusters-common/gen/call-command-handler.h @@ -1,4 +1,3 @@ - /* * * Copyright (c) 2020 Project CHIP Authors diff --git a/examples/all-clusters-app/all-clusters-common/gen/callback-stub.cpp b/examples/all-clusters-app/all-clusters-common/gen/callback-stub.cpp index e8214b31cc4718..a333cb52b82ebd 100644 --- a/examples/all-clusters-app/all-clusters-common/gen/callback-stub.cpp +++ b/examples/all-clusters-app/all-clusters-common/gen/callback-stub.cpp @@ -1,4 +1,3 @@ - /* * * Copyright (c) 2020 Project CHIP Authors diff --git a/examples/all-clusters-app/all-clusters-common/gen/callback.h b/examples/all-clusters-app/all-clusters-common/gen/callback.h index 7391f06f5fcdf0..29f62581d7f8bd 100644 --- a/examples/all-clusters-app/all-clusters-common/gen/callback.h +++ b/examples/all-clusters-app/all-clusters-common/gen/callback.h @@ -1,4 +1,3 @@ - /* * * Copyright (c) 2020 Project CHIP Authors @@ -1536,6 +1535,12 @@ bool emberAfBarrierControlClusterBarrierControlGoToPercentCallback(uint8_t perce bool emberAfBarrierControlClusterBarrierControlStopCallback(); +/** + * @brief Basic Cluster MfgSpecificPing Command callback + */ + +bool emberAfBasicClusterMfgSpecificPingCallback(); + /** * @brief Basic Cluster ResetToFactoryDefaults Command callback */ diff --git a/examples/all-clusters-app/all-clusters-common/gen/client-command-macro.h b/examples/all-clusters-app/all-clusters-common/gen/client-command-macro.h index f1b0c4633a2b14..7116663d885eca 100644 --- a/examples/all-clusters-app/all-clusters-common/gen/client-command-macro.h +++ b/examples/all-clusters-app/all-clusters-common/gen/client-command-macro.h @@ -1,4 +1,3 @@ - /* * * Copyright (c) 2020 Project CHIP Authors @@ -5663,6 +5662,32 @@ ZCL_GET_ENDPOINT_LIST_REQUEST_COMMAND_ID, "uuuub", startIndex, total, startIndex, count, \ endpointInformationRecordList, endpointInformationRecordListLen); +/** @brief Command description for Bind + * + * Command: Bind + * @param nodeId NODE_ID + * @param groupId GROUP_ID + * @param endpointId ENDPOINT_ID + * @param clusterId CLUSTER_ID + */ +#define emberAfFillCommandBindingClusterBind(nodeId, groupId, endpointId, clusterId) \ + emberAfFillExternalBuffer(mask, \ + \ + ZCL_BIND_COMMAND_ID, "uuuu", nodeId, groupId, endpointId, clusterId); + +/** @brief Command description for Unbind + * + * Command: Unbind + * @param nodeId NODE_ID + * @param groupId GROUP_ID + * @param endpointId ENDPOINT_ID + * @param clusterId CLUSTER_ID + */ +#define emberAfFillCommandBindingClusterUnbind(nodeId, groupId, endpointId, clusterId) \ + emberAfFillExternalBuffer(mask, \ + \ + ZCL_UNBIND_COMMAND_ID, "uuuu", nodeId, groupId, endpointId, clusterId); + /** @brief Command description for CommandOne * * Command: CommandOne diff --git a/examples/all-clusters-app/all-clusters-common/gen/cluster-id.h b/examples/all-clusters-app/all-clusters-common/gen/cluster-id.h index c341b079be401d..4db65e9cad99d0 100644 --- a/examples/all-clusters-app/all-clusters-common/gen/cluster-id.h +++ b/examples/all-clusters-app/all-clusters-common/gen/cluster-id.h @@ -1,4 +1,3 @@ - /* * * Copyright (c) 2020 Project CHIP Authors @@ -331,6 +330,9 @@ // Definitions for cluster: ZLL Commissioning #define ZCL_ZLL_COMMISSIONING_CLUSTER_ID (0x1000) +// Definitions for cluster: Binding +#define ZCL_BINDING_CLUSTER_ID (0xF000) + // Definitions for cluster: Sample Mfg Specific Cluster #define ZCL_SAMPLE_MFG_SPECIFIC_CLUSTER_ID (0xFC00) diff --git a/examples/all-clusters-app/all-clusters-common/gen/command-id.h b/examples/all-clusters-app/all-clusters-common/gen/command-id.h index 940258f4527aa5..42dcc0e89c71f5 100644 --- a/examples/all-clusters-app/all-clusters-common/gen/command-id.h +++ b/examples/all-clusters-app/all-clusters-common/gen/command-id.h @@ -1,4 +1,3 @@ - /* * * Copyright (c) 2020 Project CHIP Authors @@ -46,6 +45,7 @@ // Commands for cluster: Basic #define ZCL_RESET_TO_FACTORY_DEFAULTS_COMMAND_ID (0x00) +#define ZCL_MFG_SPECIFIC_PING_COMMAND_ID (0x00) // Commands for cluster: Identify #define ZCL_IDENTIFY_COMMAND_ID (0x00) @@ -683,6 +683,10 @@ #define ZCL_GET_ENDPOINT_LIST_REQUEST_COMMAND_ID (0x42) #define ZCL_GET_ENDPOINT_LIST_RESPONSE_COMMAND_ID (0x42) +// Commands for cluster: Binding +#define ZCL_BIND_COMMAND_ID (0x00) +#define ZCL_UNBIND_COMMAND_ID (0x01) + // Commands for cluster: Sample Mfg Specific Cluster #define ZCL_COMMAND_ONE_COMMAND_ID (0x00) diff --git a/examples/all-clusters-app/all-clusters-common/gen/endpoint_config.h b/examples/all-clusters-app/all-clusters-common/gen/endpoint_config.h index 8cef47f152fda4..96be9d9b2525eb 100644 --- a/examples/all-clusters-app/all-clusters-common/gen/endpoint_config.h +++ b/examples/all-clusters-app/all-clusters-common/gen/endpoint_config.h @@ -419,8 +419,9 @@ // Generated data for the command discovery #define GENERATED_COMMANDS \ { \ - { 0x0000, 0x00, COMMAND_MASK_OUTGOING_CLIENT | COMMAND_MASK_INCOMING_SERVER }, /* Basic / ResetToFactoryDefaults */ \ - { 0x0003, 0x00, COMMAND_MASK_OUTGOING_CLIENT | COMMAND_MASK_INCOMING_SERVER }, /* Identify / Identify */ \ + { 0x0000, 0x00, COMMAND_MASK_OUTGOING_CLIENT | COMMAND_MASK_INCOMING_SERVER }, /* Basic / ResetToFactoryDefaults */ \ + { 0x0000, 0x00, COMMAND_MASK_INCOMING_SERVER | COMMAND_MASK_MANUFACTURER_SPECIFIC }, /* Basic / MfgSpecificPing */ \ + { 0x0003, 0x00, COMMAND_MASK_OUTGOING_CLIENT | COMMAND_MASK_INCOMING_SERVER }, /* Identify / Identify */ \ { 0x0003, 0x00, COMMAND_MASK_OUTGOING_SERVER | COMMAND_MASK_INCOMING_CLIENT }, /* Identify / IdentifyQueryResponse */ \ { 0x0003, 0x01, COMMAND_MASK_OUTGOING_CLIENT | COMMAND_MASK_INCOMING_SERVER }, /* Identify / IdentifyQuery */ \ { 0x0004, 0x00, COMMAND_MASK_OUTGOING_CLIENT | COMMAND_MASK_INCOMING_SERVER }, /* Groups / AddGroup */ \ @@ -592,16 +593,16 @@ { 0x0B03, 0x02, COMMAND_MASK_INCOMING_CLIENT }, /* Appliance Statistics / LogQueueResponse */ \ { 0x0B03, 0x03, COMMAND_MASK_INCOMING_CLIENT }, /* Appliance Statistics / StatisticsAvailable */ \ } -#define EMBER_AF_GENERATED_COMMAND_COUNT (160) +#define EMBER_AF_GENERATED_COMMAND_COUNT (161) // Command manufacturer codes #define GENERATED_COMMAND_MANUFACTURER_CODES \ { \ { \ - 0x00, 0x00 \ + 0x01, 0x1002 \ } \ } -#define GENERATED_COMMAND_MANUFACTURER_CODE_COUNT (0) +#define GENERATED_COMMAND_MANUFACTURER_CODE_COUNT (1) // Generated reporting configuration defaults #define EMBER_AF_GENERATED_REPORTING_CONFIG_DEFAULTS \ diff --git a/examples/all-clusters-app/all-clusters-common/gen/enums.h b/examples/all-clusters-app/all-clusters-common/gen/enums.h index 07c2881e641e97..eedb99290f59ce 100644 --- a/examples/all-clusters-app/all-clusters-common/gen/enums.h +++ b/examples/all-clusters-app/all-clusters-common/gen/enums.h @@ -1,4 +1,3 @@ - /* * * Copyright (c) 2020 Project CHIP Authors @@ -548,7 +547,7 @@ typedef enum EMBER_ZCL_DOOR_LOCK_OPERATING_MODE_PRIVACY_MODE = 0x02, EMBER_ZCL_DOOR_LOCK_OPERATING_MODE_NO_RF_LOCK_OR_UNLOCK = 0x03, EMBER_ZCL_DOOR_LOCK_OPERATING_MODE_LOCAL_PROGRAMMING_MODE = 0x04, - EMBER_ZCL_DOOR_LOCK_OPERATING_MODE_PASSAGE_MODE______ = 0x05, + EMBER_ZCL_DOOR_LOCK_OPERATING_MODE_PASSAGE_MODE = 0x05, } EmberAfDoorLockOperatingMode; // Enum for DoorLockOperationEventCode diff --git a/examples/all-clusters-app/all-clusters-common/gen/gen_config.h b/examples/all-clusters-app/all-clusters-common/gen/gen_config.h index 29ebbde513ecbf..0bd1135acf5bda 100644 --- a/examples/all-clusters-app/all-clusters-common/gen/gen_config.h +++ b/examples/all-clusters-app/all-clusters-common/gen/gen_config.h @@ -1,4 +1,3 @@ - /* * * Copyright (c) 2020 Project CHIP Authors @@ -31,7 +30,7 @@ #define EMBER_AF_BARRIER_CONTROL_CLUSTER_CLIENT_ENDPOINT_COUNT (1) #define EMBER_AF_BARRIER_CONTROL_CLUSTER_SERVER_ENDPOINT_COUNT (1) #define EMBER_AF_BASIC_CLUSTER_CLIENT_ENDPOINT_COUNT (1) -#define EMBER_AF_BASIC_CLUSTER_SERVER_ENDPOINT_COUNT (1) +#define EMBER_AF_BASIC_CLUSTER_SERVER_ENDPOINT_COUNT (2) #define EMBER_AF_COLOR_CONTROL_CLUSTER_CLIENT_ENDPOINT_COUNT (1) #define EMBER_AF_COLOR_CONTROL_CLUSTER_SERVER_ENDPOINT_COUNT (1) #define EMBER_AF_DOOR_LOCK_CLUSTER_CLIENT_ENDPOINT_COUNT (1) @@ -44,7 +43,7 @@ #define EMBER_AF_LEVEL_CONTROL_CLUSTER_CLIENT_ENDPOINT_COUNT (1) #define EMBER_AF_LEVEL_CONTROL_CLUSTER_SERVER_ENDPOINT_COUNT (1) #define EMBER_AF_ON_OFF_CLUSTER_CLIENT_ENDPOINT_COUNT (1) -#define EMBER_AF_ON_OFF_CLUSTER_SERVER_ENDPOINT_COUNT (1) +#define EMBER_AF_ON_OFF_CLUSTER_SERVER_ENDPOINT_COUNT (2) #define EMBER_AF_SCENES_CLUSTER_CLIENT_ENDPOINT_COUNT (1) #define EMBER_AF_SCENES_CLUSTER_SERVER_ENDPOINT_COUNT (1) #define EMBER_AF_TEMP_MEASUREMENT_CLUSTER_SERVER_ENDPOINT_COUNT (1) @@ -158,5 +157,5 @@ // Use this macro to check if Reporting plugin is included #define EMBER_AF_PLUGIN_REPORTING // User options for plugin Reporting -#define EMBER_AF_PLUGIN_REPORTING_TABLE_SIZE 5 +#define EMBER_AF_PLUGIN_REPORTING_TABLE_SIZE 20 #define EMBER_AF_PLUGIN_REPORTING_ENABLE_GROUP_BOUND_REPORTS diff --git a/examples/all-clusters-app/all-clusters-common/gen/print-cluster.h b/examples/all-clusters-app/all-clusters-common/gen/print-cluster.h index a37d7fb0495995..7155ccf0294122 100644 --- a/examples/all-clusters-app/all-clusters-common/gen/print-cluster.h +++ b/examples/all-clusters-app/all-clusters-common/gen/print-cluster.h @@ -1,4 +1,3 @@ - /* * * Copyright (c) 2020 Project CHIP Authors @@ -715,6 +714,12 @@ #define CHIP_PRINTCLUSTER_ZLL_COMMISSIONING_CLUSTER #endif +#if defined(ZCL_USING_BINDING_CLUSTER_SERVER) || defined(ZCL_USING_BINDING_CLUSTER_CLIENT) +#define CHIP_PRINTCLUSTER_BINDING_CLUSTER { ZCL_BINDING_CLUSTER_ID, 61440, "Binding" }, +#else +#define CHIP_PRINTCLUSTER_BINDING_CLUSTER +#endif + #if defined(ZCL_USING_SAMPLE_MFG_SPECIFIC_CLUSTER_SERVER) || defined(ZCL_USING_SAMPLE_MFG_SPECIFIC_CLUSTER_CLIENT) #define CHIP_PRINTCLUSTER_SAMPLE_MFG_SPECIFIC_CLUSTER { ZCL_SAMPLE_MFG_SPECIFIC_CLUSTER_ID, 64512, "Sample Mfg Specific Cluster" }, #else @@ -851,6 +856,7 @@ CHIP_PRINTCLUSTER_ELECTRICAL_MEASUREMENT_CLUSTER \ CHIP_PRINTCLUSTER_DIAGNOSTICS_CLUSTER \ CHIP_PRINTCLUSTER_ZLL_COMMISSIONING_CLUSTER \ + CHIP_PRINTCLUSTER_BINDING_CLUSTER \ CHIP_PRINTCLUSTER_SAMPLE_MFG_SPECIFIC_CLUSTER \ CHIP_PRINTCLUSTER_SAMPLE_MFG_SPECIFIC_CLUSTER_2 \ CHIP_PRINTCLUSTER_OTA_CONFIGURATION_CLUSTER \ diff --git a/examples/all-clusters-app/esp32/main/DeviceCallbacks.cpp b/examples/all-clusters-app/esp32/main/DeviceCallbacks.cpp index f40b1fa013e8c3..6a5e9d76e3f2ee 100644 --- a/examples/all-clusters-app/esp32/main/DeviceCallbacks.cpp +++ b/examples/all-clusters-app/esp32/main/DeviceCallbacks.cpp @@ -33,7 +33,8 @@ #include "gen/attribute-id.h" #include "gen/cluster-id.h" #include -#include +#include +#include #include static const char * TAG = "app-devicecallbacks"; @@ -92,7 +93,11 @@ void DeviceCallbacks::OnInternetConnectivityChange(const ChipDeviceEvent * event { ESP_LOGI(TAG, "Server ready at: %s:%d", event->InternetConnectivityChange.address, CHIP_PORT); wifiLED.Set(true); - chip::Mdns::DiscoveryManager::GetInstance().StartPublishDevice(); + + if (chip::Mdns::ServiceAdvertiser::Instance().Start(&DeviceLayer::InetLayer, chip::Mdns::kMdnsPort) != CHIP_NO_ERROR) + { + ESP_LOGE(TAG, "Failed to start mDNS advertisement"); + } } else if (event->InternetConnectivityChange.IPv4 == kConnectivity_Lost) { @@ -102,7 +107,10 @@ void DeviceCallbacks::OnInternetConnectivityChange(const ChipDeviceEvent * event if (event->InternetConnectivityChange.IPv6 == kConnectivity_Established) { ESP_LOGI(TAG, "IPv6 Server ready..."); - chip::Mdns::DiscoveryManager::GetInstance().StartPublishDevice(); + if (chip::Mdns::ServiceAdvertiser::Instance().Start(&DeviceLayer::InetLayer, chip::Mdns::kMdnsPort) != CHIP_NO_ERROR) + { + ESP_LOGE(TAG, "Failed to start mDNS advertisement"); + } } else if (event->InternetConnectivityChange.IPv6 == kConnectivity_Lost) { @@ -160,3 +168,9 @@ void DeviceCallbacks::OnIdentifyPostAttributeChangeCallback(EndpointId endpointI exit: return; } + +bool emberAfBasicClusterMfgSpecificPingCallback(void) +{ + emberAfSendDefaultResponse(emberAfCurrentCommand(), EMBER_ZCL_STATUS_SUCCESS); + return true; +} diff --git a/examples/all-clusters-app/esp32/main/component.mk b/examples/all-clusters-app/esp32/main/component.mk index 6eef1d02ab74d7..dcb0d49a5cf9a7 100644 --- a/examples/all-clusters-app/esp32/main/component.mk +++ b/examples/all-clusters-app/esp32/main/component.mk @@ -23,8 +23,8 @@ COMPONENT_DEPENDS := chip QRCode tft spidriver COMPONENT_SRCDIRS := \ . \ - ../third_party/connectedhomeip/examples/common/chip-app-server \ ../third_party/connectedhomeip/examples/all-clusters-app/all-clusters-common/gen \ + ../third_party/connectedhomeip/src/app/server \ ../third_party/connectedhomeip/src/app/util \ ../third_party/connectedhomeip/src/app/clusters/on-off-server \ ../third_party/connectedhomeip/src/app/clusters/level-control \ @@ -38,6 +38,7 @@ COMPONENT_SRCDIRS := ../third_party/connectedhomeip/src/app/clusters/temperature-measurement-server \ ../third_party/connectedhomeip/src/app/clusters/scenes \ ../third_party/connectedhomeip/src/app/clusters/basic \ + ../third_party/connectedhomeip/src/app/clusters/bindings \ ../third_party/connectedhomeip/src/app/reporting \ ../third_party/connectedhomeip/src/app/clusters/door-lock-client \ ../third_party/connectedhomeip/src/app/clusters/door-lock-server \ @@ -46,7 +47,7 @@ COMPONENT_SRCDIRS := COMPONENT_EXTRA_INCLUDES := $(PROJECT_PATH)/third_party/connectedhomeip/src/app/util \ - $(PROJECT_PATH)/third_party/connectedhomeip/examples/common/chip-app-server/include \ + $(PROJECT_PATH)/third_party/connectedhomeip/src/app/server \ $(PROJECT_PATH)/third_party/connectedhomeip/examples/all-clusters-app/all-clusters-common \ $(PROJECT_PATH)/third_party/connectedhomeip/src diff --git a/examples/all-clusters-app/linux/BUILD.gn b/examples/all-clusters-app/linux/BUILD.gn index 01da5ec0b3b43d..06512ad002bce5 100644 --- a/examples/all-clusters-app/linux/BUILD.gn +++ b/examples/all-clusters-app/linux/BUILD.gn @@ -23,6 +23,7 @@ config("includes") { ".", "include", "${chip_root}/src/app/util", + "${chip_root}/src/app/server", ] } @@ -39,7 +40,6 @@ executable("all-clusters-server") { deps = [ "${chip_root}/examples/all-clusters-app/all-clusters-common", - "${chip_root}/examples/common/chip-app-server:chip-app-server", "${chip_root}/src/lib", ] diff --git a/examples/all-clusters-app/linux/main.cpp b/examples/all-clusters-app/linux/main.cpp index 145ce38a267ffe..18a90d159b2216 100644 --- a/examples/all-clusters-app/linux/main.cpp +++ b/examples/all-clusters-app/linux/main.cpp @@ -44,6 +44,12 @@ void emberAfPostAttributeChangeCallback(EndpointId endpoint, ClusterId clusterId uint16_t manufacturerCode, uint8_t type, uint8_t size, uint8_t * value) {} +bool emberAfBasicClusterMfgSpecificPingCallback(void) +{ + emberAfSendDefaultResponse(emberAfCurrentCommand(), EMBER_ZCL_STATUS_SUCCESS); + return true; +} + int main(int argc, char * argv[]) { CHIP_ERROR err = CHIP_NO_ERROR; diff --git a/examples/common/chip-app-server/args.gni b/examples/build_overrides/freertos.gni similarity index 82% rename from examples/common/chip-app-server/args.gni rename to examples/build_overrides/freertos.gni index aa216c8b7e753c..881cd194e5031d 100644 --- a/examples/common/chip-app-server/args.gni +++ b/examples/build_overrides/freertos.gni @@ -12,4 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -import("//build_overrides/chip.gni") +declare_args() { + # Root directory for FreeRTOS + freertos_root = "//third_party/connectedhomeip/third_party/freertos" +} diff --git a/examples/build_overrides/ti_simplelink_sdk.gni b/examples/build_overrides/ti_simplelink_sdk.gni new file mode 100644 index 00000000000000..61f4308e1635cc --- /dev/null +++ b/examples/build_overrides/ti_simplelink_sdk.gni @@ -0,0 +1,19 @@ +# 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. + +declare_args() { + # Root directory for TI SimpleLink SDK build helpers. + ti_simplelink_sdk_build_root = + "//third_party/connectedhomeip/third_party/ti_simplelink_sdk" +} diff --git a/examples/chip-tool/BUILD.gn b/examples/chip-tool/BUILD.gn index 17ed976ef3b89e..9ae80a2af5a54f 100644 --- a/examples/chip-tool/BUILD.gn +++ b/examples/chip-tool/BUILD.gn @@ -23,11 +23,9 @@ executable("chip-tool") { "commands/clusters/ModelCommand.cpp", "commands/common/Command.cpp", "commands/common/Commands.cpp", - "commands/common/Logging.cpp", - "commands/common/NetworkCommand.cpp", - "commands/echo/EchoCommand.cpp", "commands/pairing/PairingCommand.cpp", - "commands/payload/ParseCommand.cpp", + "commands/payload/AdditionalDataParseCommand.cpp", + "commands/payload/SetupPayloadParseCommand.cpp", "config/PersistentStorage.cpp", "main.cpp", ] diff --git a/examples/chip-tool/Dockerfile b/examples/chip-tool/Dockerfile index 1651eb36b24204..e149387b1d297a 100644 --- a/examples/chip-tool/Dockerfile +++ b/examples/chip-tool/Dockerfile @@ -16,7 +16,7 @@ # from chip-cirque-device-base -RUN apt-get update && apt-get install -y libglib2.0 avahi-daemon libavahi-client3 && rm -rf /var/lib/apt/lists/* + COPY out/debug/chip-tool /usr/bin/ COPY entrypoint.sh / diff --git a/examples/chip-tool/README.md b/examples/chip-tool/README.md index bf0cbdff08b5fa..5bde02613f7c51 100644 --- a/examples/chip-tool/README.md +++ b/examples/chip-tool/README.md @@ -57,15 +57,6 @@ the ESP32 all-clusters-app: $ chip-tool pairing unpair -## Using the Client to Request an Echo - -### Ping a device - - $ chip-tool echo ip - -If valid values are supplied, it will send a message to the paired device and -verify that the incoming echo from the server matches what was sent out. - ## Using the Client to Send CHIP Commands To use the Client to send a CHIP commands, run the built executable and pass it @@ -110,18 +101,25 @@ with the target cluster name and the target command name ### How to parse a setup code To parse a setup code, run the built executable with the `payload` cluster name -and the `parse` command +and the `parse-setup-payload` command - $ chip-tool payload parse code + $ chip-tool payload parse-setup-payload code #### QR Code - $ chip-tool payload parse "CH:#####" + $ chip-tool payload parse-setup-payload "CH:#####" #### QR Code with optional Vendor Info - $ chip-tool chip-tool payload parse "CH:#####" + $ chip-tool chip-tool payload parse-setup-payload "CH:#####" #### Manual Setup Code - $ chip-tool payload parse :#####" + $ chip-tool payload parse-setup-payload :#####" + +# Using the Client for Additional Data Payload + +To parse an additional data payload, run the built executable with the `payload` +cluster name and the `parse-additional-data-payload` command + + $ chip-tool payload parse-additional-data-payload "#####" diff --git a/examples/chip-tool/commands/clusters/Commands.h b/examples/chip-tool/commands/clusters/Commands.h index 039c37c0796f5a..23ae83ced68cdf 100644 --- a/examples/chip-tool/commands/clusters/Commands.h +++ b/examples/chip-tool/commands/clusters/Commands.h @@ -932,9 +932,9 @@ class BarrierControlGoToPercent : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { - return encodeBarrierControlClusterBarrierControlGoToPercentCommand(buffer->Start(), bufferSize, endPointId, mPercentOpen); + return encodeBarrierControlClusterBarrierControlGoToPercentCommand(endPointId, mPercentOpen); } // Global Response: DefaultResponse @@ -956,9 +956,9 @@ class BarrierControlStop : public ModelCommand public: BarrierControlStop() : ModelCommand("barrier-control-stop", kBarrierControlClusterId, 0x01) { ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { - return encodeBarrierControlClusterBarrierControlStopCommand(buffer->Start(), bufferSize, endPointId); + return encodeBarrierControlClusterBarrierControlStopCommand(endPointId); } // Global Response: DefaultResponse @@ -977,9 +977,9 @@ class DiscoverBarrierControlAttributes : public ModelCommand public: DiscoverBarrierControlAttributes() : ModelCommand("discover", kBarrierControlClusterId, 0x0c) { ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { - return encodeBarrierControlClusterDiscoverAttributes(buffer->Start(), bufferSize, endPointId); + return encodeBarrierControlClusterDiscoverAttributes(endPointId); } // Global Response: DiscoverAttributesResponse @@ -1002,9 +1002,9 @@ class ReadBarrierControlMovingState : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { - return encodeBarrierControlClusterReadBarrierMovingStateAttribute(buffer->Start(), bufferSize, endPointId); + return encodeBarrierControlClusterReadBarrierMovingStateAttribute(endPointId); } // Global Response: ReadAttributesResponse @@ -1027,9 +1027,9 @@ class ReadBarrierControlSafetyStatus : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { - return encodeBarrierControlClusterReadBarrierSafetyStatusAttribute(buffer->Start(), bufferSize, endPointId); + return encodeBarrierControlClusterReadBarrierSafetyStatusAttribute(endPointId); } // Global Response: ReadAttributesResponse @@ -1052,9 +1052,9 @@ class ReadBarrierControlCapabilities : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { - return encodeBarrierControlClusterReadBarrierCapabilitiesAttribute(buffer->Start(), bufferSize, endPointId); + return encodeBarrierControlClusterReadBarrierCapabilitiesAttribute(endPointId); } // Global Response: ReadAttributesResponse @@ -1077,9 +1077,9 @@ class ReadBarrierControlBarrierPosition : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { - return encodeBarrierControlClusterReadBarrierPositionAttribute(buffer->Start(), bufferSize, endPointId); + return encodeBarrierControlClusterReadBarrierPositionAttribute(endPointId); } // Global Response: ReadAttributesResponse @@ -1098,6 +1098,7 @@ class ReadBarrierControlBarrierPosition : public ModelCommand |------------------------------------------------------------------------------| | Commands: | | | * ResetToFactoryDefaults | 0x00 | +| * MfgSpecificPing | 0x00 | |------------------------------------------------------------------------------| | Attributes: | | | * ZclVersion | 0x0000 | @@ -1115,9 +1116,9 @@ class BasicResetToFactoryDefaults : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { - return encodeBasicClusterResetToFactoryDefaultsCommand(buffer->Start(), bufferSize, endPointId); + return encodeBasicClusterResetToFactoryDefaultsCommand(endPointId); } // Global Response: DefaultResponse @@ -1128,6 +1129,24 @@ class BasicResetToFactoryDefaults : public ModelCommand } }; +/* + * Command MfgSpecificPing + */ +class BasicMfgSpecificPing : public ModelCommand +{ +public: + BasicMfgSpecificPing() : ModelCommand("ping", kBasicClusterId, 0x00) { ModelCommand::AddArguments(); } + + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { return encodeBasicClusterMfgSpecificPingCommand(endPointId); } + + // Global Response: DefaultResponse + bool HandleGlobalResponse(uint8_t commandId, uint8_t * message, uint16_t messageLen) const override + { + DefaultResponse response; + return response.HandleCommandResponse(commandId, message, messageLen); + } +}; + /* * Discover attributes */ @@ -1136,10 +1155,7 @@ class DiscoverBasicAttributes : public ModelCommand public: DiscoverBasicAttributes() : ModelCommand("discover", kBasicClusterId, 0x0c) { ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override - { - return encodeBasicClusterDiscoverAttributes(buffer->Start(), bufferSize, endPointId); - } + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { return encodeBasicClusterDiscoverAttributes(endPointId); } // Global Response: DiscoverAttributesResponse bool HandleGlobalResponse(uint8_t commandId, uint8_t * message, uint16_t messageLen) const override @@ -1161,10 +1177,7 @@ class ReadBasicZclVersion : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override - { - return encodeBasicClusterReadZclVersionAttribute(buffer->Start(), bufferSize, endPointId); - } + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { return encodeBasicClusterReadZclVersionAttribute(endPointId); } // Global Response: ReadAttributesResponse bool HandleGlobalResponse(uint8_t commandId, uint8_t * message, uint16_t messageLen) const override @@ -1186,10 +1199,7 @@ class ReadBasicPowerSource : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override - { - return encodeBasicClusterReadPowerSourceAttribute(buffer->Start(), bufferSize, endPointId); - } + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { return encodeBasicClusterReadPowerSourceAttribute(endPointId); } // Global Response: ReadAttributesResponse bool HandleGlobalResponse(uint8_t commandId, uint8_t * message, uint16_t messageLen) const override @@ -1275,10 +1285,9 @@ class ColorControlMoveColor : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { - return encodeColorControlClusterMoveColorCommand(buffer->Start(), bufferSize, endPointId, mRateX, mRateY, mOptionsMask, - mOptionsOverride); + return encodeColorControlClusterMoveColorCommand(endPointId, mRateX, mRateY, mOptionsMask, mOptionsOverride); } // Global Response: DefaultResponse @@ -1312,11 +1321,10 @@ class ColorControlMoveColorTemperature : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { - return encodeColorControlClusterMoveColorTemperatureCommand(buffer->Start(), bufferSize, endPointId, mMoveMode, mRate, - mColorTemperatureMinimum, mColorTemperatureMaximum, - mOptionsMask, mOptionsOverride); + return encodeColorControlClusterMoveColorTemperatureCommand(endPointId, mMoveMode, mRate, mColorTemperatureMinimum, + mColorTemperatureMaximum, mOptionsMask, mOptionsOverride); } // Global Response: DefaultResponse @@ -1350,10 +1358,9 @@ class ColorControlMoveHue : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { - return encodeColorControlClusterMoveHueCommand(buffer->Start(), bufferSize, endPointId, mMoveMode, mRate, mOptionsMask, - mOptionsOverride); + return encodeColorControlClusterMoveHueCommand(endPointId, mMoveMode, mRate, mOptionsMask, mOptionsOverride); } // Global Response: DefaultResponse @@ -1385,10 +1392,9 @@ class ColorControlMoveSaturation : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { - return encodeColorControlClusterMoveSaturationCommand(buffer->Start(), bufferSize, endPointId, mMoveMode, mRate, - mOptionsMask, mOptionsOverride); + return encodeColorControlClusterMoveSaturationCommand(endPointId, mMoveMode, mRate, mOptionsMask, mOptionsOverride); } // Global Response: DefaultResponse @@ -1421,10 +1427,10 @@ class ColorControlMoveToColor : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { - return encodeColorControlClusterMoveToColorCommand(buffer->Start(), bufferSize, endPointId, mColorX, mColorY, - mTransitionTime, mOptionsMask, mOptionsOverride); + return encodeColorControlClusterMoveToColorCommand(endPointId, mColorX, mColorY, mTransitionTime, mOptionsMask, + mOptionsOverride); } // Global Response: DefaultResponse @@ -1457,10 +1463,10 @@ class ColorControlMoveToColorTemperature : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { - return encodeColorControlClusterMoveToColorTemperatureCommand(buffer->Start(), bufferSize, endPointId, mColorTemperature, - mTransitionTime, mOptionsMask, mOptionsOverride); + return encodeColorControlClusterMoveToColorTemperatureCommand(endPointId, mColorTemperature, mTransitionTime, mOptionsMask, + mOptionsOverride); } // Global Response: DefaultResponse @@ -1493,10 +1499,10 @@ class ColorControlMoveToHue : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { - return encodeColorControlClusterMoveToHueCommand(buffer->Start(), bufferSize, endPointId, mHue, mDirection, mTransitionTime, - mOptionsMask, mOptionsOverride); + return encodeColorControlClusterMoveToHueCommand(endPointId, mHue, mDirection, mTransitionTime, mOptionsMask, + mOptionsOverride); } // Global Response: DefaultResponse @@ -1530,10 +1536,10 @@ class ColorControlMoveToHueAndSaturation : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { - return encodeColorControlClusterMoveToHueAndSaturationCommand(buffer->Start(), bufferSize, endPointId, mHue, mSaturation, - mTransitionTime, mOptionsMask, mOptionsOverride); + return encodeColorControlClusterMoveToHueAndSaturationCommand(endPointId, mHue, mSaturation, mTransitionTime, mOptionsMask, + mOptionsOverride); } // Global Response: DefaultResponse @@ -1566,10 +1572,10 @@ class ColorControlMoveToSaturation : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { - return encodeColorControlClusterMoveToSaturationCommand(buffer->Start(), bufferSize, endPointId, mSaturation, - mTransitionTime, mOptionsMask, mOptionsOverride); + return encodeColorControlClusterMoveToSaturationCommand(endPointId, mSaturation, mTransitionTime, mOptionsMask, + mOptionsOverride); } // Global Response: DefaultResponse @@ -1602,10 +1608,10 @@ class ColorControlStepColor : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { - return encodeColorControlClusterStepColorCommand(buffer->Start(), bufferSize, endPointId, mStepX, mStepY, mTransitionTime, - mOptionsMask, mOptionsOverride); + return encodeColorControlClusterStepColorCommand(endPointId, mStepX, mStepY, mTransitionTime, mOptionsMask, + mOptionsOverride); } // Global Response: DefaultResponse @@ -1641,11 +1647,11 @@ class ColorControlStepColorTemperature : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { - return encodeColorControlClusterStepColorTemperatureCommand(buffer->Start(), bufferSize, endPointId, mStepMode, mStepSize, - mTransitionTime, mColorTemperatureMinimum, - mColorTemperatureMaximum, mOptionsMask, mOptionsOverride); + return encodeColorControlClusterStepColorTemperatureCommand(endPointId, mStepMode, mStepSize, mTransitionTime, + mColorTemperatureMinimum, mColorTemperatureMaximum, + mOptionsMask, mOptionsOverride); } // Global Response: DefaultResponse @@ -1681,10 +1687,10 @@ class ColorControlStepHue : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { - return encodeColorControlClusterStepHueCommand(buffer->Start(), bufferSize, endPointId, mStepMode, mStepSize, - mTransitionTime, mOptionsMask, mOptionsOverride); + return encodeColorControlClusterStepHueCommand(endPointId, mStepMode, mStepSize, mTransitionTime, mOptionsMask, + mOptionsOverride); } // Global Response: DefaultResponse @@ -1718,10 +1724,10 @@ class ColorControlStepSaturation : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { - return encodeColorControlClusterStepSaturationCommand(buffer->Start(), bufferSize, endPointId, mStepMode, mStepSize, - mTransitionTime, mOptionsMask, mOptionsOverride); + return encodeColorControlClusterStepSaturationCommand(endPointId, mStepMode, mStepSize, mTransitionTime, mOptionsMask, + mOptionsOverride); } // Global Response: DefaultResponse @@ -1752,10 +1758,9 @@ class ColorControlStopMoveStep : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { - return encodeColorControlClusterStopMoveStepCommand(buffer->Start(), bufferSize, endPointId, mOptionsMask, - mOptionsOverride); + return encodeColorControlClusterStopMoveStepCommand(endPointId, mOptionsMask, mOptionsOverride); } // Global Response: DefaultResponse @@ -1778,9 +1783,9 @@ class DiscoverColorControlAttributes : public ModelCommand public: DiscoverColorControlAttributes() : ModelCommand("discover", kColorControlClusterId, 0x0c) { ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { - return encodeColorControlClusterDiscoverAttributes(buffer->Start(), bufferSize, endPointId); + return encodeColorControlClusterDiscoverAttributes(endPointId); } // Global Response: DiscoverAttributesResponse @@ -1803,9 +1808,9 @@ class ReadColorControlCurrentHue : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { - return encodeColorControlClusterReadCurrentHueAttribute(buffer->Start(), bufferSize, endPointId); + return encodeColorControlClusterReadCurrentHueAttribute(endPointId); } // Global Response: ReadAttributesResponse @@ -1828,10 +1833,9 @@ class ReportColorControlCurrentHue : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { - return encodeColorControlClusterReportCurrentHueAttribute(buffer->Start(), bufferSize, endPointId, mMinInterval, - mMaxInterval, mChange); + return encodeColorControlClusterReportCurrentHueAttribute(endPointId, mMinInterval, mMaxInterval, mChange); } // Global Response: ConfigureReportingResponse @@ -1859,9 +1863,9 @@ class ReadColorControlCurrentSaturation : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { - return encodeColorControlClusterReadCurrentSaturationAttribute(buffer->Start(), bufferSize, endPointId); + return encodeColorControlClusterReadCurrentSaturationAttribute(endPointId); } // Global Response: ReadAttributesResponse @@ -1884,10 +1888,9 @@ class ReportColorControlCurrentSaturation : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { - return encodeColorControlClusterReportCurrentSaturationAttribute(buffer->Start(), bufferSize, endPointId, mMinInterval, - mMaxInterval, mChange); + return encodeColorControlClusterReportCurrentSaturationAttribute(endPointId, mMinInterval, mMaxInterval, mChange); } // Global Response: ConfigureReportingResponse @@ -1915,9 +1918,9 @@ class ReadColorControlRemainingTime : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { - return encodeColorControlClusterReadRemainingTimeAttribute(buffer->Start(), bufferSize, endPointId); + return encodeColorControlClusterReadRemainingTimeAttribute(endPointId); } // Global Response: ReadAttributesResponse @@ -1940,9 +1943,9 @@ class ReadColorControlCurrentX : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { - return encodeColorControlClusterReadCurrentXAttribute(buffer->Start(), bufferSize, endPointId); + return encodeColorControlClusterReadCurrentXAttribute(endPointId); } // Global Response: ReadAttributesResponse @@ -1965,10 +1968,9 @@ class ReportColorControlCurrentX : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { - return encodeColorControlClusterReportCurrentXAttribute(buffer->Start(), bufferSize, endPointId, mMinInterval, mMaxInterval, - mChange); + return encodeColorControlClusterReportCurrentXAttribute(endPointId, mMinInterval, mMaxInterval, mChange); } // Global Response: ConfigureReportingResponse @@ -1996,9 +1998,9 @@ class ReadColorControlCurrentY : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { - return encodeColorControlClusterReadCurrentYAttribute(buffer->Start(), bufferSize, endPointId); + return encodeColorControlClusterReadCurrentYAttribute(endPointId); } // Global Response: ReadAttributesResponse @@ -2021,10 +2023,9 @@ class ReportColorControlCurrentY : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { - return encodeColorControlClusterReportCurrentYAttribute(buffer->Start(), bufferSize, endPointId, mMinInterval, mMaxInterval, - mChange); + return encodeColorControlClusterReportCurrentYAttribute(endPointId, mMinInterval, mMaxInterval, mChange); } // Global Response: ConfigureReportingResponse @@ -2052,9 +2053,9 @@ class ReadColorControlColorTemperature : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { - return encodeColorControlClusterReadColorTemperatureAttribute(buffer->Start(), bufferSize, endPointId); + return encodeColorControlClusterReadColorTemperatureAttribute(endPointId); } // Global Response: ReadAttributesResponse @@ -2077,10 +2078,9 @@ class ReportColorControlColorTemperature : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { - return encodeColorControlClusterReportColorTemperatureAttribute(buffer->Start(), bufferSize, endPointId, mMinInterval, - mMaxInterval, mChange); + return encodeColorControlClusterReportColorTemperatureAttribute(endPointId, mMinInterval, mMaxInterval, mChange); } // Global Response: ConfigureReportingResponse @@ -2108,9 +2108,9 @@ class ReadColorControlColorMode : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { - return encodeColorControlClusterReadColorModeAttribute(buffer->Start(), bufferSize, endPointId); + return encodeColorControlClusterReadColorModeAttribute(endPointId); } // Global Response: ReadAttributesResponse @@ -2133,9 +2133,9 @@ class ReadColorControlNumberOfPrimaries : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { - return encodeColorControlClusterReadNumberOfPrimariesAttribute(buffer->Start(), bufferSize, endPointId); + return encodeColorControlClusterReadNumberOfPrimariesAttribute(endPointId); } // Global Response: ReadAttributesResponse @@ -2158,9 +2158,9 @@ class ReadColorControlPrimary1X : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { - return encodeColorControlClusterReadPrimary1XAttribute(buffer->Start(), bufferSize, endPointId); + return encodeColorControlClusterReadPrimary1XAttribute(endPointId); } // Global Response: ReadAttributesResponse @@ -2183,9 +2183,9 @@ class ReadColorControlPrimary1Y : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { - return encodeColorControlClusterReadPrimary1YAttribute(buffer->Start(), bufferSize, endPointId); + return encodeColorControlClusterReadPrimary1YAttribute(endPointId); } // Global Response: ReadAttributesResponse @@ -2208,9 +2208,9 @@ class ReadColorControlPrimary1Intensity : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { - return encodeColorControlClusterReadPrimary1IntensityAttribute(buffer->Start(), bufferSize, endPointId); + return encodeColorControlClusterReadPrimary1IntensityAttribute(endPointId); } // Global Response: ReadAttributesResponse @@ -2233,9 +2233,9 @@ class ReadColorControlPrimary2X : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { - return encodeColorControlClusterReadPrimary2XAttribute(buffer->Start(), bufferSize, endPointId); + return encodeColorControlClusterReadPrimary2XAttribute(endPointId); } // Global Response: ReadAttributesResponse @@ -2258,9 +2258,9 @@ class ReadColorControlPrimary2Y : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { - return encodeColorControlClusterReadPrimary2YAttribute(buffer->Start(), bufferSize, endPointId); + return encodeColorControlClusterReadPrimary2YAttribute(endPointId); } // Global Response: ReadAttributesResponse @@ -2283,9 +2283,9 @@ class ReadColorControlPrimary2Intensity : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { - return encodeColorControlClusterReadPrimary2IntensityAttribute(buffer->Start(), bufferSize, endPointId); + return encodeColorControlClusterReadPrimary2IntensityAttribute(endPointId); } // Global Response: ReadAttributesResponse @@ -2308,9 +2308,9 @@ class ReadColorControlPrimary3X : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { - return encodeColorControlClusterReadPrimary3XAttribute(buffer->Start(), bufferSize, endPointId); + return encodeColorControlClusterReadPrimary3XAttribute(endPointId); } // Global Response: ReadAttributesResponse @@ -2333,9 +2333,9 @@ class ReadColorControlPrimary3Y : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { - return encodeColorControlClusterReadPrimary3YAttribute(buffer->Start(), bufferSize, endPointId); + return encodeColorControlClusterReadPrimary3YAttribute(endPointId); } // Global Response: ReadAttributesResponse @@ -2358,9 +2358,9 @@ class ReadColorControlPrimary3Intensity : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { - return encodeColorControlClusterReadPrimary3IntensityAttribute(buffer->Start(), bufferSize, endPointId); + return encodeColorControlClusterReadPrimary3IntensityAttribute(endPointId); } // Global Response: ReadAttributesResponse @@ -2383,9 +2383,9 @@ class ReadColorControlPrimary4X : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { - return encodeColorControlClusterReadPrimary4XAttribute(buffer->Start(), bufferSize, endPointId); + return encodeColorControlClusterReadPrimary4XAttribute(endPointId); } // Global Response: ReadAttributesResponse @@ -2408,9 +2408,9 @@ class ReadColorControlPrimary4Y : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { - return encodeColorControlClusterReadPrimary4YAttribute(buffer->Start(), bufferSize, endPointId); + return encodeColorControlClusterReadPrimary4YAttribute(endPointId); } // Global Response: ReadAttributesResponse @@ -2433,9 +2433,9 @@ class ReadColorControlPrimary4Intensity : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { - return encodeColorControlClusterReadPrimary4IntensityAttribute(buffer->Start(), bufferSize, endPointId); + return encodeColorControlClusterReadPrimary4IntensityAttribute(endPointId); } // Global Response: ReadAttributesResponse @@ -2458,9 +2458,9 @@ class ReadColorControlPrimary5X : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { - return encodeColorControlClusterReadPrimary5XAttribute(buffer->Start(), bufferSize, endPointId); + return encodeColorControlClusterReadPrimary5XAttribute(endPointId); } // Global Response: ReadAttributesResponse @@ -2483,9 +2483,9 @@ class ReadColorControlPrimary5Y : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { - return encodeColorControlClusterReadPrimary5YAttribute(buffer->Start(), bufferSize, endPointId); + return encodeColorControlClusterReadPrimary5YAttribute(endPointId); } // Global Response: ReadAttributesResponse @@ -2508,9 +2508,9 @@ class ReadColorControlPrimary5Intensity : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { - return encodeColorControlClusterReadPrimary5IntensityAttribute(buffer->Start(), bufferSize, endPointId); + return encodeColorControlClusterReadPrimary5IntensityAttribute(endPointId); } // Global Response: ReadAttributesResponse @@ -2533,9 +2533,9 @@ class ReadColorControlPrimary6X : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { - return encodeColorControlClusterReadPrimary6XAttribute(buffer->Start(), bufferSize, endPointId); + return encodeColorControlClusterReadPrimary6XAttribute(endPointId); } // Global Response: ReadAttributesResponse @@ -2558,9 +2558,9 @@ class ReadColorControlPrimary6Y : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { - return encodeColorControlClusterReadPrimary6YAttribute(buffer->Start(), bufferSize, endPointId); + return encodeColorControlClusterReadPrimary6YAttribute(endPointId); } // Global Response: ReadAttributesResponse @@ -2583,9 +2583,9 @@ class ReadColorControlPrimary6Intensity : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { - return encodeColorControlClusterReadPrimary6IntensityAttribute(buffer->Start(), bufferSize, endPointId); + return encodeColorControlClusterReadPrimary6IntensityAttribute(endPointId); } // Global Response: ReadAttributesResponse @@ -2608,9 +2608,9 @@ class ReadColorControlEnhancedCurrentHue : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { - return encodeColorControlClusterReadEnhancedCurrentHueAttribute(buffer->Start(), bufferSize, endPointId); + return encodeColorControlClusterReadEnhancedCurrentHueAttribute(endPointId); } // Global Response: ReadAttributesResponse @@ -2633,9 +2633,9 @@ class ReadColorControlEnhancedColorMode : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { - return encodeColorControlClusterReadEnhancedColorModeAttribute(buffer->Start(), bufferSize, endPointId); + return encodeColorControlClusterReadEnhancedColorModeAttribute(endPointId); } // Global Response: ReadAttributesResponse @@ -2658,9 +2658,9 @@ class ReadColorControlColorLoopActive : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { - return encodeColorControlClusterReadColorLoopActiveAttribute(buffer->Start(), bufferSize, endPointId); + return encodeColorControlClusterReadColorLoopActiveAttribute(endPointId); } // Global Response: ReadAttributesResponse @@ -2683,9 +2683,9 @@ class ReadColorControlColorLoopDirection : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { - return encodeColorControlClusterReadColorLoopDirectionAttribute(buffer->Start(), bufferSize, endPointId); + return encodeColorControlClusterReadColorLoopDirectionAttribute(endPointId); } // Global Response: ReadAttributesResponse @@ -2708,9 +2708,9 @@ class ReadColorControlColorLoopTime : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { - return encodeColorControlClusterReadColorLoopTimeAttribute(buffer->Start(), bufferSize, endPointId); + return encodeColorControlClusterReadColorLoopTimeAttribute(endPointId); } // Global Response: ReadAttributesResponse @@ -2733,9 +2733,9 @@ class ReadColorControlColorCapabilities : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { - return encodeColorControlClusterReadColorCapabilitiesAttribute(buffer->Start(), bufferSize, endPointId); + return encodeColorControlClusterReadColorCapabilitiesAttribute(endPointId); } // Global Response: ReadAttributesResponse @@ -2758,9 +2758,9 @@ class ReadColorControlColorTempPhysicalMin : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { - return encodeColorControlClusterReadColorTempPhysicalMinAttribute(buffer->Start(), bufferSize, endPointId); + return encodeColorControlClusterReadColorTempPhysicalMinAttribute(endPointId); } // Global Response: ReadAttributesResponse @@ -2783,9 +2783,9 @@ class ReadColorControlColorTempPhysicalMax : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { - return encodeColorControlClusterReadColorTempPhysicalMaxAttribute(buffer->Start(), bufferSize, endPointId); + return encodeColorControlClusterReadColorTempPhysicalMaxAttribute(endPointId); } // Global Response: ReadAttributesResponse @@ -2808,9 +2808,9 @@ class ReadColorControlCoupleColorTempToLevelMinMireds : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { - return encodeColorControlClusterReadCoupleColorTempToLevelMinMiredsAttribute(buffer->Start(), bufferSize, endPointId); + return encodeColorControlClusterReadCoupleColorTempToLevelMinMiredsAttribute(endPointId); } // Global Response: ReadAttributesResponse @@ -2833,9 +2833,9 @@ class ReadColorControlStartUpColorTemperatureMireds : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { - return encodeColorControlClusterReadStartUpColorTemperatureMiredsAttribute(buffer->Start(), bufferSize, endPointId); + return encodeColorControlClusterReadStartUpColorTemperatureMiredsAttribute(endPointId); } // Global Response: ReadAttributesResponse @@ -3506,10 +3506,7 @@ class DoorLockClearAllPins : public ModelCommand public: DoorLockClearAllPins() : ModelCommand("clear-all-pins", kDoorLockClusterId, 0x08) { ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override - { - return encodeDoorLockClusterClearAllPinsCommand(buffer->Start(), bufferSize, endPointId); - } + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { return encodeDoorLockClusterClearAllPinsCommand(endPointId); } // Global Response: DefaultResponse bool HandleGlobalResponse(uint8_t commandId, uint8_t * message, uint16_t messageLen) const override @@ -3534,10 +3531,7 @@ class DoorLockClearAllRfids : public ModelCommand public: DoorLockClearAllRfids() : ModelCommand("clear-all-rfids", kDoorLockClusterId, 0x19) { ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override - { - return encodeDoorLockClusterClearAllRfidsCommand(buffer->Start(), bufferSize, endPointId); - } + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { return encodeDoorLockClusterClearAllRfidsCommand(endPointId); } // Global Response: DefaultResponse bool HandleGlobalResponse(uint8_t commandId, uint8_t * message, uint16_t messageLen) const override @@ -3566,9 +3560,9 @@ class DoorLockClearHolidaySchedule : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { - return encodeDoorLockClusterClearHolidayScheduleCommand(buffer->Start(), bufferSize, endPointId, mHolidayScheduleID); + return encodeDoorLockClusterClearHolidayScheduleCommand(endPointId, mHolidayScheduleID); } // Global Response: DefaultResponse @@ -3601,9 +3595,9 @@ class DoorLockClearPin : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { - return encodeDoorLockClusterClearPinCommand(buffer->Start(), bufferSize, endPointId, mUserID); + return encodeDoorLockClusterClearPinCommand(endPointId, mUserID); } // Global Response: DefaultResponse @@ -3636,9 +3630,9 @@ class DoorLockClearRfid : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { - return encodeDoorLockClusterClearRfidCommand(buffer->Start(), bufferSize, endPointId, mUserID); + return encodeDoorLockClusterClearRfidCommand(endPointId, mUserID); } // Global Response: DefaultResponse @@ -3672,9 +3666,9 @@ class DoorLockClearWeekdaySchedule : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { - return encodeDoorLockClusterClearWeekdayScheduleCommand(buffer->Start(), bufferSize, endPointId, mScheduleID, mUserID); + return encodeDoorLockClusterClearWeekdayScheduleCommand(endPointId, mScheduleID, mUserID); } // Global Response: DefaultResponse @@ -3709,9 +3703,9 @@ class DoorLockClearYeardaySchedule : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { - return encodeDoorLockClusterClearYeardayScheduleCommand(buffer->Start(), bufferSize, endPointId, mScheduleID, mUserID); + return encodeDoorLockClusterClearYeardayScheduleCommand(endPointId, mScheduleID, mUserID); } // Global Response: DefaultResponse @@ -3745,9 +3739,9 @@ class DoorLockGetHolidaySchedule : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { - return encodeDoorLockClusterGetHolidayScheduleCommand(buffer->Start(), bufferSize, endPointId, mHolidayScheduleID); + return encodeDoorLockClusterGetHolidayScheduleCommand(endPointId, mHolidayScheduleID); } // Global Response: DefaultResponse @@ -3780,9 +3774,9 @@ class DoorLockGetPin : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { - return encodeDoorLockClusterGetPinCommand(buffer->Start(), bufferSize, endPointId, mUserID); + return encodeDoorLockClusterGetPinCommand(endPointId, mUserID); } // Global Response: DefaultResponse @@ -3815,9 +3809,9 @@ class DoorLockGetRfid : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { - return encodeDoorLockClusterGetRfidCommand(buffer->Start(), bufferSize, endPointId, mUserID); + return encodeDoorLockClusterGetRfidCommand(endPointId, mUserID); } // Global Response: DefaultResponse @@ -3850,9 +3844,9 @@ class DoorLockGetUserType : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { - return encodeDoorLockClusterGetUserTypeCommand(buffer->Start(), bufferSize, endPointId, mUserID); + return encodeDoorLockClusterGetUserTypeCommand(endPointId, mUserID); } // Global Response: DefaultResponse @@ -3886,9 +3880,9 @@ class DoorLockGetWeekdaySchedule : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { - return encodeDoorLockClusterGetWeekdayScheduleCommand(buffer->Start(), bufferSize, endPointId, mScheduleID, mUserID); + return encodeDoorLockClusterGetWeekdayScheduleCommand(endPointId, mScheduleID, mUserID); } // Global Response: DefaultResponse @@ -3923,9 +3917,9 @@ class DoorLockGetYeardaySchedule : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { - return encodeDoorLockClusterGetYeardayScheduleCommand(buffer->Start(), bufferSize, endPointId, mScheduleID, mUserID); + return encodeDoorLockClusterGetYeardayScheduleCommand(endPointId, mScheduleID, mUserID); } // Global Response: DefaultResponse @@ -3959,9 +3953,9 @@ class DoorLockLockDoor : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { - return encodeDoorLockClusterLockDoorCommand(buffer->Start(), bufferSize, endPointId, mPINOrRFIDCode); + return encodeDoorLockClusterLockDoorCommand(endPointId, mPINOrRFIDCode); } // Global Response: DefaultResponse @@ -3997,10 +3991,10 @@ class DoorLockSetHolidaySchedule : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { - return encodeDoorLockClusterSetHolidayScheduleCommand(buffer->Start(), bufferSize, endPointId, mHolidayScheduleID, - mLocalStartTime, mLocalEndTime, mOperatingModeDuringHoliday); + return encodeDoorLockClusterSetHolidayScheduleCommand(endPointId, mHolidayScheduleID, mLocalStartTime, mLocalEndTime, + mOperatingModeDuringHoliday); } // Global Response: DefaultResponse @@ -4039,9 +4033,9 @@ class DoorLockSetPin : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { - return encodeDoorLockClusterSetPinCommand(buffer->Start(), bufferSize, endPointId, mUserID, mUserStatus, mUserType, mPIN); + return encodeDoorLockClusterSetPinCommand(endPointId, mUserID, mUserStatus, mUserType, mPIN); } // Global Response: DefaultResponse @@ -4080,9 +4074,9 @@ class DoorLockSetRfid : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { - return encodeDoorLockClusterSetRfidCommand(buffer->Start(), bufferSize, endPointId, mUserID, mUserStatus, mUserType, mRFID); + return encodeDoorLockClusterSetRfidCommand(endPointId, mUserID, mUserStatus, mUserType, mRFID); } // Global Response: DefaultResponse @@ -4119,9 +4113,9 @@ class DoorLockSetUserType : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { - return encodeDoorLockClusterSetUserTypeCommand(buffer->Start(), bufferSize, endPointId, mUserID, mUserType); + return encodeDoorLockClusterSetUserTypeCommand(endPointId, mUserID, mUserType); } // Global Response: DefaultResponse @@ -4161,10 +4155,10 @@ class DoorLockSetWeekdaySchedule : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { - return encodeDoorLockClusterSetWeekdayScheduleCommand(buffer->Start(), bufferSize, endPointId, mScheduleID, mUserID, - mDaysMask, mStartHour, mStartMinute, mEndHour, mEndMinute); + return encodeDoorLockClusterSetWeekdayScheduleCommand(endPointId, mScheduleID, mUserID, mDaysMask, mStartHour, mStartMinute, + mEndHour, mEndMinute); } // Global Response: DefaultResponse @@ -4206,10 +4200,9 @@ class DoorLockSetYeardaySchedule : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { - return encodeDoorLockClusterSetYeardayScheduleCommand(buffer->Start(), bufferSize, endPointId, mScheduleID, mUserID, - mLocalStartTime, mLocalEndTime); + return encodeDoorLockClusterSetYeardayScheduleCommand(endPointId, mScheduleID, mUserID, mLocalStartTime, mLocalEndTime); } // Global Response: DefaultResponse @@ -4245,9 +4238,9 @@ class DoorLockUnlockDoor : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { - return encodeDoorLockClusterUnlockDoorCommand(buffer->Start(), bufferSize, endPointId, mPINOrRFIDCode); + return encodeDoorLockClusterUnlockDoorCommand(endPointId, mPINOrRFIDCode); } // Global Response: DefaultResponse @@ -4281,10 +4274,9 @@ class DoorLockUnlockWithTimeout : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { - return encodeDoorLockClusterUnlockWithTimeoutCommand(buffer->Start(), bufferSize, endPointId, mTimeoutInSeconds, - mPINOrRFIDCode); + return encodeDoorLockClusterUnlockWithTimeoutCommand(endPointId, mTimeoutInSeconds, mPINOrRFIDCode); } // Global Response: DefaultResponse @@ -4314,10 +4306,7 @@ class DiscoverDoorLockAttributes : public ModelCommand public: DiscoverDoorLockAttributes() : ModelCommand("discover", kDoorLockClusterId, 0x0c) { ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override - { - return encodeDoorLockClusterDiscoverAttributes(buffer->Start(), bufferSize, endPointId); - } + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { return encodeDoorLockClusterDiscoverAttributes(endPointId); } // Global Response: DiscoverAttributesResponse bool HandleGlobalResponse(uint8_t commandId, uint8_t * message, uint16_t messageLen) const override @@ -4339,9 +4328,9 @@ class ReadDoorLockLockState : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { - return encodeDoorLockClusterReadLockStateAttribute(buffer->Start(), bufferSize, endPointId); + return encodeDoorLockClusterReadLockStateAttribute(endPointId); } // Global Response: ReadAttributesResponse @@ -4363,9 +4352,9 @@ class ReportDoorLockLockState : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { - return encodeDoorLockClusterReportLockStateAttribute(buffer->Start(), bufferSize, endPointId, mMinInterval, mMaxInterval); + return encodeDoorLockClusterReportLockStateAttribute(endPointId, mMinInterval, mMaxInterval); } // Global Response: ConfigureReportingResponse @@ -4392,10 +4381,7 @@ class ReadDoorLockLockType : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override - { - return encodeDoorLockClusterReadLockTypeAttribute(buffer->Start(), bufferSize, endPointId); - } + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { return encodeDoorLockClusterReadLockTypeAttribute(endPointId); } // Global Response: ReadAttributesResponse bool HandleGlobalResponse(uint8_t commandId, uint8_t * message, uint16_t messageLen) const override @@ -4417,9 +4403,9 @@ class ReadDoorLockActuatorEnabled : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { - return encodeDoorLockClusterReadActuatorEnabledAttribute(buffer->Start(), bufferSize, endPointId); + return encodeDoorLockClusterReadActuatorEnabledAttribute(endPointId); } // Global Response: ReadAttributesResponse @@ -4584,9 +4570,9 @@ class GroupsAddGroup : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { - return encodeGroupsClusterAddGroupCommand(buffer->Start(), bufferSize, endPointId, mGroupId, mGroupName); + return encodeGroupsClusterAddGroupCommand(endPointId, mGroupId, mGroupName); } // Global Response: DefaultResponse @@ -4621,9 +4607,9 @@ class GroupsAddGroupIfIdentifying : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { - return encodeGroupsClusterAddGroupIfIdentifyingCommand(buffer->Start(), bufferSize, endPointId, mGroupId, mGroupName); + return encodeGroupsClusterAddGroupIfIdentifyingCommand(endPointId, mGroupId, mGroupName); } // Global Response: DefaultResponse @@ -4653,9 +4639,9 @@ class GroupsGetGroupMembership : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { - return encodeGroupsClusterGetGroupMembershipCommand(buffer->Start(), bufferSize, endPointId, mGroupCount, mGroupList); + return encodeGroupsClusterGetGroupMembershipCommand(endPointId, mGroupCount, mGroupList); } // Global Response: DefaultResponse @@ -4685,10 +4671,7 @@ class GroupsRemoveAllGroups : public ModelCommand public: GroupsRemoveAllGroups() : ModelCommand("remove-all-groups", kGroupsClusterId, 0x04) { ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override - { - return encodeGroupsClusterRemoveAllGroupsCommand(buffer->Start(), bufferSize, endPointId); - } + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { return encodeGroupsClusterRemoveAllGroupsCommand(endPointId); } // Global Response: DefaultResponse bool HandleGlobalResponse(uint8_t commandId, uint8_t * message, uint16_t messageLen) const override @@ -4710,9 +4693,9 @@ class GroupsRemoveGroup : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { - return encodeGroupsClusterRemoveGroupCommand(buffer->Start(), bufferSize, endPointId, mGroupId); + return encodeGroupsClusterRemoveGroupCommand(endPointId, mGroupId); } // Global Response: DefaultResponse @@ -4745,9 +4728,9 @@ class GroupsViewGroup : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { - return encodeGroupsClusterViewGroupCommand(buffer->Start(), bufferSize, endPointId, mGroupId); + return encodeGroupsClusterViewGroupCommand(endPointId, mGroupId); } // Global Response: DefaultResponse @@ -4776,10 +4759,7 @@ class DiscoverGroupsAttributes : public ModelCommand public: DiscoverGroupsAttributes() : ModelCommand("discover", kGroupsClusterId, 0x0c) { ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override - { - return encodeGroupsClusterDiscoverAttributes(buffer->Start(), bufferSize, endPointId); - } + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { return encodeGroupsClusterDiscoverAttributes(endPointId); } // Global Response: DiscoverAttributesResponse bool HandleGlobalResponse(uint8_t commandId, uint8_t * message, uint16_t messageLen) const override @@ -4801,9 +4781,9 @@ class ReadGroupsNameSupport : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { - return encodeGroupsClusterReadNameSupportAttribute(buffer->Start(), bufferSize, endPointId); + return encodeGroupsClusterReadNameSupportAttribute(endPointId); } // Global Response: ReadAttributesResponse @@ -4838,10 +4818,7 @@ class DiscoverIasZoneAttributes : public ModelCommand public: DiscoverIasZoneAttributes() : ModelCommand("discover", kIasZoneClusterId, 0x0c) { ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override - { - return encodeIasZoneClusterDiscoverAttributes(buffer->Start(), bufferSize, endPointId); - } + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { return encodeIasZoneClusterDiscoverAttributes(endPointId); } // Global Response: DiscoverAttributesResponse bool HandleGlobalResponse(uint8_t commandId, uint8_t * message, uint16_t messageLen) const override @@ -4863,10 +4840,7 @@ class ReadIasZoneZoneState : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override - { - return encodeIasZoneClusterReadZoneStateAttribute(buffer->Start(), bufferSize, endPointId); - } + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { return encodeIasZoneClusterReadZoneStateAttribute(endPointId); } // Global Response: ReadAttributesResponse bool HandleGlobalResponse(uint8_t commandId, uint8_t * message, uint16_t messageLen) const override @@ -4888,10 +4862,7 @@ class ReadIasZoneZoneType : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override - { - return encodeIasZoneClusterReadZoneTypeAttribute(buffer->Start(), bufferSize, endPointId); - } + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { return encodeIasZoneClusterReadZoneTypeAttribute(endPointId); } // Global Response: ReadAttributesResponse bool HandleGlobalResponse(uint8_t commandId, uint8_t * message, uint16_t messageLen) const override @@ -4913,9 +4884,9 @@ class ReadIasZoneZoneStatus : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { - return encodeIasZoneClusterReadZoneStatusAttribute(buffer->Start(), bufferSize, endPointId); + return encodeIasZoneClusterReadZoneStatusAttribute(endPointId); } // Global Response: ReadAttributesResponse @@ -4938,9 +4909,9 @@ class ReadIasZoneIasCieAddress : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { - return encodeIasZoneClusterReadIasCieAddressAttribute(buffer->Start(), bufferSize, endPointId); + return encodeIasZoneClusterReadIasCieAddressAttribute(endPointId); } // Global Response: ReadAttributesResponse @@ -4961,9 +4932,9 @@ class WriteIasZoneIasCieAddress : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { - return encodeIasZoneClusterWriteIasCieAddressAttribute(buffer->Start(), bufferSize, endPointId, mIasCieAddress); + return encodeIasZoneClusterWriteIasCieAddressAttribute(endPointId, mIasCieAddress); } // Global Response: WriteAttributesResponse @@ -4989,10 +4960,7 @@ class ReadIasZoneZoneID : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override - { - return encodeIasZoneClusterReadZoneIdAttribute(buffer->Start(), bufferSize, endPointId); - } + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { return encodeIasZoneClusterReadZoneIdAttribute(endPointId); } // Global Response: ReadAttributesResponse bool HandleGlobalResponse(uint8_t commandId, uint8_t * message, uint16_t messageLen) const override @@ -5050,9 +5018,9 @@ class IdentifyIdentify : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { - return encodeIdentifyClusterIdentifyCommand(buffer->Start(), bufferSize, endPointId, mIdentifyTime); + return encodeIdentifyClusterIdentifyCommand(endPointId, mIdentifyTime); } // Global Response: DefaultResponse @@ -5074,10 +5042,7 @@ class IdentifyIdentifyQuery : public ModelCommand public: IdentifyIdentifyQuery() : ModelCommand("identify-query", kIdentifyClusterId, 0x01) { ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override - { - return encodeIdentifyClusterIdentifyQueryCommand(buffer->Start(), bufferSize, endPointId); - } + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { return encodeIdentifyClusterIdentifyQueryCommand(endPointId); } // Global Response: DefaultResponse bool HandleGlobalResponse(uint8_t commandId, uint8_t * message, uint16_t messageLen) const override @@ -5102,10 +5067,7 @@ class DiscoverIdentifyAttributes : public ModelCommand public: DiscoverIdentifyAttributes() : ModelCommand("discover", kIdentifyClusterId, 0x0c) { ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override - { - return encodeIdentifyClusterDiscoverAttributes(buffer->Start(), bufferSize, endPointId); - } + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { return encodeIdentifyClusterDiscoverAttributes(endPointId); } // Global Response: DiscoverAttributesResponse bool HandleGlobalResponse(uint8_t commandId, uint8_t * message, uint16_t messageLen) const override @@ -5127,9 +5089,9 @@ class ReadIdentifyIdentifyTime : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { - return encodeIdentifyClusterReadIdentifyTimeAttribute(buffer->Start(), bufferSize, endPointId); + return encodeIdentifyClusterReadIdentifyTimeAttribute(endPointId); } // Global Response: ReadAttributesResponse @@ -5175,10 +5137,9 @@ class LevelMove : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { - return encodeLevelControlClusterMoveCommand(buffer->Start(), bufferSize, endPointId, mMoveMode, mRate, mOptionsMask, - mOptionsOverride); + return encodeLevelControlClusterMoveCommand(endPointId, mMoveMode, mRate, mOptionsMask, mOptionsOverride); } // Global Response: DefaultResponse @@ -5210,10 +5171,9 @@ class LevelMoveToLevel : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { - return encodeLevelControlClusterMoveToLevelCommand(buffer->Start(), bufferSize, endPointId, mLevel, mTransitionTime, - mOptionsMask, mOptionsOverride); + return encodeLevelControlClusterMoveToLevelCommand(endPointId, mLevel, mTransitionTime, mOptionsMask, mOptionsOverride); } // Global Response: DefaultResponse @@ -5243,10 +5203,9 @@ class LevelMoveToLevelWithOnOff : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { - return encodeLevelControlClusterMoveToLevelWithOnOffCommand(buffer->Start(), bufferSize, endPointId, mLevel, - mTransitionTime); + return encodeLevelControlClusterMoveToLevelWithOnOffCommand(endPointId, mLevel, mTransitionTime); } // Global Response: DefaultResponse @@ -5274,9 +5233,9 @@ class LevelMoveWithOnOff : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { - return encodeLevelControlClusterMoveWithOnOffCommand(buffer->Start(), bufferSize, endPointId, mMoveMode, mRate); + return encodeLevelControlClusterMoveWithOnOffCommand(endPointId, mMoveMode, mRate); } // Global Response: DefaultResponse @@ -5307,10 +5266,10 @@ class LevelStep : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { - return encodeLevelControlClusterStepCommand(buffer->Start(), bufferSize, endPointId, mStepMode, mStepSize, mTransitionTime, - mOptionsMask, mOptionsOverride); + return encodeLevelControlClusterStepCommand(endPointId, mStepMode, mStepSize, mTransitionTime, mOptionsMask, + mOptionsOverride); } // Global Response: DefaultResponse @@ -5342,10 +5301,9 @@ class LevelStepWithOnOff : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { - return encodeLevelControlClusterStepWithOnOffCommand(buffer->Start(), bufferSize, endPointId, mStepMode, mStepSize, - mTransitionTime); + return encodeLevelControlClusterStepWithOnOffCommand(endPointId, mStepMode, mStepSize, mTransitionTime); } // Global Response: DefaultResponse @@ -5374,9 +5332,9 @@ class LevelStop : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { - return encodeLevelControlClusterStopCommand(buffer->Start(), bufferSize, endPointId, mOptionsMask, mOptionsOverride); + return encodeLevelControlClusterStopCommand(endPointId, mOptionsMask, mOptionsOverride); } // Global Response: DefaultResponse @@ -5399,9 +5357,9 @@ class LevelStopWithOnOff : public ModelCommand public: LevelStopWithOnOff() : ModelCommand("stop-with-on-off", kLevelClusterId, 0x07) { ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { - return encodeLevelControlClusterStopWithOnOffCommand(buffer->Start(), bufferSize, endPointId); + return encodeLevelControlClusterStopWithOnOffCommand(endPointId); } // Global Response: DefaultResponse @@ -5420,9 +5378,9 @@ class DiscoverLevelAttributes : public ModelCommand public: DiscoverLevelAttributes() : ModelCommand("discover", kLevelClusterId, 0x0c) { ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { - return encodeLevelControlClusterDiscoverAttributes(buffer->Start(), bufferSize, endPointId); + return encodeLevelControlClusterDiscoverAttributes(endPointId); } // Global Response: DiscoverAttributesResponse @@ -5445,9 +5403,9 @@ class ReadLevelCurrentLevel : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { - return encodeLevelControlClusterReadCurrentLevelAttribute(buffer->Start(), bufferSize, endPointId); + return encodeLevelControlClusterReadCurrentLevelAttribute(endPointId); } // Global Response: ReadAttributesResponse @@ -5470,10 +5428,9 @@ class ReportLevelCurrentLevel : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { - return encodeLevelControlClusterReportCurrentLevelAttribute(buffer->Start(), bufferSize, endPointId, mMinInterval, - mMaxInterval, mChange); + return encodeLevelControlClusterReportCurrentLevelAttribute(endPointId, mMinInterval, mMaxInterval, mChange); } // Global Response: ConfigureReportingResponse @@ -5512,10 +5469,7 @@ class OnOffOff : public ModelCommand public: OnOffOff() : ModelCommand("off", kOnOffClusterId, 0x00) { ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override - { - return encodeOnOffClusterOffCommand(buffer->Start(), bufferSize, endPointId); - } + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { return encodeOnOffClusterOffCommand(endPointId); } // Global Response: DefaultResponse bool HandleGlobalResponse(uint8_t commandId, uint8_t * message, uint16_t messageLen) const override @@ -5533,10 +5487,7 @@ class OnOffOn : public ModelCommand public: OnOffOn() : ModelCommand("on", kOnOffClusterId, 0x01) { ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override - { - return encodeOnOffClusterOnCommand(buffer->Start(), bufferSize, endPointId); - } + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { return encodeOnOffClusterOnCommand(endPointId); } // Global Response: DefaultResponse bool HandleGlobalResponse(uint8_t commandId, uint8_t * message, uint16_t messageLen) const override @@ -5554,10 +5505,7 @@ class OnOffToggle : public ModelCommand public: OnOffToggle() : ModelCommand("toggle", kOnOffClusterId, 0x02) { ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override - { - return encodeOnOffClusterToggleCommand(buffer->Start(), bufferSize, endPointId); - } + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { return encodeOnOffClusterToggleCommand(endPointId); } // Global Response: DefaultResponse bool HandleGlobalResponse(uint8_t commandId, uint8_t * message, uint16_t messageLen) const override @@ -5575,10 +5523,7 @@ class DiscoverOnOffAttributes : public ModelCommand public: DiscoverOnOffAttributes() : ModelCommand("discover", kOnOffClusterId, 0x0c) { ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override - { - return encodeOnOffClusterDiscoverAttributes(buffer->Start(), bufferSize, endPointId); - } + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { return encodeOnOffClusterDiscoverAttributes(endPointId); } // Global Response: DiscoverAttributesResponse bool HandleGlobalResponse(uint8_t commandId, uint8_t * message, uint16_t messageLen) const override @@ -5600,10 +5545,7 @@ class ReadOnOffOnOff : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override - { - return encodeOnOffClusterReadOnOffAttribute(buffer->Start(), bufferSize, endPointId); - } + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { return encodeOnOffClusterReadOnOffAttribute(endPointId); } // Global Response: ReadAttributesResponse bool HandleGlobalResponse(uint8_t commandId, uint8_t * message, uint16_t messageLen) const override @@ -5624,9 +5566,9 @@ class ReportOnOffOnOff : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { - return encodeOnOffClusterReportOnOffAttribute(buffer->Start(), bufferSize, endPointId, mMinInterval, mMaxInterval); + return encodeOnOffClusterReportOnOffAttribute(endPointId, mMinInterval, mMaxInterval); } // Global Response: ConfigureReportingResponse @@ -5902,10 +5844,10 @@ class ScenesAddScene : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { - return encodeScenesClusterAddSceneCommand(buffer->Start(), bufferSize, endPointId, mGroupID, mSceneID, mTransitionTime, - mSceneName, mClusterId, mLength, mValue); + return encodeScenesClusterAddSceneCommand(endPointId, mGroupID, mSceneID, mTransitionTime, mSceneName, mClusterId, mLength, + mValue); } // Global Response: DefaultResponse @@ -5944,9 +5886,9 @@ class ScenesGetSceneMembership : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { - return encodeScenesClusterGetSceneMembershipCommand(buffer->Start(), bufferSize, endPointId, mGroupID); + return encodeScenesClusterGetSceneMembershipCommand(endPointId, mGroupID); } // Global Response: DefaultResponse @@ -5981,9 +5923,9 @@ class ScenesRecallScene : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { - return encodeScenesClusterRecallSceneCommand(buffer->Start(), bufferSize, endPointId, mGroupID, mSceneID, mTransitionTime); + return encodeScenesClusterRecallSceneCommand(endPointId, mGroupID, mSceneID, mTransitionTime); } // Global Response: DefaultResponse @@ -6011,9 +5953,9 @@ class ScenesRemoveAllScenes : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { - return encodeScenesClusterRemoveAllScenesCommand(buffer->Start(), bufferSize, endPointId, mGroupID); + return encodeScenesClusterRemoveAllScenesCommand(endPointId, mGroupID); } // Global Response: DefaultResponse @@ -6047,9 +5989,9 @@ class ScenesRemoveScene : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { - return encodeScenesClusterRemoveSceneCommand(buffer->Start(), bufferSize, endPointId, mGroupID, mSceneID); + return encodeScenesClusterRemoveSceneCommand(endPointId, mGroupID, mSceneID); } // Global Response: DefaultResponse @@ -6084,9 +6026,9 @@ class ScenesStoreScene : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { - return encodeScenesClusterStoreSceneCommand(buffer->Start(), bufferSize, endPointId, mGroupID, mSceneID); + return encodeScenesClusterStoreSceneCommand(endPointId, mGroupID, mSceneID); } // Global Response: DefaultResponse @@ -6121,9 +6063,9 @@ class ScenesViewScene : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { - return encodeScenesClusterViewSceneCommand(buffer->Start(), bufferSize, endPointId, mGroupID, mSceneID); + return encodeScenesClusterViewSceneCommand(endPointId, mGroupID, mSceneID); } // Global Response: DefaultResponse @@ -6153,10 +6095,7 @@ class DiscoverScenesAttributes : public ModelCommand public: DiscoverScenesAttributes() : ModelCommand("discover", kScenesClusterId, 0x0c) { ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override - { - return encodeScenesClusterDiscoverAttributes(buffer->Start(), bufferSize, endPointId); - } + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { return encodeScenesClusterDiscoverAttributes(endPointId); } // Global Response: DiscoverAttributesResponse bool HandleGlobalResponse(uint8_t commandId, uint8_t * message, uint16_t messageLen) const override @@ -6178,10 +6117,7 @@ class ReadScenesSceneCount : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override - { - return encodeScenesClusterReadSceneCountAttribute(buffer->Start(), bufferSize, endPointId); - } + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { return encodeScenesClusterReadSceneCountAttribute(endPointId); } // Global Response: ReadAttributesResponse bool HandleGlobalResponse(uint8_t commandId, uint8_t * message, uint16_t messageLen) const override @@ -6203,9 +6139,9 @@ class ReadScenesCurrentScene : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { - return encodeScenesClusterReadCurrentSceneAttribute(buffer->Start(), bufferSize, endPointId); + return encodeScenesClusterReadCurrentSceneAttribute(endPointId); } // Global Response: ReadAttributesResponse @@ -6228,9 +6164,9 @@ class ReadScenesCurrentGroup : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { - return encodeScenesClusterReadCurrentGroupAttribute(buffer->Start(), bufferSize, endPointId); + return encodeScenesClusterReadCurrentGroupAttribute(endPointId); } // Global Response: ReadAttributesResponse @@ -6253,10 +6189,7 @@ class ReadScenesSceneValid : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override - { - return encodeScenesClusterReadSceneValidAttribute(buffer->Start(), bufferSize, endPointId); - } + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { return encodeScenesClusterReadSceneValidAttribute(endPointId); } // Global Response: ReadAttributesResponse bool HandleGlobalResponse(uint8_t commandId, uint8_t * message, uint16_t messageLen) const override @@ -6278,9 +6211,9 @@ class ReadScenesNameSupport : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { - return encodeScenesClusterReadNameSupportAttribute(buffer->Start(), bufferSize, endPointId); + return encodeScenesClusterReadNameSupportAttribute(endPointId); } // Global Response: ReadAttributesResponse @@ -6316,9 +6249,9 @@ class DiscoverTemperatureMeasurementAttributes : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { - return encodeTemperatureMeasurementClusterDiscoverAttributes(buffer->Start(), bufferSize, endPointId); + return encodeTemperatureMeasurementClusterDiscoverAttributes(endPointId); } // Global Response: DiscoverAttributesResponse @@ -6341,9 +6274,9 @@ class ReadTemperatureMeasurementMeasuredValue : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { - return encodeTemperatureMeasurementClusterReadMeasuredValueAttribute(buffer->Start(), bufferSize, endPointId); + return encodeTemperatureMeasurementClusterReadMeasuredValueAttribute(endPointId); } // Global Response: ReadAttributesResponse @@ -6366,10 +6299,9 @@ class ReportTemperatureMeasurementMeasuredValue : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { - return encodeTemperatureMeasurementClusterReportMeasuredValueAttribute(buffer->Start(), bufferSize, endPointId, - mMinInterval, mMaxInterval, mChange); + return encodeTemperatureMeasurementClusterReportMeasuredValueAttribute(endPointId, mMinInterval, mMaxInterval, mChange); } // Global Response: ConfigureReportingResponse @@ -6397,9 +6329,9 @@ class ReadTemperatureMeasurementMinMeasuredValue : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { - return encodeTemperatureMeasurementClusterReadMinMeasuredValueAttribute(buffer->Start(), bufferSize, endPointId); + return encodeTemperatureMeasurementClusterReadMinMeasuredValueAttribute(endPointId); } // Global Response: ReadAttributesResponse @@ -6422,9 +6354,9 @@ class ReadTemperatureMeasurementMaxMeasuredValue : public ModelCommand ModelCommand::AddArguments(); } - uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) override + PacketBufferHandle EncodeCommand(uint8_t endPointId) override { - return encodeTemperatureMeasurementClusterReadMaxMeasuredValueAttribute(buffer->Start(), bufferSize, endPointId); + return encodeTemperatureMeasurementClusterReadMaxMeasuredValueAttribute(endPointId); } // Global Response: ReadAttributesResponse @@ -6457,10 +6389,8 @@ void registerClusterBasic(Commands & commands) const char * clusterName = "Basic"; commands_list clusterCommands = { - make_unique(), - make_unique(), - make_unique(), - make_unique(), + make_unique(), make_unique(), make_unique(), + make_unique(), make_unique(), }; commands.Register(clusterName, clusterCommands); diff --git a/examples/chip-tool/commands/clusters/ModelCommand.cpp b/examples/chip-tool/commands/clusters/ModelCommand.cpp index 5d3bf097f2a901..62924704082824 100644 --- a/examples/chip-tool/commands/clusters/ModelCommand.cpp +++ b/examples/chip-tool/commands/clusters/ModelCommand.cpp @@ -21,34 +21,94 @@ using namespace ::chip; namespace { -constexpr uint8_t kZCLGlobalCmdFrameControlHeader = 8; -constexpr uint8_t kZCLClusterCmdFrameControlHeader = 9; +constexpr uint16_t kWaitDurationInSeconds = 10; +constexpr uint8_t kZCLGlobalCmdFrameControlHeader = 8; +constexpr uint8_t kZCLClusterCmdFrameControlHeader = 9; +constexpr uint8_t kZCLGlobalMfgSpecificCmdFrameControlHeader = 12; bool isValidFrame(uint8_t frameControl) { // Bit 3 of the frame control byte set means direction is server to client. - return (frameControl == kZCLGlobalCmdFrameControlHeader || frameControl == kZCLClusterCmdFrameControlHeader); + return (frameControl == kZCLGlobalCmdFrameControlHeader || frameControl == kZCLClusterCmdFrameControlHeader || + kZCLGlobalMfgSpecificCmdFrameControlHeader); } bool isGlobalCommand(uint8_t frameControl) { - return (frameControl == kZCLGlobalCmdFrameControlHeader); + return (frameControl == kZCLGlobalCmdFrameControlHeader || frameControl == kZCLGlobalMfgSpecificCmdFrameControlHeader); } } // namespace -uint16_t ModelCommand::Encode(PacketBufferHandle & buffer, uint16_t bufferSize) +CHIP_ERROR ModelCommand::Run(PersistentStorage & storage, NodeId localId, NodeId remoteId) { + CHIP_ERROR err = CHIP_NO_ERROR; + + err = mCommissioner.SetUdpListenPort(storage.GetListenPort()); + VerifyOrExit(err == CHIP_NO_ERROR, ChipLogError(Controller, "Init failure! Commissioner: %s", chip::ErrorStr(err))); + + err = mCommissioner.Init(localId, &storage); + VerifyOrExit(err == CHIP_NO_ERROR, ChipLogError(Controller, "Init failure! Commissioner: %s", chip::ErrorStr(err))); + + err = mCommissioner.ServiceEvents(); + VerifyOrExit(err == CHIP_NO_ERROR, ChipLogError(Controller, "Init failure! Run Loop: %s", chip::ErrorStr(err))); + + err = RunInternal(remoteId); + SuccessOrExit(err); + + VerifyOrExit(GetCommandExitStatus(), err = CHIP_ERROR_INTERNAL); + +exit: + mCommissioner.ServiceEventSignal(); + mCommissioner.Shutdown(); + return err; +} + +CHIP_ERROR ModelCommand::RunInternal(NodeId remoteId) +{ + ChipDevice * device; + CHIP_ERROR err = mCommissioner.GetDevice(remoteId, &device); + VerifyOrExit(err == CHIP_NO_ERROR, ChipLogError(chipTool, "Could not find a paired device. Are you sure it has been paired ?")); + + device->SetDelegate(this); + + err = RunCommandInternal(device); + SuccessOrExit(err); + + UpdateWaitForResponse(true); + WaitForResponse(kWaitDurationInSeconds); + +exit: + return err; +} + +CHIP_ERROR ModelCommand::RunCommandInternal(ChipDevice * device) +{ + CHIP_ERROR err = CHIP_NO_ERROR; ChipLogProgress(chipTool, "Endpoint id: '0x%02x', Cluster id: '0x%04x', Command id: '0x%02x'", mEndPointId, mClusterId, mCommandId); - return EncodeCommand(buffer, bufferSize, mEndPointId); + PacketBufferHandle buffer = EncodeCommand(mEndPointId); + VerifyOrExit(!buffer.IsNull(), err = CHIP_ERROR_INTERNAL); + +#ifdef DEBUG + PrintBuffer(buffer); +#endif + + err = device->SendMessage(std::move(buffer)); + VerifyOrExit(err == CHIP_NO_ERROR, ChipLogError(chipTool, "Failed to send message: %s", ErrorStr(err))); + +exit: + return err; } -bool ModelCommand::Decode(PacketBufferHandle & buffer) const +void ModelCommand::OnMessage(PacketBufferHandle buffer) { + ChipLogDetail(chipTool, "OnMessage: Received %zu bytes", buffer->DataLength()); + EmberApsFrame frame; uint8_t * message; uint16_t messageLen; + uint16_t mfgCode; uint8_t frameControl; uint8_t sequenceNumber; uint8_t commandId; @@ -62,9 +122,17 @@ bool ModelCommand::Decode(PacketBufferHandle & buffer) const ChipLogDetail(chipTool, "APS frame processing success!"); messageLen = extractMessage(buffer->Start(), buffer->DataLength(), &message); - VerifyOrExit(messageLen >= 3, ChipLogError(chipTool, "Unexpected response length: %d", messageLen)); + VerifyOrExit(messageLen >= 1, ChipLogError(chipTool, "Unexpected response length: %d", messageLen)); - frameControl = chip::Encoding::Read8(message); + frameControl = chip::Encoding::Read8(message); + if (frameControl & (1u << 2)) + { + VerifyOrExit(messageLen >= 5, ChipLogError(chipTool, "Unexpected response length: %d", messageLen)); + mfgCode = chip::Encoding::LittleEndian::Read16(message); + ChipLogDetail(chipTool, "Manufacturer specific code in response: 0x%04x", mfgCode); + messageLen = static_cast(messageLen - 2); + } + VerifyOrExit(messageLen >= 3, ChipLogError(chipTool, "Unexpected response length: %d", messageLen)); sequenceNumber = chip::Encoding::Read8(message); commandId = chip::Encoding::Read8(message); messageLen = static_cast(messageLen - 3); @@ -77,7 +145,24 @@ bool ModelCommand::Decode(PacketBufferHandle & buffer) const success = isGlobalCommand(frameControl) ? HandleGlobalResponse(commandId, message, messageLen) : HandleSpecificResponse(commandId, message, messageLen); - exit: - return success; + SetCommandExitStatus(success); + UpdateWaitForResponse(false); +} + +void ModelCommand::OnStatusChange(void) +{ + ChipLogProgress(chipTool, "DeviceStatusDelegate::OnStatusChange"); +} + +void ModelCommand::PrintBuffer(const PacketBufferHandle & buffer) const +{ + const size_t dataLen = buffer->DataLength(); + + fprintf(stderr, "SENDING: %zu ", dataLen); + for (size_t i = 0; i < dataLen; ++i) + { + fprintf(stderr, "%02x ", buffer->Start()[i]); + } + fprintf(stderr, "\n"); } diff --git a/examples/chip-tool/commands/clusters/ModelCommand.h b/examples/chip-tool/commands/clusters/ModelCommand.h index b8d159d182a0af..838b546050ceba 100644 --- a/examples/chip-tool/commands/clusters/ModelCommand.h +++ b/examples/chip-tool/commands/clusters/ModelCommand.h @@ -18,8 +18,8 @@ #pragma once -#include "../common/NetworkCommand.h" - +#include "../../config/PersistentStorage.h" +#include "../common/Command.h" #include #include @@ -28,24 +28,33 @@ #define CHIP_ZCL_ENDPOINT_MIN 0x01 #define CHIP_ZCL_ENDPOINT_MAX 0xF0 -class ModelCommand : public NetworkCommand +class ModelCommand : public Command, public chip::Controller::DeviceStatusDelegate { public: ModelCommand(const char * commandName, uint16_t clusterId, uint8_t commandId) : - NetworkCommand(commandName), mClusterId(clusterId), mCommandId(commandId) + Command(commandName), mClusterId(clusterId), mCommandId(commandId) {} void AddArguments() { AddArgument("endpoint-id", CHIP_ZCL_ENDPOINT_MIN, CHIP_ZCL_ENDPOINT_MAX, &mEndPointId); } - /////////// NetworkCommand Interface ///////// - uint16_t Encode(PacketBufferHandle & buffer, uint16_t bufferSize) override; - bool Decode(PacketBufferHandle & buffer) const override; + /////////// Command Interface ///////// + CHIP_ERROR Run(PersistentStorage & storage, NodeId localId, NodeId remoteId) override; + + /////////// DeviceStatusDelegate Interface ///////// + void OnMessage(PacketBufferHandle buffer) override; + void OnStatusChange(void) override; - virtual uint16_t EncodeCommand(const PacketBufferHandle & buffer, uint16_t bufferSize, uint8_t endPointId) = 0; + virtual PacketBufferHandle EncodeCommand(uint8_t endPointId) = 0; virtual bool HandleGlobalResponse(uint8_t commandId, uint8_t * message, uint16_t messageLen) const { return false; } virtual bool HandleSpecificResponse(uint8_t commandId, uint8_t * message, uint16_t messageLen) const { return false; } private: + CHIP_ERROR RunInternal(NodeId remoteId); + CHIP_ERROR RunCommandInternal(ChipDevice * device); + + void PrintBuffer(const PacketBufferHandle & buffer) const; + + ChipDeviceCommissioner mCommissioner; const uint16_t mClusterId; const uint8_t mCommandId; uint8_t mEndPointId; diff --git a/examples/chip-tool/commands/common/Commands.cpp b/examples/chip-tool/commands/common/Commands.cpp index 346d507fa34aba..c8b4d49584af5b 100644 --- a/examples/chip-tool/commands/common/Commands.cpp +++ b/examples/chip-tool/commands/common/Commands.cpp @@ -19,7 +19,6 @@ #include "Commands.h" #include "Command.h" -#include "Logging.h" #include #include @@ -38,7 +37,6 @@ int Commands::Run(NodeId localId, NodeId remoteId, int argc, char ** argv) { CHIP_ERROR err = CHIP_NO_ERROR; PersistentStorage storage; - ConfigureChipLogging(); err = chip::Platform::MemoryInit(); VerifyOrExit(err == CHIP_NO_ERROR, ChipLogError(Controller, "Init Memory failure: %s", chip::ErrorStr(err))); @@ -46,6 +44,8 @@ int Commands::Run(NodeId localId, NodeId remoteId, int argc, char ** argv) err = storage.Init(); VerifyOrExit(err == CHIP_NO_ERROR, ChipLogError(Controller, "Init Storage failure: %s", chip::ErrorStr(err))); + chip::Logging::SetLogFilter(storage.GetLoggingLevel()); + err = RunCommand(storage, localId, remoteId, argc, argv); SuccessOrExit(err); diff --git a/examples/chip-tool/commands/common/Logging.cpp b/examples/chip-tool/commands/common/Logging.cpp deleted file mode 100644 index 9830ec3202ab08..00000000000000 --- a/examples/chip-tool/commands/common/Logging.cpp +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (c) 2020 Project CHIP Authors - * All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include -#include - -#include -#include - -using namespace ::chip::Logging; - -constexpr LogCategory kDefaultLoggingLevel = kLogCategory_Detail; - -void ConfigureChipLogging() -{ - LogCategory chipLogLevel = kDefaultLoggingLevel; - - const char * level = getenv("CHIP_LOG_LEVEL"); - VerifyOrExit(level != NULL, /**/); - - if (strcasecmp(level, "none") == 0) - { - chipLogLevel = kLogCategory_None; - } - else if (strcasecmp(level, "error") == 0) - { - chipLogLevel = kLogCategory_Error; - } - else if (strcasecmp(level, "progress") == 0) - { - chipLogLevel = kLogCategory_Progress; - } - else if (strcasecmp(level, "detail") == 0) - { - chipLogLevel = kLogCategory_Detail; - } - else if (strcasecmp(level, "retain") == 0) - { - chipLogLevel = kLogCategory_Retain; - } - -exit: - SetLogFilter(chipLogLevel); -} diff --git a/examples/chip-tool/commands/common/Logging.h b/examples/chip-tool/commands/common/Logging.h deleted file mode 100644 index c2893208a70969..00000000000000 --- a/examples/chip-tool/commands/common/Logging.h +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (c) 2020 Project CHIP Authors - * All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#pragma once - -void ConfigureChipLogging(); diff --git a/examples/chip-tool/commands/common/NetworkCommand.cpp b/examples/chip-tool/commands/common/NetworkCommand.cpp deleted file mode 100644 index e79cc7f11c8bfb..00000000000000 --- a/examples/chip-tool/commands/common/NetworkCommand.cpp +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright (c) 2020 Project CHIP Authors - * All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "NetworkCommand.h" - -using namespace ::chip; - -constexpr uint16_t kWaitDurationInSeconds = 10; - -// Make sure our buffer is big enough, but this will need a better setup! -constexpr uint16_t kMaxBufferSize = 1024; - -CHIP_ERROR NetworkCommand::Run(PersistentStorage & storage, NodeId localId, NodeId remoteId) -{ - CHIP_ERROR err = CHIP_NO_ERROR; - - err = mCommissioner.Init(localId, &storage); - VerifyOrExit(err == CHIP_NO_ERROR, ChipLogError(Controller, "Init failure! Commissioner: %s", chip::ErrorStr(err))); - - err = mCommissioner.ServiceEvents(); - VerifyOrExit(err == CHIP_NO_ERROR, ChipLogError(Controller, "Init failure! Run Loop: %s", chip::ErrorStr(err))); - - err = RunInternal(remoteId); - SuccessOrExit(err); - - VerifyOrExit(GetCommandExitStatus(), err = CHIP_ERROR_INTERNAL); - -exit: - mCommissioner.ServiceEventSignal(); - mCommissioner.Shutdown(); - return err; -} - -CHIP_ERROR NetworkCommand::RunInternal(NodeId remoteId) -{ - ChipDevice * device; - CHIP_ERROR err = mCommissioner.GetDevice(remoteId, &device); - VerifyOrExit(err == CHIP_NO_ERROR, ChipLogError(chipTool, "Could not find a paired device. Are you sure it has been paired ?")); - - device->SetDelegate(this); - - err = RunCommandInternal(device); - SuccessOrExit(err); - - UpdateWaitForResponse(true); - WaitForResponse(kWaitDurationInSeconds); - -exit: - return err; -} - -CHIP_ERROR NetworkCommand::RunCommandInternal(ChipDevice * device) -{ - CHIP_ERROR err = CHIP_NO_ERROR; - uint16_t payloadLen = 0; - - PacketBufferHandle buffer = PacketBuffer::NewWithAvailableSize(kMaxBufferSize); - VerifyOrExit(!buffer.IsNull(), err = CHIP_ERROR_NO_MEMORY); - - payloadLen = Encode(buffer, kMaxBufferSize); - VerifyOrExit(payloadLen != 0, err = CHIP_ERROR_INVALID_MESSAGE_LENGTH); - - buffer->SetDataLength(payloadLen); - -#ifdef DEBUG - PrintBuffer(buffer); -#endif - - err = device->SendMessage(std::move(buffer)); - VerifyOrExit(err == CHIP_NO_ERROR, ChipLogError(chipTool, "Failed to send message: %s", ErrorStr(err))); - -exit: - return err; -} - -void NetworkCommand::OnMessage(PacketBufferHandle buffer) -{ - ChipLogDetail(chipTool, "OnMessage: Received %zu bytes", buffer->DataLength()); - - SetCommandExitStatus(Decode(buffer)); - UpdateWaitForResponse(false); -} - -void NetworkCommand::OnStatusChange(void) -{ - ChipLogProgress(chipTool, "DeviceStatusDelegate::OnStatusChange"); -} - -void NetworkCommand::PrintBuffer(PacketBufferHandle & buffer) const -{ - const size_t data_len = buffer->DataLength(); - - fprintf(stderr, "SENDING: %zu ", data_len); - for (size_t i = 0; i < data_len; ++i) - { - fprintf(stderr, "%d ", buffer->Start()[i]); - } - fprintf(stderr, "\n"); -} diff --git a/examples/chip-tool/commands/common/NetworkCommand.h b/examples/chip-tool/commands/common/NetworkCommand.h deleted file mode 100644 index d520f6d7dfd0e5..00000000000000 --- a/examples/chip-tool/commands/common/NetworkCommand.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (c) 2020 Project CHIP Authors - * All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#pragma once - -#include "../../config/PersistentStorage.h" -#include "Command.h" - -class NetworkCommand : public Command, public chip::Controller::DeviceStatusDelegate -{ -public: - NetworkCommand(const char * commandName) : Command(commandName) {} - - virtual uint16_t Encode(PacketBufferHandle & buffer, uint16_t bufferSize) = 0; - virtual bool Decode(PacketBufferHandle & buffer) const = 0; - - /////////// Command Interface ///////// - CHIP_ERROR Run(PersistentStorage & storage, NodeId localId, NodeId remoteId) override; - - /////////// DeviceStatusDelegate Interface ///////// - void OnMessage(PacketBufferHandle buffer) override; - void OnStatusChange(void) override; - -private: - CHIP_ERROR RunInternal(NodeId remoteId); - CHIP_ERROR RunCommandInternal(ChipDevice * device); - - void PrintBuffer(PacketBufferHandle & buffer) const; - - ChipDeviceCommissioner mCommissioner; -}; diff --git a/examples/chip-tool/commands/echo/EchoCommand.cpp b/examples/chip-tool/commands/echo/EchoCommand.cpp deleted file mode 100644 index 04e2fe20ab49b0..00000000000000 --- a/examples/chip-tool/commands/echo/EchoCommand.cpp +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (c) 2020 Project CHIP Authors - * All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "EchoCommand.h" - -using namespace ::chip; - -namespace { -static const char PAYLOAD[] = "Message from Standalone CHIP echo client!"; - -bool IsIdenticalMessage(System::PacketBufferHandle & buffer) -{ - size_t dataLen = buffer->DataLength(); - return (dataLen + 1 == sizeof PAYLOAD) && (memcmp(buffer->Start(), PAYLOAD, dataLen) == 0); -} -} // namespace - -uint16_t EchoCommand::Encode(PacketBufferHandle & buffer, uint16_t bufferSize) -{ - uint16_t payloadLen = 0; - - if (strlen(PAYLOAD) > bufferSize) - { - ChipLogError(chipTool, "PAYLOAD length too big for PacketBuffer (> bufferSize)"); - } - else - { - payloadLen = static_cast(strlen(PAYLOAD)); - memcpy(buffer->Start(), PAYLOAD, payloadLen); - } - - return payloadLen; -} - -bool EchoCommand::Decode(PacketBufferHandle & buffer) const -{ - bool success = IsIdenticalMessage(buffer); - - if (!success) - { - ChipLogError(chipTool, "Echo: Error \nSend: %s \nRecv: %.*s", PAYLOAD, buffer->DataLength(), buffer->Start()); - } - - return success; -} diff --git a/examples/chip-tool/commands/echo/EchoCommand.h b/examples/chip-tool/commands/echo/EchoCommand.h deleted file mode 100644 index 5ce008d68ff8b0..00000000000000 --- a/examples/chip-tool/commands/echo/EchoCommand.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (c) 2020 Project CHIP Authors - * All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#pragma once - -#include "../common/NetworkCommand.h" - -class EchoCommand : public NetworkCommand -{ -public: - EchoCommand(const char * commandName) : NetworkCommand(commandName) {} - - /////////// NetworkCommand Interface ///////// - uint16_t Encode(PacketBufferHandle & buffer, uint16_t bufferSize) override; - bool Decode(PacketBufferHandle & buffer) const override; -}; diff --git a/examples/chip-tool/commands/payload/AdditionalDataParseCommand.cpp b/examples/chip-tool/commands/payload/AdditionalDataParseCommand.cpp new file mode 100644 index 00000000000000..3edad12d30ad4f --- /dev/null +++ b/examples/chip-tool/commands/payload/AdditionalDataParseCommand.cpp @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2020 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "AdditionalDataParseCommand.h" +#include +#include +#include + +using namespace ::chip; +using namespace ::chip::SetupPayload; + +CHIP_ERROR AdditionalDataParseCommand::Run(PersistentStorage & storage, NodeId localId, NodeId remoteId) +{ + std::vector payloadData; + AdditionalDataPayload resultPayload; + CHIP_ERROR err = CHIP_NO_ERROR; + std::string payloadString(mPayload); + + // Decode input payload + size_t len = payloadString.length(); + + for (size_t i = 0; i < len; i += 2) + { + auto str = payloadString.substr(i, 2); + uint8_t x = (uint8_t) stoi(str, 0, 16); + payloadData.push_back(x); + } + err = AdditionalDataPayloadParser(payloadData.data(), (uint32_t) payloadData.size()).populatePayload(resultPayload); + SuccessOrExit(err); + ChipLogProgress(chipTool, "AdditionalDataParseCommand, RotatingDeviceId=%s", resultPayload.rotatingDeviceId.c_str()); +exit: + return err; +} diff --git a/examples/chip-tool/commands/echo/Commands.h b/examples/chip-tool/commands/payload/AdditionalDataParseCommand.h similarity index 68% rename from examples/chip-tool/commands/echo/Commands.h rename to examples/chip-tool/commands/payload/AdditionalDataParseCommand.h index a9702dbe3d607b..ddb0bd462618d4 100644 --- a/examples/chip-tool/commands/echo/Commands.h +++ b/examples/chip-tool/commands/payload/AdditionalDataParseCommand.h @@ -18,21 +18,14 @@ #pragma once -#include "EchoCommand.h" +#include "../common/Command.h" -class Echo : public EchoCommand +class AdditionalDataParseCommand : public Command { public: - Echo() : EchoCommand("ip") {} -}; - -void registerCommandsEcho(Commands & commands) -{ - const char * clusterName = "Echo"; + AdditionalDataParseCommand() : Command("parse-additional-data-payload") { AddArgument("payload", &mPayload); } + CHIP_ERROR Run(PersistentStorage & storage, NodeId localId, NodeId remoteId) override; - commands_list clusterCommands = { - make_unique(), - }; - - commands.Register(clusterName, clusterCommands); -} +private: + char * mPayload; +}; diff --git a/examples/chip-tool/commands/payload/Commands.h b/examples/chip-tool/commands/payload/Commands.h index 83c1124af44910..e0ed52f25795f0 100644 --- a/examples/chip-tool/commands/payload/Commands.h +++ b/examples/chip-tool/commands/payload/Commands.h @@ -18,14 +18,13 @@ #pragma once -#include "ParseCommand.h" +#include "AdditionalDataParseCommand.h" +#include "SetupPayloadParseCommand.h" void registerCommandsPayload(Commands & commands) { const char * clusterName = "Payload"; - commands_list clusterCommands = { - make_unique(), - }; + commands_list clusterCommands = { make_unique(), make_unique() }; commands.Register(clusterName, clusterCommands); } diff --git a/examples/chip-tool/commands/payload/ParseCommand.cpp b/examples/chip-tool/commands/payload/SetupPayloadParseCommand.cpp similarity index 89% rename from examples/chip-tool/commands/payload/ParseCommand.cpp rename to examples/chip-tool/commands/payload/SetupPayloadParseCommand.cpp index 534efb14e2acc9..69d94884904e88 100644 --- a/examples/chip-tool/commands/payload/ParseCommand.cpp +++ b/examples/chip-tool/commands/payload/SetupPayloadParseCommand.cpp @@ -16,14 +16,14 @@ * */ -#include "ParseCommand.h" +#include "SetupPayloadParseCommand.h" #include #include #include using namespace ::chip; -CHIP_ERROR ParseCommand::Run(PersistentStorage & storage, NodeId localId, NodeId remoteId) +CHIP_ERROR SetupPayloadParseCommand::Run(PersistentStorage & storage, NodeId localId, NodeId remoteId) { std::string codeString(mCode); SetupPayload payload; @@ -38,7 +38,7 @@ CHIP_ERROR ParseCommand::Run(PersistentStorage & storage, NodeId localId, NodeId return err; } -CHIP_ERROR ParseCommand::Print(chip::SetupPayload payload) +CHIP_ERROR SetupPayloadParseCommand::Print(chip::SetupPayload payload) { std::string serialNumber; std::vector optionalVendorData; @@ -80,7 +80,7 @@ CHIP_ERROR ParseCommand::Print(chip::SetupPayload payload) return err; } -CHIP_ERROR ParseCommand::Parse(std::string codeString, chip::SetupPayload & payload) +CHIP_ERROR SetupPayloadParseCommand::Parse(std::string codeString, chip::SetupPayload & payload) { CHIP_ERROR err = CHIP_NO_ERROR; @@ -98,7 +98,7 @@ CHIP_ERROR ParseCommand::Parse(std::string codeString, chip::SetupPayload & payl return err; } -bool ParseCommand::IsQRCode(std::string codeString) +bool SetupPayloadParseCommand::IsQRCode(std::string codeString) { return codeString.rfind(QRCODE_PREFIX) == 0; } diff --git a/examples/chip-tool/commands/payload/ParseCommand.h b/examples/chip-tool/commands/payload/SetupPayloadParseCommand.h similarity index 88% rename from examples/chip-tool/commands/payload/ParseCommand.h rename to examples/chip-tool/commands/payload/SetupPayloadParseCommand.h index f7d2a41a7ad8cc..58aac2409200a6 100644 --- a/examples/chip-tool/commands/payload/ParseCommand.h +++ b/examples/chip-tool/commands/payload/SetupPayloadParseCommand.h @@ -21,10 +21,10 @@ #include "../common/Command.h" #include -class ParseCommand : public Command +class SetupPayloadParseCommand : public Command { public: - ParseCommand() : Command("parse") { AddArgument("code", &mCode); } + SetupPayloadParseCommand() : Command("parse-setup-payload") { AddArgument("payload", &mCode); } CHIP_ERROR Run(PersistentStorage & storage, NodeId localId, NodeId remoteId) override; private: diff --git a/examples/chip-tool/config/PersistentStorage.cpp b/examples/chip-tool/config/PersistentStorage.cpp index 24d270f3c68d38..f909f3b44cbcc5 100644 --- a/examples/chip-tool/config/PersistentStorage.cpp +++ b/examples/chip-tool/config/PersistentStorage.cpp @@ -25,9 +25,13 @@ using Sections = std::map; using namespace ::chip; using namespace ::chip::Controller; +using namespace ::chip::Logging; constexpr const char kFilename[] = "/tmp/chip_tool_config.ini"; constexpr const char kDefaultSectionName[] = "Default"; +constexpr const char kPortKey[] = "ListenPort"; +constexpr const char kLoggingKey[] = "LoggingLevel"; +constexpr LogCategory kDefaultLoggingLevel = kLogCategory_Detail; CHIP_ERROR PersistentStorage::Init() { @@ -66,7 +70,7 @@ CHIP_ERROR PersistentStorage::GetKeyValue(const char * key, char * value, uint16 VerifyOrExit(inipp::extract(section[key], iniValue), err = CHIP_ERROR_INVALID_ARGUMENT); iniValueLength = iniValue.size(); - VerifyOrExit(iniValueLength < static_cast(size) - 1, err = CHIP_ERROR_BUFFER_TOO_SMALL); + VerifyOrExit(iniValueLength <= static_cast(size) - 1, err = CHIP_ERROR_BUFFER_TOO_SMALL); iniValueLength = iniValue.copy(value, iniValueLength); value[iniValueLength] = '\0'; @@ -112,3 +116,60 @@ CHIP_ERROR PersistentStorage::CommitConfig() exit: return err; } + +uint16_t PersistentStorage::GetListenPort() +{ + CHIP_ERROR err = CHIP_NO_ERROR; + uint16_t chipListenPort = CHIP_PORT; + + char value[6]; + uint16_t size = static_cast(sizeof(value)); + err = GetKeyValue(kPortKey, value, size); + if (CHIP_NO_ERROR == err) + { + uint16_t tmpValue; + std::stringstream ss(value); + ss >> tmpValue; + if (!ss.fail() && ss.eof()) + { + chipListenPort = tmpValue; + } + } + + return chipListenPort; +} + +LogCategory PersistentStorage::GetLoggingLevel() +{ + CHIP_ERROR err = CHIP_NO_ERROR; + LogCategory chipLogLevel = kDefaultLoggingLevel; + + char value[9]; + uint16_t size = static_cast(sizeof(value)); + err = GetKeyValue(kLoggingKey, value, size); + if (CHIP_NO_ERROR == err) + { + if (strcasecmp(value, "none") == 0) + { + chipLogLevel = kLogCategory_None; + } + else if (strcasecmp(value, "error") == 0) + { + chipLogLevel = kLogCategory_Error; + } + else if (strcasecmp(value, "progress") == 0) + { + chipLogLevel = kLogCategory_Progress; + } + else if (strcasecmp(value, "detail") == 0) + { + chipLogLevel = kLogCategory_Detail; + } + else if (strcasecmp(value, "retain") == 0) + { + chipLogLevel = kLogCategory_Retain; + } + } + + return chipLogLevel; +} diff --git a/examples/chip-tool/config/PersistentStorage.h b/examples/chip-tool/config/PersistentStorage.h index e4b0d0ec0bea58..4f2a3b6297e554 100644 --- a/examples/chip-tool/config/PersistentStorage.h +++ b/examples/chip-tool/config/PersistentStorage.h @@ -20,6 +20,7 @@ #include #include +#include class PersistentStorage : public chip::Controller::PersistentStorageDelegate { @@ -33,6 +34,9 @@ class PersistentStorage : public chip::Controller::PersistentStorageDelegate void SetKeyValue(const char * key, const char * value) override; void DeleteKeyValue(const char * key) override; + uint16_t GetListenPort(); + chip::Logging::LogCategory GetLoggingLevel(); + private: CHIP_ERROR CommitConfig(); inipp::Ini mConfig; diff --git a/examples/chip-tool/main.cpp b/examples/chip-tool/main.cpp index a7bf3ec9b1f478..ce59b9758a3330 100644 --- a/examples/chip-tool/main.cpp +++ b/examples/chip-tool/main.cpp @@ -19,7 +19,6 @@ #include "commands/common/Commands.h" #include "commands/clusters/Commands.h" -#include "commands/echo/Commands.h" #include "commands/pairing/Commands.h" #include "commands/payload/Commands.h" @@ -31,7 +30,6 @@ int main(int argc, char * argv[]) { Commands commands; - registerCommandsEcho(commands); registerCommandsPayload(commands); registerCommandsPairing(commands); registerClusters(commands); diff --git a/examples/common/README.md b/examples/common/README.md new file mode 100644 index 00000000000000..5f0f8790a26241 --- /dev/null +++ b/examples/common/README.md @@ -0,0 +1,14 @@ +# Examples common libraries + +## What is this? + +The purpose of this directory is to contain libraries, which are not part of +CHIP libraries nor provided by the CHIP, but still very useful for the CHIP +examples in order to provide specific functionalities. + +## Available libraries + +- **m5stack-tft** - TFT library for ESP32 platform. +- **QRCode** - QR Code generator library +- **screen-framework** - Framework for creating simple on screen user + interfaces. diff --git a/examples/common/chip-app-server/DataModelHandler.cpp b/examples/common/chip-app-server/DataModelHandler.cpp deleted file mode 100644 index 9aa86739d7736e..00000000000000 --- a/examples/common/chip-app-server/DataModelHandler.cpp +++ /dev/null @@ -1,201 +0,0 @@ -/* - * - * Copyright (c) 2020 Project CHIP Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @file - * This file implements the handler for data model messages. - */ - -#include "DataModelHandler.h" - -#include -#include -#include -#include -#include -#include -#include - -using namespace ::chip; - -/** - * A data model message has nonzero length and always has a first byte whose - * value is one of: 0x00, 0x01, 0x02, 0x03. See chipZclEncodeZclHeader for the - * construction of the message and in particular the first byte. - * - * Echo messages should generally not have a first byte with those values, so we - * can use that to try to distinguish between the two. - */ -bool ContentMayBeADataModelMessage(const System::PacketBufferHandle & buffer) -{ - const size_t data_len = buffer->DataLength(); - const uint8_t * data = buffer->Start(); - bool maybeDataModelMessage = true; - - // Has to have nonzero length. - VerifyOrExit(data_len > 0, maybeDataModelMessage = false); - - // Has to have a valid first byte value. - VerifyOrExit(data[0] < 0x04, maybeDataModelMessage = false); - -exit: - return maybeDataModelMessage; -} - -/** - * @brief implements something like "od -c", changes an arbitrary byte string - * into a single-line of ascii. Destroys any byte-wise encoding that - * might be present, e.g. utf-8. - * - * @param bytes potentially unprintable buffer - * @param bytes_len length of bytes - * @param out where to put the printable string - * @param out_len length of out - * @return size_t required size of output buffer, including null-termination - */ -static size_t BinaryBytesToPrintableString(const uint8_t * bytes, size_t bytes_len, char * out, size_t out_len) -{ - size_t required = 1; // always need null termination - memset(out, 0, out_len); - // count and print - for (; bytes_len > 0; bytes_len--, bytes++) - { - uint8_t byte = *bytes; - - if ((byte >= '\t' && byte <= '\r') || byte == '\\') - { - static const char * kCodes = "tnvfr"; - char code = (byte == '\\') ? '\\' : kCodes[byte - '\t']; - required += 2; - if (out_len > 2) - { - *out++ = '\\'; - *out++ = code; - out_len -= 2; - } - } - else if (byte >= ' ' && byte <= '~') - { - required += 1; - if (out_len > 1) - { - *out++ = byte; - out_len--; - } - } - else - { - static const size_t kBinCodeLen = sizeof("\\xFF") - 1; - static const char * kCodes = "0123456789ABCDEF"; - - required += kBinCodeLen; - if (out_len > kBinCodeLen) - { - *out++ = '\\'; - *out++ = 'x'; - *out++ = kCodes[(byte & 0xf0) >> 4]; - *out++ = kCodes[byte & 0xf]; - out_len -= kBinCodeLen; - } - } - } - - return required; -} - -void ProcessOthersMessage(const PacketHeader & header, System::PacketBufferHandle & buffer, SecureSessionMgr * mgr) -{ - CHIP_ERROR err; - char logmsg[512]; - - BinaryBytesToPrintableString(buffer->Start(), buffer->DataLength(), logmsg, sizeof(logmsg)); - - ChipLogProgress(AppServer, "Client sent: %s", logmsg); - - // Attempt to echo back - err = mgr->SendMessage(header.GetSourceNodeId().Value(), std::move(buffer)); - if (err != CHIP_NO_ERROR) - { - ChipLogProgress(AppServer, "Unable to echo back to client: %s", ErrorStr(err)); - } - else - { - ChipLogProgress(AppServer, "Echo sent"); - } -} - -void ProcessDataModelMessage(const PacketHeader & header, System::PacketBufferHandle & buffer) -{ - EmberApsFrame frame; - bool ok = extractApsFrame(buffer->Start(), buffer->DataLength(), &frame) > 0; - if (ok) - { - ChipLogProgress(Zcl, "APS frame processing success!"); - } - else - { - ChipLogProgress(Zcl, "APS frame processing failure!"); - return; - } - - uint8_t * message; - uint16_t messageLen = extractMessage(buffer->Start(), buffer->DataLength(), &message); - ok = emberAfProcessMessage(&frame, - 0, // type - message, messageLen, - header.GetSourceNodeId().Value(), // source identifier - NULL); - - if (ok) - { - ChipLogProgress(Zcl, "Data model processing success!"); - } - else - { - ChipLogProgress(Zcl, "Data model processing failure!"); - } -} - -/** - * Handle a message that should be processed via our data model processing - * codepath. This function will free the packet buffer. - * - * @param [in] buffer The buffer holding the message. This function guarantees - * that it will free the buffer before returning. - */ -void HandleDataModelMessage(const PacketHeader & header, System::PacketBufferHandle buffer, SecureSessionMgr * mgr) -{ - // FIXME: Long-term we shouldn't be guessing what sort of message this is - // based on the message bytes. We're doing this for now to support both - // data model messages and text echo messages, but in the long term we - // should either do echo via a data model command or do echo on a separate - // port from data model processing. - if (ContentMayBeADataModelMessage(buffer)) - { - ProcessDataModelMessage(header, buffer); - } - else - { - ProcessOthersMessage(header, buffer, mgr); - } -} - -void InitDataModelHandler() -{ - emberAfEndpointConfigure(); - emberAfInit(); -} diff --git a/examples/lighting-app/efr32/BUILD.gn b/examples/lighting-app/efr32/BUILD.gn index afc819bc2480f2..0793614b421d23 100644 --- a/examples/lighting-app/efr32/BUILD.gn +++ b/examples/lighting-app/efr32/BUILD.gn @@ -31,8 +31,7 @@ declare_args() { show_qr_code = true # BRD4166A --> ThunderBoard Sense 2 (No LCD) -# BRD4180A --> GPIO Conflict with Radio and LCD -if (efr32_board == "BRD4166A" || efr32_board == "BRD4180A") { +if (efr32_board == "BRD4166A") { show_qr_code = false } @@ -68,7 +67,6 @@ efr32_executable("lighting_app") { public_deps = [ ":sdk", "${chip_root}/examples/common/QRCode", - "${chip_root}/examples/common/chip-app-server:chip-app-server", "${chip_root}/examples/lighting-app/lighting-common", "${chip_root}/src/lib", "${chip_root}/src/setup_payload", @@ -81,6 +79,7 @@ efr32_executable("lighting_app") { include_dirs += [ "${efr32_project_dir}/include", "${chip_root}/src/app/util", + "${chip_root}/src/app/server", "${examples_plat_dir}", ] diff --git a/examples/lighting-app/efr32/README.md b/examples/lighting-app/efr32/README.md index e16d48ad0daa7d..9f4312cae923f8 100644 --- a/examples/lighting-app/efr32/README.md +++ b/examples/lighting-app/efr32/README.md @@ -20,8 +20,16 @@ An example showing the use of CHIP on the Silicon Labs EFR32 MG12. ## Introduction The EFR32 lighting example provides a baseline demonstration of a Light control -device, built using CHIP and the Silicon Labs gecko SDK. The example currently -support OpenThread. The BLE feature is still a work in progress. +device, built using CHIP and the Silicon Labs gecko SDK. It can be controlled by +a Chip controller over Openthread network.. + +The EFR32 device can be commissioned over Bluetooth Low Energy where the device +and the Chip controller will exchange security information with the Rendez-vous +procedure. Thread Network credentials are then provided to the EFR32 device +which will then join the network. + +The LCD on the Silabs WSTK shows a QR Code containing the needed commissioning +information for the BLE connection and starting the Rendez-vous procedure. The lighting example is intended to serve both as a means to explore the workings of CHIP as well as a template for creating real products based on the @@ -82,14 +90,25 @@ Silicon Labs platform. $ cd ~/connectedhomeip/examples/lighting-app/efr32 $ rm -rf out/ +OR use the script + + cd ~/connectedhomeip + $ export EFR32_SDK_ROOT= + $ export EFR32_BOARD=BRD4161A + ./scripts/examples/gn_efr32_example.sh examples/lighting-app/efr32/ out/debug/efr32_lighting_app + +- To delete generated executable, libraries and object files use: + $ cd ~/connectedhomeip + $ rm -rf out/debug/efr32_lighting_app + ## Flashing the Application - On the command line: - $ cd ~/connectedhomeip/examples/lock-app/efr32 - $ python3 out/debug/chip-efr32-lighting-example.flash.py + $ cd ~/connectedhomeip/examples/lighting-app/efr32 + $ python3 out/debug/chip-efr32-lighting-example.out.flash.py - Or with the Ozone debugger, just load the .out file. @@ -105,7 +124,9 @@ embedded application without the need for a dedicated UART. Using the RTT facility requires downloading and installing the _SEGGER J-Link Software and Documentation Pack_ ([web site](https://www.segger.com/downloads/jlink#J-LinkSoftwareAndDocumentationPack)). -Alternatively the _SEGGER Ozone - J-Link Debugger_ can be used to view RTT logs. + +Alternatively, SEGGER Ozone J-Link debugger can be used to view RTT logs too +after flashing the .out file. - Download the J-Link installer by navigating to the appropriate URL and agreeing to the license agreement. @@ -145,24 +166,102 @@ combination with JLinkRTTClient as follows: ## Running the Complete Example -- Once the example is flashed on the board, you should be able to establish a - connection with an OpenThread border router. See +- It is assumed here that you already have an OpenThread border router + configured and running. If not, see the following guide [OpenThread Border Router](https://openthread.io/guides/border-router) for more information on how to setup a border router. Take note that the RCP code is available directly through [Simplicity Studio 5](https://www.silabs.com/products/development-tools/software/simplicity-studio/simplicity-studio-5) under File->New->Project Wizard->Examples->Thread : ot-rcp -- Once said connectection is established (you can verify that with the command + +- User interface : **LCD** The LCD on Silabs WSTK shows a QR Code. This QR + Code is be scanned by the CHIP Tool app For the Rendez-vous procedure over + BLE + + * On devices that do not have or support the LCD Display like the BRD4166A Thunderboard Sense 2, + a URL can be found in the RTT logs. + + [SVR] Copy/paste the below URL in a browser to see the QR Code: + [SVR] https://dhrishi.github.io/connectedhomeip/qrcode.html?data=CH%3AI34NM%20-00%200C9SS0 + + **LED 0** shows the overall state of the device and its connectivity. The + following states are possible: + + - _Short Flash On (50 ms on/950 ms off)_ ; The device is in the + unprovisioned (unpaired) state and is waiting for a commissioning + application to connect. + + - _Rapid Even Flashing_ ; (100 ms on/100 ms off)_ — The device is in the + unprovisioned state and a commissioning application is connected through + Bluetooth LE. + + - _Short Flash Off_ ; (950ms on/50ms off)_ — The device is fully + provisioned, but does not yet have full Thread network or service + connectivity. + + - _Solid On_ ; The device is fully provisioned and has full Thread + network and service connectivity. + + **LED 1** Simulates the Light The following states are possible: + + - _Solid On_ ; Light is on + - _Off_ ; Light is off + + **Push Button 0** - Press and Release : If not commissioned, start thread + with default configurations (DEBUG) + + + - Pressed and hold for 6 s: Initiates the factory reset of the device. + Releasing the button within the 6-second window cancels the factory reset + procedure. **LEDs** blink in unison when the factory reset procedure is + initiated. + + **Push Button 1** + Toggles the light state On/Off + +- Once the device is provisioned, it will join the Thread network is + established, look for the RTT log + + ``` +     [DL] Device Role: CHILD +     [DL] Partition Id:0x6A7491B7 +     [DL] \_OnPlatformEvent default: event->Type = 32778 +     [DL] OpenThread State Changed (Flags: 0x00000001) +     [DL] Thread Unicast Addresses: +     [DL]    2001:DB8::E1A2:87F1:7D5D:FECA/64 valid preferred +     [DL]    FDDE:AD00:BEEF::FF:FE00:2402/64 valid preferred rloc +     [DL]    FDDE:AD00:BEEF:0:383F:5E81:A05A:B168/64 valid preferred +     [DL]    FE80::D8F2:592E:C109:CF00/64 valid preferred +     [DL] LwIP Thread interface addresses updated +     [DL] FE80::D8F2:592E:C109:CF00 IPv6 link-local address, preferred) +     [DL] FDDE:AD00:BEEF:0:383F:5E81:A05A:B168 Thread mesh-local address, preferred) +     [DL] 2001:DB8::E1A2:87F1:7D5D:FECA IPv6 global unicast address, preferred) + ``` + + Keep The global unicast address; It is to be used to reach the Device with + the chip-tool. The device will be promoted to Router shortly after [DL] + Device Role: ROUTER + + (you can verify that the device is on the thread network with the command `router table` using a serial terminal (screen / minicom etc.) on the board - running the lighting-app example) + running the lighting-app example. You can also get the address list with the + command ipaddr again in the serial terminal ) + - Using chip-tool you can now control the light status with on/off command - such as `chip-tool onoff on 1 11097` + such as `chip-tool onoff on 1` + + \*\* Currently, chip-tool for Mac or Linux do not yet have the Thread + provisioning feature + `chip-tool bypass 11097` + + You can provision the Chip device using Chip tool Android or iOS app or + through CLI commands on your OT BR ### Notes - Depending on your network settings your router might not provide native ipv6 addresses to your devices (Border router / PC). If this is the case, you - need to add a static ipv6 addresses on both device and then a ipv6 route to + need to add a static ipv6 addresses on both device and then an ipv6 route to the border router on your PC # On Border Router : @@ -172,4 +271,4 @@ combination with JLinkRTTClient as follows: $ sudo ip addr add dev 2002::1/64 # Add Ipv6 route on PC (Linux) - $ sudo ip route add /64 via 2002::2 + $ sudo ip route add /64 via 2002::2 diff --git a/examples/lighting-app/efr32/src/AppTask.cpp b/examples/lighting-app/efr32/src/AppTask.cpp index a3ed269afcfffc..c0a9438ce54f4a 100644 --- a/examples/lighting-app/efr32/src/AppTask.cpp +++ b/examples/lighting-app/efr32/src/AppTask.cpp @@ -23,6 +23,7 @@ #include "ButtonHandler.h" #include "DataModelHandler.h" #include "LEDWidget.h" +#include "QRCodeUtil.h" #include "Server.h" #include "Service.h" #include "attribute-storage.h" @@ -132,52 +133,20 @@ int AppTask::Init() // Print setup info on LCD if available #ifdef DISPLAY_ENABLED - chip::SetupPayload payload; - uint32_t setUpPINCode = 0; - uint16_t setUpDiscriminator = 0; - uint16_t vendorId = 0; - uint16_t productId = 0; + uint32_t setupPinCode; + std::string QRCode; - err = ConfigurationMgr().GetSetupPinCode(setUpPINCode); - if (err != CHIP_NO_ERROR) - { - EFR32_LOG("ConfigurationMgr().GetSetupPinCode() failed: %s", chip::ErrorStr(err)); - } - - err = ConfigurationMgr().GetSetupDiscriminator(setUpDiscriminator); - if (err != CHIP_NO_ERROR) - { - EFR32_LOG("ConfigurationMgr().GetSetupDiscriminator() failed: %s", chip::ErrorStr(err)); - } - - err = ConfigurationMgr().GetVendorId(vendorId); - if (err != CHIP_NO_ERROR) + if (GetQRCode(setupPinCode, QRCode, chip::RendezvousInformationFlags::kBLE) == CHIP_NO_ERROR) { - EFR32_LOG("ConfigurationMgr().GetVendorId() failed: %s", chip::ErrorStr(err)); + EFR32_LOG("SetupPINCode: [%09u]", setupPinCode); + LCDWriteQRCode((uint8_t *) QRCode.c_str()); } - - err = ConfigurationMgr().GetProductId(productId); - if (err != CHIP_NO_ERROR) - { - EFR32_LOG("ConfigurationMgr().GetProductId() failed: %s", chip::ErrorStr(err)); - } - - payload.version = 1; - payload.vendorID = vendorId; - payload.productID = productId; - payload.setUpPINCode = setUpPINCode; - payload.discriminator = setUpDiscriminator; - chip::QRCodeSetupPayloadGenerator generator(payload); - - std::string result; - err = generator.payloadBase41Representation(result); - if (err != CHIP_NO_ERROR) + else { - EFR32_LOG("Failed to get Base41 payload for QR code with %s", chip::ErrorStr(err)); + EFR32_LOG("Getting QR code failed!"); } - - EFR32_LOG("SetupPINCode: [%09u]", setUpPINCode); - LCDWriteQRCode((uint8_t *) result.c_str()); +#else + PrintQRCode(chip::RendezvousInformationFlags::kBLE); #endif return err; @@ -418,7 +387,7 @@ void AppTask::FunctionHandler(AppEvent * aEvent) { EFR32_LOG("Device is commissioned to a Thread network."); } -#elif +#else EFR32_LOG("Thread is not defined."); #endif } diff --git a/examples/lighting-app/lighting-common/BUILD.gn b/examples/lighting-app/lighting-common/BUILD.gn index 3678a2e4381f93..8d1af58e6b3184 100644 --- a/examples/lighting-app/lighting-common/BUILD.gn +++ b/examples/lighting-app/lighting-common/BUILD.gn @@ -23,11 +23,12 @@ config("includes") { source_set("lighting-common") { sources = [ - "${chip_root}/examples/common/chip-app-server/DataModelHandler.cpp", + "${chip_root}/src/app/clusters/bindings/bindings.cpp", "${chip_root}/src/app/clusters/level-control/level-control.cpp", "${chip_root}/src/app/clusters/on-off-server/on-off.cpp", "${chip_root}/src/app/reporting/reporting-default-configuration.cpp", "${chip_root}/src/app/reporting/reporting.cpp", + "${chip_root}/src/app/server/DataModelHandler.cpp", "${chip_root}/src/app/util/af-event.cpp", "${chip_root}/src/app/util/af-main-common.cpp", "${chip_root}/src/app/util/attribute-size.cpp", @@ -45,10 +46,7 @@ source_set("lighting-common") { "gen/callback-stub.cpp", ] - deps = [ - "${chip_root}/examples/common/chip-app-server:chip-app-server", - "${chip_root}/src/lib", - ] + deps = [ "${chip_root}/src/lib" ] public_configs = [ ":includes" ] } diff --git a/examples/lighting-app/lighting-common/gen/af-structs.h b/examples/lighting-app/lighting-common/gen/af-structs.h index 6d04f3faa8e82d..02960bec60ddfb 100644 --- a/examples/lighting-app/lighting-common/gen/af-structs.h +++ b/examples/lighting-app/lighting-common/gen/af-structs.h @@ -1,4 +1,3 @@ - /* * * Copyright (c) 2020 Project CHIP Authors diff --git a/examples/lighting-app/lighting-common/gen/att-storage.h b/examples/lighting-app/lighting-common/gen/att-storage.h index 7572c8cbc338fb..74b44d6111b3e4 100644 --- a/examples/lighting-app/lighting-common/gen/att-storage.h +++ b/examples/lighting-app/lighting-common/gen/att-storage.h @@ -1,4 +1,3 @@ - /* * * Copyright (c) 2020 Project CHIP Authors diff --git a/examples/lighting-app/lighting-common/gen/attribute-id.h b/examples/lighting-app/lighting-common/gen/attribute-id.h index 648809ca67cd83..901653b7d8f3b6 100644 --- a/examples/lighting-app/lighting-common/gen/attribute-id.h +++ b/examples/lighting-app/lighting-common/gen/attribute-id.h @@ -1,4 +1,3 @@ - /* * * Copyright (c) 2020 Project CHIP Authors @@ -19,11 +18,15 @@ // Prevent multiple inclusion #pragma once +// Global cluster attribute ids +#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) +#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) +#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) +#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) + // Attribute ids for cluster: Basic // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_VERSION_ATTRIBUTE_ID (0x0000) @@ -44,14 +47,10 @@ #define ZCL_ALARM_MASK_ATTRIBUTE_ID (0x0013) #define ZCL_DISABLE_LOCAL_CONFIG_ATTRIBUTE_ID (0x0014) #define ZCL_SW_BUILD_ID_ATTRIBUTE_ID (0x4000) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Power Configuration // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_MAINS_VOLTAGE_ATTRIBUTE_ID (0x0000) @@ -111,14 +110,10 @@ #define ZCL_BATTERY_3_PERCENTAGE_THRESHOLD_2_ATTRIBUTE_ID (0x007C) #define ZCL_BATTERY_3_PERCENTAGE_THRESHOLD_3_ATTRIBUTE_ID (0x007D) #define ZCL_BATTERY_3_ALARM_STATE_ATTRIBUTE_ID (0x007E) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Device Temperature Configuration // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_CURRENT_TEMPERATURE_ATTRIBUTE_ID (0x0000) @@ -130,37 +125,25 @@ #define ZCL_HIGH_TEMP_THRESHOLD_ATTRIBUTE_ID (0x0012) #define ZCL_LOW_TEMP_DWELL_TRIP_POINT_ATTRIBUTE_ID (0x0013) #define ZCL_HIGH_TEMP_DWELL_TRIP_POINT_ATTRIBUTE_ID (0x0014) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Identify // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_IDENTIFY_TIME_ATTRIBUTE_ID (0x0000) #define ZCL_COMMISSION_STATE_ATTRIBUTE_ID (0x0001) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Groups // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_GROUP_NAME_SUPPORT_ATTRIBUTE_ID (0x0000) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Scenes // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_SCENE_COUNT_ATTRIBUTE_ID (0x0000) @@ -169,14 +152,10 @@ #define ZCL_SCENE_VALID_ATTRIBUTE_ID (0x0003) #define ZCL_SCENE_NAME_SUPPORT_ATTRIBUTE_ID (0x0004) #define ZCL_LAST_CONFIGURED_BY_ATTRIBUTE_ID (0x0005) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: On/off // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_ON_OFF_ATTRIBUTE_ID (0x0000) @@ -188,26 +167,18 @@ #define ZCL_ON_TIME_ATTRIBUTE_ID (0x4001) #define ZCL_OFF_WAIT_TIME_ATTRIBUTE_ID (0x4002) #define ZCL_START_UP_ON_OFF_ATTRIBUTE_ID (0x4003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: On/off Switch Configuration // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_SWITCH_TYPE_ATTRIBUTE_ID (0x0000) #define ZCL_SWITCH_ACTIONS_ATTRIBUTE_ID (0x0010) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Level Control // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_CURRENT_LEVEL_ATTRIBUTE_ID (0x0000) @@ -219,25 +190,17 @@ #define ZCL_OFF_TRANSITION_TIME_ATTRIBUTE_ID (0x0013) #define ZCL_DEFAULT_MOVE_RATE_ATTRIBUTE_ID (0x0014) #define ZCL_START_UP_CURRENT_LEVEL_ATTRIBUTE_ID (0x4000) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Alarms // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_ALARM_COUNT_ATTRIBUTE_ID (0x0000) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Time // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_TIME_ATTRIBUTE_ID (0x0000) @@ -250,14 +213,10 @@ #define ZCL_LOCAL_TIME_ATTRIBUTE_ID (0x0007) #define ZCL_LAST_SET_TIME_ATTRIBUTE_ID (0x0008) #define ZCL_VALID_UNTIL_TIME_ATTRIBUTE_ID (0x0009) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: RSSI Location // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_LOCATION_TYPE_ATTRIBUTE_ID (0x0000) @@ -273,14 +232,10 @@ #define ZCL_REPORTING_PERIOD_ATTRIBUTE_ID (0x0015) #define ZCL_CALCULATION_PERIOD_ATTRIBUTE_ID (0x0016) #define ZCL_NUMBER_RSSI_MEASUREMENTS_ATTRIBUTE_ID (0x0017) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Binary Input (Basic) // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_ACTIVE_TEXT_ATTRIBUTE_ID (0x0004) @@ -292,14 +247,10 @@ #define ZCL_RELIABILITY_ATTRIBUTE_ID (0x0067) #define ZCL_STATUS_FLAGS_ATTRIBUTE_ID (0x006F) #define ZCL_APPLICATION_TYPE_ATTRIBUTE_ID (0x0100) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Commissioning // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_SHORT_ADDRESS_ATTRIBUTE_ID (0x0000) @@ -326,14 +277,10 @@ #define ZCL_CONCENTRATOR_FLAG_ATTRIBUTE_ID (0x0040) #define ZCL_CONCENTRATOR_RADIUS_ATTRIBUTE_ID (0x0041) #define ZCL_CONCENTRATOR_DISCOVERY_TIME_ATTRIBUTE_ID (0x0042) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Partition // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_PARTITION_MAXIMUM_INCOMING_TRANSFER_SIZE_ATTRIBUTE_ID (0x0000) @@ -346,8 +293,6 @@ #define ZCL_NUMBER_OF_SEND_RETRIES_ATTRIBUTE_ID (0x0007) #define ZCL_SENDER_TIMEOUT_ATTRIBUTE_ID (0x0008) #define ZCL_RECEIVER_TIMEOUT_ATTRIBUTE_ID (0x0009) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Over the Air Bootloading @@ -365,18 +310,12 @@ #define ZCL_IMAGE_STAMP_ATTRIBUTE_ID (0x000A) #define ZCL_UPGRADE_ACTIVATION_POLICY_ATTRIBUTE_ID (0x000B) #define ZCL_UPGRADE_TIMEOUT_POLICY_ATTRIBUTE_ID (0x000C) -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Power Profile // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_TOTAL_PROFILE_NUM_ATTRIBUTE_ID (0x0000) @@ -384,27 +323,19 @@ #define ZCL_ENERGY_FORMATTING_ATTRIBUTE_ID (0x0002) #define ZCL_ENERGY_REMOTE_ATTRIBUTE_ID (0x0003) #define ZCL_SCHEDULE_MODE_ATTRIBUTE_ID (0x0004) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Appliance Control // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_START_TIME_ATTRIBUTE_ID (0x0000) #define ZCL_FINISH_TIME_ATTRIBUTE_ID (0x0001) #define ZCL_REMAINING_TIME_ATTRIBUTE_ID (0x0002) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Poll Control // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_CHECK_IN_INTERVAL_ATTRIBUTE_ID (0x0000) @@ -414,8 +345,6 @@ #define ZCL_CHECK_IN_INTERVAL_MIN_ATTRIBUTE_ID (0x0004) #define ZCL_LONG_POLL_INTERVAL_MIN_ATTRIBUTE_ID (0x0005) #define ZCL_FAST_POLL_TIMEOUT_MAX_ATTRIBUTE_ID (0x0006) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Green Power @@ -431,8 +360,6 @@ #define ZCL_GP_CLIENT_GP_SHARED_SECURITY_KEY_TYPE_ATTRIBUTE_ID (0x0020) #define ZCL_GP_CLIENT_GP_SHARED_SECURITY_KEY_ATTRIBUTE_ID (0x0021) #define ZCL_GP_CLIENT_GP_LINK_KEY_ATTRIBUTE_ID (0x0022) -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_GP_SERVER_GPS_MAX_SINK_TABLE_ENTRIES_ATTRIBUTE_ID (0x0000) @@ -446,26 +373,18 @@ #define ZCL_GP_SERVER_GP_SHARED_SECURITY_KEY_TYPE_ATTRIBUTE_ID (0x0020) #define ZCL_GP_SERVER_GP_SHARED_SECURITY_KEY_ATTRIBUTE_ID (0x0021) #define ZCL_GP_SERVER_GP_LINK_KEY_ATTRIBUTE_ID (0x0022) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Keep-Alive // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_KEEPALIVE_BASE_ATTRIBUTE_ID (0x0000) #define ZCL_KEEPALIVE_JITTER_ATTRIBUTE_ID (0x0001) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Shade Configuration // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_SHADE_CONFIG_PHYSICAL_CLOSED_LIMIT_ATTRIBUTE_ID (0x0000) @@ -473,14 +392,10 @@ #define ZCL_SHADE_CONFIG_STATUS_ATTRIBUTE_ID (0x0002) #define ZCL_SHADE_CONFIG_CLOSED_LIMIT_ATTRIBUTE_ID (0x0010) #define ZCL_SHADE_CONFIG_MODE_ATTRIBUTE_ID (0x0011) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Door Lock // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_LOCK_STATE_ATTRIBUTE_ID (0x0000) @@ -526,14 +441,10 @@ #define ZCL_KEYPAD_PROGRAMMING_EVENT_MASK_ATTRIBUTE_ID (0x0045) #define ZCL_RF_PROGRAMMING_EVENT_MASK_ATTRIBUTE_ID (0x0046) #define ZCL_RFID_PROGRAMMING_EVENT_MASK_ATTRIBUTE_ID (0x0047) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Window Covering // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_COVERING_TYPE_ATTRIBUTE_ID (0x0000) @@ -556,14 +467,10 @@ #define ZCL_MODE_ATTRIBUTE_ID (0x0017) #define ZCL_SETPOINTS_LIFT_ATTRIBUTE_ID (0x0018) #define ZCL_SETPOINTS_TILT_ATTRIBUTE_ID (0x0019) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Barrier Control // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_BARRIER_MOVING_STATE_ATTRIBUTE_ID (0x0001) @@ -576,14 +483,10 @@ #define ZCL_BARRIER_OPEN_PERIOD_ATTRIBUTE_ID (0x0008) #define ZCL_BARRIER_CLOSE_PERIOD_ATTRIBUTE_ID (0x0009) #define ZCL_BARRIER_POSITION_ATTRIBUTE_ID (0x000A) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Pump Configuration and Control // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_MAX_PRESSURE_ATTRIBUTE_ID (0x0000) @@ -610,14 +513,10 @@ #define ZCL_OPERATION_MODE_ATTRIBUTE_ID (0x0020) #define ZCL_CONTROL_MODE_ATTRIBUTE_ID (0x0021) #define ZCL_PUMP_ALARM_MASK_ATTRIBUTE_ID (0x0022) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Thermostat // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_LOCAL_TEMPERATURE_ATTRIBUTE_ID (0x0000) @@ -663,26 +562,18 @@ #define ZCL_AC_LOUVER_POSITION_ATTRIBUTE_ID (0x0045) #define ZCL_AC_COIL_TEMPERATURE_ATTRIBUTE_ID (0x0046) #define ZCL_AC_CAPACITY_FORMAT_ATTRIBUTE_ID (0x0047) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Fan Control // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_FAN_CONTROL_FAN_MODE_ATTRIBUTE_ID (0x0000) #define ZCL_FAN_CONTROL_FAN_MODE_SEQUENCE_ATTRIBUTE_ID (0x0001) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Dehumidification Control // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_RELATIVE_HUMIDITY_ATTRIBUTE_ID (0x0000) @@ -693,27 +584,19 @@ #define ZCL_DEHUMIDIFICATION_HYSTERESIS_ATTRIBUTE_ID (0x0013) #define ZCL_DEHUMIDIFICATION_MAX_COOL_ATTRIBUTE_ID (0x0014) #define ZCL_RELATIVE_HUMIDITY_DISPLAY_ATTRIBUTE_ID (0x0015) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Thermostat User Interface Configuration // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_TEMPERATURE_DISPLAY_MODE_ATTRIBUTE_ID (0x0000) #define ZCL_KEYPAD_LOCKOUT_ATTRIBUTE_ID (0x0001) #define ZCL_SCHEDULE_PROGRAMMING_VISIBILITY_ATTRIBUTE_ID (0x0002) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Color Control // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_COLOR_CONTROL_CURRENT_HUE_ATTRIBUTE_ID (0x0000) @@ -768,14 +651,10 @@ #define ZCL_COLOR_CONTROL_COLOR_TEMP_PHYSICAL_MAX_ATTRIBUTE_ID (0x400C) #define ZCL_COLOR_CONTROL_TEMPERATURE_LEVEL_MIN_MIREDS_ATTRIBUTE_ID (0x400D) #define ZCL_START_UP_COLOR_TEMPERATURE_MIREDS_ATTRIBUTE_ID (0x4010) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Ballast Configuration // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_PHYSICAL_MIN_LEVEL_ATTRIBUTE_ID (0x0000) @@ -794,14 +673,10 @@ #define ZCL_LAMP_BURN_HOURS_ATTRIBUTE_ID (0x0033) #define ZCL_LAMP_ALARM_MODE_ATTRIBUTE_ID (0x0034) #define ZCL_LAMP_BURN_HOURS_TRIP_POINT_ATTRIBUTE_ID (0x0035) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Illuminance Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_ILLUM_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) @@ -809,41 +684,29 @@ #define ZCL_ILLUM_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_ILLUM_TOLERANCE_ATTRIBUTE_ID (0x0003) #define ZCL_MEASUREMENT_LIGHT_SENSOR_TYPE_ATTRIBUTE_ID (0x0004) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Illuminance Level Sensing // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_LEVEL_STATUS_ATTRIBUTE_ID (0x0000) #define ZCL_SENSING_LIGHT_SENSOR_TYPE_ATTRIBUTE_ID (0x0001) #define ZCL_ILLUMINANCE_TARGET_LEVEL_ATTRIBUTE_ID (0x0010) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Temperature Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_TEMP_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_TEMP_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_TEMP_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_TEMP_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Pressure Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_PRESSURE_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) @@ -855,42 +718,30 @@ #define ZCL_PRESSURE_MAX_SCALED_VALUE_ATTRIBUTE_ID (0x0012) #define ZCL_PRESSURE_SCALED_TOLERANCE_ATTRIBUTE_ID (0x0013) #define ZCL_PRESSURE_SCALE_ATTRIBUTE_ID (0x0014) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Flow Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_FLOW_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_FLOW_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_FLOW_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_FLOW_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Relative Humidity Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_RELATIVE_HUMIDITY_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_RELATIVE_HUMIDITY_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_RELATIVE_HUMIDITY_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_RELATIVE_HUMIDITY_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Occupancy Sensing // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_OCCUPANCY_ATTRIBUTE_ID (0x0000) @@ -905,434 +756,310 @@ #define ZCL_PHYSICAL_CONTACT_OCCUPIED_TO_UNOCCUPIED_DELAY_ATTRIBUTE_ID (0x0030) #define ZCL_PHYSICAL_CONTACT_UNOCCUPIED_TO_OCCUPIED_DELAY_ATTRIBUTE_ID (0x0031) #define ZCL_PHYSICAL_CONTACT_UNOCCUPIED_TO_OCCUPIED_THRESHOLD_ATTRIBUTE_ID (0x0032) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Carbon Monoxide Concentration Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_CARBON_MONOXIDE_CONCENTRATION_MEASUREMENT_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_CARBON_MONOXIDE_CONCENTRATION_MEASUREMENT_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_CARBON_MONOXIDE_CONCENTRATION_MEASUREMENT_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_CARBON_MONOXIDE_CONCENTRATION_MEASUREMENT_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Carbon Dioxide Concentration Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_CARBON_DIOXIDE_CONCENTRATION_MEASUREMENT_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_CARBON_DIOXIDE_CONCENTRATION_MEASUREMENT_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_CARBON_DIOXIDE_CONCENTRATION_MEASUREMENT_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_CARBON_DIOXIDE_CONCENTRATION_MEASUREMENT_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Ethylene Concentration Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_ETHYLENE_CONCENTRATION_MEASUREMENT_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_ETHYLENE_CONCENTRATION_MEASUREMENT_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_ETHYLENE_CONCENTRATION_MEASUREMENT_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_ETHYLENE_CONCENTRATION_MEASUREMENT_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Ethylene Oxide Concentration Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_ETHYLENE_OXIDE_CONCENTRATION_MEASUREMENT_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_ETHYLENE_OXIDE_CONCENTRATION_MEASUREMENT_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_ETHYLENE_OXIDE_CONCENTRATION_MEASUREMENT_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_ETHYLENE_OXIDE_CONCENTRATION_MEASUREMENT_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Hydrogen Concentration Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_HYDROGEN_CONCENTRATION_MEASUREMENT_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_HYDROGEN_CONCENTRATION_MEASUREMENT_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_HYDROGEN_CONCENTRATION_MEASUREMENT_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_HYDROGEN_CONCENTRATION_MEASUREMENT_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Hydrogen Sulphide Concentration Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_HYDROGEN_SULPHIDE_CONCENTRATION_MEASUREMENT_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_HYDROGEN_SULPHIDE_CONCENTRATION_MEASUREMENT_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_HYDROGEN_SULPHIDE_CONCENTRATION_MEASUREMENT_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_HYDROGEN_SULPHIDE_CONCENTRATION_MEASUREMENT_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Nitric Oxide Concentration Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_NITRIC_OXIDE_CONCENTRATION_MEASUREMENT_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_NITRIC_OXIDE_CONCENTRATION_MEASUREMENT_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_NITRIC_OXIDE_CONCENTRATION_MEASUREMENT_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_NITRIC_OXIDE_CONCENTRATION_MEASUREMENT_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Nitrogen Dioxide Concentration Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_NITROGEN_DIOXIDE_CONCENTRATION_MEASUREMENT_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_NITROGEN_DIOXIDE_CONCENTRATION_MEASUREMENT_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_NITROGEN_DIOXIDE_CONCENTRATION_MEASUREMENT_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_NITROGEN_DIOXIDE_CONCENTRATION_MEASUREMENT_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Oxygen Concentration Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_OXYGEN_CONCENTRATION_MEASUREMENT_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_OXYGEN_CONCENTRATION_MEASUREMENT_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_OXYGEN_CONCENTRATION_MEASUREMENT_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_OXYGEN_CONCENTRATION_MEASUREMENT_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Ozone Concentration Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_OZONE_CONCENTRATION_MEASUREMENT_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_OZONE_CONCENTRATION_MEASUREMENT_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_OZONE_CONCENTRATION_MEASUREMENT_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_OZONE_CONCENTRATION_MEASUREMENT_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Sulfur Dioxide Concentration Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_SULFUR_DIOXIDE_CONCENTRATION_MEASUREMENT_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_SULFUR_DIOXIDE_CONCENTRATION_MEASUREMENT_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_SULFUR_DIOXIDE_CONCENTRATION_MEASUREMENT_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_SULFUR_DIOXIDE_CONCENTRATION_MEASUREMENT_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Dissolved Oxygen Concentration Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_DISSOLVED_OXYGEN_CONCENTRATION_MEASUREMENT_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_DISSOLVED_OXYGEN_CONCENTRATION_MEASUREMENT_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_DISSOLVED_OXYGEN_CONCENTRATION_MEASUREMENT_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_DISSOLVED_OXYGEN_CONCENTRATION_MEASUREMENT_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Bromate Concentration Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_BROMATE_CONCENTRATION_MEASUREMENT_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_BROMATE_CONCENTRATION_MEASUREMENT_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_BROMATE_CONCENTRATION_MEASUREMENT_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_BROMATE_CONCENTRATION_MEASUREMENT_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Chloramines Concentration Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_CHLORAMINES_CONCENTRATION_MEASUREMENT_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_CHLORAMINES_CONCENTRATION_MEASUREMENT_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_CHLORAMINES_CONCENTRATION_MEASUREMENT_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_CHLORAMINES_CONCENTRATION_MEASUREMENT_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Chlorine Concentration Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_CHLORINE_CONCENTRATION_MEASUREMENT_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_CHLORINE_CONCENTRATION_MEASUREMENT_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_CHLORINE_CONCENTRATION_MEASUREMENT_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_CHLORINE_CONCENTRATION_MEASUREMENT_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Fecal coliform and E. Coli Concentration Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_FECAL_COLIFORM_AND_E_COLI_CONCENTRATION_MEASUREMENT_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_FECAL_COLIFORM_AND_E_COLI_CONCENTRATION_MEASUREMENT_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_FECAL_COLIFORM_AND_E_COLI_CONCENTRATION_MEASUREMENT_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_FECAL_COLIFORM_AND_E_COLI_CONCENTRATION_MEASUREMENT_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Fluoride Concentration Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_FLUORIDE_CONCENTRATION_MEASUREMENT_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_FLUORIDE_CONCENTRATION_MEASUREMENT_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_FLUORIDE_CONCENTRATION_MEASUREMENT_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_FLUORIDE_CONCENTRATION_MEASUREMENT_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Haloacetic Acids Concentration Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_HALOACETIC_ACIDS_CONCENTRATION_MEASUREMENT_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_HALOACETIC_ACIDS_CONCENTRATION_MEASUREMENT_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_HALOACETIC_ACIDS_CONCENTRATION_MEASUREMENT_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_HALOACETIC_ACIDS_CONCENTRATION_MEASUREMENT_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Total Trihalomethanes Concentration Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_TOTAL_TRIHALOMETHANES_CONCENTRATION_MEASUREMENT_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_TOTAL_TRIHALOMETHANES_CONCENTRATION_MEASUREMENT_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_TOTAL_TRIHALOMETHANES_CONCENTRATION_MEASUREMENT_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_TOTAL_TRIHALOMETHANES_CONCENTRATION_MEASUREMENT_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Total Coliform Bacteria Concentration Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_TOTAL_COLIFORM_BACTERIA_CONCENTRATION_MEASUREMENT_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_TOTAL_COLIFORM_BACTERIA_CONCENTRATION_MEASUREMENT_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_TOTAL_COLIFORM_BACTERIA_CONCENTRATION_MEASUREMENT_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_TOTAL_COLIFORM_BACTERIA_CONCENTRATION_MEASUREMENT_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Turbidity Concentration Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_TURBIDITY_CONCENTRATION_MEASUREMENT_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_TURBIDITY_CONCENTRATION_MEASUREMENT_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_TURBIDITY_CONCENTRATION_MEASUREMENT_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_TURBIDITY_CONCENTRATION_MEASUREMENT_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Copper Concentration Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_COPPER_CONCENTRATION_MEASUREMENT_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_COPPER_CONCENTRATION_MEASUREMENT_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_COPPER_CONCENTRATION_MEASUREMENT_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_COPPER_CONCENTRATION_MEASUREMENT_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Lead Concentration Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_LEAD_CONCENTRATION_MEASUREMENT_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_LEAD_CONCENTRATION_MEASUREMENT_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_LEAD_CONCENTRATION_MEASUREMENT_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_LEAD_CONCENTRATION_MEASUREMENT_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Manganese Concentration Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_MANGANESE_CONCENTRATION_MEASUREMENT_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_MANGANESE_CONCENTRATION_MEASUREMENT_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_MANGANESE_CONCENTRATION_MEASUREMENT_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_MANGANESE_CONCENTRATION_MEASUREMENT_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Sulfate Concentration Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_SULFATE_CONCENTRATION_MEASUREMENT_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_SULFATE_CONCENTRATION_MEASUREMENT_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_SULFATE_CONCENTRATION_MEASUREMENT_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_SULFATE_CONCENTRATION_MEASUREMENT_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Bromodichloromethane Concentration Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_BROMODICHLOROMETHANE_CONCENTRATION_MEASUREMENT_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_BROMODICHLOROMETHANE_CONCENTRATION_MEASUREMENT_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_BROMODICHLOROMETHANE_CONCENTRATION_MEASUREMENT_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_BROMODICHLOROMETHANE_CONCENTRATION_MEASUREMENT_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Bromoform Concentration Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_BROMOFORM_CONCENTRATION_MEASUREMENT_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_BROMOFORM_CONCENTRATION_MEASUREMENT_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_BROMOFORM_CONCENTRATION_MEASUREMENT_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_BROMOFORM_CONCENTRATION_MEASUREMENT_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Chlorodibromomethane Concentration Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_CHLORODIBROMOMETHANE_CONCENTRATION_MEASUREMENT_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_CHLORODIBROMOMETHANE_CONCENTRATION_MEASUREMENT_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_CHLORODIBROMOMETHANE_CONCENTRATION_MEASUREMENT_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_CHLORODIBROMOMETHANE_CONCENTRATION_MEASUREMENT_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Chloroform Concentration Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_CHLOROFORM_CONCENTRATION_MEASUREMENT_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_CHLOROFORM_CONCENTRATION_MEASUREMENT_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_CHLOROFORM_CONCENTRATION_MEASUREMENT_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_CHLOROFORM_CONCENTRATION_MEASUREMENT_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Sodium Concentration Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_SODIUM_CONCENTRATION_MEASUREMENT_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_SODIUM_CONCENTRATION_MEASUREMENT_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_SODIUM_CONCENTRATION_MEASUREMENT_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_SODIUM_CONCENTRATION_MEASUREMENT_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: IAS Zone // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_ZONE_STATE_ATTRIBUTE_ID (0x0000) @@ -1342,58 +1069,38 @@ #define ZCL_ZONE_ID_ATTRIBUTE_ID (0x0011) #define ZCL_NUMBER_OF_ZONE_SENSITIVITY_LEVELS_SUPPORTED_ATTRIBUTE_ID (0x0012) #define ZCL_CURRENT_ZONE_SENSITIVITY_LEVEL_ATTRIBUTE_ID (0x0013) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: IAS ACE // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: IAS WD // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_MAX_DURATION_ATTRIBUTE_ID (0x0000) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Generic Tunnel // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_MAXIMUM_INCOMING_TRANSFER_SIZE_ATTRIBUTE_ID (0x0001) #define ZCL_MAXIMUM_OUTGOING_TRANSFER_SIZE_ATTRIBUTE_ID (0x0002) #define ZCL_PROTOCOL_ADDRESS_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: BACnet Protocol Tunnel // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: 11073 Protocol Tunnel // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_DEVICE_ID_LIST_ATTRIBUTE_ID (0x0000) @@ -1402,19 +1109,13 @@ #define ZCL_CONNECTED_ATTRIBUTE_ID (0x0003) #define ZCL_PREEMPTIBLE_ATTRIBUTE_ID (0x0004) #define ZCL_IDLE_TIMEOUT_ATTRIBUTE_ID (0x0005) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: ISO 7816 Protocol Tunnel // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_ISO7816_PROTOCOL_TUNNEL_STATUS_ATTRIBUTE_ID (0x0000) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Price @@ -1422,8 +1123,6 @@ #define ZCL_PRICE_INCREASE_RANDOMIZE_MINUTES_ATTRIBUTE_ID (0x0000) #define ZCL_PRICE_DECREASE_RANDOMIZE_MINUTES_ATTRIBUTE_ID (0x0001) #define ZCL_COMMODITY_TYPE_CLIENT_ATTRIBUTE_ID (0x0002) -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_TIER1_PRICE_LABEL_ATTRIBUTE_ID (0x0000) @@ -2438,8 +2137,6 @@ #define ZCL_RX_LAST_BILLING_PERIOD_START_ATTRIBUTE_ID (0x8702) #define ZCL_RX_LAST_BILLING_PERIOD_DURATION_ATTRIBUTE_ID (0x8703) #define ZCL_RX_LAST_BILLING_PERIOD_CONSOLIDATED_BILL_ATTRIBUTE_ID (0x8704) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Demand Response and Load Control @@ -2448,12 +2145,8 @@ #define ZCL_START_RANDOMIZATION_MINUTES_ATTRIBUTE_ID (0x0001) #define ZCL_DURATION_RANDOMIZATION_MINUTES_ATTRIBUTE_ID (0x0002) #define ZCL_DEVICE_CLASS_VALUE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Simple Metering @@ -2466,8 +2159,6 @@ #define ZCL_NOTIFICATION_FLAGS_6_ATTRIBUTE_ID (0x0005) #define ZCL_NOTIFICATION_FLAGS_7_ATTRIBUTE_ID (0x0006) #define ZCL_NOTIFICATION_FLAGS_8_ATTRIBUTE_ID (0x0007) -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_CURRENT_SUMMATION_DELIVERED_ATTRIBUTE_ID (0x0000) @@ -3354,35 +3045,23 @@ #define ZCL_CURRENT_REACTIVE_SUMMATION_Q2_ATTRIBUTE_ID (0x0D06) #define ZCL_CURRENT_REACTIVE_SUMMATION_Q3_ATTRIBUTE_ID (0x0D07) #define ZCL_CURRENT_REACTIVE_SUMMATION_Q4_ATTRIBUTE_ID (0x0D08) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Messaging // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Tunneling // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_CLOSE_TUNNEL_TIMEOUT_ATTRIBUTE_ID (0x0000) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Prepayment // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_PAYMENT_CONTROL_CONFIGURATION_ATTRIBUTE_ID (0x0000) @@ -3516,14 +3195,10 @@ #define ZCL_PREVIOUS_MONTH_13_COST_CONSUMPTION_DELIVERED_ATTRIBUTE_ID (0x055A) #define ZCL_PREVIOUS_MONTH_13_COST_CONSUMPTION_RECEIVED_ATTRIBUTE_ID (0x055B) #define ZCL_PREPAYMENT_HISTORICAL_FREEZE_TIME_ATTRIBUTE_ID (0x055C) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Energy Management // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_LOAD_CONTROL_STATE_ATTRIBUTE_ID (0x0000) @@ -3533,14 +3208,10 @@ #define ZCL_MINIMUM_OFF_TIME_ATTRIBUTE_ID (0x0004) #define ZCL_MINIMUM_ON_TIME_ATTRIBUTE_ID (0x0005) #define ZCL_MINIMUM_CYCLE_PERIOD_ATTRIBUTE_ID (0x0006) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Calendar // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_AUXILIARY_SWITCH_1_LABEL_ATTRIBUTE_ID (0x0000) @@ -3551,8 +3222,6 @@ #define ZCL_AUXILIARY_SWITCH_6_LABEL_ATTRIBUTE_ID (0x0005) #define ZCL_AUXILIARY_SWITCH_7_LABEL_ATTRIBUTE_ID (0x0006) #define ZCL_AUXILIARY_SWITCH_8_LABEL_ATTRIBUTE_ID (0x0007) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Device Management @@ -3991,8 +3660,6 @@ #define ZCL_QUERY_SPECIFIC_FILE_REQUEST_GENERATED_ATTRIBUTE_ID (0x08CC) #define ZCL_QUERY_SPECIFIC_FILE_RESPONSE_RECEIVED_ATTRIBUTE_ID (0x08CD) #define ZCL_QUERY_SPECIFIC_FILE_RESPONSE_REJECTED_ATTRIBUTE_ID (0x08CE) -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_PROVIDER_ID_SERVER_ATTRIBUTE_ID (0x0100) @@ -4014,34 +3681,22 @@ #define ZCL_WAN_STATUS_ATTRIBUTE_ID (0x0300) #define ZCL_LOW_MEDIUM_THRESHOLD_ATTRIBUTE_ID (0x0400) #define ZCL_MEDIUM_HIGH_THRESHOLD_ATTRIBUTE_ID (0x0401) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Events // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: MDU Pairing // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Sub-GHz // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_SUB_GHZ_CLUSTER_CHANNEL_CHANGE_ATTRIBUTE_ID (0x0000) @@ -4049,26 +3704,18 @@ #define ZCL_SUB_GHZ_CLUSTER_PAGE_29_CHANNEL_MASK_ATTRIBUTE_ID (0x0002) #define ZCL_SUB_GHZ_CLUSTER_PAGE_30_CHANNEL_MASK_ATTRIBUTE_ID (0x0003) #define ZCL_SUB_GHZ_CLUSTER_PAGE_31_CHANNEL_MASK_ATTRIBUTE_ID (0x0004) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Key Establishment // Client attributes #define ZCL_KEY_ESTABLISHMENT_SUITE_CLIENT_ATTRIBUTE_ID (0x0000) -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_KEY_ESTABLISHMENT_SUITE_SERVER_ATTRIBUTE_ID (0x0000) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Information // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_NODE_DESCRIPTION_ATTRIBUTE_ID (0x0000) @@ -4077,26 +3724,18 @@ #define ZCL_ENABLE_SECURE_CONFIGURATION_ATTRIBUTE_ID (0x0003) #define ZCL_NUMBER_OF_CONTENTS_ATTRIBUTE_ID (0x0010) #define ZCL_CONTENT_ROOT_ID_ATTRIBUTE_ID (0x0011) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Data Sharing // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_DEVICE_NAME_ATTRIBUTE_ID (0x0000) #define ZCL_DEVICE_DESCRIPTION_ATTRIBUTE_ID (0x0001) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Gaming // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_PLAYER_NAME_ATTRIBUTE_ID (0x0000) @@ -4119,27 +3758,19 @@ #define ZCL_COUNTER1_ATTRIBUTE_ID (0x001D) #define ZCL_COUNTER2_ATTRIBUTE_ID (0x001E) #define ZCL_DOWNLOADABLE_ATTRIBUTE_ID (0x001F) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Data Rate Control // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_AVERAGE_LATENCY_REQUIREMENT_ATTRIBUTE_ID (0x0000) #define ZCL_MAX_LATENCY_REQUIREMENT_ATTRIBUTE_ID (0x0001) #define ZCL_BANDWIDTH_REQUIREMENT_ATTRIBUTE_ID (0x0002) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Voice over ZigBee // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_CODEC_TYPE_ATTRIBUTE_ID (0x0000) @@ -4153,14 +3784,10 @@ #define ZCL_COMPRESSION_RATE_ATTRIBUTE_ID (0x0008) #define ZCL_OPTION_FLAGS_ATTRIBUTE_ID (0x0009) #define ZCL_THRESHOLD_ATTRIBUTE_ID (0x000A) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Chatting // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_U_ID_ATTRIBUTE_ID (0x0000) @@ -4168,14 +3795,10 @@ #define ZCL_C_ID_ATTRIBUTE_ID (0x0010) #define ZCL_NAME_ATTRIBUTE_ID (0x0011) #define ZCL_ENABLE_ADD_CHAT_ATTRIBUTE_ID (0x0020) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Payment // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_PAYMENT_USER_ID_ATTRIBUTE_ID (0x0000) @@ -4192,14 +3815,10 @@ #define ZCL_TRANS_ID_ATTRIBUTE_ID (0x0033) #define ZCL_TRANS_STATUS_ATTRIBUTE_ID (0x0034) #define ZCL_PAYMENT_STATUS_ATTRIBUTE_ID (0x0035) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Billing // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_USER_ID_ATTRIBUTE_ID (0x0000) @@ -4208,14 +3827,10 @@ #define ZCL_SESSION_INTERVAL_ATTRIBUTE_ID (0x0012) #define ZCL_TIMESTAMP_ATTRIBUTE_ID (0x0020) #define ZCL_DURATION_ATTRIBUTE_ID (0x0021) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Appliance Identification // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_BASIC_IDENTIFICATION_ATTRIBUTE_ID (0x0000) @@ -4230,14 +3845,10 @@ #define ZCL_PRODUCT_TYPE_NAME_ATTRIBUTE_ID (0x0018) #define ZCL_PRODUCT_TYPE_ID_ATTRIBUTE_ID (0x0019) #define ZCL_CECED_SPECIFICATION_VERSION_ATTRIBUTE_ID (0x001A) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Meter Identification // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_METER_COMPANY_NAME_ATTRIBUTE_ID (0x0000) @@ -4252,36 +3863,24 @@ #define ZCL_POD_ATTRIBUTE_ID (0x000C) #define ZCL_AVAILABLE_POWER_ATTRIBUTE_ID (0x000D) #define ZCL_POWER_THRESHOLD_ATTRIBUTE_ID (0x000E) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Appliance Events and Alert // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Appliance Statistics // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_LOG_MAX_SIZE_ATTRIBUTE_ID (0x0000) #define ZCL_LOG_QUEUE_MAX_SIZE_ATTRIBUTE_ID (0x0001) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Electrical Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_MEASUREMENT_TYPE_ATTRIBUTE_ID (0x0000) @@ -4412,14 +4011,10 @@ #define ZCL_RMS_EXTREME_UNDER_VOLTAGE_PERIOD_PHASE_C_ATTRIBUTE_ID (0x0A15) #define ZCL_RMS_VOLTAGE_SAG_PERIOD_PHASE_C_ATTRIBUTE_ID (0x0A16) #define ZCL_RMS_VOLTAGE_SWELL_PERIOD_PHASE_C_ATTRIBUTE_ID (0x0A17) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Diagnostics // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_NUMBER_OF_RESETS_ATTRIBUTE_ID (0x0000) @@ -4454,72 +4049,54 @@ #define ZCL_AVERAGE_MAC_RETRY_PER_APS_MSG_SENT_ATTRIBUTE_ID (0x011B) #define ZCL_LAST_MESSAGE_LQI_ATTRIBUTE_ID (0x011C) #define ZCL_LAST_MESSAGE_RSSI_ATTRIBUTE_ID (0x011D) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: ZLL Commissioning // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) + +// Attribute ids for cluster: Binding + +// Client attributes + +// Server attributes // Attribute ids for cluster: Sample Mfg Specific Cluster // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_ATTRIBUTE_ONE_ATTRIBUTE_ID (0x0000) #define ZCL_ATTRIBUTE_TWO_ATTRIBUTE_ID (0x0001) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Sample Mfg Specific Cluster 2 // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_ATTRIBUTE_THREE_ATTRIBUTE_ID (0x0000) #define ZCL_ATTRIBUTE_FOUR_ATTRIBUTE_ID (0x0001) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Configuration Cluster // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_TOKENS_LOCKED_ATTRIBUTE_ID (0x0000) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: MFGLIB Cluster // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_PACKETS_RECEIVED_ATTRIBUTE_ID (0x0000) #define ZCL_SAVED_RSSI_ATTRIBUTE_ID (0x0001) #define ZCL_SAVED_LQI_ATTRIBUTE_ID (0x0002) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: SL Works With All Hubs // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_SL_DISABLE_OTA_DOWNGRADES_ATTRIBUTE_ID (0x0002) @@ -4540,5 +4117,3 @@ #define ZCL_SL_PENDING_NETWORK_UPDATE_CHANNEL_ATTRIBUTE_ID (0x0011) #define ZCL_SL_PENDING_NETWORK_UPDATE_PANID_ATTRIBUTE_ID (0x0012) #define ZCL_SL_OTA_MAX_OFFLINE_DURATION_ATTRIBUTE_ID (0x0013) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) diff --git a/examples/lighting-app/lighting-common/gen/attribute-size.h b/examples/lighting-app/lighting-common/gen/attribute-size.h index 8d8659ee7ece2e..f9ef9212244eca 100644 --- a/examples/lighting-app/lighting-common/gen/attribute-size.h +++ b/examples/lighting-app/lighting-common/gen/attribute-size.h @@ -1,4 +1,3 @@ - /* * * Copyright (c) 2020 Project CHIP Authors @@ -32,3 +31,5 @@ ZCL_DATA8_ATTRIBUTE_TYPE, 1, ZCL_DATA16_ATTRIBUTE_TYPE, 2, ZCL_DATA24_ATTRIBUTE_ ZCL_FLOAT_SINGLE_ATTRIBUTE_TYPE, 4, ZCL_FLOAT_DOUBLE_ATTRIBUTE_TYPE, 8, ZCL_TIME_OF_DAY_ATTRIBUTE_TYPE, 4, ZCL_DATE_ATTRIBUTE_TYPE, 4, ZCL_UTC_TIME_ATTRIBUTE_TYPE, 4, ZCL_CLUSTER_ID_ATTRIBUTE_TYPE, 2, ZCL_ATTRIBUTE_ID_ATTRIBUTE_TYPE, 2, ZCL_BACNET_OID_ATTRIBUTE_TYPE, 4, ZCL_IEEE_ADDRESS_ATTRIBUTE_TYPE, 8, ZCL_SECURITY_KEY_ATTRIBUTE_TYPE, 16, + ZCL_ENDPOINT_ID_ATTRIBUTE_TYPE, 1, ZCL_GROUP_ID_ATTRIBUTE_TYPE, 2, ZCL_COMMAND_ID_ATTRIBUTE_TYPE, 1, ZCL_NODE_ID_ATTRIBUTE_TYPE, + 8, diff --git a/examples/lighting-app/lighting-common/gen/attribute-type.h b/examples/lighting-app/lighting-common/gen/attribute-type.h index bc5d1bae34b365..225cbc68be49c2 100644 --- a/examples/lighting-app/lighting-common/gen/attribute-type.h +++ b/examples/lighting-app/lighting-common/gen/attribute-type.h @@ -1,4 +1,3 @@ - /* * * Copyright (c) 2020 Project CHIP Authors @@ -77,5 +76,9 @@ enum ZCL_BACNET_OID_ATTRIBUTE_TYPE = 0xEA, // BACnet OID ZCL_IEEE_ADDRESS_ATTRIBUTE_TYPE = 0xF0, // IEEE address ZCL_SECURITY_KEY_ATTRIBUTE_TYPE = 0xF1, // 128-bit security key + ZCL_ENDPOINT_ID_ATTRIBUTE_TYPE = 0xF2, // Endpoint Id + ZCL_GROUP_ID_ATTRIBUTE_TYPE = 0xF3, // Group Id + ZCL_COMMAND_ID_ATTRIBUTE_TYPE = 0xF4, // Command Id + ZCL_NODE_ID_ATTRIBUTE_TYPE = 0xF5, // Node Id ZCL_UNKNOWN_ATTRIBUTE_TYPE = 0xFF, // Unknown }; diff --git a/examples/lighting-app/lighting-common/gen/call-command-handler.cpp b/examples/lighting-app/lighting-common/gen/call-command-handler.cpp index 0b9ff9100e931b..f177ad441c6909 100644 --- a/examples/lighting-app/lighting-common/gen/call-command-handler.cpp +++ b/examples/lighting-app/lighting-common/gen/call-command-handler.cpp @@ -1,4 +1,3 @@ - /* * * Copyright (c) 2020 Project CHIP Authors diff --git a/examples/lighting-app/lighting-common/gen/call-command-handler.h b/examples/lighting-app/lighting-common/gen/call-command-handler.h index c1b06642f07ac9..43164ad576bfa8 100644 --- a/examples/lighting-app/lighting-common/gen/call-command-handler.h +++ b/examples/lighting-app/lighting-common/gen/call-command-handler.h @@ -1,4 +1,3 @@ - /* * * Copyright (c) 2020 Project CHIP Authors diff --git a/examples/lighting-app/lighting-common/gen/callback-stub.cpp b/examples/lighting-app/lighting-common/gen/callback-stub.cpp index 232854b0ab82d5..2fdef872d8c4c4 100644 --- a/examples/lighting-app/lighting-common/gen/callback-stub.cpp +++ b/examples/lighting-app/lighting-common/gen/callback-stub.cpp @@ -1,4 +1,3 @@ - /* * * Copyright (c) 2020 Project CHIP Authors diff --git a/examples/lighting-app/lighting-common/gen/callback.h b/examples/lighting-app/lighting-common/gen/callback.h index 3172c588538880..d9a7391fb52899 100644 --- a/examples/lighting-app/lighting-common/gen/callback.h +++ b/examples/lighting-app/lighting-common/gen/callback.h @@ -1,4 +1,3 @@ - /* * * Copyright (c) 2020 Project CHIP Authors diff --git a/examples/lighting-app/lighting-common/gen/client-command-macro.h b/examples/lighting-app/lighting-common/gen/client-command-macro.h index f1b0c4633a2b14..7116663d885eca 100644 --- a/examples/lighting-app/lighting-common/gen/client-command-macro.h +++ b/examples/lighting-app/lighting-common/gen/client-command-macro.h @@ -1,4 +1,3 @@ - /* * * Copyright (c) 2020 Project CHIP Authors @@ -5663,6 +5662,32 @@ ZCL_GET_ENDPOINT_LIST_REQUEST_COMMAND_ID, "uuuub", startIndex, total, startIndex, count, \ endpointInformationRecordList, endpointInformationRecordListLen); +/** @brief Command description for Bind + * + * Command: Bind + * @param nodeId NODE_ID + * @param groupId GROUP_ID + * @param endpointId ENDPOINT_ID + * @param clusterId CLUSTER_ID + */ +#define emberAfFillCommandBindingClusterBind(nodeId, groupId, endpointId, clusterId) \ + emberAfFillExternalBuffer(mask, \ + \ + ZCL_BIND_COMMAND_ID, "uuuu", nodeId, groupId, endpointId, clusterId); + +/** @brief Command description for Unbind + * + * Command: Unbind + * @param nodeId NODE_ID + * @param groupId GROUP_ID + * @param endpointId ENDPOINT_ID + * @param clusterId CLUSTER_ID + */ +#define emberAfFillCommandBindingClusterUnbind(nodeId, groupId, endpointId, clusterId) \ + emberAfFillExternalBuffer(mask, \ + \ + ZCL_UNBIND_COMMAND_ID, "uuuu", nodeId, groupId, endpointId, clusterId); + /** @brief Command description for CommandOne * * Command: CommandOne diff --git a/examples/lighting-app/lighting-common/gen/cluster-id.h b/examples/lighting-app/lighting-common/gen/cluster-id.h index c341b079be401d..4db65e9cad99d0 100644 --- a/examples/lighting-app/lighting-common/gen/cluster-id.h +++ b/examples/lighting-app/lighting-common/gen/cluster-id.h @@ -1,4 +1,3 @@ - /* * * Copyright (c) 2020 Project CHIP Authors @@ -331,6 +330,9 @@ // Definitions for cluster: ZLL Commissioning #define ZCL_ZLL_COMMISSIONING_CLUSTER_ID (0x1000) +// Definitions for cluster: Binding +#define ZCL_BINDING_CLUSTER_ID (0xF000) + // Definitions for cluster: Sample Mfg Specific Cluster #define ZCL_SAMPLE_MFG_SPECIFIC_CLUSTER_ID (0xFC00) diff --git a/examples/lighting-app/lighting-common/gen/command-id.h b/examples/lighting-app/lighting-common/gen/command-id.h index 940258f4527aa5..42dcc0e89c71f5 100644 --- a/examples/lighting-app/lighting-common/gen/command-id.h +++ b/examples/lighting-app/lighting-common/gen/command-id.h @@ -1,4 +1,3 @@ - /* * * Copyright (c) 2020 Project CHIP Authors @@ -46,6 +45,7 @@ // Commands for cluster: Basic #define ZCL_RESET_TO_FACTORY_DEFAULTS_COMMAND_ID (0x00) +#define ZCL_MFG_SPECIFIC_PING_COMMAND_ID (0x00) // Commands for cluster: Identify #define ZCL_IDENTIFY_COMMAND_ID (0x00) @@ -683,6 +683,10 @@ #define ZCL_GET_ENDPOINT_LIST_REQUEST_COMMAND_ID (0x42) #define ZCL_GET_ENDPOINT_LIST_RESPONSE_COMMAND_ID (0x42) +// Commands for cluster: Binding +#define ZCL_BIND_COMMAND_ID (0x00) +#define ZCL_UNBIND_COMMAND_ID (0x01) + // Commands for cluster: Sample Mfg Specific Cluster #define ZCL_COMMAND_ONE_COMMAND_ID (0x00) diff --git a/examples/lighting-app/lighting-common/gen/endpoint_config.h b/examples/lighting-app/lighting-common/gen/endpoint_config.h index e13dfcab99d0b5..4d3b983ae14db6 100644 --- a/examples/lighting-app/lighting-common/gen/endpoint_config.h +++ b/examples/lighting-app/lighting-common/gen/endpoint_config.h @@ -101,7 +101,7 @@ #define ATTRIBUTE_SINGLETONS_SIZE (0) // Total size of attribute storage -#define ATTRIBUTE_MAX_SIZE 3 +#define ATTRIBUTE_MAX_SIZE 6 // Array of endpoints that are supported #define FIXED_ENDPOINT_ARRAY \ @@ -139,11 +139,6 @@ 0 \ } -#define EMBER_AF_GENERATED_PLUGIN_STACK_STATUS_FUNCTION_DECLARATIONS \ - void emberAfPluginNetworkSteeringStackStatusCallback(EmberStatus status); - -#define EMBER_AF_GENERATED_PLUGIN_STACK_STATUS_FUNCTION_CALLS emberAfPluginNetworkSteeringStackStatusCallback(status); - // Generated data for the command discovery #define GENERATED_COMMANDS \ { \ diff --git a/examples/lighting-app/lighting-common/gen/enums.h b/examples/lighting-app/lighting-common/gen/enums.h index 07c2881e641e97..eedb99290f59ce 100644 --- a/examples/lighting-app/lighting-common/gen/enums.h +++ b/examples/lighting-app/lighting-common/gen/enums.h @@ -1,4 +1,3 @@ - /* * * Copyright (c) 2020 Project CHIP Authors @@ -548,7 +547,7 @@ typedef enum EMBER_ZCL_DOOR_LOCK_OPERATING_MODE_PRIVACY_MODE = 0x02, EMBER_ZCL_DOOR_LOCK_OPERATING_MODE_NO_RF_LOCK_OR_UNLOCK = 0x03, EMBER_ZCL_DOOR_LOCK_OPERATING_MODE_LOCAL_PROGRAMMING_MODE = 0x04, - EMBER_ZCL_DOOR_LOCK_OPERATING_MODE_PASSAGE_MODE______ = 0x05, + EMBER_ZCL_DOOR_LOCK_OPERATING_MODE_PASSAGE_MODE = 0x05, } EmberAfDoorLockOperatingMode; // Enum for DoorLockOperationEventCode diff --git a/examples/lighting-app/lighting-common/gen/gen_config.h b/examples/lighting-app/lighting-common/gen/gen_config.h index cb2ad59b3767e1..ec6a2529108f34 100644 --- a/examples/lighting-app/lighting-common/gen/gen_config.h +++ b/examples/lighting-app/lighting-common/gen/gen_config.h @@ -1,4 +1,3 @@ - /* * * Copyright (c) 2020 Project CHIP Authors @@ -51,5 +50,5 @@ // Use this macro to check if Reporting plugin is included #define EMBER_AF_PLUGIN_REPORTING // User options for plugin Reporting -#define EMBER_AF_PLUGIN_REPORTING_TABLE_SIZE 5 +#define EMBER_AF_PLUGIN_REPORTING_TABLE_SIZE 20 #define EMBER_AF_PLUGIN_REPORTING_ENABLE_GROUP_BOUND_REPORTS diff --git a/examples/lighting-app/lighting-common/gen/print-cluster.h b/examples/lighting-app/lighting-common/gen/print-cluster.h index a37d7fb0495995..7155ccf0294122 100644 --- a/examples/lighting-app/lighting-common/gen/print-cluster.h +++ b/examples/lighting-app/lighting-common/gen/print-cluster.h @@ -1,4 +1,3 @@ - /* * * Copyright (c) 2020 Project CHIP Authors @@ -715,6 +714,12 @@ #define CHIP_PRINTCLUSTER_ZLL_COMMISSIONING_CLUSTER #endif +#if defined(ZCL_USING_BINDING_CLUSTER_SERVER) || defined(ZCL_USING_BINDING_CLUSTER_CLIENT) +#define CHIP_PRINTCLUSTER_BINDING_CLUSTER { ZCL_BINDING_CLUSTER_ID, 61440, "Binding" }, +#else +#define CHIP_PRINTCLUSTER_BINDING_CLUSTER +#endif + #if defined(ZCL_USING_SAMPLE_MFG_SPECIFIC_CLUSTER_SERVER) || defined(ZCL_USING_SAMPLE_MFG_SPECIFIC_CLUSTER_CLIENT) #define CHIP_PRINTCLUSTER_SAMPLE_MFG_SPECIFIC_CLUSTER { ZCL_SAMPLE_MFG_SPECIFIC_CLUSTER_ID, 64512, "Sample Mfg Specific Cluster" }, #else @@ -851,6 +856,7 @@ CHIP_PRINTCLUSTER_ELECTRICAL_MEASUREMENT_CLUSTER \ CHIP_PRINTCLUSTER_DIAGNOSTICS_CLUSTER \ CHIP_PRINTCLUSTER_ZLL_COMMISSIONING_CLUSTER \ + CHIP_PRINTCLUSTER_BINDING_CLUSTER \ CHIP_PRINTCLUSTER_SAMPLE_MFG_SPECIFIC_CLUSTER \ CHIP_PRINTCLUSTER_SAMPLE_MFG_SPECIFIC_CLUSTER_2 \ CHIP_PRINTCLUSTER_OTA_CONFIGURATION_CLUSTER \ diff --git a/examples/lighting-app/linux/BUILD.gn b/examples/lighting-app/linux/BUILD.gn index 34d6446083dc30..80477ba7332b3e 100644 --- a/examples/lighting-app/linux/BUILD.gn +++ b/examples/lighting-app/linux/BUILD.gn @@ -23,6 +23,7 @@ config("includes") { ".", "include", "${chip_root}/src/app/util", + "${chip_root}/src/app/server", ] } @@ -43,7 +44,6 @@ executable("chip-tool-server") { public_configs = [ ":includes" ] deps = [ - "${chip_root}/examples/common/chip-app-server:chip-app-server", "${chip_root}/examples/lighting-app/lighting-common", "${chip_root}/src/lib", ] diff --git a/examples/lighting-app/linux/Dockerfile b/examples/lighting-app/linux/Dockerfile index e1161e58c11295..dd885ca214b24c 100644 --- a/examples/lighting-app/linux/Dockerfile +++ b/examples/lighting-app/linux/Dockerfile @@ -16,7 +16,7 @@ # from chip-cirque-device-base -RUN apt-get update && apt-get install -y libglib2.0 avahi-daemon libavahi-client3 && rm -rf /var/lib/apt/lists/* + COPY out/debug/chip-tool-server /usr/bin/ COPY entrypoint.sh / diff --git a/examples/lighting-app/linux/main.cpp b/examples/lighting-app/linux/main.cpp index 9a1500a04f77b2..a6a3d9b390c367 100644 --- a/examples/lighting-app/linux/main.cpp +++ b/examples/lighting-app/linux/main.cpp @@ -44,8 +44,6 @@ using namespace chip::Inet; using namespace chip::Transport; using namespace chip::DeviceLayer; -constexpr uint32_t kDefaultSetupPinCode = 12345678; // TODO: Should be a macro in CHIPProjectConfig.h like other example apps. - void emberAfPostAttributeChangeCallback(EndpointId endpoint, ClusterId clusterId, AttributeId attributeId, uint8_t mask, uint16_t manufacturerCode, uint8_t type, uint8_t size, uint8_t * value) { @@ -113,19 +111,9 @@ CHIP_ERROR PrintQRCodeContent() std::string result; err = ConfigurationMgr().GetSetupPinCode(setUpPINCode); - if (err == CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND) - { - setUpPINCode = kDefaultSetupPinCode; - err = ConfigurationMgr().StoreSetupPinCode(setUpPINCode); - } SuccessOrExit(err); err = ConfigurationMgr().GetSetupDiscriminator(setUpDiscriminator); - if (err == CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND) - { - setUpDiscriminator = GetRandU16() & 0xFFF; - err = ConfigurationMgr().StoreSetupDiscriminator(setUpDiscriminator); - } SuccessOrExit(err); err = ConfigurationMgr().GetVendorId(vendorId); diff --git a/examples/lighting-app/nrfconnect/CMakeLists.txt b/examples/lighting-app/nrfconnect/CMakeLists.txt index 981d765d3666cb..91722d72bf96b8 100644 --- a/examples/lighting-app/nrfconnect/CMakeLists.txt +++ b/examples/lighting-app/nrfconnect/CMakeLists.txt @@ -16,23 +16,25 @@ cmake_minimum_required(VERSION 3.13.1) get_filename_component(CHIP_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/third_party/connectedhomeip REALPATH) -get_filename_component(CHIP_APP_SERVER ${CHIP_ROOT}/examples/common/chip-app-server REALPATH) get_filename_component(NRFCONNECT_COMMON ${CHIP_ROOT}/examples/platform/nrfconnect REALPATH) get_filename_component(LIGHTING_COMMON ${CHIP_ROOT}/examples/lighting-app/lighting-common REALPATH) -set(CONF_FILE ${CHIP_ROOT}/config/nrfconnect/sample-defaults.conf prj.conf) -set(CHIP_OPENTHREAD_CONFIG ${NRFCONNECT_COMMON}/project_include/OpenThreadConfig.h) +set(CONF_FILE ${CHIP_ROOT}/config/nrfconnect/app/sample-defaults.conf prj.conf) -set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CHIP_ROOT}/config/nrfconnect/) -include(nrfconnect-app) +include(${CHIP_ROOT}/config/nrfconnect/app/app.cmake) project(chip-nrf52840-lighting-example) -target_include_directories(app PRIVATE main/include ${LIGHTING_COMMON} ${NRFCONNECT_COMMON}/util/include ${NRFCONNECT_COMMON}/app/include ${CHIP_APP_SERVER}/include) + +target_include_directories(app PRIVATE + main/include + ${LIGHTING_COMMON} + ${NRFCONNECT_COMMON}/util/include + ${NRFCONNECT_COMMON}/app/include) + target_sources(app PRIVATE main/AppTask.cpp main/LightingManager.cpp main/main.cpp - main/Rpc.cpp main/ZclCallbacks.cpp ${LIGHTING_COMMON}/gen/call-command-handler.cpp ${LIGHTING_COMMON}/gen/callback-stub.cpp @@ -40,10 +42,7 @@ target_sources(app PRIVATE ${NRFCONNECT_COMMON}/util/NFCWidget.cpp ${NRFCONNECT_COMMON}/util/ThreadUtil.cpp ${NRFCONNECT_COMMON}/app/Service.cpp - ${CHIP_APP_SERVER}/DataModelHandler.cpp - ${CHIP_APP_SERVER}/Server.cpp - ${CHIP_APP_SERVER}/QRCodeUtil.cpp - ${CHIP_APP_SERVER}/RendezvousServer.cpp + ${CHIP_ROOT}/src/app/server/DataModelHandler.cpp ${CHIP_ROOT}/src/app/reporting/reporting-default-configuration.cpp ${CHIP_ROOT}/src/app/reporting/reporting.cpp ${CHIP_ROOT}/src/app/util/af-event.cpp @@ -59,6 +58,7 @@ target_sources(app PRIVATE ${CHIP_ROOT}/src/app/util/process-cluster-message.cpp ${CHIP_ROOT}/src/app/util/process-global-message.cpp ${CHIP_ROOT}/src/app/util/util.cpp + ${CHIP_ROOT}/src/app/clusters/bindings/bindings.cpp ${CHIP_ROOT}/src/app/clusters/on-off-server/on-off.cpp ${CHIP_ROOT}/src/app/clusters/level-control/level-control.cpp ) @@ -83,12 +83,20 @@ pw_proto_library(pigweed_lighting_protolib main/pigweed_lighting.proto ) +target_sources(app PRIVATE + main/Rpc.cpp + ${NRFCONNECT_COMMON}/util/PigweedLogger.cpp +) + +target_include_directories(app PRIVATE + ${ZEPHYR_BASE}/subsys // required to get access to `log_output_std.h` +) + target_link_libraries(app PRIVATE - pigweed_lighting_protolib.nanopb_rpc - pw_hdlc_lite - pw_log - pw_rpc.nanopb.echo_service - pw_rpc.server + pigweed_lighting_protolib.nanopb_rpc + pw_hdlc_lite + pw_log + pw_rpc.server ) endif(CONFIG_CHIP_PW_RPC) diff --git a/examples/lighting-app/nrfconnect/README.md b/examples/lighting-app/nrfconnect/README.md index bd3fc373ba64a1..cc5711c1a3c262 100644 --- a/examples/lighting-app/nrfconnect/README.md +++ b/examples/lighting-app/nrfconnect/README.md @@ -1,9 +1,9 @@ # CHIP nRF Connect Lighting Example Application The nRF Connect Lighting Example demonstrates how to remotely control a white -non-dimmable light bulb. It uses buttons to test changing the lighting and -device states and LEDs to show the state of these changes. You can use this -example as a reference for creating your own application. +dimmable light bulb. It uses buttons to test changing the lighting and device +states and LEDs to show the state of these changes. You can use this example as +a reference for creating your own application. The example is based on [CHIP](https://github.com/project-chip/connectedhomeip) and the nRF Connect platform, and supports remote access and control of a @@ -14,23 +14,21 @@ into an existing CHIP network and can be controlled by this network.
-- [CHIP nRF Connect Lighting Example Application](#chip-nrf-connect-lighting-example-application) - - [Overview](#overview) - - [Bluetooth LE advertising](#bluetooth-le-advertising) - - [Bluetooth LE rendezvous](#bluetooth-le-rendezvous) - - [Thread provisioning](#thread-provisioning) - - [Requirements](#requirements) - - [Device UI](#device-ui) - - [Setting up the environment](#setting-up-the-environment) - - [Using Docker container for setup](#using-docker-container-for-setup) - - [Using native shell for setup](#using-native-shell-for-setup) - - [Building](#building) - - [Removing build artifacts](#removing-build-artifacts) - - [Building with release configuration](#building-with-release-configuration) - - [Configuring the example](#configuring-the-example) +- [Overview](#overview) + - [Bluetooth LE advertising](#bluetooth-le-advertising) + - [Bluetooth LE rendezvous](#bluetooth-le-rendezvous) +- [Requirements](#requirements) +- [Device UI](#device-ui) +- [Setting up the environment](#setting-up-the-environment) + - [Using Docker container for setup](#using-docker-container-for-setup) + - [Using native shell for setup](#using-native-shell-for-setup) +- [Building](#building) + - [Removing build artifacts](#removing-build-artifacts) + - [Building with release configuration](#building-with-release-configuration) - [Building with Pigweed RPCs](#building-with-pigweed-rpcs) - - [Flashing and debugging](#flashing-and-debugging) - - [Testing the example](#testing-the-example) +- [Configuring the example](#configuring-the-example) +- [Flashing and debugging](#flashing-and-debugging) +- [Testing the example](#testing-the-example)
@@ -69,7 +67,9 @@ commissioner role. To start the rendezvous, the controller must get the commissioning information from the CHIP device. The data payload is encoded within a QR code, printed to -the UART console, and shared using an NFC tag. +the UART console, and shared using an NFC tag. For security reasons, you must +start NFC tag emulation manually after powering up the device by pressing +**Button 4**. #### Thread provisioning @@ -145,8 +145,8 @@ opposite one. **Button 3** — Pressing the button once starts the Thread networking in the test mode using the default configuration. -**Button 4** — Pressing the button once starts the Bluetooth LE -advertising for the predefined period of time. +**Button 4** — Pressing the button once starts the NFC tag emulation and +enables Bluetooth LE advertising for the predefined period of time. **SEGGER J-Link USB port** can be used to get logs from the device or communicate with it using the @@ -294,11 +294,20 @@ following command: To build the example with release configuration that disables the diagnostic features like logs and command-line interface, run the following command: - $ west build -b board-name -- -DOVERLAY_CONFIG=third_party/connectedhomeip/config/nrfconnect/release.conf + $ west build -b board-name -- -DOVERLAY_CONFIG=third_party/connectedhomeip/config/nrfconnect/app/release.conf Remember to replace _board-name_ with the name of the Nordic Semiconductor's board you own. +### Building with Pigweed RPCs + +The RPCs in `lighting-common/pigweed-lighting.proto` can be used to control +various functionalities of the lighting app from a USB-connected host computer. +To build the example with the RPC server, run the following command with +_board-name_ replaced with the name of the Nordic Semiconductor's board you own: + + $ west build -b board-name -- -DOVERLAY_CONFIG=rpc.overlay +
@@ -326,18 +335,6 @@ page. -## Building with Pigweed RPCs - -The RPCs in lighting-common/pigweed-lighting.proto can be used to control -various functionalities of the lighting app from a USB-connected host computer. - - $ cd - # First time build - $ west build -b nrf52840dk_nrf52840 -- -DOVERLAY_CONFIG=rpc.overlay - - # Any subsequent build - $ west build -- -DOVERLAY_CONFIG=rpc.overlay - ## Flashing and debugging To flash the application to the device, use the west tool and run the following diff --git a/examples/lighting-app/nrfconnect/dts.overlay b/examples/lighting-app/nrfconnect/dts.overlay index e3716a4a9248e9..ffe1d09ad6e40a 100644 --- a/examples/lighting-app/nrfconnect/dts.overlay +++ b/examples/lighting-app/nrfconnect/dts.overlay @@ -15,13 +15,36 @@ */ / { + /* * In some default configurations within the nRF Connect SDK, * e.g. on nRF52840, the chosen zephyr,entropy node is &cryptocell. * This devicetree overlay ensures that default is overridden wherever it * is set, as this application uses the RNG node for entropy exclusively. */ + chosen { zephyr,entropy = &rng; }; + + /* + * By default, PWM module is only configured for led0 (LED1 on the board). + * The lighting-app, however, uses LED2 to show the state of the lighting, + * including its brightness level. + */ + aliases { + pwm-led1 = &pwm_led1; + }; + + pwmleds { + pwm_led1: pwm_led_1 { + pwms = < &pwm0 0xe >; + }; + }; + +}; + +&pwm0 { + ch1-pin = < 0xe >; + ch1-inverted; }; diff --git a/examples/lighting-app/nrfconnect/main/AppTask.cpp b/examples/lighting-app/nrfconnect/main/AppTask.cpp index 267597170e9bf9..888373455d7cbb 100644 --- a/examples/lighting-app/nrfconnect/main/AppTask.cpp +++ b/examples/lighting-app/nrfconnect/main/AppTask.cpp @@ -22,7 +22,6 @@ #include "AppEvent.h" #include "LEDWidget.h" #include "LightingManager.h" -#include "LogUtils.h" #include "QRCodeUtil.h" #include "Server.h" #include "Service.h" @@ -43,8 +42,11 @@ #include #include +#include #include +LOG_MODULE_DECLARE(app); + namespace { constexpr int kFactoryResetTriggerTimeout = 3000; @@ -100,7 +102,7 @@ int AppTask::Init() k_timer_init(&sFunctionTimer, &AppTask::TimerEventHandler, nullptr); k_timer_user_data_set(&sFunctionTimer, this); - ret = LightingMgr().Init(LIGHTING_GPIO_DEVICE_NAME, LIGHTING_GPIO_PIN); + ret = LightingMgr().Init(LIGHTING_PWM_DEVICE, LIGHTING_PWM_CHANNEL); if (ret != 0) return ret; @@ -119,13 +121,6 @@ int AppTask::Init() } PlatformMgr().AddEventHandler(AppTask::ThreadProvisioningHandler, 0); - - ret = StartNFCTag(); - if (ret) - { - LOG_ERR("Starting NFC Tag failed"); - return ret; - } #endif return 0; @@ -381,6 +376,22 @@ void AppTask::StartBLEAdvertisementHandler(AppEvent * aEvent) if (aEvent->ButtonEvent.PinNo != BLE_ADVERTISEMENT_START_BUTTON) return; + if (!sNFC.IsTagEmulationStarted()) + { + if (!(GetAppTask().StartNFCTag() < 0)) + { + LOG_INF("Started NFC Tag emulation"); + } + else + { + LOG_ERR("Starting NFC Tag failed"); + } + } + else + { + LOG_INF("NFC Tag emulation is already started"); + } + if (!ConnectivityMgr().IsBLEAdvertisingEnabled()) { ConnectivityMgr().SetBLEAdvertisingEnabled(true); @@ -430,7 +441,7 @@ int AppTask::StartNFCTag() VerifyOrExit(!result, ChipLogError(AppServer, "Getting QR code payload failed")); result = sNFC.StartTagEmulation(QRCode.c_str(), QRCode.size()); - VerifyOrExit(!result, ChipLogError(AppServer, "Starting NFC Tag emulation failed")); + VerifyOrExit(result >= 0, ChipLogError(AppServer, "Starting NFC Tag emulation failed")); exit: return result; @@ -505,13 +516,23 @@ void AppTask::DispatchEvent(AppEvent * aEvent) void AppTask::UpdateClusterState() { - uint8_t newValue = LightingMgr().IsTurnedOn(); + uint8_t onoff = LightingMgr().IsTurnedOn(); // write the new on/off value - EmberAfStatus status = emberAfWriteAttribute(1, ZCL_ON_OFF_CLUSTER_ID, ZCL_ON_OFF_ATTRIBUTE_ID, CLUSTER_MASK_SERVER, &newValue, + EmberAfStatus status = emberAfWriteAttribute(1, ZCL_ON_OFF_CLUSTER_ID, ZCL_ON_OFF_ATTRIBUTE_ID, CLUSTER_MASK_SERVER, &onoff, ZCL_BOOLEAN_ATTRIBUTE_TYPE); if (status != EMBER_ZCL_STATUS_SUCCESS) { - LOG_ERR("Updating on/off %x", status); + LOG_ERR("Updating on/off cluster failed: %x", status); + } + + uint8_t level = LightingMgr().GetLevel(); + + status = emberAfWriteAttribute(1, ZCL_LEVEL_CONTROL_CLUSTER_ID, ZCL_CURRENT_LEVEL_ATTRIBUTE_ID, CLUSTER_MASK_SERVER, &level, + ZCL_DATA8_ATTRIBUTE_TYPE); + + if (status != EMBER_ZCL_STATUS_SUCCESS) + { + LOG_ERR("Updating level cluster failed: %x", status); } } diff --git a/examples/lighting-app/nrfconnect/main/LightingManager.cpp b/examples/lighting-app/nrfconnect/main/LightingManager.cpp index b437e5b4502cef..c89f1b2412842b 100644 --- a/examples/lighting-app/nrfconnect/main/LightingManager.cpp +++ b/examples/lighting-app/nrfconnect/main/LightingManager.cpp @@ -19,34 +19,31 @@ #include "LightingManager.h" #include "AppConfig.h" -#include "LogUtils.h" +#include +#include #include +LOG_MODULE_DECLARE(app); + LightingManager LightingManager::sLight; -int LightingManager::Init(const char * gpioDeviceName, gpio_pin_t gpioPin) +int LightingManager::Init(const char * pwmDeviceName, uint32_t pwmChannel) { // We use a gpioPin instead of a LEDWidget here because we want to use PWM // and other features instead of just on/off. mState = kState_On; - mGPIOPin = gpioPin; - mGPIODevice = const_cast(device_get_binding(gpioDeviceName)); + mLevel = kMaxLevel; + mPwmDevice = device_get_binding(pwmDeviceName); + mPwmChannel = pwmChannel; - if (!mGPIODevice) + if (!mPwmDevice) { - LOG_ERR("Cannot find GPIO port %s", LOG_STRDUP(gpioDeviceName)); + LOG_ERR("Cannot find PWM device %s", log_strdup(pwmDeviceName)); return -ENODEV; } - int res = gpio_pin_configure(mGPIODevice, mGPIOPin, GPIO_OUTPUT); - if (res != 0) - { - LOG_ERR("Cannot configure GPIO pin"); - return res; - } - Set(false); return 0; } @@ -74,7 +71,7 @@ bool LightingManager::InitiateAction(Action_t aAction, int32_t aActor, uint8_t s action_initiated = true; new_state = kState_Off; } - else if (aAction == LEVEL_ACTION) + else if (aAction == LEVEL_ACTION && *value != mLevel) { action_initiated = true; if (*value == 0) @@ -114,20 +111,20 @@ bool LightingManager::InitiateAction(Action_t aAction, int32_t aActor, uint8_t s void LightingManager::SetLevel(uint8_t aLevel) { - LOG_INF("LEVEL %u", aLevel); - // TODO: use the level for PWM + LOG_INF("Setting brightness level to %u", aLevel); + mLevel = aLevel; + UpdateLight(); } void LightingManager::Set(bool aOn) { - if (aOn) - { - mState = kState_On; - gpio_pin_set_raw(mGPIODevice, mGPIOPin, 0); - } - else - { - mState = kState_Off; - gpio_pin_set_raw(mGPIODevice, mGPIOPin, 1); - } + mState = aOn ? kState_On : kState_Off; + UpdateLight(); +} + +void LightingManager::UpdateLight() +{ + constexpr uint32_t kPwmWidthUs = 1000u; + const uint8_t level = mState == kState_On ? mLevel : 0; + pwm_pin_set_usec(mPwmDevice, mPwmChannel, kPwmWidthUs, kPwmWidthUs * level / kMaxLevel, 0); } diff --git a/examples/lighting-app/nrfconnect/main/Rpc.cpp b/examples/lighting-app/nrfconnect/main/Rpc.cpp index 2694c5927529dc..98c5a08164ea71 100644 --- a/examples/lighting-app/nrfconnect/main/Rpc.cpp +++ b/examples/lighting-app/nrfconnect/main/Rpc.cpp @@ -17,27 +17,25 @@ */ #include "Rpc.h" -#ifdef CONFIG_CHIP_PW_RPC #include "AppTask.h" + #include "main/pigweed_lighting.rpc.pb.h" -#include "pw_hdlc_lite/encoder.h" #include "pw_hdlc_lite/rpc_channel.h" #include "pw_hdlc_lite/rpc_packets.h" -#include "pw_hdlc_lite/sys_io_stream.h" -#include "pw_rpc/echo_service_nanopb.h" #include "pw_rpc/server.h" +#include "pw_stream/sys_io_stream.h" #include "pw_sys_io/sys_io.h" #include "pw_sys_io_nrfconnect/init.h" + +#include + #include -#include -#include -#endif + +LOG_MODULE_DECLARE(app); namespace chip { namespace rpc { -#ifdef CONFIG_CHIP_PW_RPC - class LightingService final : public generated::LightingService { public: @@ -80,18 +78,13 @@ void RegisterServices() void Start() { - // Send log messages to HDLC address 1. This prevents logs from interfering - // with pw_rpc communications. - pw::log_basic::SetOutput( - [](std::string_view log) { pw::hdlc_lite::WriteInformationFrame(1, std::as_bytes(std::span(log)), writer); }); - // Set up the server and start processing data. RegisterServices(); // Buffer for decoding incoming HDLC frames. std::array input_buffer; - PW_LOG_INFO("Starting pw_rpc server"); + LOG_INF("Starting pw_rpc server"); pw::hdlc_lite::ReadAndProcessPackets(server, hdlc_channel_output, input_buffer); } @@ -110,17 +103,5 @@ void RunRpcService(void *, void *, void *) Start(); } -#else // CONFIG_CHIP_PW_RPC -class LightingService -{ -}; - -k_tid_t Init() -{ - return nullptr; -} - -#endif - } // namespace rpc } // namespace chip diff --git a/examples/lighting-app/nrfconnect/main/include/AppConfig.h b/examples/lighting-app/nrfconnect/main/include/AppConfig.h index c9245dd0c6368f..1ec504dc95430d 100644 --- a/examples/lighting-app/nrfconnect/main/include/AppConfig.h +++ b/examples/lighting-app/nrfconnect/main/include/AppConfig.h @@ -30,8 +30,8 @@ #define BLE_ADVERTISEMENT_START_BUTTON_MASK DK_BTN4_MSK #define SYSTEM_STATE_LED DK_LED1 // led0 in device tree -#define LIGHTING_GPIO_DEVICE_NAME DT_GPIO_LABEL(DT_ALIAS(led1), gpios) -#define LIGHTING_GPIO_PIN DT_GPIO_PIN(DT_ALIAS(led1), gpios) +#define LIGHTING_PWM_DEVICE DT_PWMS_LABEL(DT_ALIAS(pwm_led1)) +#define LIGHTING_PWM_CHANNEL DT_PWMS_CHANNEL(DT_ALIAS(pwm_led1)) // Time it takes in ms for the simulated actuator to move from one state to another. #define ACTUATOR_MOVEMENT_PERIOS_MS 2000 diff --git a/examples/lighting-app/nrfconnect/main/include/LightingManager.h b/examples/lighting-app/nrfconnect/main/include/LightingManager.h index 03fc91c9326d04..06aabbf3fb651b 100644 --- a/examples/lighting-app/nrfconnect/main/include/LightingManager.h +++ b/examples/lighting-app/nrfconnect/main/include/LightingManager.h @@ -43,22 +43,27 @@ class LightingManager using LightingCallback_fn = void (*)(Action_t, int32_t); - int Init(const char * gpioDeviceName, gpio_pin_t gpioPin); + int Init(const char * pwmDeviceName, uint32_t pwmChannel); bool IsTurnedOn() const { return mState == kState_On; } + uint8_t GetLevel() const { return mLevel; } bool InitiateAction(Action_t aAction, int32_t aActor, uint8_t size, uint8_t * value); void SetCallbacks(LightingCallback_fn aActionInitiated_CB, LightingCallback_fn aActionCompleted_CB); private: - friend LightingManager & LightingMgr(void); + static constexpr uint8_t kMaxLevel = 255; + + friend LightingManager & LightingMgr(); State_t mState; - gpio_pin_t mGPIOPin; - device * mGPIODevice; + uint8_t mLevel; + const device * mPwmDevice; + uint32_t mPwmChannel; LightingCallback_fn mActionInitiated_CB; LightingCallback_fn mActionCompleted_CB; void Set(bool aOn); void SetLevel(uint8_t aLevel); + void UpdateLight(); static LightingManager sLight; }; diff --git a/examples/lighting-app/nrfconnect/main/main.cpp b/examples/lighting-app/nrfconnect/main/main.cpp index 3cb6e86f6113e4..2211f127183a7b 100644 --- a/examples/lighting-app/nrfconnect/main/main.cpp +++ b/examples/lighting-app/nrfconnect/main/main.cpp @@ -17,7 +17,6 @@ */ #include "AppTask.h" -#include "LogUtils.h" #include "Rpc.h" #include @@ -25,13 +24,18 @@ #include +LOG_MODULE_REGISTER(app); + using namespace ::chip; using namespace ::chip::Inet; using namespace ::chip::DeviceLayer; int main(void) { +#if CONFIG_CHIP_PW_RPC chip::rpc::Init(); +#endif + int ret = 0; k_thread_priority_set(k_current_get(), K_PRIO_COOP(CONFIG_NUM_COOP_PRIORITIES - 1)); diff --git a/examples/lighting-app/nrfconnect/prj.conf b/examples/lighting-app/nrfconnect/prj.conf index 027504c40df4fb..5072d04cfba9ff 100644 --- a/examples/lighting-app/nrfconnect/prj.conf +++ b/examples/lighting-app/nrfconnect/prj.conf @@ -20,6 +20,7 @@ # Add support for LEDs and buttons on Nordic development kits CONFIG_DK_LIBRARY=y +CONFIG_PWM=y # Default OpenThread network settings CONFIG_OPENTHREAD_PANID=4660 @@ -33,3 +34,7 @@ CONFIG_BT_DEVICE_NAME="ChipLight" # Additional configs for debbugging experience. CONFIG_THREAD_NAME=y CONFIG_MPU_STACK_GUARD=y + +# CHIP configuration +CONFIG_CHIP_PROJECT_CONFIG="main/include/CHIPProjectConfig.h" +CONFIG_CHIP_OPENTHREAD_CONFIG="../../platform/nrfconnect/project_include/OpenThreadConfig.h" diff --git a/examples/lighting-app/nrfconnect/rpc.overlay b/examples/lighting-app/nrfconnect/rpc.overlay index c672c74585a142..a1c47c3b84edf6 100644 --- a/examples/lighting-app/nrfconnect/rpc.overlay +++ b/examples/lighting-app/nrfconnect/rpc.overlay @@ -23,12 +23,23 @@ CONFIG_CHIP_PW_RPC=y # Add support for C++17 to build Pigweed components +CONFIG_STD_CPP14=n CONFIG_STD_CPP17=y # Add support for Zephyr console component to use it for Pigweed console purposes CONFIG_CONSOLE_SUBSYS=y CONFIG_CONSOLE_GETCHAR=y +CONFIG_CONSOLE_PUTCHAR_BUFSIZE=256 -CONFIG_BOOT_BANNER=n -CONFIG_LOG=n +# Disable features which may interfere with Pigweed HDLC transport CONFIG_SHELL=n +CONFIG_OPENTHREAD_SHELL=n +CONFIG_BOOT_BANNER=n + +# Configure Zephyr logger with defaults backends disabled as the app provides its own, +# based on Pigweed HDLC. +CONFIG_LOG=y +CONFIG_LOG_MINIMAL=n +CONFIG_LOG_IMMEDIATE=y +CONFIG_LOG_BACKEND_UART=n +CONFIG_LOG_BACKEND_RTT=n diff --git a/examples/common/chip-app-server/.gn b/examples/lock-app/cc13x2_26x2/.gn similarity index 94% rename from examples/common/chip-app-server/.gn rename to examples/lock-app/cc13x2_26x2/.gn index c3cfa5fd40318d..89dc9a6fcb5f6c 100644 --- a/examples/common/chip-app-server/.gn +++ b/examples/lock-app/cc13x2_26x2/.gn @@ -19,5 +19,8 @@ buildconfig = "//build/config/BUILDCONFIG.gn" check_system_includes = true default_args = { + target_cpu = "arm" + target_os = "freertos" + import("//args.gni") } diff --git a/examples/lock-app/cc13x2_26x2/BUILD.gn b/examples/lock-app/cc13x2_26x2/BUILD.gn new file mode 100644 index 00000000000000..f74f6ec3122bc5 --- /dev/null +++ b/examples/lock-app/cc13x2_26x2/BUILD.gn @@ -0,0 +1,97 @@ +# Copyright (c) 2020 Project CHIP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/config/defaults.gni") +import("//build_overrides/chip.gni") +import("//build_overrides/openthread.gni") +import("//build_overrides/ti_simplelink_sdk.gni") +import("${ti_simplelink_sdk_build_root}/ti_simplelink_executable.gni") +import("${ti_simplelink_sdk_build_root}/ti_simplelink_sdk.gni") + +assert(current_os == "freertos") + +project_dir = "${chip_root}/examples/lock-app/cc13x2_26x2" + +ti_simplelink_sdk("sdk") { + include_dirs = [ "${project_dir}/main/include" ] + + defines = [] + if (is_debug) { + defines += [ "BUILD_RELEASE=0" ] + } else { + defines += [ "BUILD_RELEASE=1" ] + } +} + +ti_sysconfig("sysconfig") { + sources = [ "${project_dir}/chip.syscfg" ] + outputs = [ + "ti_devices_config.c", + "ti_radio_config.c", + "ti_radio_config.h", + "ti_drivers_config.c", + "ti_drivers_config.h", + + # disabled until upstream generation is aligned + #"tiop_config.h", + #"tiop_config.c", + + # not traditional source files + #"ti_utils_build_linker.cmd.genlibs", + #"syscfg_c.rov.xs", + #"ti_utils_runtime_model.gv", + #"ti_utils_runtime_Makefile", + ] +} + +ti_simplelink_executable("lock_app") { + include_dirs = [ + "${chip_root}/src/app/util", + "${chip_root}/src/app/server", + "${project_dir}", + "${project_dir}/main", + "${project_dir}/main/include", + ] + defines = [] + output_name = "chip-cc13x2_26x2-lock-example.out" + + public_deps = [ + ":sdk", + ":sysconfig", + "${chip_root}/examples/lock-app/lock-common", + "${chip_root}/src/lib", + "${openthread_root}:libopenthread-cli-mtd", + ] + + sources = [ + "${project_dir}/main/AppTask.cpp", + "${project_dir}/main/BoltLockManager.cpp", + "${project_dir}/main/ZclCallbacks.cpp", + "${project_dir}/main/main.cpp", + ] + + output_dir = root_out_dir + + ldscript = "${ti_simplelink_sdk_root}/source/ti/boards/cc13x2_cc26x2/cc13x2_cc26x2_freertos.lds" + + ldflags = [ "-T" + rebase_path(ldscript, root_build_dir) ] +} + +group("cc13x2_26x2") { + deps = [ ":lock_app" ] +} + +group("default") { + deps = [ ":cc13x2_26x2" ] +} diff --git a/examples/lock-app/cc13x2_26x2/README.md b/examples/lock-app/cc13x2_26x2/README.md new file mode 100644 index 00000000000000..88a45f9d1e0662 --- /dev/null +++ b/examples/lock-app/cc13x2_26x2/README.md @@ -0,0 +1,175 @@ +# CHIP CC1352 CC2652 Lock Example Application + +An example application showing the use [CHIP][chip] on the Texas Instruments +CC13X2_26X2 family of Wireless MCUs. + +--- + +- [CHIP CC1352 CC2652 Lock Example Application](#chip-cc1352-cc2652-lock-example-application) + - [Introduction](#introduction) + - [Device UI](#device-ui) + - [Building](#building) + - [Preparation](#preparation) + - [Compilation](#compilation) + - [Programming](#programming) + - [UniFlash](#uniflash) + - [Code Composer Studio](#code-composer-studio) + - [Viewing Logging Output](#viewing-logging-output) + +--- + +## Introduction + +![CC1352R1_LAUNCHXL](doc/images/cc1352r1_launchxl.jpg) + +The CC13X2_26X2 lock example application provides a working demonstration of a +connected door lock device. This uses the open-source CHIP implementation and +the Texas Instruments SimpleLink™ CC13x2 and CC26x2 software development kit. + +This example is enabled to build on all members of the `CC13X2_26X2` family of +MCUs [recommended for Thread][ti_thread_dnd]. By default this example targets +the [CC1352R1_LAUNCHXL][cc1352r1_launchxl] LaunchPad. + +The lock example is intended to serve both as a means to explore the workings of +CHIP, as well as a template for creating real products based on the Texas +Instruments devices. + +## Device UI + +This example application has a simple User Interface to depict the state of the +door lock and to control the state. The user LEDs on the LaunchPad are set on +when the lock is locked, and are set off when unlocked. The LEDs will flash when +in the transition state between locked and unlocked. The user buttons are used +for requesting lock and unlock of the door lock. The left button (`BTN-1`) is +used to request locking. The right button (`BTN-2`) us used to request +unlocking. + +## Building + +### Preparation + +Some initial setup is necessary for preparing the build environment. This +section will need to be done when migrating to new versions of the SDK. + +- Download and install the [SimpleLink™ CC13x2 and CC26x2 software development + kit (SDK)][simplelink_sdk] ([4.30.00.54][simplelink_sdk_4.30.00.54]) + + - Follow the default installation instructions when executing the + installer. + + - The version of OpenThread used in this repository is newer than the one + packaged with the TI SDK. Check the following section for a list of + changes needed. + +- Download and install [SysConfig][sysconfig] + ([sysconfig-1.5.0_1397][sysconfig-1.5.0_1397]) + + - This may have already been installed with your SimpleLink SDK install + +- If you have installed different versions, the build defaults will need to be + changed to reflect this in + `${chip_root}/examples/build_overrides/ti_simplelink_sdk.gni`. + +- Install Python 3.8 for the GN build system: + + ``` + # Linux + $ sudo apt-get install python3.8 python3.8-distutils python3.8-dev python3.8-venv + # Distutils listed due to a package manager error on Ubuntu 18.04 + + ``` + + - You will have to ensure that the default version of Python 3 is Python + 3.8. + +- run the bootstrap script to setup the build environment. + + ``` + $ cd ~/connectedhomeip + $ source ./script/bootstrap.sh + + ``` + +#### Changes to the TI SDK + +The OpenThread library will set the short address assigned to the device as soon +as it receives the Child ID response. This may happen while the radio driver is +still in transmit mode. This is easilly fixed by removing state check in the +else condition in +`${ti_simplelink_sdk_root}/examples/rtos/${ti_simplelink_board}/thread/cli_mtd/platform/radio.c` +on linke 1791. + +``` +- else if (sState != platformRadio_phyState_Transmit) ++ else + { + sReceiveCmd.localShortAddr = aAddress; + } +``` + +### Compilation + +It is necessary to activate the environment in every new shell. Then run GN and +Ninja to build the executable. + +- Activate the build environment with the repository activate script. + + ``` + $ cd ~/connectedhomeip + $ source ./script/activate.sh + + ``` + +- Run the build to produce a default executable. By default on Linux both the + TI SimpleLink SDK and Sysconfig are located in a `ti` folder in the user's + home directory, and you must provide the absolute path to them. For example + `/home/username/ti/simplelink_cc13x2_26x2_sdk_4_30_00_54` and + `/home/username/ti/sysconfig_1.6.0`. On Windows the default directory is + `C:\ti` + + ``` + $ cd ~/connectedhomeip/examples/lock-app/cc13x2_26x2 + $ export TI_SIMPLELINK_SDK_ROOT= + $ export TI_SYSCONFIG_ROOT= + $ gn gen out/debug --args="ti_simplelink_sdk_root=\"${TI_SIMPLELINK_SDK_ROOT}\" ti_sysconfig_root=\"${TI_SYSCONFIG_ROOT}\"" + $ ninja -C out/debug + + ``` + +## Programming + +Loading the built image onto a LaunchPad is supported through two methods; +Uniflash and Code Composer Studio (CCS). UniFlash can be used to load the image. +Code Composer Studio can be used to load the image and debug the source code. + +### UniFlash + +[Programming UniFlash](doc/programming-uniflash.md) + +### Code Composer Studio + +[Programming and Debugging with CCS](doc/programming-ccs.md) + +## Viewing Logging Output + +By default the log output will be sent to the Application/User UART. Open a +terminal emulator to that port to see the output with the following options: + +| Parameter | Value | +| ------------ | -------- | +| Speed (baud) | `115200` | +| Data bits | `8` | +| Stop bits | `1` | +| Parity | `None` | +| Flow control | `None` | + +[chip]: https://github.com/project-chip/connectedhomeip +[cc1352r1_launchxl]: https://www.ti.com/tool/LAUNCHXL-CC1352R1 +[simplelink_sdk]: https://www.ti.com/tool/SIMPLELINK-CC13X2-26X2-SDK +[simplelink_sdk_4.30.00.54]: + https://www.ti.com/tool/download/SIMPLELINK-CC13X2-26X2-SDK/4.30.00.54 +[sysconfig]: https://www.ti.com/tool/SYSCONFIG +[sysconfig-1.5.0_1397]: + http://software-dl.ti.com/ccs/esd/sysconfig/sysconfig-1.5.0_1397-setup.run +[ti_thread_dnd]: + https://www.ti.com/wireless-connectivity/thread/design-development.html diff --git a/examples/lock-app/cc13x2_26x2/args.gni b/examples/lock-app/cc13x2_26x2/args.gni new file mode 100644 index 00000000000000..ad369fe0d90291 --- /dev/null +++ b/examples/lock-app/cc13x2_26x2/args.gni @@ -0,0 +1,29 @@ +# Copyright (c) 2020 Project CHIP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build_overrides/chip.gni") +import("${chip_root}/examples/platform/cc13x2_26x2/args.gni") + +ti_simplelink_sdk_target = get_label_info(":sdk", "label_no_toolchain") +ti_simplelink_sysconfig_target = + get_label_info(":sysconfig", "label_no_toolchain") + +ti_simplelink_board = "CC1352R1_LAUNCHXL" + +# use -Os instead of -Og +#is_debug = false + +# disable BLE for now +chip_config_network_layer_ble = false +chip_bypass_rendezvous = true diff --git a/examples/common/chip-app-server/build b/examples/lock-app/cc13x2_26x2/build similarity index 100% rename from examples/common/chip-app-server/build rename to examples/lock-app/cc13x2_26x2/build diff --git a/examples/lock-app/cc13x2_26x2/build_overrides b/examples/lock-app/cc13x2_26x2/build_overrides new file mode 120000 index 00000000000000..e578e73312ebd1 --- /dev/null +++ b/examples/lock-app/cc13x2_26x2/build_overrides @@ -0,0 +1 @@ +../../build_overrides \ No newline at end of file diff --git a/examples/lock-app/cc13x2_26x2/chip.syscfg b/examples/lock-app/cc13x2_26x2/chip.syscfg new file mode 100644 index 00000000000000..21978a1be2e902 --- /dev/null +++ b/examples/lock-app/cc13x2_26x2/chip.syscfg @@ -0,0 +1,123 @@ +/* + * + * Copyright (c) 2020 Project CHIP Authors + * Copyright (c) 2020 Texas Instruments Incorporated + * 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. + */ + +/* + * chip.syscfg + */ + +/* Modules */ +var AESCCM = scripting.addModule("/ti/drivers/AESCCM"); +var AESECB = scripting.addModule("/ti/drivers/AESECB"); +var Button = scripting.addModule("/ti/drivers/apps/Button"); +var ECJPAKE = scripting.addModule("/ti/drivers/ECJPAKE"); +var LED = scripting.addModule("/ti/drivers/apps/LED"); +var NVS = scripting.addModule("/ti/drivers/NVS"); +var RF = scripting.addModule("/ti/drivers/RF"); +var RFDesign = scripting.addModule("ti/devices/radioconfig/rfdesign"); +var RTOS = scripting.addModule("/ti/drivers/RTOS"); +var TRNG = scripting.addModule("/ti/drivers/TRNG"); +var Thread = scripting.addModule("/ti/thread/thread"); +var SHA2 = scripting.addModule("/ti/drivers/SHA2"); +var UART = scripting.addModule("/ti/drivers/UART"); + +/* Instances */ +var AESCCM = AESCCM.addInstance(); +var AESECB = AESECB.addInstance(); +var Button1 = Button.addInstance(); +var Button2 = Button.addInstance(); +var ECJPAKE = ECJPAKE.addInstance(); +var NVS1 = NVS.addInstance(); +var SHA21 = SHA2.addInstance(); +var LED1 = LED.addInstance(); +var LED2 = LED.addInstance(); +var TRNG1 = TRNG.addInstance(); +var UART1 = UART.addInstance(); +var UART2 = UART.addInstance(); + +/* RTOS */ +RTOS.name = "FreeRTOS"; + +/* Left Button */ +Button1.$name = "CONFIG_BTN_LEFT"; +Button1.$hardware = system.deviceData.board.components["BTN-1"]; +Button1.gpioPin.$name = "CONFIG_GPIO_BTN1"; +Button1.gpioPin.pull = "Pull Up"; +Button1.gpioPin.interruptTrigger = "Falling Edge"; +Button1.gpioPin.pinInstance.$name = "CONFIG_PIN_BTN1"; + +/* Left Button */ +Button2.$name = "CONFIG_BTN_RIGHT"; +Button2.$hardware = system.deviceData.board.components["BTN-2"]; +Button2.gpioPin.$name = "CONFIG_GPIO_BTN2"; +Button2.gpioPin.pull = "Pull Up"; +Button2.gpioPin.interruptTrigger = "Falling Edge"; +Button2.gpioPin.pinInstance.$name = "CONFIG_PIN_BTN2"; + +/* NVS */ +NVS1.$name = "CONFIG_NVSINTERNAL"; +NVS1.internalFlash.regionBase = 0x52000; // Base Address of Region +NVS1.internalFlash.regionSize = 0x4000; // Size of Region (in bytes) + +/* RF */ +RF.$name = "CONFIG_RF0"; +/* if an antenna component exists, assign it to the rf instance */ +if (system.deviceData.board && system.deviceData.board.components.RF) { + RF.$hardware = system.deviceData.board.components.RF; +} + +const rfDesignSettings = system.getScript("/ti/common/lprf_rf_design_settings.js").rfDesignSettings; +for(var setting in rfDesignSettings) +{ + RFDesign[setting] = rfDesignSettings[setting]; +} + +/* Red LED */ +LED1.$name = "CONFIG_LED_RED"; +LED1.$hardware = system.deviceData.board.components.LED_RED; +LED1.gpioPin.$name = "CONFIG_GPIO_RLED"; +LED1.gpioPin.mode = "Output"; +LED1.gpioPin.callbackFunction = ""; +LED1.gpioPin.pinInstance.$name = "CONFIG_PIN_RLED"; + +/* Green LED */ +LED2.$name = "CONFIG_LED_GREEN"; +LED2.$hardware = system.deviceData.board.components.LED_GREEN; +LED2.gpioPin.$name = "CONFIG_GPIO_GLED"; +LED2.gpioPin.mode = "Output"; +LED2.gpioPin.callbackFunction = ""; +LED2.gpioPin.pinInstance.$name = "CONFIG_PIN_GLED"; + +/* Debug UART */ +UART1.$hardware = system.deviceData.board.components.XDS110UART; +UART1.$name = "CONFIG_UART_DEBUG"; + +/* Display UART */ +UART2.$name = "CONFIG_DISPLAY_UART"; +UART2.uart.txPin.$suggestSolution = "boosterpack.32"; +UART2.uart.rxPin.$suggestSolution = "boosterpack.18"; + +/* TRNG */ +TRNG1.$name = "CONFIG_TRNG_0"; + +/* Thread */ +Thread.deviceType = "mtd"; +Thread.deviceTypeReadOnly = true; +/* Thread SysConfig generated sources are not used until the upstream modules + * can be updated to enable CHIP. + */ diff --git a/examples/lock-app/cc13x2_26x2/doc/images/cc1352r1_launchxl.jpg b/examples/lock-app/cc13x2_26x2/doc/images/cc1352r1_launchxl.jpg new file mode 100644 index 00000000000000..b46e258311e19b Binary files /dev/null and b/examples/lock-app/cc13x2_26x2/doc/images/cc1352r1_launchxl.jpg differ diff --git a/examples/lock-app/cc13x2_26x2/doc/images/ccs-1.jpg b/examples/lock-app/cc13x2_26x2/doc/images/ccs-1.jpg new file mode 100644 index 00000000000000..85dc32c0530acc Binary files /dev/null and b/examples/lock-app/cc13x2_26x2/doc/images/ccs-1.jpg differ diff --git a/examples/lock-app/cc13x2_26x2/doc/images/ccs-10.jpg b/examples/lock-app/cc13x2_26x2/doc/images/ccs-10.jpg new file mode 100644 index 00000000000000..f1563f8933b01c Binary files /dev/null and b/examples/lock-app/cc13x2_26x2/doc/images/ccs-10.jpg differ diff --git a/examples/lock-app/cc13x2_26x2/doc/images/ccs-11.jpg b/examples/lock-app/cc13x2_26x2/doc/images/ccs-11.jpg new file mode 100644 index 00000000000000..a3d63e4dfcd944 Binary files /dev/null and b/examples/lock-app/cc13x2_26x2/doc/images/ccs-11.jpg differ diff --git a/examples/lock-app/cc13x2_26x2/doc/images/ccs-12.jpg b/examples/lock-app/cc13x2_26x2/doc/images/ccs-12.jpg new file mode 100644 index 00000000000000..ad07cbf180d1d0 Binary files /dev/null and b/examples/lock-app/cc13x2_26x2/doc/images/ccs-12.jpg differ diff --git a/examples/lock-app/cc13x2_26x2/doc/images/ccs-13.jpg b/examples/lock-app/cc13x2_26x2/doc/images/ccs-13.jpg new file mode 100644 index 00000000000000..43010467f37d95 Binary files /dev/null and b/examples/lock-app/cc13x2_26x2/doc/images/ccs-13.jpg differ diff --git a/examples/lock-app/cc13x2_26x2/doc/images/ccs-2.jpg b/examples/lock-app/cc13x2_26x2/doc/images/ccs-2.jpg new file mode 100644 index 00000000000000..119886b184c7c5 Binary files /dev/null and b/examples/lock-app/cc13x2_26x2/doc/images/ccs-2.jpg differ diff --git a/examples/lock-app/cc13x2_26x2/doc/images/ccs-3.jpg b/examples/lock-app/cc13x2_26x2/doc/images/ccs-3.jpg new file mode 100644 index 00000000000000..4bd4776f692973 Binary files /dev/null and b/examples/lock-app/cc13x2_26x2/doc/images/ccs-3.jpg differ diff --git a/examples/lock-app/cc13x2_26x2/doc/images/ccs-4.jpg b/examples/lock-app/cc13x2_26x2/doc/images/ccs-4.jpg new file mode 100644 index 00000000000000..33cb488a6541ec Binary files /dev/null and b/examples/lock-app/cc13x2_26x2/doc/images/ccs-4.jpg differ diff --git a/examples/lock-app/cc13x2_26x2/doc/images/ccs-5.jpg b/examples/lock-app/cc13x2_26x2/doc/images/ccs-5.jpg new file mode 100644 index 00000000000000..66a2855628808b Binary files /dev/null and b/examples/lock-app/cc13x2_26x2/doc/images/ccs-5.jpg differ diff --git a/examples/lock-app/cc13x2_26x2/doc/images/ccs-6.jpg b/examples/lock-app/cc13x2_26x2/doc/images/ccs-6.jpg new file mode 100644 index 00000000000000..d0270ecaaedf9f Binary files /dev/null and b/examples/lock-app/cc13x2_26x2/doc/images/ccs-6.jpg differ diff --git a/examples/lock-app/cc13x2_26x2/doc/images/ccs-7.jpg b/examples/lock-app/cc13x2_26x2/doc/images/ccs-7.jpg new file mode 100644 index 00000000000000..73f21c9a69d118 Binary files /dev/null and b/examples/lock-app/cc13x2_26x2/doc/images/ccs-7.jpg differ diff --git a/examples/lock-app/cc13x2_26x2/doc/images/ccs-8.jpg b/examples/lock-app/cc13x2_26x2/doc/images/ccs-8.jpg new file mode 100644 index 00000000000000..36a34f4a5e12e3 Binary files /dev/null and b/examples/lock-app/cc13x2_26x2/doc/images/ccs-8.jpg differ diff --git a/examples/lock-app/cc13x2_26x2/doc/images/ccs-9.jpg b/examples/lock-app/cc13x2_26x2/doc/images/ccs-9.jpg new file mode 100644 index 00000000000000..e6a4e04371a369 Binary files /dev/null and b/examples/lock-app/cc13x2_26x2/doc/images/ccs-9.jpg differ diff --git a/examples/lock-app/cc13x2_26x2/doc/images/uniflash-1.jpg b/examples/lock-app/cc13x2_26x2/doc/images/uniflash-1.jpg new file mode 100644 index 00000000000000..6a38f067e4fc4c Binary files /dev/null and b/examples/lock-app/cc13x2_26x2/doc/images/uniflash-1.jpg differ diff --git a/examples/lock-app/cc13x2_26x2/doc/images/uniflash-2.jpg b/examples/lock-app/cc13x2_26x2/doc/images/uniflash-2.jpg new file mode 100644 index 00000000000000..6a2a9a8a813ce0 Binary files /dev/null and b/examples/lock-app/cc13x2_26x2/doc/images/uniflash-2.jpg differ diff --git a/examples/lock-app/cc13x2_26x2/doc/images/uniflash-3.jpg b/examples/lock-app/cc13x2_26x2/doc/images/uniflash-3.jpg new file mode 100644 index 00000000000000..c6e6dd2249f498 Binary files /dev/null and b/examples/lock-app/cc13x2_26x2/doc/images/uniflash-3.jpg differ diff --git a/examples/lock-app/cc13x2_26x2/doc/programming-ccs.md b/examples/lock-app/cc13x2_26x2/doc/programming-ccs.md new file mode 100644 index 00000000000000..f56fc6057011c9 --- /dev/null +++ b/examples/lock-app/cc13x2_26x2/doc/programming-ccs.md @@ -0,0 +1,115 @@ +# Programming and Debugging with CCS + +- Download and install [Code Composer Studio][ccs]. + +- Use `xdsdfu` to determine the XDS110 serial number to identify the device. + This may be skipped if there is only one LaunchPad connected to your PC, but + it is recommended. + + ``` + C:\>cd \ti\ccs1010\ccs\ccs_base\common\uscif\xds110 + + C:\ti\ccs1010\ccs\ccs_base\common\uscif\xds110>xdsdfu.exe -e + + USB Device Firmware Upgrade Utility + Copyright (c) 2008-2019 Texas Instruments Incorporated. All rights reserved. + + Scanning USB buses for supported XDS110 devices... + ``` + +<<<< Device 0 >>>> + +VID: 0x0451 PID: 0xbef3 Device Name: XDS110 Embed with CMSIS-DAP Version: +3.0.0.13 Manufacturer: Texas Instruments Serial Num: L4100652 Mode: Runtime +Configuration: Standard + +Found 1 device. + +``` +In this example, my LaunchPad's XDS110 has a serial number of `L4100652`. + +- Start a new Code Composer Studio Workspace. This can be named anything you +would like. But it is recommended that you use a blank workspace. + +![CCS step 1](images/ccs-1.jpg) + +- Create a new Target Configuration File by selecting `File` >> `New` >> +`Target Configuration File`. This file can also be exported from UniFlash +with the `download ccxml` function. + +![CCS step 2](images/ccs-2.jpg) + +- Name the new ccxml file a useful name. Here I use the XDS110 serial number +from before. Leave the Location as the shared location and click `Finish` to +create the file. + +![CCS step 3](images/ccs-3.jpg) + +- In the new ccxml, select the `Connection` and the `Board or Device`. This may +be different for your setup, but all LaunchPads will use the `Texas +Instruments XDS110 USB Debug Probe` for the target connection. And the and a +`CC1352R1F3` is mounted on the `CC1352R1_LAUNCHXL` LaunchPads. Builds for +other LaunchPads should use the corresponding SoC name. + +![CCS step 4](images/ccs-4.jpg) + +- Now set the XDS110 serial number in the advanced tab of the ccxml. First +select the `Advanced` tab at the bottom of the window. Then select the Debug +Probe in the connection tree. Then select `Select by serial number` in the +`Debug Probe Selection`. Then enter the serial number from `xdsdfu` earlier +in the `Enter the serial number` text field. Finally click `Save` to save +your ccxml. + +![CCS step 5](images/ccs-5.jpg) + +- Clicking `Test Connection` with the LaunchPad connected will cause a JTAG +Integrity scan with the Debug Probe. This is a nice way to check that your +ccxml is setup correctly. + +![CCS step 6](images/ccs-6.jpg) + +- Now open the Debug Configurations dialog to setup a new debug configuration. +Select `Run` >> `Debug Configurations...`. + +![CCS step 7](images/ccs-7.jpg) + +- Create a new launch configuration from the default CCS launch configuration. +Select `Code Composer Studio - Device Debugging` and then create a new launch +configuration with the `New launch configuration` button. + +![CCS step 8](images/ccs-8.jpg) + +- Name your new configuration. Update the `Target Configuration` field with the +ccxml you created earlier. Click `Apply` to save the launch configuration. + +Once the launch configuration is created you do not need to re-create it +every time. The Debug session can be started with the `Debug` button in the +`Debug Configurations` dialog, or by selecting `Run` >> `Debug History` >> +``. + +![CCS step 9](images/ccs-9.jpg) + +- Now that the Debug session is started we can connect to the target. Make sure +that the right Debug Probe is selected in the `Debug` window and click +`Connect Target`. + +![CCS step 9](images/ccs-10.jpg) + +- The target MCU is connected. The MCU is halted on connection by default. +Select the `Load Program...` option to select the ELF image to load. + +![CCS step 9](images/ccs-11.jpg) + +- Navigate to the ELF file +(`${connectedhomeip}/examples/lock-app/cc13x2_26x2/out/debug/chip-cc13x2_26x2-lock-example.out` +file) in the `Load Program` dialog. Click `OK` to begin loading the target. + +![CCS step 9](images/ccs-12.jpg) + +- After loacating the source file for `main.cpp` we can step through the code +as it executes. + +![CCS step 9](images/ccs-13.jpg) + +[ccs]: https://www.ti.com/tool/CCSTUDIO +``` diff --git a/examples/lock-app/cc13x2_26x2/doc/programming-uniflash.md b/examples/lock-app/cc13x2_26x2/doc/programming-uniflash.md new file mode 100644 index 00000000000000..f6b3acb27b9b28 --- /dev/null +++ b/examples/lock-app/cc13x2_26x2/doc/programming-uniflash.md @@ -0,0 +1,23 @@ +# Programming with UniFlash + +- Download and install [UniFlash][uniflash]. + +- Select the Device Detect option. Then select the device you wish to program. + Or you can create a new configuration if you know the debugger serial number + + ![UniFlash step 1](images/uniflash-1.jpg) + +- Browse for your build image by clicking the `Browse` button. It will be at + `${connectedhomeip}/examples/lock-app/cc13x2_26x2/out/debug/chip-cc13x2_26x2-lock-example.out` + + ![UniFlash step 2](images/uniflash-2.jpg) + +- Load the image by clicking the `Load Image` button. This will eventually + result in a success message in the console below. + + ![UniFlash step 3](images/uniflash-3.jpg) + +- Open a terminal to the XDS110 User UART and interact with the example + application. + +[uniflash]: https://www.ti.com/tool/download/UNIFLASH diff --git a/examples/lock-app/cc13x2_26x2/main/AppTask.cpp b/examples/lock-app/cc13x2_26x2/main/AppTask.cpp new file mode 100644 index 00000000000000..3faface6713d5c --- /dev/null +++ b/examples/lock-app/cc13x2_26x2/main/AppTask.cpp @@ -0,0 +1,323 @@ +/* + * + * Copyright (c) 2020 Project CHIP Authors + * Copyright (c) 2020 Texas Instruments Incorporated + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "AppTask.h" +#include "AppConfig.h" +#include "AppEvent.h" +#include "Server.h" + +#include "FreeRTOS.h" + +#include + +#include "DataModelHandler.h" + +#include +#include + +/* syscfg */ +#include + +#define APP_TASK_STACK_SIZE (4096) +#define APP_TASK_PRIORITY 2 +#define APP_EVENT_QUEUE_SIZE 10 + +using namespace ::chip::DeviceLayer; + +static TaskHandle_t sAppTaskHandle; +static QueueHandle_t sAppEventQueue; + +static LED_Handle sAppRedHandle; +static LED_Handle sAppGreenHandle; +static Button_Handle sAppLeftHandle; +static Button_Handle sAppRightHandle; + +AppTask AppTask::sAppTask; + +int AppTask::StartAppTask() +{ + int ret = 0; + + sAppEventQueue = xQueueCreate(APP_EVENT_QUEUE_SIZE, sizeof(AppEvent)); + if (sAppEventQueue == NULL) + { + PLAT_LOG("Failed to allocate app event queue"); + while (1) + ; + } + + // Start App task. + if (xTaskCreate(AppTaskMain, "APP", APP_TASK_STACK_SIZE / sizeof(StackType_t), NULL, APP_TASK_PRIORITY, &sAppTaskHandle) != + pdPASS) + { + PLAT_LOG("Failed to create app task"); + while (1) + ; + } + return ret; +} + +int AppTask::Init() +{ + int ret = CHIP_ERROR_MAX; + LED_Params ledParams; + Button_Params buttionParams; + ConnectivityManager::ThreadPollingConfig pollingConfig; + + cc13x2_26x2LogInit(); + + ret = PlatformMgr().InitChipStack(); + if (ret != CHIP_NO_ERROR) + { + PLAT_LOG("PlatformMgr().InitChipStack() failed"); + while (1) + ; + } + + ret = ThreadStackMgr().InitThreadStack(); + if (ret != CHIP_NO_ERROR) + { + PLAT_LOG("ThreadStackMgr().InitThreadStack() failed"); + while (1) + ; + } + + ret = ConnectivityMgr().SetThreadDeviceType(ConnectivityManager::kThreadDeviceType_SleepyEndDevice); + if (ret != CHIP_NO_ERROR) + { + PLAT_LOG("ConnectivityMgr().SetThreadDeviceType() failed"); + while (1) + ; + } + + pollingConfig.Clear(); + pollingConfig.ActivePollingIntervalMS = 5000; // ms + pollingConfig.InactivePollingIntervalMS = 5000; // ms + + ret = ConnectivityMgr().SetThreadPollingConfig(pollingConfig); + if (ret != CHIP_NO_ERROR) + { + PLAT_LOG("ConnectivityMgr().SetThreadPollingConfig() failed"); + while (1) + ; + } + + ret = PlatformMgr().StartEventLoopTask(); + if (ret != CHIP_NO_ERROR) + { + PLAT_LOG("PlatformMgr().StartEventLoopTask() failed"); + while (1) + ; + } + + ret = ThreadStackMgrImpl().StartThreadTask(); + if (ret != CHIP_NO_ERROR) + { + PLAT_LOG("ThreadStackMgr().StartThreadTask() failed"); + while (1) + ; + } + + // Init ZCL Data Model and start server + PLAT_LOG("Initialize Server"); + InitServer(); + + // Initialize LEDs + PLAT_LOG("Initialize LEDs"); + LED_init(); + + LED_Params_init(&ledParams); // default PWM LED + sAppRedHandle = LED_open(CONFIG_LED_RED, &ledParams); + LED_setOn(sAppRedHandle, LED_BRIGHTNESS_MAX); + + LED_Params_init(&ledParams); // default PWM LED + sAppGreenHandle = LED_open(CONFIG_LED_GREEN, &ledParams); + LED_setOn(sAppGreenHandle, LED_BRIGHTNESS_MAX); + + // Initialize buttons + PLAT_LOG("Initialize buttons"); + Button_init(); + + Button_Params_init(&buttionParams); + buttionParams.buttonEventMask = Button_EV_CLICKED | Button_EV_LONGCLICKED; + buttionParams.longPressDuration = 1000U; // ms + sAppLeftHandle = Button_open(CONFIG_BTN_LEFT, ButtonLeftEventHandler, &buttionParams); + + Button_Params_init(&buttionParams); + buttionParams.buttonEventMask = Button_EV_CLICKED | Button_EV_LONGCLICKED; + buttionParams.longPressDuration = 1000U; // ms + sAppRightHandle = Button_open(CONFIG_BTN_RIGHT, ButtonRightEventHandler, &buttionParams); + + // Initialize BoltLock module + PLAT_LOG("Initialize BoltLock"); + BoltLockMgr().Init(); + + BoltLockMgr().SetCallbacks(ActionInitiated, ActionCompleted); + + return 0; +} + +void AppTask::AppTaskMain(void * pvParameter) +{ + AppEvent event; + + sAppTask.Init(); + + while (1) + { + /* Task pend until we have stuff to do */ + if (xQueueReceive(sAppEventQueue, &event, portMAX_DELAY) == pdTRUE) + { + sAppTask.DispatchEvent(&event); + } + } +} + +void AppTask::PostEvent(const AppEvent * aEvent) +{ + if (xQueueSend(sAppEventQueue, aEvent, 0) != pdPASS) + { + /* Failed to post the message */ + } +} + +void AppTask::ButtonLeftEventHandler(Button_Handle handle, Button_EventMask events) +{ + AppEvent event; + event.Type = AppEvent::kEventType_ButtonLeft; + + if (events & Button_EV_CLICKED) + { + event.ButtonEvent.Type = AppEvent::kAppEventButtonType_Clicked; + } + else if (events & Button_EV_LONGCLICKED) + { + event.ButtonEvent.Type = AppEvent::kAppEventButtonType_LongClicked; + } + // button callbacks are in ISR context + if (xQueueSendFromISR(sAppEventQueue, &event, NULL) != pdPASS) + { + /* Failed to post the message */ + } +} + +void AppTask::ButtonRightEventHandler(Button_Handle handle, Button_EventMask events) +{ + AppEvent event; + event.Type = AppEvent::kEventType_ButtonRight; + + if (events & Button_EV_CLICKED) + { + event.ButtonEvent.Type = AppEvent::kAppEventButtonType_Clicked; + } + else if (events & Button_EV_LONGCLICKED) + { + event.ButtonEvent.Type = AppEvent::kAppEventButtonType_LongClicked; + } + // button callbacks are in ISR context + if (xQueueSendFromISR(sAppEventQueue, &event, NULL) != pdPASS) + { + /* Failed to post the message */ + } +} + +void AppTask::ActionInitiated(BoltLockManager::Action_t aAction, int32_t aActor) +{ + // If the action has been initiated by the lock, update the bolt lock trait + // and start flashing the LEDs rapidly to indicate action initiation. + if (aAction == BoltLockManager::LOCK_ACTION) + { + PLAT_LOG("Lock initiated"); + ; // TODO + } + else if (aAction == BoltLockManager::UNLOCK_ACTION) + { + PLAT_LOG("Unlock initiated"); + ; // TODO + } + + LED_setOn(sAppGreenHandle, LED_BRIGHTNESS_MAX); + LED_startBlinking(sAppGreenHandle, 50 /* ms */, LED_BLINK_FOREVER); + LED_setOn(sAppRedHandle, LED_BRIGHTNESS_MAX); + LED_startBlinking(sAppRedHandle, 110 /* ms */, LED_BLINK_FOREVER); +} + +void AppTask::ActionCompleted(BoltLockManager::Action_t aAction) +{ + // if the action has been completed by the lock, update the bolt lock trait. + // Turn on the lock LED if in a LOCKED state OR + // Turn off the lock LED if in an UNLOCKED state. + if (aAction == BoltLockManager::LOCK_ACTION) + { + PLAT_LOG("Lock completed"); + LED_stopBlinking(sAppGreenHandle); + LED_setOn(sAppGreenHandle, LED_BRIGHTNESS_MAX); + LED_stopBlinking(sAppRedHandle); + LED_setOn(sAppRedHandle, LED_BRIGHTNESS_MAX); + } + else if (aAction == BoltLockManager::UNLOCK_ACTION) + { + PLAT_LOG("Unlock completed"); + LED_stopBlinking(sAppGreenHandle); + LED_setOff(sAppGreenHandle); + LED_stopBlinking(sAppRedHandle); + LED_setOff(sAppRedHandle); + } +} + +void AppTask::DispatchEvent(AppEvent * aEvent) +{ + switch (aEvent->Type) + { + case AppEvent::kEventType_ButtonLeft: + if (AppEvent::kAppEventButtonType_Clicked == aEvent->ButtonEvent.Type) + { + BoltLockMgr().InitiateAction(0, BoltLockManager::UNLOCK_ACTION); + } + else if (AppEvent::kAppEventButtonType_LongClicked == aEvent->ButtonEvent.Type) + { + // TODO: factory reset device + BoltLockMgr().InitiateAction(0, BoltLockManager::UNLOCK_ACTION); + } + break; + + case AppEvent::kEventType_ButtonRight: + if (AppEvent::kAppEventButtonType_Clicked == aEvent->ButtonEvent.Type) + { + BoltLockMgr().InitiateAction(0, BoltLockManager::LOCK_ACTION); + } + else if (AppEvent::kAppEventButtonType_LongClicked == aEvent->ButtonEvent.Type) + { + // TODO: factory reset device + BoltLockMgr().InitiateAction(0, BoltLockManager::LOCK_ACTION); + } + break; + + case AppEvent::kEventType_AppEvent: + if (NULL != aEvent->Handler) + { + aEvent->Handler(aEvent); + } + break; + + case AppEvent::kEventType_None: + default: + break; + } +} diff --git a/examples/lock-app/cc13x2_26x2/main/BoltLockManager.cpp b/examples/lock-app/cc13x2_26x2/main/BoltLockManager.cpp new file mode 100644 index 00000000000000..a6c927cb6cd04b --- /dev/null +++ b/examples/lock-app/cc13x2_26x2/main/BoltLockManager.cpp @@ -0,0 +1,204 @@ +/* + * + * Copyright (c) 2020 Project CHIP Authors + * Copyright (c) 2019 Google LLC. + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "BoltLockManager.h" + +#include "AppConfig.h" +#include "AppTask.h" +#include "FreeRTOS.h" + +#define ACTUATOR_MOVEMENT_PERIOS_MS 500 + +BoltLockManager BoltLockManager::sLock; + +int BoltLockManager::Init() +{ + int ret = 0; + + mTimerHandle = xTimerCreate("BLT_TIMER", pdMS_TO_TICKS(ACTUATOR_MOVEMENT_PERIOS_MS), pdFALSE, this, TimerEventHandler); + if (NULL == mTimerHandle) + { + PLAT_LOG("failed to create bolt lock timer"); + while (1) + ; + } + + mState = kState_LockingCompleted; + mAutoLockTimerArmed = false; + mAutoRelock = false; + mAutoLockDuration = 0; + + return ret; +} + +void BoltLockManager::SetCallbacks(Callback_fn_initiated aActionInitiated_CB, Callback_fn_completed aActionCompleted_CB) +{ + mActionInitiated_CB = aActionInitiated_CB; + mActionCompleted_CB = aActionCompleted_CB; +} + +bool BoltLockManager::IsActionInProgress() +{ + return (mState == kState_LockingInitiated || mState == kState_UnlockingInitiated); +} + +bool BoltLockManager::IsUnlocked() +{ + return (mState == kState_UnlockingCompleted); +} + +void BoltLockManager::EnableAutoRelock(bool aOn) +{ + mAutoRelock = aOn; +} + +void BoltLockManager::SetAutoLockDuration(uint32_t aDurationInSecs) +{ + mAutoLockDuration = aDurationInSecs; +} + +bool BoltLockManager::InitiateAction(int32_t aActor, Action_t aAction) +{ + bool action_initiated = false; + State_t new_state; + + // Initiate Lock/Unlock Action only when the previous one is complete. + if (mState == kState_LockingCompleted && aAction == UNLOCK_ACTION) + { + action_initiated = true; + + new_state = kState_UnlockingInitiated; + } + else if (mState == kState_UnlockingCompleted && aAction == LOCK_ACTION) + { + action_initiated = true; + + new_state = kState_LockingInitiated; + } + + if (action_initiated) + { + if (mAutoLockTimerArmed && new_state == kState_LockingInitiated) + { + // If auto lock timer has been armed and someone initiates locking, + // cancel the timer and continue as normal. + mAutoLockTimerArmed = false; + + CancelTimer(); + } + + StartTimer(ACTUATOR_MOVEMENT_PERIOS_MS); + + // Since the timer started successfully, update the state and trigger callback + mState = new_state; + + if (mActionInitiated_CB) + { + mActionInitiated_CB(aAction, aActor); + } + } + + return action_initiated; +} + +void BoltLockManager::StartTimer(uint32_t aTimeoutMs) +{ + xTimerChangePeriod(mTimerHandle, pdMS_TO_TICKS(aTimeoutMs), 100); + xTimerStart(mTimerHandle, 100); +} + +void BoltLockManager::CancelTimer(void) +{ + xTimerStop(mTimerHandle, 100); +} + +void BoltLockManager::TimerEventHandler(TimerHandle_t aTimer) +{ + BoltLockManager * lock = static_cast(pvTimerGetTimerID(aTimer)); + + // The timer event handler will be called in the context of the timer task + // once sLockTimer expires. Post an event to apptask queue with the actual handler + // so that the event can be handled in the context of the apptask. + AppEvent event; + event.Type = AppEvent::kEventType_AppEvent; + event.BoltLockEvent.Context = static_cast(lock); + if (lock->mAutoLockTimerArmed) + { + event.Handler = AutoReLockTimerEventHandler; + } + else + { + event.Handler = ActuatorMovementTimerEventHandler; + } + GetAppTask().PostEvent(&event); +} + +void BoltLockManager::AutoReLockTimerEventHandler(AppEvent * aEvent) +{ + BoltLockManager * lock = static_cast(aEvent->BoltLockEvent.Context); + int32_t actor = 0; + + // Make sure auto lock timer is still armed. + if (!lock->mAutoLockTimerArmed) + { + return; + } + + lock->mAutoLockTimerArmed = false; + + PLAT_LOG("Auto Re-Lock has been triggered!"); + + lock->InitiateAction(actor, LOCK_ACTION); +} + +void BoltLockManager::ActuatorMovementTimerEventHandler(AppEvent * aEvent) +{ + Action_t actionCompleted = INVALID_ACTION; + + BoltLockManager * lock = static_cast(aEvent->BoltLockEvent.Context); + + if (lock->mState == kState_LockingInitiated) + { + lock->mState = kState_LockingCompleted; + actionCompleted = LOCK_ACTION; + } + else if (lock->mState == kState_UnlockingInitiated) + { + lock->mState = kState_UnlockingCompleted; + actionCompleted = UNLOCK_ACTION; + } + + if (actionCompleted != INVALID_ACTION) + { + if (lock->mActionCompleted_CB) + { + lock->mActionCompleted_CB(actionCompleted); + } + + if (lock->mAutoRelock && actionCompleted == UNLOCK_ACTION) + { + // Start the timer for auto relock + lock->StartTimer(lock->mAutoLockDuration * 1000); + + lock->mAutoLockTimerArmed = true; + + PLAT_LOG("Auto Re-lock enabled. Will be triggered in %u seconds", lock->mAutoLockDuration); + } + } +} diff --git a/examples/lock-app/cc13x2_26x2/main/ZclCallbacks.cpp b/examples/lock-app/cc13x2_26x2/main/ZclCallbacks.cpp new file mode 100644 index 00000000000000..08e8b78a690334 --- /dev/null +++ b/examples/lock-app/cc13x2_26x2/main/ZclCallbacks.cpp @@ -0,0 +1,75 @@ +/* + * + * 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 "AppConfig.h" +#include "BoltLockManager.h" + +#include "gen/attribute-id.h" +#include "gen/cluster-id.h" +#include +#include +#include +#include + +using namespace ::chip; + +void emberAfPostAttributeChangeCallback(EndpointId endpoint, ClusterId clusterId, AttributeId attributeId, uint8_t mask, + uint16_t manufacturerCode, uint8_t type, uint8_t size, uint8_t * value) +{ + if (clusterId != ZCL_ON_OFF_CLUSTER_ID) + { + ChipLogProgress(Zcl, "Unknown cluster ID: %d", clusterId); + return; + } + + if (attributeId != ZCL_ON_OFF_ATTRIBUTE_ID) + { + ChipLogProgress(Zcl, "Unknown attribute ID: %d", attributeId); + return; + } + + if (*value) + { + BoltLockMgr().InitiateAction(0, BoltLockManager::LOCK_ACTION); + } + else + { + BoltLockMgr().InitiateAction(0, BoltLockManager::UNLOCK_ACTION); + } +} + +/** @brief OnOff Cluster Init + * + * This function is called when a specific cluster is initialized. It gives the + * application an opportunity to take care of cluster initialization procedures. + * It is called exactly once for each endpoint where cluster is present. + * + * @param endpoint Ver.: always + * + * TODO Issue #3841 + * emberAfOnOffClusterInitCallback happens before the stack initialize the cluster + * attributes to the default value. + * The logic here expects something similar to the deprecated Plugins callback + * emberAfPluginOnOffClusterServerPostInitCallback. + * + */ +void emberAfOnOffClusterInitCallback(EndpointId endpoint) +{ + // TODO: implement any additional Cluster Server init actions +} diff --git a/examples/lock-app/cc13x2_26x2/main/include/AppConfig.h b/examples/lock-app/cc13x2_26x2/main/include/AppConfig.h new file mode 100644 index 00000000000000..3cead418532caa --- /dev/null +++ b/examples/lock-app/cc13x2_26x2/main/include/AppConfig.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2020 Project CHIP Authors + * Copyright (c) 2019 Google LLC. + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef APP_CONFIG_H +#define APP_CONFIG_H + +// Logging +#ifdef __cplusplus +extern "C" { +#endif + +int cc13x2_26x2LogInit(void); +void cc13x2_26x2Log(const char * aFormat, ...); +#define PLAT_LOG(...) cc13x2_26x2Log(__VA_ARGS__); + +#ifdef __cplusplus +} +#endif +#endif // APP_CONFIG_H diff --git a/examples/lock-app/cc13x2_26x2/main/include/AppEvent.h b/examples/lock-app/cc13x2_26x2/main/include/AppEvent.h new file mode 100644 index 00000000000000..ad9e93ee3ad1a5 --- /dev/null +++ b/examples/lock-app/cc13x2_26x2/main/include/AppEvent.h @@ -0,0 +1,60 @@ +/* + * + * 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. + */ + +#ifndef APP_EVENT_H +#define APP_EVENT_H + +struct AppEvent; +typedef void (*EventHandler)(AppEvent *); + +struct AppEvent +{ + enum AppEventType + { + kEventType_None = 0, + kEventType_ButtonLeft, + kEventType_ButtonRight, + kEventType_AppEvent, + }; + + enum AppEventButtonType + { + kAppEventButtonType_None = 0, + kAppEventButtonType_Clicked, + kAppEventButtonType_LongClicked, + }; + + enum AppEventType Type; + + union + { + struct + { + enum AppEventButtonType Type; + } ButtonEvent; + + struct + { + void * Context; + } BoltLockEvent; + }; + + EventHandler Handler; +}; + +#endif // APP_EVENT_H diff --git a/examples/lock-app/cc13x2_26x2/main/include/AppTask.h b/examples/lock-app/cc13x2_26x2/main/include/AppTask.h new file mode 100644 index 00000000000000..21d552fa89b7d7 --- /dev/null +++ b/examples/lock-app/cc13x2_26x2/main/include/AppTask.h @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2020 Project CHIP Authors + * Copyright (c) 2019 Google LLC. + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef APP_TASK_H +#define APP_TASK_H + +#include +#include + +#include "FreeRTOS.h" +#include "semphr.h" +#include "task.h" + +#include "AppEvent.h" +#include "BoltLockManager.h" + +#include + +class AppTask +{ +public: + int StartAppTask(); + static void AppTaskMain(void * pvParameter); + + void PostLockActionRequest(int32_t aActor, BoltLockManager::Action_t aAction); + void PostEvent(const AppEvent * event); + +private: + friend AppTask & GetAppTask(void); + + int Init(); + + // should this be done by BoltLock Manager? I don't want to unravel this spaghetti quite yet + static void ActionInitiated(BoltLockManager::Action_t aAction, int32_t aActor); + static void ActionCompleted(BoltLockManager::Action_t aAction); + + void DispatchEvent(AppEvent * event); + + static void ButtonLeftEventHandler(Button_Handle handle, Button_EventMask events); + static void ButtonRightEventHandler(Button_Handle handle, Button_EventMask events); + static void TimerEventHandler(void * p_context); + + enum Function_t + { + kFunction_NoneSelected = 0, + kFunction_SoftwareUpdate = 0, + kFunction_FactoryReset, + + kFunction_Invalid + } Function; + + Function_t mFunction; + bool mFunctionTimerActive; + + static AppTask sAppTask; +}; + +inline AppTask & GetAppTask(void) +{ + return AppTask::sAppTask; +} + +#endif // APP_TASK_H diff --git a/examples/lock-app/cc13x2_26x2/main/include/BoltLockManager.h b/examples/lock-app/cc13x2_26x2/main/include/BoltLockManager.h new file mode 100644 index 00000000000000..40fc4ffb338a67 --- /dev/null +++ b/examples/lock-app/cc13x2_26x2/main/include/BoltLockManager.h @@ -0,0 +1,87 @@ +/* + * + * 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. + */ + +#ifndef LOCK_MANAGER_H +#define LOCK_MANAGER_H + +#include +#include + +#include "AppEvent.h" + +#include +#include + +class BoltLockManager +{ +public: + enum Action_t + { + LOCK_ACTION = 0, + UNLOCK_ACTION, + + INVALID_ACTION + } Action; + + enum State_t + { + kState_LockingInitiated = 0, + kState_LockingCompleted, + kState_UnlockingInitiated, + kState_UnlockingCompleted, + } State; + + int Init(); + bool IsUnlocked(); + void EnableAutoRelock(bool aOn); + void SetAutoLockDuration(uint32_t aDurationInSecs); + bool IsActionInProgress(); + bool InitiateAction(int32_t aActor, Action_t aAction); + + typedef void (*Callback_fn_initiated)(Action_t, int32_t aActor); + typedef void (*Callback_fn_completed)(Action_t); + void SetCallbacks(Callback_fn_initiated aActionInitiated_CB, Callback_fn_completed aActionCompleted_CB); + +private: + friend BoltLockManager & BoltLockMgr(void); + State_t mState; + + Callback_fn_initiated mActionInitiated_CB; + Callback_fn_completed mActionCompleted_CB; + + bool mAutoRelock; + uint32_t mAutoLockDuration; + bool mAutoLockTimerArmed; + TimerHandle_t mTimerHandle; + + void CancelTimer(void); + void StartTimer(uint32_t aTimeoutMs); + + static void TimerEventHandler(TimerHandle_t aTimer); + static void AutoReLockTimerEventHandler(AppEvent * aEvent); + static void ActuatorMovementTimerEventHandler(AppEvent * aEvent); + + static BoltLockManager sLock; +}; + +inline BoltLockManager & BoltLockMgr(void) +{ + return BoltLockManager::sLock; +} + +#endif // LOCK_MANAGER_H diff --git a/examples/lock-app/cc13x2_26x2/main/include/CHIPProjectConfig.h b/examples/lock-app/cc13x2_26x2/main/include/CHIPProjectConfig.h new file mode 100644 index 00000000000000..30cd4b9912ff24 --- /dev/null +++ b/examples/lock-app/cc13x2_26x2/main/include/CHIPProjectConfig.h @@ -0,0 +1,157 @@ +/* + * Copyright (c) 2020 Project CHIP Authors + * Copyright (c) 2019 Google LLC. + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @file + * Example project configuration file for CHIP. + * + * This is a place to put application or project-specific overrides + * to the default configuration values for general CHIP features. + * + */ + +#ifndef CHIP_PROJECT_CONFIG_H +#define CHIP_PROJECT_CONFIG_H + +#if BUILD_RELEASE // release build + +// Security and Authentication enabled for release build. +#define CHIP_CONFIG_SECURITY_TEST_MODE 0 +#define CHIP_CONFIG_REQUIRE_AUTH 1 + +#else // development build + +// Security and Authentication disabled for development build. +// For convenience, enable CHIP Security Test Mode and disable the requirement for +// authentication in various protocols. +// 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 1 +#define CHIP_CONFIG_REQUIRE_AUTH 0 + +/** + * 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. +#define CHIP_DEVICE_CONFIG_USE_TEST_SETUP_PIN_CODE 12345678 +#define CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR 0xF00 + +// Use a default pairing code if one hasn't been provisioned in flash. +#define CHIP_DEVICE_CONFIG_USE_TEST_PAIRING_CODE "CHIPUS" + +/** + * CHIP_DEVICE_CONFIG_USE_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_USE_TEST_SERIAL_NUMBER "DUMMY_SN" + +#endif // BUILD_RELEASE + +/** + * CHIP_DEVICE_CONFIG_THREAD_FTD + * + * Disable Full Thread Device features + */ +#define CHIP_DEVICE_CONFIG_THREAD_FTD 0 + +/** + * CHIP_DEVICE_CONFIG_DEVICE_VENDOR_ID + * + * 0xE100: Google's Vendor Id. + */ +#define CHIP_DEVICE_CONFIG_DEVICE_VENDOR_ID 0xE100 + +/** + * CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_ID + * + * 0xFE00: SDK Sample Lock Resource + */ +#define CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_ID 0xFE00 + +/** + * CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_REVISION + * + * The product revision 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 revisions. + */ +#define CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_REVISION 1 + +/** + * CHIP_DEVICE_CONFIG_DEVICE_FIRMWARE_REVISION + * + * A string identifying the firmware revision running on the device. + * CHIP currently expects the firmware version to be in the format + * {MAJOR_VERSION}.0d{MINOR_VERSION} + */ +#ifndef CHIP_DEVICE_CONFIG_DEVICE_FIRMWARE_REVISION +#define CHIP_DEVICE_CONFIG_DEVICE_FIRMWARE_REVISION "1.0d1" +#endif +/** + * CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE + * + * Enable support for CHIP-over-BLE (CHIPOBLE). + */ +#define CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE 0 + +/** + * CHIP_DEVICE_CONFIG_ENABLE_CHIP_TIME_SERVICE_TIME_SYNC + * + * Enables synchronizing the device's real time clock with a remote CHIP Time service + * using the CHIP Time Sync protocol. + */ +//#define CHIP_DEVICE_CONFIG_ENABLE_CHIP_TIME_SERVICE_TIME_SYNC 1 + +/** + * 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) + +/** + * CHIP_CONFIG_EVENT_LOGGING_DEFAULT_IMPORTANCE + * + * For a development build, set the default importance of events to be logged as Debug. + * Since debug is the lowest importance level, this means all standard, critical, info and + * debug importance level vi events get logged. + */ +#if BUILD_RELEASE +#define CHIP_CONFIG_EVENT_LOGGING_DEFAULT_IMPORTANCE chip::Profiles::DataManagement::Production +#else +#define CHIP_CONFIG_EVENT_LOGGING_DEFAULT_IMPORTANCE chip::Profiles::DataManagement::Debug +#endif // BUILD_RELEASE + +#endif // CHIP_PROJECT_CONFIG_H diff --git a/examples/lock-app/cc13x2_26x2/main/include/OpenThreadConfig.h b/examples/lock-app/cc13x2_26x2/main/include/OpenThreadConfig.h new file mode 100644 index 00000000000000..bccc34b919a28b --- /dev/null +++ b/examples/lock-app/cc13x2_26x2/main/include/OpenThreadConfig.h @@ -0,0 +1,56 @@ +/* + * + * Copyright (c) 2020 Project CHIP Authors + * Copyright (c) 2019 Google LLC. + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @file + * Overrides to default OpenThread configuration. + * + */ + +#ifndef OPENTHREAD_PLATFORM_CONFIG_H +#define OPENTHREAD_PLATFORM_CONFIG_H + +// Disable the Nordic-supplied OpenThread logging facilities and use +// the facilities provided by the CHIP Device Layer +#define OPENTHREAD_CONFIG_LOG_OUTPUT OPENTHREAD_CONFIG_LOG_OUTPUT_APP + +// When operating in a less than ideal RF environment, having a more forgiving configuration +// of OpenThread makes thread a great deal more reliable. +#define OPENTHREAD_CONFIG_TMF_ADDRESS_QUERY_MAX_RETRY_DELAY 120 // default is 28800 +#define OPENTHREAD_CONFIG_MAC_DEFAULT_MAX_FRAME_RETRIES_DIRECT 15 // default is 3 +#define OPENTHREAD_CONFIG_MAC_DEFAULT_MAX_FRAME_RETRIES_INDIRECT 1 // default is 0 +#define OPENTHREAD_CONFIG_MAC_MAX_TX_ATTEMPTS_INDIRECT_POLLS 16 // default is 4 + +// Enable periodic parent search to speed up finding a better parent. +#define OPENTHREAD_CONFIG_PARENT_SEARCH_ENABLE 1 // default is 0 +#define OPENTHREAD_CONFIG_PARENT_SEARCH_RSS_THRESHOLD -45 // default is -65 +#define OPENTHREAD_CONFIG_MLE_INFORM_PREVIOUS_PARENT_ON_REATTACH 1 // default is 0 + +// Use smaller maximum interval to speed up reattaching. +#define OPENTHREAD_CONFIG_MLE_ATTACH_BACKOFF_MAXIMUM_INTERVAL (60 * 10 * 1000) // default 1200000 ms + +#define OPENTHREAD_CONFIG_JOINER_ENABLE 1 +#define OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE 1 +#define UART_AS_SERIAL_TRANSPORT 1 +#define OPENTHREAD_CONFIG_PLATFORM_USEC_TIMER_ENABLE 1 + +// Use the TI-supplied default platform configuration for remainder +#include "openthread-core-cc13x2_26x2-config.h" + +#endif // OPENTHREAD_PLATFORM_CONFIG_H diff --git a/examples/lock-app/cc13x2_26x2/main/main.cpp b/examples/lock-app/cc13x2_26x2/main/main.cpp new file mode 100644 index 00000000000000..7785e9f5c8eb5b --- /dev/null +++ b/examples/lock-app/cc13x2_26x2/main/main.cpp @@ -0,0 +1,89 @@ +/* + * + * Copyright (c) 2020 Project CHIP Authors + * Copyright (c) 2020 Texas Instruments Incorporated + * + * 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 + +/* Driver Header files */ +#include +#include +#include +#include + +#include +#include +#include + +using namespace ::chip; +using namespace ::chip::Inet; +using namespace ::chip::DeviceLayer; + +// ================================================================================ +// FreeRTOS Callbacks +// ================================================================================ +extern "C" void vApplicationStackOverflowHook(void) +{ + while (1) + { + ; + } +} + +// ================================================================================ +// Main Code +// ================================================================================ +int main(void) +{ + int ret = CHIP_ERROR_MAX; + + Board_init(); + + GPIO_init(); + + NVS_init(); + + UART_init(); + + ECJPAKE_init(); + + AESECB_init(); + + SHA2_init(); + + ret = GetAppTask().StartAppTask(); + if (ret != CHIP_NO_ERROR) + { + // can't log until the kernel is started + // PLAT_LOG("GetAppTask().StartAppTask() failed"); + while (1) + ; + } + + vTaskStartScheduler(); + + // Should never get here. + while (1) + ; +} diff --git a/examples/lock-app/cc13x2_26x2/third_party/connectedhomeip b/examples/lock-app/cc13x2_26x2/third_party/connectedhomeip new file mode 120000 index 00000000000000..c866b86874994d --- /dev/null +++ b/examples/lock-app/cc13x2_26x2/third_party/connectedhomeip @@ -0,0 +1 @@ +../../../.. \ No newline at end of file diff --git a/examples/lock-app/efr32/BUILD.gn b/examples/lock-app/efr32/BUILD.gn index 89d8b087e20395..2670214f0f53f0 100644 --- a/examples/lock-app/efr32/BUILD.gn +++ b/examples/lock-app/efr32/BUILD.gn @@ -31,8 +31,7 @@ declare_args() { show_qr_code = true # BRD4166A --> ThunderBoard Sense 2 (No LCD) -# BRD4180A --> GPIO Conflict with Radio and LCD -if (efr32_board == "BRD4166A" || efr32_board == "BRD4180A") { +if (efr32_board == "BRD4166A") { show_qr_code = false } @@ -68,7 +67,6 @@ efr32_executable("lock_app") { public_deps = [ ":sdk", "${chip_root}/examples/common/QRCode", - "${chip_root}/examples/common/chip-app-server:chip-app-server", "${chip_root}/examples/lock-app/lock-common", "${chip_root}/src/lib", "${chip_root}/src/setup_payload", @@ -81,6 +79,7 @@ efr32_executable("lock_app") { include_dirs += [ "${efr32_project_dir}/include", "${chip_root}/src/app/util", + "${chip_root}/src/app/server", "${examples_plat_dir}", ] diff --git a/examples/lock-app/efr32/README.md b/examples/lock-app/efr32/README.md index bf80acb0178fcd..14bbe1a944edf1 100644 --- a/examples/lock-app/efr32/README.md +++ b/examples/lock-app/efr32/README.md @@ -19,13 +19,21 @@ An example showing the use of CHIP on the Silicon Labs EFR32 MG12. ## Introduction -The EFR32 lock example provides a baseline demonstration of a door lock device, -built using CHIP and the Silicon Labs gecko SDK. The example currently support -OpenThread. The BLE feature is still a work in progress. +The EFR32 lock example provides a baseline demonstration of a door lock control +device, built using CHIP and the Silicon Labs gecko SDK. It can be controlled by +a Chip controller over Openthread network.. -The lock example is intended to serve both as a means to explore the workings of -CHIP as well as a template for creating real products based on the Silicon Labs -platform. +The EFR32 device can be commissioned over Bluetooth Low Energy where the device +and the Chip controller will exchange security information with the Rendez-vous +procedure. Thread Network credentials are then provided to the EFR32 device +which will then join the network. + +The LCD on the Silabs WSTK shows a QR Code containing the needed commissioning +information for the BLE connection and starting the Rendez-vous procedure. + +The lighting example is intended to serve both as a means to explore the +workings of CHIP as well as a template for creating real products based on the +Silicon Labs platform. @@ -79,9 +87,20 @@ platform. - To delete generated executable, libraries and object files use: - $ cd ~/connectedhomeip/examples/lighting-app/efr32 + $ cd ~/connectedhomeip/examples/lock-app/efr32 $ rm -rf out/ +OR use the script + + cd ~/connectedhomeip + $ export EFR32_SDK_ROOT= + $ export EFR32_BOARD=BRD4161A + ./scripts/examples/gn_efr32_example.sh examples/lock-app/efr32/ out/debug/efr32_lock_app + +- To delete generated executable, libraries and object files use: + $ cd ~/connectedhomeip + $ rm -rf out/debug/efr32_lock_app + ## Flashing the Application @@ -105,7 +124,9 @@ embedded application without the need for a dedicated UART. Using the RTT facility requires downloading and installing the _SEGGER J-Link Software and Documentation Pack_ ([web site](https://www.segger.com/downloads/jlink#J-LinkSoftwareAndDocumentationPack)). -Alternatively the _SEGGER Ozone - J-Link Debugger_ can be used to view RTT logs. + +Alternatively, SEGGER Ozone J-Link debugger can be used to view RTT logs too +after flashing the .out file. - Download the J-Link installer by navigating to the appropriate URL and agreeing to the license agreement. @@ -145,24 +166,103 @@ combination with JLinkRTTClient as follows: ## Running the Complete Example -- Once the example is flashed on the board, you should be able to establish a - connection with an OpenThread border router. See +- It is assumed here that you already have an OpenThread border router + configured and running. If not, see the following guide [OpenThread Border Router](https://openthread.io/guides/border-router) for more information on how to setup a border router. Take note that the RCP code is available directly through [Simplicity Studio 5](https://www.silabs.com/products/development-tools/software/simplicity-studio/simplicity-studio-5) under File->New->Project Wizard->Examples->Thread : ot-rcp -- Once said connectection is established (you can verify that with the command + +- User interface : **LCD** The LCD on Silabs WSTK shows a QR Code. This QR + Code is be scanned by the CHIP Tool app For the Rendez-vous procedure over + BLE + + * On devices that do not have or support the LCD Display like the BRD4166A Thunderboard Sense 2, + a URL can be found in the RTT logs. + + [SVR] Copy/paste the below URL in a browser to see the QR Code: + [SVR] https://dhrishi.github.io/connectedhomeip/qrcode.html?data=CH%3AI34NM%20-00%200C9SS0 + + **LED 0** shows the overall state of the device and its connectivity. The + following states are possible: + + - _Short Flash On (50 ms on/950 ms off)_ ; The device is in the + unprovisioned (unpaired) state and is waiting for a commissioning + application to connect. + + - _Rapid Even Flashing_ ; (100 ms on/100 ms off)_ — The device is in the + unprovisioned state and a commissioning application is connected through + Bluetooth LE. + + - _Short Flash Off_ ; (950ms on/50ms off)_ — The device is fully + provisioned, but does not yet have full Thread network or service + connectivity. + + - _Solid On_ ; The device is fully provisioned and has full Thread + network and service connectivity. + + **LED 1** Simulates the Lock The following states are possible: + + - _Solid On_ ; Bolt is locked + - _Blinking_ ; Bolt is moving to the desired state + - _Off_ ; Bolt is unlocked + + **Push Button 0** - Press and Release : If not commissioned, start thread + with default configurations (DEBUG) + + + - Pressed and hold for 6 s: Initiates the factory reset of the device. + Releasing the button within the 6-second window cancels the factory reset + procedure. **LEDs** blink in unison when the factory reset procedure is + initiated. + + **Push Button 1** + Toggles the bolt state On/Off + +- Once the device is provisioned, it will join the Thread network is + established, look for the RTT log + + ``` +     [DL] Device Role: CHILD +     [DL] Partition Id:0x6A7491B7 +     [DL] \_OnPlatformEvent default: event->Type = 32778 +     [DL] OpenThread State Changed (Flags: 0x00000001) +     [DL] Thread Unicast Addresses: +     [DL]    2001:DB8::E1A2:87F1:7D5D:FECA/64 valid preferred +     [DL]    FDDE:AD00:BEEF::FF:FE00:2402/64 valid preferred rloc +     [DL]    FDDE:AD00:BEEF:0:383F:5E81:A05A:B168/64 valid preferred +     [DL]    FE80::D8F2:592E:C109:CF00/64 valid preferred +     [DL] LwIP Thread interface addresses updated +     [DL] FE80::D8F2:592E:C109:CF00 IPv6 link-local address, preferred) +     [DL] FDDE:AD00:BEEF:0:383F:5E81:A05A:B168 Thread mesh-local address, preferred) +     [DL] 2001:DB8::E1A2:87F1:7D5D:FECA IPv6 global unicast address, preferred) + ``` + + Keep The global unicast address; It is to be used to reach the Device with + the chip-tool. The device will be promoted to Router shortly after [DL] + Device Role: ROUTER + + (you can verify that the device is on the thread network with the command `router table` using a serial terminal (screen / minicom etc.) on the board - running the lock-app example) + running the lighting-app example. You can also get the address list with the + command ipaddr again in the serial terminal ) + - Using chip-tool you can now control the lock status with on/off command such - as `chip-tool onoff on 1 11097` + as `chip-tool onoff on 1` + + \*\* Currently, chip-tool for Mac or Linux do not yet have the Thread + provisioning feature + `chip-tool bypass 11097` + + You can provision the Chip device using Chip tool Android or iOS app or + through CLI commands on your OT BR ### Notes - Depending on your network settings your router might not provide native ipv6 addresses to your devices (Border router / PC). If this is the case, you - need to add a static ipv6 addresses on both device and then a ipv6 route to + need to add a static ipv6 addresses on both device and then an ipv6 route to the border router on your PC # On Border Router : @@ -172,4 +272,4 @@ combination with JLinkRTTClient as follows: $ sudo ip addr add dev 2002::1/64 # Add Ipv6 route on PC (Linux) - $ sudo ip route add /64 via 2002::2 + $ sudo ip route add /64 via 2002::2 diff --git a/examples/lock-app/efr32/src/AppTask.cpp b/examples/lock-app/efr32/src/AppTask.cpp index adf109b5540645..e53278d6a3e77e 100644 --- a/examples/lock-app/efr32/src/AppTask.cpp +++ b/examples/lock-app/efr32/src/AppTask.cpp @@ -23,6 +23,7 @@ #include "ButtonHandler.h" #include "DataModelHandler.h" #include "LEDWidget.h" +#include "QRCodeUtil.h" #include "Server.h" #include "Service.h" #include "attribute-storage.h" @@ -130,55 +131,22 @@ int AppTask::Init() sLockLED.Set(!BoltLockMgr().IsUnlocked()); UpdateClusterState(); -// Print setup info on LCD if available + // Print setup info on LCD if available #ifdef DISPLAY_ENABLED - chip::SetupPayload payload; - uint32_t setUpPINCode = 0; - uint16_t setUpDiscriminator = 0; - uint16_t vendorId = 0; - uint16_t productId = 0; + uint32_t setupPinCode; + std::string QRCode; - err = ConfigurationMgr().GetSetupPinCode(setUpPINCode); - if (err != CHIP_NO_ERROR) - { - EFR32_LOG("ConfigurationMgr().GetSetupPinCode() failed: %s", chip::ErrorStr(err)); - } - - err = ConfigurationMgr().GetSetupDiscriminator(setUpDiscriminator); - if (err != CHIP_NO_ERROR) + if (GetQRCode(setupPinCode, QRCode, chip::RendezvousInformationFlags::kBLE) == CHIP_NO_ERROR) { - EFR32_LOG("ConfigurationMgr().GetSetupDiscriminator() failed: %s", chip::ErrorStr(err)); + EFR32_LOG("SetupPINCode: [%09u]", setupPinCode); + LCDWriteQRCode((uint8_t *) QRCode.c_str()); } - - err = ConfigurationMgr().GetVendorId(vendorId); - if (err != CHIP_NO_ERROR) - { - EFR32_LOG("ConfigurationMgr().GetVendorId() failed: %s", chip::ErrorStr(err)); - } - - err = ConfigurationMgr().GetProductId(productId); - if (err != CHIP_NO_ERROR) - { - EFR32_LOG("ConfigurationMgr().GetProductId() failed: %s", chip::ErrorStr(err)); - } - - payload.version = 1; - payload.vendorID = vendorId; - payload.productID = productId; - payload.setUpPINCode = setUpPINCode; - payload.discriminator = setUpDiscriminator; - chip::QRCodeSetupPayloadGenerator generator(payload); - - std::string result; - err = generator.payloadBase41Representation(result); - if (err != CHIP_NO_ERROR) + else { - EFR32_LOG("Failed to get Base41 payload for QR code with %s", chip::ErrorStr(err)); + EFR32_LOG("Getting QR code failed!"); } - - EFR32_LOG("SetupPINCode: [%09u]", setUpPINCode); - LCDWriteQRCode((uint8_t *) result.c_str()); - +#else + PrintQRCode(chip::RendezvousInformationFlags::kBLE); #endif return err; @@ -220,6 +188,7 @@ void AppTask::AppTaskMain(void * pvParameter) sIsThreadEnabled = ConnectivityMgr().IsThreadEnabled(); sIsThreadAttached = ConnectivityMgr().IsThreadAttached(); sHaveBLEConnections = (ConnectivityMgr().NumBLEConnections() != 0); + sIsPairedToAccount = ConfigurationMgr().IsPairedToAccount(); sHaveServiceConnectivity = ConnectivityMgr().HaveServiceConnectivity(); PlatformMgr().UnlockChipStack(); } @@ -244,8 +213,7 @@ void AppTask::AppTaskMain(void * pvParameter) { sStatusLED.Set(true); } - else if (sIsThreadProvisioned && sIsThreadEnabled && sIsPairedToAccount && - (!sIsThreadAttached || !sHaveServiceConnectivity)) + else if (sIsThreadProvisioned && sIsThreadEnabled && (!sIsThreadAttached || !sHaveServiceConnectivity)) { sStatusLED.Blink(950, 50); } @@ -420,7 +388,7 @@ void AppTask::FunctionHandler(AppEvent * aEvent) { EFR32_LOG("Device is commissioned to a Thread network."); } -#elif +#else EFR32_LOG("Thread is not defined."); #endif } diff --git a/examples/lock-app/k32w/BUILD.gn b/examples/lock-app/k32w/BUILD.gn index 5a023e38fc5bda..e795903cf20131 100644 --- a/examples/lock-app/k32w/BUILD.gn +++ b/examples/lock-app/k32w/BUILD.gn @@ -31,6 +31,7 @@ k32w_sdk("sdk") { "${k32w_platform_dir}/app/support", "${chip_root}/examples/lock-app/lock-common", "${chip_root}/src/app/util", + "${chip_root}/src/app/server", "${k32w_platform_dir}/util/include", ] @@ -69,7 +70,6 @@ k32w_executable("lock_app") { deps = [ ":sdk", - "${chip_root}/examples/common/chip-app-server:chip-app-server", "${chip_root}/examples/lock-app/lock-common", "${chip_root}/src/lib", "${chip_root}/third_party/mbedtls:mbedtls", diff --git a/examples/lock-app/k32w/Makefile b/examples/lock-app/k32w/Makefile index 44d55b16e73fbb..abca292064ce2e 100644 --- a/examples/lock-app/k32w/Makefile +++ b/examples/lock-app/k32w/Makefile @@ -52,8 +52,7 @@ SRCS = \ $(CHIP_ROOT)/src/app/util/process-global-message.c \ $(CHIP_ROOT)/src/app/util/util.c \ $(CHIP_ROOT)/src/app/clusters/on-off-server/on-off.c \ - $(CHIP_ROOT)/examples/common/chip-app-server/DataModelHandler.cpp \ - $(CHIP_ROOT)/examples/common/chip-app-server/Server.cpp \ + $(CHIP_ROOT)/src/app/server/DataModelHandler.cpp \ $(CHIP_ROOT)/examples/lock-app/lock-common/gen/call-command-handler.c \ $(CHIP_ROOT)/examples/lock-app/lock-common/gen/callback-stub.c \ $(K32W061_SDK_ROOT)/rtos/amazon-freertos/lib/FreeRTOS/tasks.c \ @@ -109,7 +108,6 @@ INC_DIRS = \ $(CHIP_ROOT)/examples/platform/k32w/app/support \ $(CHIP_ROOT)/examples/platform/k32w/app/project_include \ $(CHIP_ROOT)/examples/lock-app/lock-common/ \ - $(CHIP_ROOT)/examples/common/chip-app-server/include/ \ $(CHIP_ROOT)/src/include/ \ $(CHIP_ROOT)/src/lib \ $(CHIP_ROOT)/src/ \ diff --git a/examples/lock-app/lock-common/BUILD.gn b/examples/lock-app/lock-common/BUILD.gn index 4fcf200f154619..932a186ba4d4bd 100644 --- a/examples/lock-app/lock-common/BUILD.gn +++ b/examples/lock-app/lock-common/BUILD.gn @@ -24,10 +24,11 @@ config("includes") { source_set("lock-common") { sources = [ - "${chip_root}/examples/common/chip-app-server/DataModelHandler.cpp", + "${chip_root}/src/app/clusters/bindings/bindings.cpp", "${chip_root}/src/app/clusters/on-off-server/on-off.cpp", "${chip_root}/src/app/reporting/reporting-default-configuration.cpp", "${chip_root}/src/app/reporting/reporting.cpp", + "${chip_root}/src/app/server/DataModelHandler.cpp", "${chip_root}/src/app/util/af-event.cpp", "${chip_root}/src/app/util/af-main-common.cpp", "${chip_root}/src/app/util/attribute-size.cpp", @@ -45,10 +46,7 @@ source_set("lock-common") { "gen/callback-stub.cpp", ] - deps = [ - "${chip_root}/examples/common/chip-app-server:chip-app-server", - "${chip_root}/src/lib", - ] + deps = [ "${chip_root}/src/lib" ] public_configs = [ ":includes" ] } diff --git a/examples/lock-app/lock-common/gen/af-structs.h b/examples/lock-app/lock-common/gen/af-structs.h index 6d04f3faa8e82d..02960bec60ddfb 100644 --- a/examples/lock-app/lock-common/gen/af-structs.h +++ b/examples/lock-app/lock-common/gen/af-structs.h @@ -1,4 +1,3 @@ - /* * * Copyright (c) 2020 Project CHIP Authors diff --git a/examples/lock-app/lock-common/gen/att-storage.h b/examples/lock-app/lock-common/gen/att-storage.h index 7572c8cbc338fb..74b44d6111b3e4 100644 --- a/examples/lock-app/lock-common/gen/att-storage.h +++ b/examples/lock-app/lock-common/gen/att-storage.h @@ -1,4 +1,3 @@ - /* * * Copyright (c) 2020 Project CHIP Authors diff --git a/examples/lock-app/lock-common/gen/attribute-id.h b/examples/lock-app/lock-common/gen/attribute-id.h index 648809ca67cd83..901653b7d8f3b6 100644 --- a/examples/lock-app/lock-common/gen/attribute-id.h +++ b/examples/lock-app/lock-common/gen/attribute-id.h @@ -1,4 +1,3 @@ - /* * * Copyright (c) 2020 Project CHIP Authors @@ -19,11 +18,15 @@ // Prevent multiple inclusion #pragma once +// Global cluster attribute ids +#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) +#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) +#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) +#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) + // Attribute ids for cluster: Basic // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_VERSION_ATTRIBUTE_ID (0x0000) @@ -44,14 +47,10 @@ #define ZCL_ALARM_MASK_ATTRIBUTE_ID (0x0013) #define ZCL_DISABLE_LOCAL_CONFIG_ATTRIBUTE_ID (0x0014) #define ZCL_SW_BUILD_ID_ATTRIBUTE_ID (0x4000) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Power Configuration // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_MAINS_VOLTAGE_ATTRIBUTE_ID (0x0000) @@ -111,14 +110,10 @@ #define ZCL_BATTERY_3_PERCENTAGE_THRESHOLD_2_ATTRIBUTE_ID (0x007C) #define ZCL_BATTERY_3_PERCENTAGE_THRESHOLD_3_ATTRIBUTE_ID (0x007D) #define ZCL_BATTERY_3_ALARM_STATE_ATTRIBUTE_ID (0x007E) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Device Temperature Configuration // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_CURRENT_TEMPERATURE_ATTRIBUTE_ID (0x0000) @@ -130,37 +125,25 @@ #define ZCL_HIGH_TEMP_THRESHOLD_ATTRIBUTE_ID (0x0012) #define ZCL_LOW_TEMP_DWELL_TRIP_POINT_ATTRIBUTE_ID (0x0013) #define ZCL_HIGH_TEMP_DWELL_TRIP_POINT_ATTRIBUTE_ID (0x0014) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Identify // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_IDENTIFY_TIME_ATTRIBUTE_ID (0x0000) #define ZCL_COMMISSION_STATE_ATTRIBUTE_ID (0x0001) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Groups // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_GROUP_NAME_SUPPORT_ATTRIBUTE_ID (0x0000) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Scenes // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_SCENE_COUNT_ATTRIBUTE_ID (0x0000) @@ -169,14 +152,10 @@ #define ZCL_SCENE_VALID_ATTRIBUTE_ID (0x0003) #define ZCL_SCENE_NAME_SUPPORT_ATTRIBUTE_ID (0x0004) #define ZCL_LAST_CONFIGURED_BY_ATTRIBUTE_ID (0x0005) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: On/off // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_ON_OFF_ATTRIBUTE_ID (0x0000) @@ -188,26 +167,18 @@ #define ZCL_ON_TIME_ATTRIBUTE_ID (0x4001) #define ZCL_OFF_WAIT_TIME_ATTRIBUTE_ID (0x4002) #define ZCL_START_UP_ON_OFF_ATTRIBUTE_ID (0x4003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: On/off Switch Configuration // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_SWITCH_TYPE_ATTRIBUTE_ID (0x0000) #define ZCL_SWITCH_ACTIONS_ATTRIBUTE_ID (0x0010) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Level Control // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_CURRENT_LEVEL_ATTRIBUTE_ID (0x0000) @@ -219,25 +190,17 @@ #define ZCL_OFF_TRANSITION_TIME_ATTRIBUTE_ID (0x0013) #define ZCL_DEFAULT_MOVE_RATE_ATTRIBUTE_ID (0x0014) #define ZCL_START_UP_CURRENT_LEVEL_ATTRIBUTE_ID (0x4000) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Alarms // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_ALARM_COUNT_ATTRIBUTE_ID (0x0000) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Time // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_TIME_ATTRIBUTE_ID (0x0000) @@ -250,14 +213,10 @@ #define ZCL_LOCAL_TIME_ATTRIBUTE_ID (0x0007) #define ZCL_LAST_SET_TIME_ATTRIBUTE_ID (0x0008) #define ZCL_VALID_UNTIL_TIME_ATTRIBUTE_ID (0x0009) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: RSSI Location // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_LOCATION_TYPE_ATTRIBUTE_ID (0x0000) @@ -273,14 +232,10 @@ #define ZCL_REPORTING_PERIOD_ATTRIBUTE_ID (0x0015) #define ZCL_CALCULATION_PERIOD_ATTRIBUTE_ID (0x0016) #define ZCL_NUMBER_RSSI_MEASUREMENTS_ATTRIBUTE_ID (0x0017) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Binary Input (Basic) // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_ACTIVE_TEXT_ATTRIBUTE_ID (0x0004) @@ -292,14 +247,10 @@ #define ZCL_RELIABILITY_ATTRIBUTE_ID (0x0067) #define ZCL_STATUS_FLAGS_ATTRIBUTE_ID (0x006F) #define ZCL_APPLICATION_TYPE_ATTRIBUTE_ID (0x0100) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Commissioning // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_SHORT_ADDRESS_ATTRIBUTE_ID (0x0000) @@ -326,14 +277,10 @@ #define ZCL_CONCENTRATOR_FLAG_ATTRIBUTE_ID (0x0040) #define ZCL_CONCENTRATOR_RADIUS_ATTRIBUTE_ID (0x0041) #define ZCL_CONCENTRATOR_DISCOVERY_TIME_ATTRIBUTE_ID (0x0042) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Partition // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_PARTITION_MAXIMUM_INCOMING_TRANSFER_SIZE_ATTRIBUTE_ID (0x0000) @@ -346,8 +293,6 @@ #define ZCL_NUMBER_OF_SEND_RETRIES_ATTRIBUTE_ID (0x0007) #define ZCL_SENDER_TIMEOUT_ATTRIBUTE_ID (0x0008) #define ZCL_RECEIVER_TIMEOUT_ATTRIBUTE_ID (0x0009) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Over the Air Bootloading @@ -365,18 +310,12 @@ #define ZCL_IMAGE_STAMP_ATTRIBUTE_ID (0x000A) #define ZCL_UPGRADE_ACTIVATION_POLICY_ATTRIBUTE_ID (0x000B) #define ZCL_UPGRADE_TIMEOUT_POLICY_ATTRIBUTE_ID (0x000C) -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Power Profile // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_TOTAL_PROFILE_NUM_ATTRIBUTE_ID (0x0000) @@ -384,27 +323,19 @@ #define ZCL_ENERGY_FORMATTING_ATTRIBUTE_ID (0x0002) #define ZCL_ENERGY_REMOTE_ATTRIBUTE_ID (0x0003) #define ZCL_SCHEDULE_MODE_ATTRIBUTE_ID (0x0004) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Appliance Control // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_START_TIME_ATTRIBUTE_ID (0x0000) #define ZCL_FINISH_TIME_ATTRIBUTE_ID (0x0001) #define ZCL_REMAINING_TIME_ATTRIBUTE_ID (0x0002) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Poll Control // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_CHECK_IN_INTERVAL_ATTRIBUTE_ID (0x0000) @@ -414,8 +345,6 @@ #define ZCL_CHECK_IN_INTERVAL_MIN_ATTRIBUTE_ID (0x0004) #define ZCL_LONG_POLL_INTERVAL_MIN_ATTRIBUTE_ID (0x0005) #define ZCL_FAST_POLL_TIMEOUT_MAX_ATTRIBUTE_ID (0x0006) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Green Power @@ -431,8 +360,6 @@ #define ZCL_GP_CLIENT_GP_SHARED_SECURITY_KEY_TYPE_ATTRIBUTE_ID (0x0020) #define ZCL_GP_CLIENT_GP_SHARED_SECURITY_KEY_ATTRIBUTE_ID (0x0021) #define ZCL_GP_CLIENT_GP_LINK_KEY_ATTRIBUTE_ID (0x0022) -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_GP_SERVER_GPS_MAX_SINK_TABLE_ENTRIES_ATTRIBUTE_ID (0x0000) @@ -446,26 +373,18 @@ #define ZCL_GP_SERVER_GP_SHARED_SECURITY_KEY_TYPE_ATTRIBUTE_ID (0x0020) #define ZCL_GP_SERVER_GP_SHARED_SECURITY_KEY_ATTRIBUTE_ID (0x0021) #define ZCL_GP_SERVER_GP_LINK_KEY_ATTRIBUTE_ID (0x0022) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Keep-Alive // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_KEEPALIVE_BASE_ATTRIBUTE_ID (0x0000) #define ZCL_KEEPALIVE_JITTER_ATTRIBUTE_ID (0x0001) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Shade Configuration // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_SHADE_CONFIG_PHYSICAL_CLOSED_LIMIT_ATTRIBUTE_ID (0x0000) @@ -473,14 +392,10 @@ #define ZCL_SHADE_CONFIG_STATUS_ATTRIBUTE_ID (0x0002) #define ZCL_SHADE_CONFIG_CLOSED_LIMIT_ATTRIBUTE_ID (0x0010) #define ZCL_SHADE_CONFIG_MODE_ATTRIBUTE_ID (0x0011) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Door Lock // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_LOCK_STATE_ATTRIBUTE_ID (0x0000) @@ -526,14 +441,10 @@ #define ZCL_KEYPAD_PROGRAMMING_EVENT_MASK_ATTRIBUTE_ID (0x0045) #define ZCL_RF_PROGRAMMING_EVENT_MASK_ATTRIBUTE_ID (0x0046) #define ZCL_RFID_PROGRAMMING_EVENT_MASK_ATTRIBUTE_ID (0x0047) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Window Covering // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_COVERING_TYPE_ATTRIBUTE_ID (0x0000) @@ -556,14 +467,10 @@ #define ZCL_MODE_ATTRIBUTE_ID (0x0017) #define ZCL_SETPOINTS_LIFT_ATTRIBUTE_ID (0x0018) #define ZCL_SETPOINTS_TILT_ATTRIBUTE_ID (0x0019) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Barrier Control // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_BARRIER_MOVING_STATE_ATTRIBUTE_ID (0x0001) @@ -576,14 +483,10 @@ #define ZCL_BARRIER_OPEN_PERIOD_ATTRIBUTE_ID (0x0008) #define ZCL_BARRIER_CLOSE_PERIOD_ATTRIBUTE_ID (0x0009) #define ZCL_BARRIER_POSITION_ATTRIBUTE_ID (0x000A) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Pump Configuration and Control // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_MAX_PRESSURE_ATTRIBUTE_ID (0x0000) @@ -610,14 +513,10 @@ #define ZCL_OPERATION_MODE_ATTRIBUTE_ID (0x0020) #define ZCL_CONTROL_MODE_ATTRIBUTE_ID (0x0021) #define ZCL_PUMP_ALARM_MASK_ATTRIBUTE_ID (0x0022) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Thermostat // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_LOCAL_TEMPERATURE_ATTRIBUTE_ID (0x0000) @@ -663,26 +562,18 @@ #define ZCL_AC_LOUVER_POSITION_ATTRIBUTE_ID (0x0045) #define ZCL_AC_COIL_TEMPERATURE_ATTRIBUTE_ID (0x0046) #define ZCL_AC_CAPACITY_FORMAT_ATTRIBUTE_ID (0x0047) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Fan Control // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_FAN_CONTROL_FAN_MODE_ATTRIBUTE_ID (0x0000) #define ZCL_FAN_CONTROL_FAN_MODE_SEQUENCE_ATTRIBUTE_ID (0x0001) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Dehumidification Control // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_RELATIVE_HUMIDITY_ATTRIBUTE_ID (0x0000) @@ -693,27 +584,19 @@ #define ZCL_DEHUMIDIFICATION_HYSTERESIS_ATTRIBUTE_ID (0x0013) #define ZCL_DEHUMIDIFICATION_MAX_COOL_ATTRIBUTE_ID (0x0014) #define ZCL_RELATIVE_HUMIDITY_DISPLAY_ATTRIBUTE_ID (0x0015) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Thermostat User Interface Configuration // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_TEMPERATURE_DISPLAY_MODE_ATTRIBUTE_ID (0x0000) #define ZCL_KEYPAD_LOCKOUT_ATTRIBUTE_ID (0x0001) #define ZCL_SCHEDULE_PROGRAMMING_VISIBILITY_ATTRIBUTE_ID (0x0002) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Color Control // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_COLOR_CONTROL_CURRENT_HUE_ATTRIBUTE_ID (0x0000) @@ -768,14 +651,10 @@ #define ZCL_COLOR_CONTROL_COLOR_TEMP_PHYSICAL_MAX_ATTRIBUTE_ID (0x400C) #define ZCL_COLOR_CONTROL_TEMPERATURE_LEVEL_MIN_MIREDS_ATTRIBUTE_ID (0x400D) #define ZCL_START_UP_COLOR_TEMPERATURE_MIREDS_ATTRIBUTE_ID (0x4010) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Ballast Configuration // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_PHYSICAL_MIN_LEVEL_ATTRIBUTE_ID (0x0000) @@ -794,14 +673,10 @@ #define ZCL_LAMP_BURN_HOURS_ATTRIBUTE_ID (0x0033) #define ZCL_LAMP_ALARM_MODE_ATTRIBUTE_ID (0x0034) #define ZCL_LAMP_BURN_HOURS_TRIP_POINT_ATTRIBUTE_ID (0x0035) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Illuminance Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_ILLUM_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) @@ -809,41 +684,29 @@ #define ZCL_ILLUM_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_ILLUM_TOLERANCE_ATTRIBUTE_ID (0x0003) #define ZCL_MEASUREMENT_LIGHT_SENSOR_TYPE_ATTRIBUTE_ID (0x0004) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Illuminance Level Sensing // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_LEVEL_STATUS_ATTRIBUTE_ID (0x0000) #define ZCL_SENSING_LIGHT_SENSOR_TYPE_ATTRIBUTE_ID (0x0001) #define ZCL_ILLUMINANCE_TARGET_LEVEL_ATTRIBUTE_ID (0x0010) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Temperature Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_TEMP_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_TEMP_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_TEMP_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_TEMP_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Pressure Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_PRESSURE_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) @@ -855,42 +718,30 @@ #define ZCL_PRESSURE_MAX_SCALED_VALUE_ATTRIBUTE_ID (0x0012) #define ZCL_PRESSURE_SCALED_TOLERANCE_ATTRIBUTE_ID (0x0013) #define ZCL_PRESSURE_SCALE_ATTRIBUTE_ID (0x0014) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Flow Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_FLOW_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_FLOW_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_FLOW_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_FLOW_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Relative Humidity Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_RELATIVE_HUMIDITY_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_RELATIVE_HUMIDITY_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_RELATIVE_HUMIDITY_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_RELATIVE_HUMIDITY_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Occupancy Sensing // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_OCCUPANCY_ATTRIBUTE_ID (0x0000) @@ -905,434 +756,310 @@ #define ZCL_PHYSICAL_CONTACT_OCCUPIED_TO_UNOCCUPIED_DELAY_ATTRIBUTE_ID (0x0030) #define ZCL_PHYSICAL_CONTACT_UNOCCUPIED_TO_OCCUPIED_DELAY_ATTRIBUTE_ID (0x0031) #define ZCL_PHYSICAL_CONTACT_UNOCCUPIED_TO_OCCUPIED_THRESHOLD_ATTRIBUTE_ID (0x0032) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Carbon Monoxide Concentration Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_CARBON_MONOXIDE_CONCENTRATION_MEASUREMENT_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_CARBON_MONOXIDE_CONCENTRATION_MEASUREMENT_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_CARBON_MONOXIDE_CONCENTRATION_MEASUREMENT_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_CARBON_MONOXIDE_CONCENTRATION_MEASUREMENT_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Carbon Dioxide Concentration Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_CARBON_DIOXIDE_CONCENTRATION_MEASUREMENT_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_CARBON_DIOXIDE_CONCENTRATION_MEASUREMENT_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_CARBON_DIOXIDE_CONCENTRATION_MEASUREMENT_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_CARBON_DIOXIDE_CONCENTRATION_MEASUREMENT_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Ethylene Concentration Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_ETHYLENE_CONCENTRATION_MEASUREMENT_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_ETHYLENE_CONCENTRATION_MEASUREMENT_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_ETHYLENE_CONCENTRATION_MEASUREMENT_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_ETHYLENE_CONCENTRATION_MEASUREMENT_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Ethylene Oxide Concentration Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_ETHYLENE_OXIDE_CONCENTRATION_MEASUREMENT_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_ETHYLENE_OXIDE_CONCENTRATION_MEASUREMENT_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_ETHYLENE_OXIDE_CONCENTRATION_MEASUREMENT_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_ETHYLENE_OXIDE_CONCENTRATION_MEASUREMENT_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Hydrogen Concentration Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_HYDROGEN_CONCENTRATION_MEASUREMENT_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_HYDROGEN_CONCENTRATION_MEASUREMENT_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_HYDROGEN_CONCENTRATION_MEASUREMENT_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_HYDROGEN_CONCENTRATION_MEASUREMENT_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Hydrogen Sulphide Concentration Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_HYDROGEN_SULPHIDE_CONCENTRATION_MEASUREMENT_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_HYDROGEN_SULPHIDE_CONCENTRATION_MEASUREMENT_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_HYDROGEN_SULPHIDE_CONCENTRATION_MEASUREMENT_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_HYDROGEN_SULPHIDE_CONCENTRATION_MEASUREMENT_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Nitric Oxide Concentration Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_NITRIC_OXIDE_CONCENTRATION_MEASUREMENT_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_NITRIC_OXIDE_CONCENTRATION_MEASUREMENT_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_NITRIC_OXIDE_CONCENTRATION_MEASUREMENT_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_NITRIC_OXIDE_CONCENTRATION_MEASUREMENT_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Nitrogen Dioxide Concentration Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_NITROGEN_DIOXIDE_CONCENTRATION_MEASUREMENT_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_NITROGEN_DIOXIDE_CONCENTRATION_MEASUREMENT_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_NITROGEN_DIOXIDE_CONCENTRATION_MEASUREMENT_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_NITROGEN_DIOXIDE_CONCENTRATION_MEASUREMENT_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Oxygen Concentration Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_OXYGEN_CONCENTRATION_MEASUREMENT_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_OXYGEN_CONCENTRATION_MEASUREMENT_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_OXYGEN_CONCENTRATION_MEASUREMENT_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_OXYGEN_CONCENTRATION_MEASUREMENT_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Ozone Concentration Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_OZONE_CONCENTRATION_MEASUREMENT_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_OZONE_CONCENTRATION_MEASUREMENT_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_OZONE_CONCENTRATION_MEASUREMENT_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_OZONE_CONCENTRATION_MEASUREMENT_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Sulfur Dioxide Concentration Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_SULFUR_DIOXIDE_CONCENTRATION_MEASUREMENT_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_SULFUR_DIOXIDE_CONCENTRATION_MEASUREMENT_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_SULFUR_DIOXIDE_CONCENTRATION_MEASUREMENT_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_SULFUR_DIOXIDE_CONCENTRATION_MEASUREMENT_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Dissolved Oxygen Concentration Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_DISSOLVED_OXYGEN_CONCENTRATION_MEASUREMENT_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_DISSOLVED_OXYGEN_CONCENTRATION_MEASUREMENT_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_DISSOLVED_OXYGEN_CONCENTRATION_MEASUREMENT_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_DISSOLVED_OXYGEN_CONCENTRATION_MEASUREMENT_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Bromate Concentration Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_BROMATE_CONCENTRATION_MEASUREMENT_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_BROMATE_CONCENTRATION_MEASUREMENT_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_BROMATE_CONCENTRATION_MEASUREMENT_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_BROMATE_CONCENTRATION_MEASUREMENT_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Chloramines Concentration Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_CHLORAMINES_CONCENTRATION_MEASUREMENT_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_CHLORAMINES_CONCENTRATION_MEASUREMENT_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_CHLORAMINES_CONCENTRATION_MEASUREMENT_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_CHLORAMINES_CONCENTRATION_MEASUREMENT_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Chlorine Concentration Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_CHLORINE_CONCENTRATION_MEASUREMENT_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_CHLORINE_CONCENTRATION_MEASUREMENT_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_CHLORINE_CONCENTRATION_MEASUREMENT_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_CHLORINE_CONCENTRATION_MEASUREMENT_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Fecal coliform and E. Coli Concentration Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_FECAL_COLIFORM_AND_E_COLI_CONCENTRATION_MEASUREMENT_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_FECAL_COLIFORM_AND_E_COLI_CONCENTRATION_MEASUREMENT_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_FECAL_COLIFORM_AND_E_COLI_CONCENTRATION_MEASUREMENT_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_FECAL_COLIFORM_AND_E_COLI_CONCENTRATION_MEASUREMENT_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Fluoride Concentration Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_FLUORIDE_CONCENTRATION_MEASUREMENT_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_FLUORIDE_CONCENTRATION_MEASUREMENT_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_FLUORIDE_CONCENTRATION_MEASUREMENT_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_FLUORIDE_CONCENTRATION_MEASUREMENT_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Haloacetic Acids Concentration Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_HALOACETIC_ACIDS_CONCENTRATION_MEASUREMENT_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_HALOACETIC_ACIDS_CONCENTRATION_MEASUREMENT_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_HALOACETIC_ACIDS_CONCENTRATION_MEASUREMENT_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_HALOACETIC_ACIDS_CONCENTRATION_MEASUREMENT_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Total Trihalomethanes Concentration Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_TOTAL_TRIHALOMETHANES_CONCENTRATION_MEASUREMENT_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_TOTAL_TRIHALOMETHANES_CONCENTRATION_MEASUREMENT_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_TOTAL_TRIHALOMETHANES_CONCENTRATION_MEASUREMENT_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_TOTAL_TRIHALOMETHANES_CONCENTRATION_MEASUREMENT_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Total Coliform Bacteria Concentration Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_TOTAL_COLIFORM_BACTERIA_CONCENTRATION_MEASUREMENT_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_TOTAL_COLIFORM_BACTERIA_CONCENTRATION_MEASUREMENT_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_TOTAL_COLIFORM_BACTERIA_CONCENTRATION_MEASUREMENT_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_TOTAL_COLIFORM_BACTERIA_CONCENTRATION_MEASUREMENT_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Turbidity Concentration Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_TURBIDITY_CONCENTRATION_MEASUREMENT_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_TURBIDITY_CONCENTRATION_MEASUREMENT_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_TURBIDITY_CONCENTRATION_MEASUREMENT_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_TURBIDITY_CONCENTRATION_MEASUREMENT_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Copper Concentration Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_COPPER_CONCENTRATION_MEASUREMENT_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_COPPER_CONCENTRATION_MEASUREMENT_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_COPPER_CONCENTRATION_MEASUREMENT_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_COPPER_CONCENTRATION_MEASUREMENT_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Lead Concentration Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_LEAD_CONCENTRATION_MEASUREMENT_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_LEAD_CONCENTRATION_MEASUREMENT_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_LEAD_CONCENTRATION_MEASUREMENT_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_LEAD_CONCENTRATION_MEASUREMENT_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Manganese Concentration Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_MANGANESE_CONCENTRATION_MEASUREMENT_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_MANGANESE_CONCENTRATION_MEASUREMENT_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_MANGANESE_CONCENTRATION_MEASUREMENT_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_MANGANESE_CONCENTRATION_MEASUREMENT_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Sulfate Concentration Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_SULFATE_CONCENTRATION_MEASUREMENT_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_SULFATE_CONCENTRATION_MEASUREMENT_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_SULFATE_CONCENTRATION_MEASUREMENT_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_SULFATE_CONCENTRATION_MEASUREMENT_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Bromodichloromethane Concentration Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_BROMODICHLOROMETHANE_CONCENTRATION_MEASUREMENT_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_BROMODICHLOROMETHANE_CONCENTRATION_MEASUREMENT_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_BROMODICHLOROMETHANE_CONCENTRATION_MEASUREMENT_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_BROMODICHLOROMETHANE_CONCENTRATION_MEASUREMENT_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Bromoform Concentration Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_BROMOFORM_CONCENTRATION_MEASUREMENT_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_BROMOFORM_CONCENTRATION_MEASUREMENT_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_BROMOFORM_CONCENTRATION_MEASUREMENT_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_BROMOFORM_CONCENTRATION_MEASUREMENT_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Chlorodibromomethane Concentration Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_CHLORODIBROMOMETHANE_CONCENTRATION_MEASUREMENT_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_CHLORODIBROMOMETHANE_CONCENTRATION_MEASUREMENT_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_CHLORODIBROMOMETHANE_CONCENTRATION_MEASUREMENT_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_CHLORODIBROMOMETHANE_CONCENTRATION_MEASUREMENT_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Chloroform Concentration Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_CHLOROFORM_CONCENTRATION_MEASUREMENT_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_CHLOROFORM_CONCENTRATION_MEASUREMENT_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_CHLOROFORM_CONCENTRATION_MEASUREMENT_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_CHLOROFORM_CONCENTRATION_MEASUREMENT_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Sodium Concentration Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_SODIUM_CONCENTRATION_MEASUREMENT_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_SODIUM_CONCENTRATION_MEASUREMENT_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_SODIUM_CONCENTRATION_MEASUREMENT_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_SODIUM_CONCENTRATION_MEASUREMENT_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: IAS Zone // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_ZONE_STATE_ATTRIBUTE_ID (0x0000) @@ -1342,58 +1069,38 @@ #define ZCL_ZONE_ID_ATTRIBUTE_ID (0x0011) #define ZCL_NUMBER_OF_ZONE_SENSITIVITY_LEVELS_SUPPORTED_ATTRIBUTE_ID (0x0012) #define ZCL_CURRENT_ZONE_SENSITIVITY_LEVEL_ATTRIBUTE_ID (0x0013) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: IAS ACE // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: IAS WD // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_MAX_DURATION_ATTRIBUTE_ID (0x0000) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Generic Tunnel // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_MAXIMUM_INCOMING_TRANSFER_SIZE_ATTRIBUTE_ID (0x0001) #define ZCL_MAXIMUM_OUTGOING_TRANSFER_SIZE_ATTRIBUTE_ID (0x0002) #define ZCL_PROTOCOL_ADDRESS_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: BACnet Protocol Tunnel // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: 11073 Protocol Tunnel // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_DEVICE_ID_LIST_ATTRIBUTE_ID (0x0000) @@ -1402,19 +1109,13 @@ #define ZCL_CONNECTED_ATTRIBUTE_ID (0x0003) #define ZCL_PREEMPTIBLE_ATTRIBUTE_ID (0x0004) #define ZCL_IDLE_TIMEOUT_ATTRIBUTE_ID (0x0005) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: ISO 7816 Protocol Tunnel // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_ISO7816_PROTOCOL_TUNNEL_STATUS_ATTRIBUTE_ID (0x0000) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Price @@ -1422,8 +1123,6 @@ #define ZCL_PRICE_INCREASE_RANDOMIZE_MINUTES_ATTRIBUTE_ID (0x0000) #define ZCL_PRICE_DECREASE_RANDOMIZE_MINUTES_ATTRIBUTE_ID (0x0001) #define ZCL_COMMODITY_TYPE_CLIENT_ATTRIBUTE_ID (0x0002) -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_TIER1_PRICE_LABEL_ATTRIBUTE_ID (0x0000) @@ -2438,8 +2137,6 @@ #define ZCL_RX_LAST_BILLING_PERIOD_START_ATTRIBUTE_ID (0x8702) #define ZCL_RX_LAST_BILLING_PERIOD_DURATION_ATTRIBUTE_ID (0x8703) #define ZCL_RX_LAST_BILLING_PERIOD_CONSOLIDATED_BILL_ATTRIBUTE_ID (0x8704) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Demand Response and Load Control @@ -2448,12 +2145,8 @@ #define ZCL_START_RANDOMIZATION_MINUTES_ATTRIBUTE_ID (0x0001) #define ZCL_DURATION_RANDOMIZATION_MINUTES_ATTRIBUTE_ID (0x0002) #define ZCL_DEVICE_CLASS_VALUE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Simple Metering @@ -2466,8 +2159,6 @@ #define ZCL_NOTIFICATION_FLAGS_6_ATTRIBUTE_ID (0x0005) #define ZCL_NOTIFICATION_FLAGS_7_ATTRIBUTE_ID (0x0006) #define ZCL_NOTIFICATION_FLAGS_8_ATTRIBUTE_ID (0x0007) -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_CURRENT_SUMMATION_DELIVERED_ATTRIBUTE_ID (0x0000) @@ -3354,35 +3045,23 @@ #define ZCL_CURRENT_REACTIVE_SUMMATION_Q2_ATTRIBUTE_ID (0x0D06) #define ZCL_CURRENT_REACTIVE_SUMMATION_Q3_ATTRIBUTE_ID (0x0D07) #define ZCL_CURRENT_REACTIVE_SUMMATION_Q4_ATTRIBUTE_ID (0x0D08) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Messaging // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Tunneling // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_CLOSE_TUNNEL_TIMEOUT_ATTRIBUTE_ID (0x0000) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Prepayment // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_PAYMENT_CONTROL_CONFIGURATION_ATTRIBUTE_ID (0x0000) @@ -3516,14 +3195,10 @@ #define ZCL_PREVIOUS_MONTH_13_COST_CONSUMPTION_DELIVERED_ATTRIBUTE_ID (0x055A) #define ZCL_PREVIOUS_MONTH_13_COST_CONSUMPTION_RECEIVED_ATTRIBUTE_ID (0x055B) #define ZCL_PREPAYMENT_HISTORICAL_FREEZE_TIME_ATTRIBUTE_ID (0x055C) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Energy Management // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_LOAD_CONTROL_STATE_ATTRIBUTE_ID (0x0000) @@ -3533,14 +3208,10 @@ #define ZCL_MINIMUM_OFF_TIME_ATTRIBUTE_ID (0x0004) #define ZCL_MINIMUM_ON_TIME_ATTRIBUTE_ID (0x0005) #define ZCL_MINIMUM_CYCLE_PERIOD_ATTRIBUTE_ID (0x0006) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Calendar // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_AUXILIARY_SWITCH_1_LABEL_ATTRIBUTE_ID (0x0000) @@ -3551,8 +3222,6 @@ #define ZCL_AUXILIARY_SWITCH_6_LABEL_ATTRIBUTE_ID (0x0005) #define ZCL_AUXILIARY_SWITCH_7_LABEL_ATTRIBUTE_ID (0x0006) #define ZCL_AUXILIARY_SWITCH_8_LABEL_ATTRIBUTE_ID (0x0007) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Device Management @@ -3991,8 +3660,6 @@ #define ZCL_QUERY_SPECIFIC_FILE_REQUEST_GENERATED_ATTRIBUTE_ID (0x08CC) #define ZCL_QUERY_SPECIFIC_FILE_RESPONSE_RECEIVED_ATTRIBUTE_ID (0x08CD) #define ZCL_QUERY_SPECIFIC_FILE_RESPONSE_REJECTED_ATTRIBUTE_ID (0x08CE) -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_PROVIDER_ID_SERVER_ATTRIBUTE_ID (0x0100) @@ -4014,34 +3681,22 @@ #define ZCL_WAN_STATUS_ATTRIBUTE_ID (0x0300) #define ZCL_LOW_MEDIUM_THRESHOLD_ATTRIBUTE_ID (0x0400) #define ZCL_MEDIUM_HIGH_THRESHOLD_ATTRIBUTE_ID (0x0401) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Events // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: MDU Pairing // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Sub-GHz // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_SUB_GHZ_CLUSTER_CHANNEL_CHANGE_ATTRIBUTE_ID (0x0000) @@ -4049,26 +3704,18 @@ #define ZCL_SUB_GHZ_CLUSTER_PAGE_29_CHANNEL_MASK_ATTRIBUTE_ID (0x0002) #define ZCL_SUB_GHZ_CLUSTER_PAGE_30_CHANNEL_MASK_ATTRIBUTE_ID (0x0003) #define ZCL_SUB_GHZ_CLUSTER_PAGE_31_CHANNEL_MASK_ATTRIBUTE_ID (0x0004) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Key Establishment // Client attributes #define ZCL_KEY_ESTABLISHMENT_SUITE_CLIENT_ATTRIBUTE_ID (0x0000) -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_KEY_ESTABLISHMENT_SUITE_SERVER_ATTRIBUTE_ID (0x0000) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Information // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_NODE_DESCRIPTION_ATTRIBUTE_ID (0x0000) @@ -4077,26 +3724,18 @@ #define ZCL_ENABLE_SECURE_CONFIGURATION_ATTRIBUTE_ID (0x0003) #define ZCL_NUMBER_OF_CONTENTS_ATTRIBUTE_ID (0x0010) #define ZCL_CONTENT_ROOT_ID_ATTRIBUTE_ID (0x0011) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Data Sharing // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_DEVICE_NAME_ATTRIBUTE_ID (0x0000) #define ZCL_DEVICE_DESCRIPTION_ATTRIBUTE_ID (0x0001) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Gaming // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_PLAYER_NAME_ATTRIBUTE_ID (0x0000) @@ -4119,27 +3758,19 @@ #define ZCL_COUNTER1_ATTRIBUTE_ID (0x001D) #define ZCL_COUNTER2_ATTRIBUTE_ID (0x001E) #define ZCL_DOWNLOADABLE_ATTRIBUTE_ID (0x001F) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Data Rate Control // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_AVERAGE_LATENCY_REQUIREMENT_ATTRIBUTE_ID (0x0000) #define ZCL_MAX_LATENCY_REQUIREMENT_ATTRIBUTE_ID (0x0001) #define ZCL_BANDWIDTH_REQUIREMENT_ATTRIBUTE_ID (0x0002) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Voice over ZigBee // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_CODEC_TYPE_ATTRIBUTE_ID (0x0000) @@ -4153,14 +3784,10 @@ #define ZCL_COMPRESSION_RATE_ATTRIBUTE_ID (0x0008) #define ZCL_OPTION_FLAGS_ATTRIBUTE_ID (0x0009) #define ZCL_THRESHOLD_ATTRIBUTE_ID (0x000A) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Chatting // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_U_ID_ATTRIBUTE_ID (0x0000) @@ -4168,14 +3795,10 @@ #define ZCL_C_ID_ATTRIBUTE_ID (0x0010) #define ZCL_NAME_ATTRIBUTE_ID (0x0011) #define ZCL_ENABLE_ADD_CHAT_ATTRIBUTE_ID (0x0020) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Payment // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_PAYMENT_USER_ID_ATTRIBUTE_ID (0x0000) @@ -4192,14 +3815,10 @@ #define ZCL_TRANS_ID_ATTRIBUTE_ID (0x0033) #define ZCL_TRANS_STATUS_ATTRIBUTE_ID (0x0034) #define ZCL_PAYMENT_STATUS_ATTRIBUTE_ID (0x0035) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Billing // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_USER_ID_ATTRIBUTE_ID (0x0000) @@ -4208,14 +3827,10 @@ #define ZCL_SESSION_INTERVAL_ATTRIBUTE_ID (0x0012) #define ZCL_TIMESTAMP_ATTRIBUTE_ID (0x0020) #define ZCL_DURATION_ATTRIBUTE_ID (0x0021) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Appliance Identification // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_BASIC_IDENTIFICATION_ATTRIBUTE_ID (0x0000) @@ -4230,14 +3845,10 @@ #define ZCL_PRODUCT_TYPE_NAME_ATTRIBUTE_ID (0x0018) #define ZCL_PRODUCT_TYPE_ID_ATTRIBUTE_ID (0x0019) #define ZCL_CECED_SPECIFICATION_VERSION_ATTRIBUTE_ID (0x001A) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Meter Identification // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_METER_COMPANY_NAME_ATTRIBUTE_ID (0x0000) @@ -4252,36 +3863,24 @@ #define ZCL_POD_ATTRIBUTE_ID (0x000C) #define ZCL_AVAILABLE_POWER_ATTRIBUTE_ID (0x000D) #define ZCL_POWER_THRESHOLD_ATTRIBUTE_ID (0x000E) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Appliance Events and Alert // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Appliance Statistics // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_LOG_MAX_SIZE_ATTRIBUTE_ID (0x0000) #define ZCL_LOG_QUEUE_MAX_SIZE_ATTRIBUTE_ID (0x0001) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Electrical Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_MEASUREMENT_TYPE_ATTRIBUTE_ID (0x0000) @@ -4412,14 +4011,10 @@ #define ZCL_RMS_EXTREME_UNDER_VOLTAGE_PERIOD_PHASE_C_ATTRIBUTE_ID (0x0A15) #define ZCL_RMS_VOLTAGE_SAG_PERIOD_PHASE_C_ATTRIBUTE_ID (0x0A16) #define ZCL_RMS_VOLTAGE_SWELL_PERIOD_PHASE_C_ATTRIBUTE_ID (0x0A17) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Diagnostics // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_NUMBER_OF_RESETS_ATTRIBUTE_ID (0x0000) @@ -4454,72 +4049,54 @@ #define ZCL_AVERAGE_MAC_RETRY_PER_APS_MSG_SENT_ATTRIBUTE_ID (0x011B) #define ZCL_LAST_MESSAGE_LQI_ATTRIBUTE_ID (0x011C) #define ZCL_LAST_MESSAGE_RSSI_ATTRIBUTE_ID (0x011D) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: ZLL Commissioning // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) + +// Attribute ids for cluster: Binding + +// Client attributes + +// Server attributes // Attribute ids for cluster: Sample Mfg Specific Cluster // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_ATTRIBUTE_ONE_ATTRIBUTE_ID (0x0000) #define ZCL_ATTRIBUTE_TWO_ATTRIBUTE_ID (0x0001) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Sample Mfg Specific Cluster 2 // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_ATTRIBUTE_THREE_ATTRIBUTE_ID (0x0000) #define ZCL_ATTRIBUTE_FOUR_ATTRIBUTE_ID (0x0001) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Configuration Cluster // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_TOKENS_LOCKED_ATTRIBUTE_ID (0x0000) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: MFGLIB Cluster // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_PACKETS_RECEIVED_ATTRIBUTE_ID (0x0000) #define ZCL_SAVED_RSSI_ATTRIBUTE_ID (0x0001) #define ZCL_SAVED_LQI_ATTRIBUTE_ID (0x0002) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: SL Works With All Hubs // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_SL_DISABLE_OTA_DOWNGRADES_ATTRIBUTE_ID (0x0002) @@ -4540,5 +4117,3 @@ #define ZCL_SL_PENDING_NETWORK_UPDATE_CHANNEL_ATTRIBUTE_ID (0x0011) #define ZCL_SL_PENDING_NETWORK_UPDATE_PANID_ATTRIBUTE_ID (0x0012) #define ZCL_SL_OTA_MAX_OFFLINE_DURATION_ATTRIBUTE_ID (0x0013) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) diff --git a/examples/lock-app/lock-common/gen/attribute-size.h b/examples/lock-app/lock-common/gen/attribute-size.h index 8d8659ee7ece2e..f9ef9212244eca 100644 --- a/examples/lock-app/lock-common/gen/attribute-size.h +++ b/examples/lock-app/lock-common/gen/attribute-size.h @@ -1,4 +1,3 @@ - /* * * Copyright (c) 2020 Project CHIP Authors @@ -32,3 +31,5 @@ ZCL_DATA8_ATTRIBUTE_TYPE, 1, ZCL_DATA16_ATTRIBUTE_TYPE, 2, ZCL_DATA24_ATTRIBUTE_ ZCL_FLOAT_SINGLE_ATTRIBUTE_TYPE, 4, ZCL_FLOAT_DOUBLE_ATTRIBUTE_TYPE, 8, ZCL_TIME_OF_DAY_ATTRIBUTE_TYPE, 4, ZCL_DATE_ATTRIBUTE_TYPE, 4, ZCL_UTC_TIME_ATTRIBUTE_TYPE, 4, ZCL_CLUSTER_ID_ATTRIBUTE_TYPE, 2, ZCL_ATTRIBUTE_ID_ATTRIBUTE_TYPE, 2, ZCL_BACNET_OID_ATTRIBUTE_TYPE, 4, ZCL_IEEE_ADDRESS_ATTRIBUTE_TYPE, 8, ZCL_SECURITY_KEY_ATTRIBUTE_TYPE, 16, + ZCL_ENDPOINT_ID_ATTRIBUTE_TYPE, 1, ZCL_GROUP_ID_ATTRIBUTE_TYPE, 2, ZCL_COMMAND_ID_ATTRIBUTE_TYPE, 1, ZCL_NODE_ID_ATTRIBUTE_TYPE, + 8, diff --git a/examples/lock-app/lock-common/gen/attribute-type.h b/examples/lock-app/lock-common/gen/attribute-type.h index bc5d1bae34b365..225cbc68be49c2 100644 --- a/examples/lock-app/lock-common/gen/attribute-type.h +++ b/examples/lock-app/lock-common/gen/attribute-type.h @@ -1,4 +1,3 @@ - /* * * Copyright (c) 2020 Project CHIP Authors @@ -77,5 +76,9 @@ enum ZCL_BACNET_OID_ATTRIBUTE_TYPE = 0xEA, // BACnet OID ZCL_IEEE_ADDRESS_ATTRIBUTE_TYPE = 0xF0, // IEEE address ZCL_SECURITY_KEY_ATTRIBUTE_TYPE = 0xF1, // 128-bit security key + ZCL_ENDPOINT_ID_ATTRIBUTE_TYPE = 0xF2, // Endpoint Id + ZCL_GROUP_ID_ATTRIBUTE_TYPE = 0xF3, // Group Id + ZCL_COMMAND_ID_ATTRIBUTE_TYPE = 0xF4, // Command Id + ZCL_NODE_ID_ATTRIBUTE_TYPE = 0xF5, // Node Id ZCL_UNKNOWN_ATTRIBUTE_TYPE = 0xFF, // Unknown }; diff --git a/examples/lock-app/lock-common/gen/call-command-handler.cpp b/examples/lock-app/lock-common/gen/call-command-handler.cpp index b4313f5129d251..6f1235aeedf742 100644 --- a/examples/lock-app/lock-common/gen/call-command-handler.cpp +++ b/examples/lock-app/lock-common/gen/call-command-handler.cpp @@ -1,4 +1,3 @@ - /* * * Copyright (c) 2020 Project CHIP Authors diff --git a/examples/lock-app/lock-common/gen/call-command-handler.h b/examples/lock-app/lock-common/gen/call-command-handler.h index c1b06642f07ac9..43164ad576bfa8 100644 --- a/examples/lock-app/lock-common/gen/call-command-handler.h +++ b/examples/lock-app/lock-common/gen/call-command-handler.h @@ -1,4 +1,3 @@ - /* * * Copyright (c) 2020 Project CHIP Authors diff --git a/examples/lock-app/lock-common/gen/callback-stub.cpp b/examples/lock-app/lock-common/gen/callback-stub.cpp index 6f597e18afb113..38608e2ee7d29b 100644 --- a/examples/lock-app/lock-common/gen/callback-stub.cpp +++ b/examples/lock-app/lock-common/gen/callback-stub.cpp @@ -1,4 +1,3 @@ - /* * * Copyright (c) 2020 Project CHIP Authors diff --git a/examples/lock-app/lock-common/gen/callback.h b/examples/lock-app/lock-common/gen/callback.h index 17c21dfad82831..3bc4bcaacaf8a2 100644 --- a/examples/lock-app/lock-common/gen/callback.h +++ b/examples/lock-app/lock-common/gen/callback.h @@ -1,4 +1,3 @@ - /* * * Copyright (c) 2020 Project CHIP Authors diff --git a/examples/lock-app/lock-common/gen/client-command-macro.h b/examples/lock-app/lock-common/gen/client-command-macro.h index f1b0c4633a2b14..7116663d885eca 100644 --- a/examples/lock-app/lock-common/gen/client-command-macro.h +++ b/examples/lock-app/lock-common/gen/client-command-macro.h @@ -1,4 +1,3 @@ - /* * * Copyright (c) 2020 Project CHIP Authors @@ -5663,6 +5662,32 @@ ZCL_GET_ENDPOINT_LIST_REQUEST_COMMAND_ID, "uuuub", startIndex, total, startIndex, count, \ endpointInformationRecordList, endpointInformationRecordListLen); +/** @brief Command description for Bind + * + * Command: Bind + * @param nodeId NODE_ID + * @param groupId GROUP_ID + * @param endpointId ENDPOINT_ID + * @param clusterId CLUSTER_ID + */ +#define emberAfFillCommandBindingClusterBind(nodeId, groupId, endpointId, clusterId) \ + emberAfFillExternalBuffer(mask, \ + \ + ZCL_BIND_COMMAND_ID, "uuuu", nodeId, groupId, endpointId, clusterId); + +/** @brief Command description for Unbind + * + * Command: Unbind + * @param nodeId NODE_ID + * @param groupId GROUP_ID + * @param endpointId ENDPOINT_ID + * @param clusterId CLUSTER_ID + */ +#define emberAfFillCommandBindingClusterUnbind(nodeId, groupId, endpointId, clusterId) \ + emberAfFillExternalBuffer(mask, \ + \ + ZCL_UNBIND_COMMAND_ID, "uuuu", nodeId, groupId, endpointId, clusterId); + /** @brief Command description for CommandOne * * Command: CommandOne diff --git a/examples/lock-app/lock-common/gen/cluster-id.h b/examples/lock-app/lock-common/gen/cluster-id.h index c341b079be401d..4db65e9cad99d0 100644 --- a/examples/lock-app/lock-common/gen/cluster-id.h +++ b/examples/lock-app/lock-common/gen/cluster-id.h @@ -1,4 +1,3 @@ - /* * * Copyright (c) 2020 Project CHIP Authors @@ -331,6 +330,9 @@ // Definitions for cluster: ZLL Commissioning #define ZCL_ZLL_COMMISSIONING_CLUSTER_ID (0x1000) +// Definitions for cluster: Binding +#define ZCL_BINDING_CLUSTER_ID (0xF000) + // Definitions for cluster: Sample Mfg Specific Cluster #define ZCL_SAMPLE_MFG_SPECIFIC_CLUSTER_ID (0xFC00) diff --git a/examples/lock-app/lock-common/gen/command-id.h b/examples/lock-app/lock-common/gen/command-id.h index 940258f4527aa5..42dcc0e89c71f5 100644 --- a/examples/lock-app/lock-common/gen/command-id.h +++ b/examples/lock-app/lock-common/gen/command-id.h @@ -1,4 +1,3 @@ - /* * * Copyright (c) 2020 Project CHIP Authors @@ -46,6 +45,7 @@ // Commands for cluster: Basic #define ZCL_RESET_TO_FACTORY_DEFAULTS_COMMAND_ID (0x00) +#define ZCL_MFG_SPECIFIC_PING_COMMAND_ID (0x00) // Commands for cluster: Identify #define ZCL_IDENTIFY_COMMAND_ID (0x00) @@ -683,6 +683,10 @@ #define ZCL_GET_ENDPOINT_LIST_REQUEST_COMMAND_ID (0x42) #define ZCL_GET_ENDPOINT_LIST_RESPONSE_COMMAND_ID (0x42) +// Commands for cluster: Binding +#define ZCL_BIND_COMMAND_ID (0x00) +#define ZCL_UNBIND_COMMAND_ID (0x01) + // Commands for cluster: Sample Mfg Specific Cluster #define ZCL_COMMAND_ONE_COMMAND_ID (0x00) diff --git a/examples/lock-app/lock-common/gen/endpoint_config.h b/examples/lock-app/lock-common/gen/endpoint_config.h index b84160d8b003dc..f375f5685fe66d 100644 --- a/examples/lock-app/lock-common/gen/endpoint_config.h +++ b/examples/lock-app/lock-common/gen/endpoint_config.h @@ -131,11 +131,6 @@ 0 \ } -#define EMBER_AF_GENERATED_PLUGIN_STACK_STATUS_FUNCTION_DECLARATIONS \ - void emberAfPluginNetworkSteeringStackStatusCallback(EmberStatus status); - -#define EMBER_AF_GENERATED_PLUGIN_STACK_STATUS_FUNCTION_CALLS emberAfPluginNetworkSteeringStackStatusCallback(status); - // Generated data for the command discovery #define GENERATED_COMMANDS \ { \ diff --git a/examples/lock-app/lock-common/gen/enums.h b/examples/lock-app/lock-common/gen/enums.h index 07c2881e641e97..eedb99290f59ce 100644 --- a/examples/lock-app/lock-common/gen/enums.h +++ b/examples/lock-app/lock-common/gen/enums.h @@ -1,4 +1,3 @@ - /* * * Copyright (c) 2020 Project CHIP Authors @@ -548,7 +547,7 @@ typedef enum EMBER_ZCL_DOOR_LOCK_OPERATING_MODE_PRIVACY_MODE = 0x02, EMBER_ZCL_DOOR_LOCK_OPERATING_MODE_NO_RF_LOCK_OR_UNLOCK = 0x03, EMBER_ZCL_DOOR_LOCK_OPERATING_MODE_LOCAL_PROGRAMMING_MODE = 0x04, - EMBER_ZCL_DOOR_LOCK_OPERATING_MODE_PASSAGE_MODE______ = 0x05, + EMBER_ZCL_DOOR_LOCK_OPERATING_MODE_PASSAGE_MODE = 0x05, } EmberAfDoorLockOperatingMode; // Enum for DoorLockOperationEventCode diff --git a/examples/lock-app/lock-common/gen/gen_config.h b/examples/lock-app/lock-common/gen/gen_config.h index 61b55dca38755d..7a769cf83c75ab 100644 --- a/examples/lock-app/lock-common/gen/gen_config.h +++ b/examples/lock-app/lock-common/gen/gen_config.h @@ -1,4 +1,3 @@ - /* * * Copyright (c) 2020 Project CHIP Authors @@ -41,5 +40,5 @@ // Use this macro to check if Reporting plugin is included #define EMBER_AF_PLUGIN_REPORTING // User options for plugin Reporting -#define EMBER_AF_PLUGIN_REPORTING_TABLE_SIZE 5 +#define EMBER_AF_PLUGIN_REPORTING_TABLE_SIZE 20 #define EMBER_AF_PLUGIN_REPORTING_ENABLE_GROUP_BOUND_REPORTS diff --git a/examples/lock-app/lock-common/gen/print-cluster.h b/examples/lock-app/lock-common/gen/print-cluster.h index a37d7fb0495995..7155ccf0294122 100644 --- a/examples/lock-app/lock-common/gen/print-cluster.h +++ b/examples/lock-app/lock-common/gen/print-cluster.h @@ -1,4 +1,3 @@ - /* * * Copyright (c) 2020 Project CHIP Authors @@ -715,6 +714,12 @@ #define CHIP_PRINTCLUSTER_ZLL_COMMISSIONING_CLUSTER #endif +#if defined(ZCL_USING_BINDING_CLUSTER_SERVER) || defined(ZCL_USING_BINDING_CLUSTER_CLIENT) +#define CHIP_PRINTCLUSTER_BINDING_CLUSTER { ZCL_BINDING_CLUSTER_ID, 61440, "Binding" }, +#else +#define CHIP_PRINTCLUSTER_BINDING_CLUSTER +#endif + #if defined(ZCL_USING_SAMPLE_MFG_SPECIFIC_CLUSTER_SERVER) || defined(ZCL_USING_SAMPLE_MFG_SPECIFIC_CLUSTER_CLIENT) #define CHIP_PRINTCLUSTER_SAMPLE_MFG_SPECIFIC_CLUSTER { ZCL_SAMPLE_MFG_SPECIFIC_CLUSTER_ID, 64512, "Sample Mfg Specific Cluster" }, #else @@ -851,6 +856,7 @@ CHIP_PRINTCLUSTER_ELECTRICAL_MEASUREMENT_CLUSTER \ CHIP_PRINTCLUSTER_DIAGNOSTICS_CLUSTER \ CHIP_PRINTCLUSTER_ZLL_COMMISSIONING_CLUSTER \ + CHIP_PRINTCLUSTER_BINDING_CLUSTER \ CHIP_PRINTCLUSTER_SAMPLE_MFG_SPECIFIC_CLUSTER \ CHIP_PRINTCLUSTER_SAMPLE_MFG_SPECIFIC_CLUSTER_2 \ CHIP_PRINTCLUSTER_OTA_CONFIGURATION_CLUSTER \ diff --git a/examples/lock-app/nrfconnect/CMakeLists.txt b/examples/lock-app/nrfconnect/CMakeLists.txt index ff11433e73f69e..51682ef7f0cd43 100644 --- a/examples/lock-app/nrfconnect/CMakeLists.txt +++ b/examples/lock-app/nrfconnect/CMakeLists.txt @@ -16,18 +16,21 @@ cmake_minimum_required(VERSION 3.13.1) get_filename_component(CHIP_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/third_party/connectedhomeip REALPATH) -get_filename_component(CHIP_APP_SERVER ${CHIP_ROOT}/examples/common/chip-app-server REALPATH) get_filename_component(NRFCONNECT_COMMON ${CHIP_ROOT}/examples/platform/nrfconnect REALPATH) get_filename_component(LOCK_COMMON ${CHIP_ROOT}/examples/lock-app/lock-common REALPATH) -set(CONF_FILE ${CHIP_ROOT}/config/nrfconnect/sample-defaults.conf prj.conf) -set(CHIP_OPENTHREAD_CONFIG ${NRFCONNECT_COMMON}/project_include/OpenThreadConfig.h) +set(CONF_FILE ${CHIP_ROOT}/config/nrfconnect/app/sample-defaults.conf prj.conf) -set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CHIP_ROOT}/config/nrfconnect/) -include(nrfconnect-app) +include(${CHIP_ROOT}/config/nrfconnect/app/app.cmake) project(chip-nrf52840-lock-example) -target_include_directories(app PRIVATE main/include ${LOCK_COMMON} ${NRFCONNECT_COMMON}/util/include ${NRFCONNECT_COMMON}/app/include ${CHIP_APP_SERVER}/include) + +target_include_directories(app PRIVATE + main/include + ${LOCK_COMMON} + ${NRFCONNECT_COMMON}/util/include + ${NRFCONNECT_COMMON}/app/include) + target_sources(app PRIVATE main/AppTask.cpp main/BoltLockManager.cpp @@ -39,10 +42,7 @@ target_sources(app PRIVATE ${NRFCONNECT_COMMON}/util/NFCWidget.cpp ${NRFCONNECT_COMMON}/util/ThreadUtil.cpp ${NRFCONNECT_COMMON}/app/Service.cpp - ${CHIP_APP_SERVER}/DataModelHandler.cpp - ${CHIP_APP_SERVER}/Server.cpp - ${CHIP_APP_SERVER}/QRCodeUtil.cpp - ${CHIP_APP_SERVER}/RendezvousServer.cpp + ${CHIP_ROOT}/src/app/server/DataModelHandler.cpp ${CHIP_ROOT}/src/app/reporting/reporting-default-configuration.cpp ${CHIP_ROOT}/src/app/reporting/reporting.cpp ${CHIP_ROOT}/src/app/util/af-event.cpp @@ -58,4 +58,5 @@ target_sources(app PRIVATE ${CHIP_ROOT}/src/app/util/process-cluster-message.cpp ${CHIP_ROOT}/src/app/util/process-global-message.cpp ${CHIP_ROOT}/src/app/util/util.cpp + ${CHIP_ROOT}/src/app/clusters/bindings/bindings.cpp ${CHIP_ROOT}/src/app/clusters/on-off-server/on-off.cpp) diff --git a/examples/lock-app/nrfconnect/README.md b/examples/lock-app/nrfconnect/README.md index 9fbf6d893f2f76..ee58ed43ea29de 100644 --- a/examples/lock-app/nrfconnect/README.md +++ b/examples/lock-app/nrfconnect/README.md @@ -64,7 +64,9 @@ commissioner role. To start the rendezvous, the controller must get the commissioning information from the CHIP device. The data payload is encoded within a QR code, printed to -the UART console, and shared using an NFC tag. +the UART console, and shared using an NFC tag. For security reasons, you must +start NFC tag emulation manually after powering up the device by pressing +**Button 4**. #### Thread provisioning @@ -143,8 +145,8 @@ opposite one. **Button 3** — Pressing the button once starts the Thread networking in the test mode using the default configuration. -**Button 4** — Pressing the button once starts the Bluetooth LE -advertising for the predefined period of time. +**Button 4** — Pressing the button once starts the NFC tag emulation and +enables Bluetooth LE advertising for the predefined period of time. **SEGGER J-Link USB port** can be used to get logs from the device or communicate with it using the @@ -292,7 +294,7 @@ following command: To build the example with release configuration that disables the diagnostic features like logs and command-line interface, run the following command: - $ west build -b board-name -- -DOVERLAY_CONFIG=third_party/connectedhomeip/config/nrfconnect/release.conf + $ west build -b board-name -- -DOVERLAY_CONFIG=third_party/connectedhomeip/config/nrfconnect/app/release.conf Remember to replace _board-name_ with the name of the Nordic Semiconductor's board you own. diff --git a/examples/lock-app/nrfconnect/main/AppTask.cpp b/examples/lock-app/nrfconnect/main/AppTask.cpp index e4d180c0e3839c..e219b750e3ce89 100644 --- a/examples/lock-app/nrfconnect/main/AppTask.cpp +++ b/examples/lock-app/nrfconnect/main/AppTask.cpp @@ -113,13 +113,6 @@ int AppTask::Init() } PlatformMgr().AddEventHandler(AppTask::ThreadProvisioningHandler, 0); - - ret = StartNFCTag(); - if (ret) - { - LOG_ERR("Starting NFC Tag failed"); - return ret; - } #endif return 0; @@ -385,6 +378,22 @@ void AppTask::StartBLEAdvertisementHandler(AppEvent * aEvent) if (aEvent->ButtonEvent.PinNo != BLE_ADVERTISEMENT_START_BUTTON) return; + if (!sNFC.IsTagEmulationStarted()) + { + if (!(GetAppTask().StartNFCTag() < 0)) + { + LOG_INF("Started NFC Tag emulation"); + } + else + { + LOG_ERR("Starting NFC Tag failed"); + } + } + else + { + LOG_INF("NFC Tag emulation is already started"); + } + if (!ConnectivityMgr().IsBLEAdvertisingEnabled()) { ConnectivityMgr().SetBLEAdvertisingEnabled(true); @@ -434,7 +443,7 @@ int AppTask::StartNFCTag() VerifyOrExit(!result, ChipLogError(AppServer, "Getting QR code payload failed")); result = sNFC.StartTagEmulation(QRCode.c_str(), QRCode.size()); - VerifyOrExit(!result, ChipLogError(AppServer, "Starting NFC Tag emulation failed")); + VerifyOrExit(result >= 0, ChipLogError(AppServer, "Starting NFC Tag emulation failed")); exit: return result; diff --git a/examples/lock-app/nrfconnect/prj.conf b/examples/lock-app/nrfconnect/prj.conf index 4c4df25d91b01c..8b1bb05fb3989c 100644 --- a/examples/lock-app/nrfconnect/prj.conf +++ b/examples/lock-app/nrfconnect/prj.conf @@ -33,3 +33,7 @@ CONFIG_BT_DEVICE_NAME="ChipLock" # Additional configs for debbugging experience. CONFIG_THREAD_NAME=y CONFIG_MPU_STACK_GUARD=y + +# CHIP configuration +CONFIG_CHIP_PROJECT_CONFIG="main/include/CHIPProjectConfig.h" +CONFIG_CHIP_OPENTHREAD_CONFIG="../../platform/nrfconnect/project_include/OpenThreadConfig.h" diff --git a/examples/lock-app/qpg6100/BUILD.gn b/examples/lock-app/qpg6100/BUILD.gn index 07e1d8e61a295c..f457bf0b4a31ba 100644 --- a/examples/lock-app/qpg6100/BUILD.gn +++ b/examples/lock-app/qpg6100/BUILD.gn @@ -22,7 +22,6 @@ assert(current_os == "freertos") qpg6100_project_dir = "${chip_root}/examples/lock-app/qpg6100" examples_plat_dir = "${chip_root}/examples/platform/qpg6100" -examples_common_dir = "${chip_root}/examples/common" qpg6100_sdk("sdk") { include_dirs = [ @@ -49,7 +48,6 @@ qpg6100_executable("lock_app") { ":sdk", "${chip_root}/src/lib", "${chip_root}/src/setup_payload", - "${examples_common_dir}/chip-app-server:chip-app-server", # OpenThread to be enabled # https://github.com/project-chip/connectedhomeip/issues/293 @@ -62,11 +60,11 @@ qpg6100_executable("lock_app") { include_dirs += [ "${qpg6100_project_dir}/include/", "${chip_root}/src/app/util", + "${chip_root}/src/app/server", "${examples_plat_dir}/", ] sources = [ - "${examples_common_dir}/chip-app-server/QRCodeUtil.cpp", "src/AppTask.cpp", "src/BoltLockManager.cpp", "src/ZclCallbacks.cpp", @@ -74,7 +72,6 @@ qpg6100_executable("lock_app") { ] deps = [ - "${chip_root}/examples/common/chip-app-server:chip-app-server", "${chip_root}/examples/lock-app/lock-common", "${chip_root}/src/lib", "${chip_root}/src/setup_payload", diff --git a/examples/lock-app/qpg6100/README.md b/examples/lock-app/qpg6100/README.md index bcfce4ca54b3bf..4da4bb267e6b6a 100644 --- a/examples/lock-app/qpg6100/README.md +++ b/examples/lock-app/qpg6100/README.md @@ -93,6 +93,7 @@ export QPG6100_SDK_ROOT=${HOME}/qpg-connectedhomeip ``` cd ~/connectedhomeip/examples/lock-app/qpg6100 +source third_party/connectedhomeip/scripts/activate.sh gn gen out/debug ninja -C out/debug ``` diff --git a/examples/lock-app/qpg6100/src/AppTask.cpp b/examples/lock-app/qpg6100/src/AppTask.cpp index 065d2f04f0a336..39c454dd97cbb5 100644 --- a/examples/lock-app/qpg6100/src/AppTask.cpp +++ b/examples/lock-app/qpg6100/src/AppTask.cpp @@ -27,7 +27,6 @@ #include "Server.h" #include "attribute-storage.h" -#include "gen/cluster-id.h" #include #include diff --git a/examples/lock-app/qpg6100/src/ZclCallbacks.cpp b/examples/lock-app/qpg6100/src/ZclCallbacks.cpp index b2271dae35dab1..5a449049517cfe 100644 --- a/examples/lock-app/qpg6100/src/ZclCallbacks.cpp +++ b/examples/lock-app/qpg6100/src/ZclCallbacks.cpp @@ -21,8 +21,6 @@ #include "AppTask.h" #include "BoltLockManager.h" -#include "gen/attribute-id.h" -#include "gen/cluster-id.h" #include #include #include diff --git a/examples/lock-app/qpg6100/src/main.cpp b/examples/lock-app/qpg6100/src/main.cpp index ea78c9518be6d9..d6614c34e8ff9e 100644 --- a/examples/lock-app/qpg6100/src/main.cpp +++ b/examples/lock-app/qpg6100/src/main.cpp @@ -15,34 +15,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -/* - * Copyright (c) 2020, Qorvo Inc - * - * - * - * This software is owned by Qorvo Inc - * and protected under applicable copyright laws. - * It is delivered under the terms of the license - * and is intended and supplied for use solely and - * exclusively with products manufactured by - * Qorvo Inc. - * - * - * THIS SOFTWARE IS PROVIDED IN AN "AS IS" - * CONDITION. NO WARRANTIES, WHETHER EXPRESS, - * IMPLIED OR STATUTORY, INCLUDING, BUT NOT - * LIMITED TO, IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A - * PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. - * QORVO INC. SHALL NOT, IN ANY - * CIRCUMSTANCES, BE LIABLE FOR SPECIAL, - * INCIDENTAL OR CONSEQUENTIAL DAMAGES, - * FOR ANY REASON WHATSOEVER. - * - * $Change: 154416 $ - * $DateTime: 2020/08/21 09:47:42 $ - * - */ /** @file "main.cpp" * @@ -62,6 +34,8 @@ // CHIP includes #include +#include +#include #include // Application level logic @@ -109,6 +83,9 @@ int CHIP_Init(void) { int ret = CHIP_ERROR_MAX; + // Init Chip memory management before the stack + chip::Platform::MemoryInit(); + ChipLogProgress(NotSpecified, "Init CHIP Stack"); ret = PlatformMgr().InitChipStack(); if (ret != CHIP_NO_ERROR) diff --git a/examples/minimal-mdns/AllInterfaceListener.h b/examples/minimal-mdns/AllInterfaceListener.h index fa87c3889a0b07..844305ee0b2c17 100644 --- a/examples/minimal-mdns/AllInterfaceListener.h +++ b/examples/minimal-mdns/AllInterfaceListener.h @@ -95,7 +95,7 @@ class AllInterfaces : public mdns::Minimal::ListenIterator return true; // not a usable interface } char name[64]; - if (!mIterator.GetInterfaceName(name, sizeof(name)) == CHIP_NO_ERROR) + if (mIterator.GetInterfaceName(name, sizeof(name)) != CHIP_NO_ERROR) { printf("!!!! FAILED TO GET INTERFACE NAME\n"); return true; diff --git a/examples/minimal-mdns/BUILD.gn b/examples/minimal-mdns/BUILD.gn index e37aea77d78708..06d530cc80e63e 100644 --- a/examples/minimal-mdns/BUILD.gn +++ b/examples/minimal-mdns/BUILD.gn @@ -57,3 +57,17 @@ executable("minimal-mdns-server") { output_dir = root_out_dir } + +executable("mdns-advertiser") { + sources = [ "advertiser.cpp" ] + + cflags = [ "-Wconversion" ] + + public_deps = [ + ":minimal-mdns-example-common", + "${chip_root}/src/lib", + "${chip_root}/src/lib/mdns", + ] + + output_dir = root_out_dir +} diff --git a/examples/minimal-mdns/README.md b/examples/minimal-mdns/README.md index 740cc59bdfb5a6..8949e8ba6e15e8 100644 --- a/examples/minimal-mdns/README.md +++ b/examples/minimal-mdns/README.md @@ -24,7 +24,7 @@ the network while running. ## Example client -The file -client.cpp` contains an example of a mdns client. By default it +The file `client.cpp` contains an example of a mdns client. By default it queries for **\_services.\_dns-sd.\_udp.local** (DNS-SD list services) and uses unicast queries. @@ -50,6 +50,29 @@ see for full command line details. +## Example advertiser + +This example uses the chip built-in advertiser, implemented in the file +`advertiser.cpp`. + +Example runs: + +```sh +./out/minimal_mdns/mdns-advertiser -4 -m operational +``` + +```sh +./out/minimal_mdns/mdns-advertiser -4 -m commisioning --vendor-id 123 --product-id 456 +``` + +see + +```sh +./out/minimal_mdns/mdns-advertiser --help +``` + +for full command line details. + ## Testing with dns-sd If you have a mac computer (or are able to install dns-sd via opkg), here are @@ -76,7 +99,7 @@ DD200C20D25AE5F7._chipc._udp.local. SRV 0 0 11111 B75AFB458ECD.local. B75AFB458ECD.local. AAAA ba2a:b311:742e:b44c:f515:576f:9783:3f30 ``` -#### Simulated commisionable node +#### Simulated commisioning node ```sh dns-sd -R DD200C20D25AE5F7 _chipd._udp,S052,L0840,V123 . 11111 D=0840 VP=123+456 PH=3 diff --git a/examples/minimal-mdns/advertiser.cpp b/examples/minimal-mdns/advertiser.cpp new file mode 100644 index 00000000000000..a68b45d2c0cc91 --- /dev/null +++ b/examples/minimal-mdns/advertiser.cpp @@ -0,0 +1,261 @@ +/* + * + * 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 +#include + +#include +#include +#include +#include + +using namespace chip; + +namespace { + +enum class AdvertisingMode +{ + kCommisioning, + kOperational, + kCommisionable, +}; + +struct Options +{ + bool enableIpV4 = false; + AdvertisingMode advertisingMode = AdvertisingMode::kCommisioning; + + // commisioning/commisionable params + uint8_t shortDiscriminator = 52; + uint16_t longDiscriminator = 840; + Optional vendorId; + Optional productId; + + // commisionable params + Optional pairingInstr; + Optional pairingHint; + + // operational params + uint64_t fabricId = 12345; + uint64_t nodeId = 6789; + +} gOptions; + +using namespace chip::ArgParser; + +constexpr uint16_t kOptionEnableIpV4 = '4'; +constexpr uint16_t kOptionAdvertisingMode = 'm'; + +constexpr uint16_t kOptionCommisioningShordDiscriminator = 's'; +constexpr uint16_t kOptionCommisioningLongDiscriminaotr = 'l'; +constexpr uint16_t kOptionCommisioningVendorId = 0x100; // v is used by 'version' +constexpr uint16_t kOptionCommisioningProductId = 'p'; +constexpr uint16_t kOptionCommisioningPairingInstr = 0x200; // Just use the long format +constexpr uint16_t kOptionCommisioningPairingHint = 0x300; + +constexpr uint16_t kOptionOperationalFabricId = 'f'; +constexpr uint16_t kOptionOperationalNodeId = 'n'; + +bool HandleOptions(const char * aProgram, OptionSet * aOptions, int aIdentifier, const char * aName, const char * aValue) +{ + switch (aIdentifier) + { + case kOptionEnableIpV4: + gOptions.enableIpV4 = true; + return true; + case kOptionAdvertisingMode: + if (strcmp(aValue, "operational") == 0) + { + gOptions.advertisingMode = AdvertisingMode::kOperational; + } + else if (strcmp(aValue, "commisioning") == 0) + { + gOptions.advertisingMode = AdvertisingMode::kCommisioning; + } + else if (strcmp(aValue, "commisionable") == 0) + { + gOptions.advertisingMode = AdvertisingMode::kCommisionable; + } + else + { + PrintArgError("%s: Invalid advertising mode %s\n", aProgram, aValue); + + return false; + } + return true; + case kOptionCommisioningShordDiscriminator: + gOptions.shortDiscriminator = static_cast(atoi(aValue)); + return true; + case kOptionCommisioningLongDiscriminaotr: + gOptions.longDiscriminator = static_cast(atoi(aValue)); + return true; + case kOptionCommisioningVendorId: + gOptions.vendorId = Optional::Value(static_cast(atoi(aValue))); + return true; + case kOptionCommisioningProductId: + gOptions.productId = Optional::Value(static_cast(atoi(aValue))); + return true; + case kOptionCommisioningPairingInstr: + gOptions.pairingInstr = Optional::Value(static_cast(aValue)); + return true; + case kOptionCommisioningPairingHint: + gOptions.pairingHint = Optional::Value(static_cast(atoi(aValue))); + return true; + case kOptionOperationalFabricId: + gOptions.fabricId = atoll(aValue); + return true; + case kOptionOperationalNodeId: + gOptions.nodeId = atoll(aValue); + return true; + default: + PrintArgError("%s: INTERNAL ERROR: Unhandled option: %s\n", aProgram, aName); + return false; + } +} + +OptionDef cmdLineOptionsDef[] = { +#if INET_CONFIG_ENABLE_IPV4 + { "enable-ip-v4", kNoArgument, kOptionEnableIpV4 }, +#endif + { "advertising-mode", kArgumentRequired, kOptionAdvertisingMode }, + + { "short-discriminator", kArgumentRequired, kOptionCommisioningShordDiscriminator }, + { "long-discriminator", kArgumentRequired, kOptionCommisioningLongDiscriminaotr }, + { "vendor-id", kArgumentRequired, kOptionCommisioningVendorId }, + { "product-id", kArgumentRequired, kOptionCommisioningProductId }, + { "pairing-instruction", kArgumentRequired, kOptionCommisioningPairingInstr }, + { "pairing-hint", kArgumentRequired, kOptionCommisioningPairingHint }, + + { "fabrid-id", kArgumentRequired, kOptionOperationalFabricId }, + { "node-id", kArgumentRequired, kOptionOperationalNodeId }, + nullptr, +}; + +OptionSet cmdLineOptions = { HandleOptions, cmdLineOptionsDef, "PROGRAM OPTIONS", +#if INET_CONFIG_ENABLE_IPV4 + " -4\n" + " --enable-ip-v4\n" + " enable listening on IPv4\n" +#endif + " -m \n" + " --advertising-mode \n" + " Advertise in this mode (operational or commisioning or commisionable).\n" + " --short-discriminator \n" + " -s \n" + " Commisioning/commisionable short discriminator.\n" + " --long-discriminator \n" + " -l \n" + " Commisioning/commisionable long discriminator.\n" + " --vendor-id \n" + " Commisioning/commisionable vendor id.\n" + " --product-id \n" + " -p \n" + " Commisioning/commisionable product id.\n" + " --pairing-instruction \n" + " Commisionable pairing instruction.\n" + " --pairing-hint \n" + " Commisionable pairing hint.\n" + " --fabrid-id \n" + " -f \n" + " Operational fabric id.\n" + " --node-id \n" + " -n \n" + " Operational node id.\n" + "\n" }; + +HelpOptions helpOptions("advertiser", "Usage: advertiser [options]", "1.0"); + +OptionSet * allOptions[] = { &cmdLineOptions, &helpOptions, nullptr }; + +} // namespace + +int main(int argc, char ** args) +{ + if (Platform::MemoryInit() != CHIP_NO_ERROR) + { + fprintf(stderr, "FAILED to initialize memory\n"); + return 1; + } + + if (DeviceLayer::PlatformMgr().InitChipStack() != CHIP_NO_ERROR) + { + fprintf(stderr, "FAILED to initialize chip stack\n"); + return 1; + } + + if (!chip::ArgParser::ParseArgs(args[0], argc, args, allOptions)) + { + return 1; + } + + if (chip::Mdns::ServiceAdvertiser::Instance().Start(&DeviceLayer::InetLayer, Mdns::kMdnsPort) != CHIP_NO_ERROR) + { + fprintf(stderr, "FAILED to start MDNS advertisement\n"); + return 1; + } + + CHIP_ERROR err; + + if (gOptions.advertisingMode == AdvertisingMode::kCommisioning) + { + err = chip::Mdns::ServiceAdvertiser::Instance().Advertise(chip::Mdns::CommisioningAdvertisingParameters() + .EnableIpV4(gOptions.enableIpV4) + .SetPort(CHIP_PORT) + .SetShortDiscriminator(gOptions.shortDiscriminator) + .SetLongDiscrimininator(gOptions.longDiscriminator) + .SetVendorId(gOptions.vendorId) + .SetProductId(gOptions.productId)); + } + else if (gOptions.advertisingMode == AdvertisingMode::kOperational) + { + err = chip::Mdns::ServiceAdvertiser::Instance().Advertise(chip::Mdns::OperationalAdvertisingParameters() + .EnableIpV4(gOptions.enableIpV4) + .SetPort(CHIP_PORT) + .SetFabricId(gOptions.fabricId) + .SetNodeId(gOptions.nodeId)); + } + else if (gOptions.advertisingMode == AdvertisingMode::kCommisionable) + { + err = chip::Mdns::ServiceAdvertiser::Instance().Advertise(chip::Mdns::CommisionableAdvertisingParameters() + .EnableIpV4(gOptions.enableIpV4) + .SetPort(CHIP_PORT) + .SetShortDiscriminator(gOptions.shortDiscriminator) + .SetLongDiscrimininator(gOptions.longDiscriminator) + .SetVendorId(gOptions.vendorId) + .SetProductId(gOptions.productId) + .SetPairingInstr(gOptions.pairingInstr) + .SetPairingHint(gOptions.pairingHint)); + } + else + { + fprintf(stderr, "FAILED to determine advertising type.\n"); + return 1; + } + + if (err != CHIP_NO_ERROR) + { + fprintf(stderr, "FAILED to setup advertisement parameters\n"); + return 1; + } + + DeviceLayer::PlatformMgr().RunEventLoop(); + + printf("Done...\n"); + return 0; +} diff --git a/examples/minimal-mdns/client.cpp b/examples/minimal-mdns/client.cpp index e9ffd1409111f1..be464ef6df84a3 100644 --- a/examples/minimal-mdns/client.cpp +++ b/examples/minimal-mdns/client.cpp @@ -63,7 +63,7 @@ constexpr uint16_t kOptionQueryPort = 0x101; constexpr uint16_t kOptionRuntimeMs = 0x102; constexpr uint16_t kOptionMulticastReplies = 0x103; -bool HandleOptions(const char * aProgram, OptionSet * aOpotions, int aIdentifier, const char * aName, const char * aValue) +bool HandleOptions(const char * aProgram, OptionSet * aOptions, int aIdentifier, const char * aName, const char * aValue) { switch (aIdentifier) { @@ -261,7 +261,7 @@ void BroadcastPacket(mdns::Minimal::ServerBase * server) QuerySplitter query; query.Split(gOptions.query); - mdns::Minimal::QueryBuilder builder(buffer.Get_ForNow()); + mdns::Minimal::QueryBuilder builder(std::move(buffer)); builder.Header().SetMessageId(kTestMessageId); builder.AddQuery(query @@ -277,7 +277,7 @@ void BroadcastPacket(mdns::Minimal::ServerBase * server) return; } - if (server->BroadcastSend(buffer.Release_ForNow(), gOptions.querySendPort) != CHIP_NO_ERROR) + if (server->BroadcastSend(builder.ReleasePacket(), gOptions.querySendPort) != CHIP_NO_ERROR) { printf("Error sending\n"); return; diff --git a/examples/minimal-mdns/server.cpp b/examples/minimal-mdns/server.cpp index 1811278c120fb7..cb9946c1140db2 100644 --- a/examples/minimal-mdns/server.cpp +++ b/examples/minimal-mdns/server.cpp @@ -56,7 +56,7 @@ constexpr uint16_t kOptionEnableIpV4 = '4'; constexpr uint16_t kOptionListenPort = 'p'; constexpr uint16_t kOptionInstanceName = 'i'; -bool HandleOptions(const char * aProgram, OptionSet * aOpotions, int aIdentifier, const char * aName, const char * aValue) +bool HandleOptions(const char * aProgram, OptionSet * aOptions, int aIdentifier, const char * aName, const char * aValue) { switch (aIdentifier) { @@ -202,8 +202,8 @@ int main(int argc, char ** args) mdns::Minimal::IPv4Responder ipv4Responder(serverName); mdns::Minimal::IPv6Responder ipv6Responder(serverName); mdns::Minimal::SrvResourceRecord srvRecord(tcpServerServiceName, serverName, CHIP_PORT); - mdns::Minimal::SrvResponder tcpSrvResponder(tcpServerServiceName, srvRecord); - mdns::Minimal::SrvResponder udpSrvResponder(udpServerServiceName, srvRecord); + mdns::Minimal::SrvResponder tcpSrvResponder(mdns::Minimal::SrvResourceRecord(tcpServerServiceName, serverName, CHIP_PORT)); + mdns::Minimal::SrvResponder udpSrvResponder(mdns::Minimal::SrvResourceRecord(udpServerServiceName, serverName, CHIP_PORT)); mdns::Minimal::PtrResponder ptrTcpResponder(tcpServiceName, tcpServerServiceName); mdns::Minimal::PtrResponder ptrUdpResponder(udpServiceName, udpServerServiceName); mdns::Minimal::PtrResponder ptrUdpDiscriminator1Responder(udpDiscriminator1, udpServerServiceName); diff --git a/examples/pigweed-app/nrf5/README.md b/examples/pigweed-app/nrf5/README.md deleted file mode 100644 index 08d5c01232c101..00000000000000 --- a/examples/pigweed-app/nrf5/README.md +++ /dev/null @@ -1,19 +0,0 @@ -# Pigweed example app - -This example app exercises functionalities in third_party/pigweed, to see what -is needed for integrating Pigweed to CHIP, as well as a precursor to CHIP -functionalities like on-device testing. - -## Currently implemented features - -### Echo RPC: - -``` -python -m pw_hdlc_lite.rpc_console --device /dev/ttyACM0 -b 115200 -p $CHIP_ROOT/third_party/pigweed/repo/pw_rpc/pw_rpc_protos/echo.proto -o /tmp/pw_rpc.out -``` - -will start an interactive python shell where Echo RPC can be invoked as - -``` -rpcs.pw.rpc.EchoService.Echo(msg="hi") -``` diff --git a/examples/pigweed-app/nrfconnect/CMakeLists.txt b/examples/pigweed-app/nrfconnect/CMakeLists.txt index b52d96aaac3968..bc457bf6811b23 100644 --- a/examples/pigweed-app/nrfconnect/CMakeLists.txt +++ b/examples/pigweed-app/nrfconnect/CMakeLists.txt @@ -17,14 +17,13 @@ cmake_minimum_required(VERSION 3.13.1) get_filename_component(CHIP_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/third_party/connectedhomeip REALPATH) get_filename_component(NRFCONNECT_COMMON ${CHIP_ROOT}/examples/platform/nrfconnect REALPATH) +set(PIGWEED_ROOT "${CHIP_ROOT}/third_party/pigweed/repo") if(${BOARD} STREQUAL "nrf52840dongle_nrf52840") -list(INSERT OVERLAY_CONFIG 0 ${CHIP_ROOT}/config/nrfconnect/overlay-usb_support.conf) + list(INSERT OVERLAY_CONFIG 0 ${CHIP_ROOT}/config/nrfconnect/app/overlay-usb_support.conf) endif() -set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CHIP_ROOT}/config/nrfconnect/) -set(PIGWEED_ROOT "${CHIP_ROOT}/third_party/pigweed/repo") -include(nrfconnect-app) +include(${CHIP_ROOT}/config/nrfconnect/app/app.cmake) project(chip-nrf52840-pigweed-example) @@ -38,7 +37,7 @@ target_include_directories(app PRIVATE main/include ${PIGWEED_ROOT}/pw_polyfill/public_overrides ${PIGWEED_ROOT}/pw_status/public ${PIGWEED_ROOT}/pw_preprocessor/public - ${NRFCONNECT_COMMON}/pw_sys_io/include) + ${NRFCONNECT_COMMON}/pw_sys_io/public) target_sources(app PRIVATE main/main.cpp ${NRFCONNECT_COMMON}/util/LEDWidget.cpp) diff --git a/examples/platform/cc13x2_26x2/BUILD.gn b/examples/platform/cc13x2_26x2/BUILD.gn new file mode 100644 index 00000000000000..11b4a300755c60 --- /dev/null +++ b/examples/platform/cc13x2_26x2/BUILD.gn @@ -0,0 +1,31 @@ +# Copyright (c) 2020 Project CHIP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build_overrides/chip.gni") + +config("chip_examples_project_config") { + include_dirs = [ "project_include" ] +} + +# TODO - create OpenThread portion of build flow +# https://github.com/project-chip/connectedhomeip/issues/2939 + +source_set("openthread_core_config_cc13x2_26x2_chip_examples") { + sources = [ "project_include/OpenThreadConfig.h" ] + + # public_deps = [ + # "${chip_root}/third_party/openthread/platforms/qpg6100:openthread_core_config_qpg6100" + # ] + public_configs = [ ":chip_examples_project_config" ] +} diff --git a/examples/platform/cc13x2_26x2/args.gni b/examples/platform/cc13x2_26x2/args.gni new file mode 100644 index 00000000000000..7d18cc869d4831 --- /dev/null +++ b/examples/platform/cc13x2_26x2/args.gni @@ -0,0 +1,26 @@ +# Copyright (c) 2020 Project CHIP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build_overrides/chip.gni") + +import("${chip_root}/src/platform/cc13x2_26x2/args.gni") + +openthread_config_file = "" +openthread_core_config_deps = [] + +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/cc13x2_26x2/project_include/OpenThreadConfig.h b/examples/platform/cc13x2_26x2/project_include/OpenThreadConfig.h new file mode 100644 index 00000000000000..8b00bf4a4cb223 --- /dev/null +++ b/examples/platform/cc13x2_26x2/project_include/OpenThreadConfig.h @@ -0,0 +1,181 @@ +/* + * + * Copyright (c) 2020 Project CHIP Authors + * Copyright (c) 2019 Google LLC. + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @file + * Overrides to default OpenThread configuration. + * + */ + +#ifndef OPENTHREAD_PLATFORM_CONFIG_H +#define OPENTHREAD_PLATFORM_CONFIG_H + +// use the logging in the CHIP platform layer +#define OPENTHREAD_CONFIG_LOG_OUTPUT OPENTHREAD_CONFIG_LOG_OUTPUT_APP + +// Turn on a moderate level of logging in OpenThread +// Enable use of external heap allocator (calloc/free) for OpenThread. +#define OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE 1 + +// Reduced for RAM consumption reasons +#define OPENTHREAD_CONFIG_NUM_MESSAGE_BUFFERS 22 + +/* Define to 1 if you want to enable CoAP to an application. */ +#define OPENTHREAD_CONFIG_COAP_API_ENABLE 1 + +/* Define to 1 to enable the border agent feature. */ +#define OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE 0 + +/* Define to 1 if you want to enable Border Router */ +#define OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE 0 + +/* Define to 1 if you want to enable log for certification test */ +#define OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE 0 + +/* Define to 1 if you want to enable channel manager feature */ +#define OPENTHREAD_CONFIG_CHANNEL_MANAGER_ENABLE 0 + +/* Define to 1 if you want to use channel monitor feature */ +#define OPENTHREAD_CONFIG_CHANNEL_MONITOR_ENABLE 0 + +/* Define to 1 if you want to use child supervision feature */ +#define OPENTHREAD_CONFIG_CHILD_SUPERVISION_ENABLE 0 + +/* Define to 1 to enable the commissioner role. */ +#define OPENTHREAD_CONFIG_COMMISSIONER_ENABLE 0 + +/* Define as 1 to enable support for adding of auto-configured SLAAC addresses by OpenThread */ +#define OPENTHREAD_CONFIG_IP6_SLAAC_ENABLE 1 + +/* Define to 1 if you want to enable multicast DHCPv6 Solicit messages */ +#define OPENTHREAD_ENABLE_DHCP6_MULTICAST_SOLICIT 1 + +/* Define to 1 if you want to enable DHCPv6 Client */ +#define OPENTHREAD_CONFIG_DHCP6_CLIENT_ENABLE 1 + +/* Define to 1 if you want to enable DHCPv6 Server */ +#define OPENTHREAD_CONFIG_DHCP6_SERVER_ENABLE 0 + +/* Define to 1 if you want to use diagnostics module */ +#define OPENTHREAD_CONFIG_DIAG_ENABLE 1 + +/* Define to 1 if you want to enable DNS Client */ +#define OPENTHREAD_CONFIG_DNS_CLIENT_ENABLE 0 + +/* Define to 1 to enable dtls support. */ +#define OPENTHREAD_CONFIG_DTLS_ENABLE 1 + +/* Define to 1 if you want to use jam detection feature */ +#define OPENTHREAD_CONFIG_JAM_DETECTION_ENABLE 0 + +/* Define to 1 to enable the joiner role. */ +#define OPENTHREAD_CONFIG_JOINER_ENABLE 1 + +/* Define to 1 if you want to use legacy network support */ +#define OPENTHREAD_CONFIG_LEGACY_ENABLE 0 + +/* Define to 1 if you want to use MAC filter feature */ +#define OPENTHREAD_CONFIG_MAC_FILTER_ENABLE 0 + +/* Define to 1 to enable network diagnostic for MTD. */ +#define OPENTHREAD_CONFIG_TMF_NETWORK_DIAG_MTD_ENABLE 0 + +/* Define to 1 if you want to enable support for multiple OpenThread + instances. */ +#define OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE 0 + +/* Define to 1 to enable the NCP SPI interface. */ +#define OPENTHREAD_CONFIG_NCP_SPI_ENABLE 0 + +/* Define to 1 if using NCP Spinel Encrypter */ +#define OPENTHREAD_ENABLE_NCP_SPINEL_ENCRYPTER 0 + +/* Define to 1 to enable the NCP UART interface. */ +#define OPENTHREAD_CONFIG_NCP_UART_ENABLE 1 + +/* Define to 1 if using NCP vendor hook */ +#define OPENTHREAD_ENABLE_NCP_VENDOR_HOOK 0 + +/* Define to 1 if you want to enable raw link-layer API */ +#define OPENTHREAD_CONFIG_LINK_RAW_ENABLE 1 + +/* Define to 1 if you want to enable Service */ +#define OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE 0 + +/* Define to 1 to enable the UDP proxy feature. */ +#define OPENTHREAD_CONFIG_UDP_FORWARD_ENABLE 0 + +#define ENABLE_ALL_LOGS_TO_UART 0 +#if ENABLE_ALL_LOGS_TO_UART +/* Enable volumous logging via the below */ + +/* Where should logs go? + * For details & options see: + * ${openthread}/src/core/openthread-core-default-config.h + * Note: Default is: OPENTHREAD_CONFIG_LOG_OUTPUT_NONE + */ +#define OPENTHREAD_CONFIG_LOG_OUTPUT OPENTHREAD_CONFIG_LOG_OUTPUT_DEBUG_UART + +/* Details of the debug uart can be found in the file: + * 'platform/dbg_uart.c' file within the examples. + */ + +/* + * This enables the Debug Uart, disabled by default + */ +#define OPENTHREAD_CONFIG_ENABLE_DEBUG_UART 1 + +/* + * For details & selections see: + * ${openthread}/include/openthread/platform/logging.h + */ +#define OPENTHREAD_CONFIG_LOG_LEVEL OT_LOG_LEVEL_DEBG + +/* Each significant area openthread can be configured to log, or not log + * The areas are enabled via various #defines, see below for a partial list. + * For more details, see the openthread internal ".hpp" + * + * See: ${openthread}/openthread/src/core/common/logging.hpp + * Also note above level is defined in the single ".h" log header + * Whereas each area is controlled by the C++ header ".hpp" log header. + */ +#define OPENTHREAD_CONFIG_LOG_API 1 +#define OPENTHREAD_CONFIG_LOG_ARP 1 +#define OPENTHREAD_CONFIG_LOG_CLI 1 +#define OPENTHREAD_CONFIG_LOG_COAP 1 +#define OPENTHREAD_CONFIG_LOG_ICMP 1 +#define OPENTHREAD_CONFIG_LOG_IP6 1 +#define OPENTHREAD_CONFIG_LOG_MAC 1 +#define OPENTHREAD_CONFIG_LOG_MEM 1 +#define OPENTHREAD_CONFIG_LOG_MLE 1 +#define OPENTHREAD_CONFIG_LOG_NETDATA 1 +#define OPENTHREAD_CONFIG_LOG_NETDIAG 1 +#define OPENTHREAD_CONFIG_LOG_PKT_DUMP 1 +#define OPENTHREAD_CONFIG_LOG_PLATFORM 1 +#define OPENTHREAD_CONFIG_LOG_PREPEND_LEVEL 1 +#define OPENTHREAD_CONFIG_LOG_PREPEND_REGION 1 + +#endif + +/* match the output buffer size to Diag process max buffer. + * size = 256. Otherwise some output chars are chopped + */ +#define OPENTHREAD_CONFIG_CLI_MAX_LINE_LENGTH 256 + +#endif // OPENTHREAD_PLATFORM_CONFIG_H diff --git a/examples/platform/nrfconnect/pw_sys_io/BUILD.gn b/examples/platform/nrfconnect/pw_sys_io/BUILD.gn index 16fb0af557a48e..09d8298c22480f 100644 --- a/examples/platform/nrfconnect/pw_sys_io/BUILD.gn +++ b/examples/platform/nrfconnect/pw_sys_io/BUILD.gn @@ -17,7 +17,7 @@ import("//build_overrides/pigweed.gni") import("$dir_pw_build/target_types.gni") config("default_config") { - include_dirs = [ "include" ] + include_dirs = [ "public" ] } pw_source_set("pw_sys_io_nrfconnect") { diff --git a/examples/platform/nrfconnect/pw_sys_io/CMakeLists.txt b/examples/platform/nrfconnect/pw_sys_io/CMakeLists.txt index bcd5d40f0a069d..d4e7bcb68d15ba 100644 --- a/examples/platform/nrfconnect/pw_sys_io/CMakeLists.txt +++ b/examples/platform/nrfconnect/pw_sys_io/CMakeLists.txt @@ -1,21 +1,16 @@ -include(chip-lib) include($ENV{PW_ROOT}/pw_build/pigweed.cmake) +add_library(suppress_zephyr_warnings INTERFACE) +target_compile_options(suppress_zephyr_warnings INTERFACE + -Wno-undef + -Wno-redundant-decls +) + pw_add_module_library(pw_sys_io.nrfconnect SOURCES sys_io_nrfconnect.cc -) - -target_include_directories(pw_sys_io.nrfconnect INTERFACE - $ENV{ZEPHYR_BASE}/include - include/ -) - -target_link_libraries(pw_sys_io.nrfconnect PUBLIC - zephyr_interface - pw_sys_io -) - -target_compile_options(pw_sys_io.nrfconnect PUBLIC - -Wno-error=redundant-decls + PRIVATE_DEPS + zephyr_interface + pw_sys_io + suppress_zephyr_warnings ) diff --git a/examples/platform/nrfconnect/pw_sys_io/include/pw_sys_io_nrfconnect/init.h b/examples/platform/nrfconnect/pw_sys_io/public/pw_sys_io_nrfconnect/init.h similarity index 100% rename from examples/platform/nrfconnect/pw_sys_io/include/pw_sys_io_nrfconnect/init.h rename to examples/platform/nrfconnect/pw_sys_io/public/pw_sys_io_nrfconnect/init.h diff --git a/examples/platform/nrfconnect/util/NFCWidget.cpp b/examples/platform/nrfconnect/util/NFCWidget.cpp index 98fd0eee6c0b4f..b008344673dd2a 100644 --- a/examples/platform/nrfconnect/util/NFCWidget.cpp +++ b/examples/platform/nrfconnect/util/NFCWidget.cpp @@ -24,6 +24,7 @@ int NFCWidget::Init(chip::DeviceLayer::ConnectivityManager & mgr) { + mIsTagStarted = false; return nfc_t2t_setup(FieldDetectionHandler, &mgr); } @@ -42,6 +43,8 @@ int NFCWidget::StartTagEmulation(const char * tagPayload, uint8_t tagPayloadLeng result = nfc_t2t_emulation_start(); VerifyOrExit(result >= 0, ChipLogProgress(AppServer, "nfc_t2t_emulation_start failed: %d", result)); + mIsTagStarted = true; + exit: return result; } @@ -50,28 +53,25 @@ int NFCWidget::StopTagEmulation() { int result = nfc_t2t_emulation_stop(); + VerifyOrExit(result >= 0, ChipLogProgress(AppServer, "nfc_t2t_emulation_stop failed: %d", result)); + memset(mNdefBuffer, 0, sizeof(mNdefBuffer)); + mIsTagStarted = false; + +exit: return result; } +bool NFCWidget::IsTagEmulationStarted() const +{ + return mIsTagStarted; +} + void NFCWidget::FieldDetectionHandler(void * context, enum nfc_t2t_event event, const uint8_t * data, size_t data_length) { + ARG_UNUSED(context); + ARG_UNUSED(event); ARG_UNUSED(data); ARG_UNUSED(data_length); - - switch (event) - { - case NFC_T2T_EVENT_FIELD_ON: { - chip::DeviceLayer::ConnectivityManager * connectivityMgr = - reinterpret_cast(context); - if (!connectivityMgr->IsBLEAdvertisingEnabled()) - { - connectivityMgr->SetBLEAdvertisingEnabled(true); - } - } - break; - default: - break; - } } diff --git a/examples/platform/nrfconnect/util/PigweedLogger.cpp b/examples/platform/nrfconnect/util/PigweedLogger.cpp new file mode 100644 index 00000000000000..da9aed76a38d6d --- /dev/null +++ b/examples/platform/nrfconnect/util/PigweedLogger.cpp @@ -0,0 +1,149 @@ +/* + * + * 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 PigweedLogger.cpp + * + * This file contains a backend of Zephyr logging system, based on Pigweed HDLC + * over UART transport. It allows to send log messages even if the application + * needs to use HDLC/UART for another purpose like the RPC server. + */ + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +namespace PigweedLogger { +namespace { + +#if CONFIG_LOG + +#if !CONFIG_LOG_IMMEDIATE +#error "Backend of Zephyr logger based on Pigweed HDLC requires LOG_IMMEDIATE=y" +#endif + +constexpr uint8_t kLogHdlcAddress = 1; // Send log messages to HDLC address 1 (other than RPC communication) +constexpr size_t kWriteBufferSize = 128; // Buffer for constructing HDLC frames + +// Exclusive access to the backend is needed to make sure that log messages coming +// from different threads are not interwoven. +K_SEM_DEFINE(sLoggerLock, 1, 1); +pw::stream::SysIoWriter sWriter; +size_t sWriteBufferPos; +uint8_t sWriteBuffer[kWriteBufferSize]; +bool sIsPanicMode; + +void flush() +{ + pw::hdlc_lite::WriteUIFrame(kLogHdlcAddress, std::as_bytes(std::span(sWriteBuffer, sWriteBufferPos)), sWriter); + sWriteBufferPos = 0; +} + +int putString(uint8_t * buffer, size_t size, void * /* ctx */) +{ + assert(sWriteBufferPos < kWriteBufferSize); + + for (size_t i = 0; i < size; ++i) + { + // Send each line excluding "\r\n" in a separate frame + + if (buffer[i] == '\r') + continue; + + if (buffer[i] == '\n') + { + flush(); + continue; + } + + sWriteBuffer[sWriteBufferPos++] = buffer[i]; + + if (sWriteBufferPos == kWriteBufferSize) + flush(); + } + + return size; +} + +LOG_OUTPUT_DEFINE(pigweedLogOutput, putString, nullptr, 0); + +void init() +{ + pw_sys_io_Init(); +} + +void putMessageSync(const log_backend *, log_msg_ids srcLevel, uint32_t timestamp, const char * fmt, va_list args) +{ + int ret = k_sem_take(&sLoggerLock, K_FOREVER); + assert(ret == 0); + + if (!sIsPanicMode) + log_backend_std_sync_string(&pigweedLogOutput, 0, srcLevel, timestamp, fmt, args); + + k_sem_give(&sLoggerLock); +} + +void putHexdumpSync(const log_backend *, log_msg_ids srcLevel, uint32_t timestamp, const char * metadata, const uint8_t * data, + uint32_t length) +{ + int ret = k_sem_take(&sLoggerLock, K_FOREVER); + assert(ret == 0); + + if (!sIsPanicMode) + log_backend_std_sync_hexdump(&pigweedLogOutput, 0, srcLevel, timestamp, metadata, data, length); + + k_sem_give(&sLoggerLock); +} + +void panic(const log_backend *) +{ + int ret = k_sem_take(&sLoggerLock, K_FOREVER); + assert(ret == 0); + + log_backend_std_panic(&pigweedLogOutput); + flush(); + sIsPanicMode = true; + + k_sem_give(&sLoggerLock); +} + +const log_backend_api pigweedLogApi = { + .put = nullptr, + .put_sync_string = putMessageSync, + .put_sync_hexdump = putHexdumpSync, + .panic = panic, + .init = init, +}; + +LOG_BACKEND_DEFINE(pigweedLogBackend, pigweedLogApi, /* autostart */ true); + +#endif // CONFIG_LOG + +} // namespace +} // namespace PigweedLogger diff --git a/examples/platform/nrfconnect/util/include/LogUtils.h b/examples/platform/nrfconnect/util/include/LogUtils.h deleted file mode 100644 index 4d9f95458ca771..00000000000000 --- a/examples/platform/nrfconnect/util/include/LogUtils.h +++ /dev/null @@ -1,12 +0,0 @@ -#pragma once - -#ifndef CONFIG_CHIP_PW_RPC -#include -LOG_MODULE_DECLARE(app); -#define LOG_STRDUP log_strdup -#else -#include "pw_log/log.h" -#define LOG_INF(message, ...) PW_LOG_INFO(message, __VA_ARGS__) -#define LOG_ERR(message, ...) PW_LOG_ERROR(message, __VA_ARGS__) -#define LOG_STRDUP -#endif diff --git a/examples/platform/nrfconnect/util/include/NFCWidget.h b/examples/platform/nrfconnect/util/include/NFCWidget.h index 7044c1dda48474..5fbb25b2889c71 100644 --- a/examples/platform/nrfconnect/util/include/NFCWidget.h +++ b/examples/platform/nrfconnect/util/include/NFCWidget.h @@ -27,6 +27,7 @@ class NFCWidget int Init(chip::DeviceLayer::ConnectivityManager & mgr); int StartTagEmulation(const char * tagPayload, uint8_t tagPayloadLength); int StopTagEmulation(); + bool IsTagEmulationStarted() const; private: static void FieldDetectionHandler(void * context, enum nfc_t2t_event event, const uint8_t * data, size_t data_length); @@ -34,4 +35,6 @@ class NFCWidget constexpr static uint8_t mNdefBufferSize = 128; uint8_t mNdefBuffer[mNdefBufferSize]; + + bool mIsTagStarted; }; diff --git a/examples/platform/nrfconnect/util/test/TestInetCommon.cpp b/examples/platform/nrfconnect/util/test/TestInetCommon.cpp index 1670b6118f772e..a5a0adac9720e3 100644 --- a/examples/platform/nrfconnect/util/test/TestInetCommon.cpp +++ b/examples/platform/nrfconnect/util/test/TestInetCommon.cpp @@ -35,7 +35,6 @@ #endif #include "TestInetCommon.h" -#include "LogUtils.h" #include diff --git a/examples/shell/nrfconnect/CMakeLists.txt b/examples/shell/nrfconnect/CMakeLists.txt index 32f52766fcbfbe..f61689dfe3daa3 100644 --- a/examples/shell/nrfconnect/CMakeLists.txt +++ b/examples/shell/nrfconnect/CMakeLists.txt @@ -17,15 +17,17 @@ cmake_minimum_required(VERSION 3.13.1) get_filename_component(CHIP_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/third_party/connectedhomeip REALPATH) get_filename_component(APP_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/.. REALPATH) -get_filename_component(NRFCONNECT_COMMON ${CHIP_ROOT}/examples/platform/nrfconnect REALPATH) -set(CONF_FILE ${CHIP_ROOT}/config/nrfconnect/sample-defaults.conf prj.conf) -set(CHIP_OPENTHREAD_CONFIG ${NRFCONNECT_COMMON}/project_include/OpenThreadConfig.h) -set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CHIP_ROOT}/config/nrfconnect/) -include(nrfconnect-app) +set(CONF_FILE ${CHIP_ROOT}/config/nrfconnect/app/sample-defaults.conf prj.conf) + +include(${CHIP_ROOT}/config/nrfconnect/app/app.cmake) project(chip-nrf52840-shell-example) -target_include_directories(app PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${APP_ROOT}/shell_common/include) + +target_include_directories(app PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR} + ${APP_ROOT}/shell_common/include) + target_sources(app PRIVATE ${APP_ROOT}/shell_common/cmd_base64.cpp ${APP_ROOT}/shell_common/cmd_device.cpp diff --git a/examples/shell/nrfconnect/prj.conf b/examples/shell/nrfconnect/prj.conf index c078b39ffd6c42..4ccaeae8ad20e1 100644 --- a/examples/shell/nrfconnect/prj.conf +++ b/examples/shell/nrfconnect/prj.conf @@ -35,3 +35,7 @@ CONFIG_OPENTHREAD_FTD=y # Additional configs for debbugging experience. CONFIG_THREAD_NAME=y CONFIG_MPU_STACK_GUARD=y + +# CHIP configuration +CONFIG_CHIP_PROJECT_CONFIG="CHIPProjectConfig.h" +CONFIG_CHIP_OPENTHREAD_CONFIG="../../platform/nrfconnect/project_include/OpenThreadConfig.h" diff --git a/examples/shell/shell_common/BUILD.gn b/examples/shell/shell_common/BUILD.gn index 2f4a4ed87f92d9..d11a5ae99a9e87 100644 --- a/examples/shell/shell_common/BUILD.gn +++ b/examples/shell/shell_common/BUILD.gn @@ -44,7 +44,8 @@ static_library("shell_common") { "${chip_root}/src/setup_payload", ] - if (current_os == "freertos" || current_os == "zephyr") { + if (chip_enable_openthread && + (current_os == "freertos" || current_os == "zephyr")) { public_deps += [ "${openthread_root}:libopenthread-cli-ftd", "${openthread_root}:libopenthread-ftd", diff --git a/examples/shell/shell_common/cmd_device.cpp b/examples/shell/shell_common/cmd_device.cpp index 5699366db65d37..4f6acb7c0224a6 100644 --- a/examples/shell/shell_common/cmd_device.cpp +++ b/examples/shell/shell_common/cmd_device.cpp @@ -53,21 +53,6 @@ int cmd_device_help(int argc, char ** argv) return 0; } -int cmd_device_start(int argc, char ** argv) -{ - CHIP_ERROR error = CHIP_NO_ERROR; - streamer_t * sout = streamer_get(); - - VerifyOrExit(argc == 0, error = CHIP_ERROR_INVALID_ARGUMENT); - - streamer_printf(sout, "Starting Platform Manager Event Loop\r\n"); - error = PlatformMgr().StartEventLoopTask(); - SuccessOrExit(error); - -exit: - return error; -} - static CHIP_ERROR ConfigGetDone(streamer_t * sout, CHIP_ERROR error) { if (error) @@ -497,6 +482,20 @@ int cmd_device_get(int argc, char ** argv) } #if CHIP_DEVICE_CONFIG_ENABLE_WPA +int cmd_device_start_wifi(int argc, char ** argv) +{ + CHIP_ERROR error = CHIP_NO_ERROR; + streamer_t * sout = streamer_get(); + + VerifyOrExit(argc == 0, error = CHIP_ERROR_INVALID_ARGUMENT); + + streamer_printf(sout, "Starting WiFi management\r\n"); + ConnectivityMgrImpl().StartWiFiManagement(); + +exit: + return error; +} + int cmd_device_sta(int argc, char ** argv) { streamer_t * sout = streamer_get(); @@ -925,13 +924,13 @@ static const shell_command_t cmds_device_root = { &cmd_device_dispatch, "device" /// Subcommands for root command: `device ` static const shell_command_t cmds_device[] = { { &cmd_device_help, "help", "Usage: device " }, - { &cmd_device_start, "start", "Start the device layer. Usage: device start" }, { &cmd_device_get, "get", "Get configuration value. Usage: device get " }, { &cmd_device_config, "config", "Dump entire configuration of device. Usage: device config" }, #if CHIP_DEVICE_CONFIG_ENABLE_THREAD { &cmd_device_thread, "thread", "Control the Thread interface. Usage: device thread " }, #endif #if CHIP_DEVICE_CONFIG_ENABLE_WPA + { &cmd_device_start_wifi, "start_wifi", "Start WiFi management. Usage: device start_wifi" }, { &cmd_device_sta, "sta", "Control the WiFi STA interface. Usage: device sta " }, { &cmd_device_ap, "ap", "Control the WiFi AP interface. Usage: device ap " }, { &cmd_device_connect, "connect", "Join the network with the given SSID and PSK. Usage: device connect " }, @@ -953,20 +952,25 @@ void cmd_device_init() streamer_t * sout = streamer_get(); + error = chip::Platform::MemoryInit(); + VerifyOrExit(error == CHIP_NO_ERROR, + streamer_printf(sout, "Failed to init CHIP platform memory with error: %s\r\n", ErrorStr(error))); + streamer_printf(sout, "Init CHIP Stack\r\n"); error = PlatformMgr().InitChipStack(); - - if (error != CHIP_NO_ERROR) - streamer_printf(sout, "Failed to init CHIP Stack with error: %s\r\n", ErrorStr(error)); + VerifyOrExit(error == CHIP_NO_ERROR, streamer_printf(sout, "Failed to init CHIP Stack with error: %s\r\n", ErrorStr(error))); #if CHIP_DEVICE_CONFIG_ENABLE_THREAD streamer_printf(sout, "Init Thread stack\r\n"); error = ThreadStackMgr().InitThreadStack(); - if (error != CHIP_NO_ERROR) - { - streamer_printf(sout, "ThreadStackMgr().InitThreadStack() failed\r\n"); - } + VerifyOrExit(error == CHIP_NO_ERROR, streamer_printf(sout, "ThreadStackMgr().InitThreadStack() failed\r\n")); #endif + // Starting Platform Manager Event Loop; + error = PlatformMgr().StartEventLoopTask(); + VerifyOrExit(error == CHIP_NO_ERROR, streamer_printf(sout, "Failed to start platform event loop\r\n")); + +exit: + return; #endif // CONFIG_DEVICE_LAYER } diff --git a/examples/temperature-measurement-app/esp32/main/component.mk b/examples/temperature-measurement-app/esp32/main/component.mk index 9762d2b50b1e47..4dedae431f4f69 100644 --- a/examples/temperature-measurement-app/esp32/main/component.mk +++ b/examples/temperature-measurement-app/esp32/main/component.mk @@ -24,16 +24,17 @@ COMPONENT_DEPENDS := chip QRCode tft spidriver COMPONENT_SRCDIRS := \ . \ gen \ - ../third_party/connectedhomeip/examples/common/chip-app-server \ + ../third_party/connectedhomeip/src/app/server \ ../third_party/connectedhomeip/src/app/util \ ../third_party/connectedhomeip/src/app/reporting \ ../third_party/connectedhomeip/src/app/clusters/basic \ + ../third_party/connectedhomeip/src/app/clusters/bindings \ ../third_party/connectedhomeip/src/app/clusters/temperature-measurement-server \ COMPONENT_EXTRA_INCLUDES := $(PROJECT_PATH)/third_party/connectedhomeip/src/app/util \ $(PROJECT_PATH)/third_party/connectedhomeip/src/app/reporting \ - $(PROJECT_PATH)/third_party/connectedhomeip/examples/common/chip-app-server/include \ + $(PROJECT_PATH)/third_party/connectedhomeip/src/app/server \ $(PROJECT_PATH)/third_party/connectedhomeip/src # So "gen/*" files are found by the src/app bits. diff --git a/examples/temperature-measurement-app/esp32/main/gen/af-structs.h b/examples/temperature-measurement-app/esp32/main/gen/af-structs.h index 6d04f3faa8e82d..02960bec60ddfb 100644 --- a/examples/temperature-measurement-app/esp32/main/gen/af-structs.h +++ b/examples/temperature-measurement-app/esp32/main/gen/af-structs.h @@ -1,4 +1,3 @@ - /* * * Copyright (c) 2020 Project CHIP Authors diff --git a/examples/temperature-measurement-app/esp32/main/gen/att-storage.h b/examples/temperature-measurement-app/esp32/main/gen/att-storage.h index 7572c8cbc338fb..74b44d6111b3e4 100644 --- a/examples/temperature-measurement-app/esp32/main/gen/att-storage.h +++ b/examples/temperature-measurement-app/esp32/main/gen/att-storage.h @@ -1,4 +1,3 @@ - /* * * Copyright (c) 2020 Project CHIP Authors diff --git a/examples/temperature-measurement-app/esp32/main/gen/attribute-id.h b/examples/temperature-measurement-app/esp32/main/gen/attribute-id.h index 648809ca67cd83..901653b7d8f3b6 100644 --- a/examples/temperature-measurement-app/esp32/main/gen/attribute-id.h +++ b/examples/temperature-measurement-app/esp32/main/gen/attribute-id.h @@ -1,4 +1,3 @@ - /* * * Copyright (c) 2020 Project CHIP Authors @@ -19,11 +18,15 @@ // Prevent multiple inclusion #pragma once +// Global cluster attribute ids +#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) +#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) +#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) +#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) + // Attribute ids for cluster: Basic // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_VERSION_ATTRIBUTE_ID (0x0000) @@ -44,14 +47,10 @@ #define ZCL_ALARM_MASK_ATTRIBUTE_ID (0x0013) #define ZCL_DISABLE_LOCAL_CONFIG_ATTRIBUTE_ID (0x0014) #define ZCL_SW_BUILD_ID_ATTRIBUTE_ID (0x4000) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Power Configuration // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_MAINS_VOLTAGE_ATTRIBUTE_ID (0x0000) @@ -111,14 +110,10 @@ #define ZCL_BATTERY_3_PERCENTAGE_THRESHOLD_2_ATTRIBUTE_ID (0x007C) #define ZCL_BATTERY_3_PERCENTAGE_THRESHOLD_3_ATTRIBUTE_ID (0x007D) #define ZCL_BATTERY_3_ALARM_STATE_ATTRIBUTE_ID (0x007E) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Device Temperature Configuration // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_CURRENT_TEMPERATURE_ATTRIBUTE_ID (0x0000) @@ -130,37 +125,25 @@ #define ZCL_HIGH_TEMP_THRESHOLD_ATTRIBUTE_ID (0x0012) #define ZCL_LOW_TEMP_DWELL_TRIP_POINT_ATTRIBUTE_ID (0x0013) #define ZCL_HIGH_TEMP_DWELL_TRIP_POINT_ATTRIBUTE_ID (0x0014) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Identify // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_IDENTIFY_TIME_ATTRIBUTE_ID (0x0000) #define ZCL_COMMISSION_STATE_ATTRIBUTE_ID (0x0001) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Groups // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_GROUP_NAME_SUPPORT_ATTRIBUTE_ID (0x0000) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Scenes // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_SCENE_COUNT_ATTRIBUTE_ID (0x0000) @@ -169,14 +152,10 @@ #define ZCL_SCENE_VALID_ATTRIBUTE_ID (0x0003) #define ZCL_SCENE_NAME_SUPPORT_ATTRIBUTE_ID (0x0004) #define ZCL_LAST_CONFIGURED_BY_ATTRIBUTE_ID (0x0005) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: On/off // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_ON_OFF_ATTRIBUTE_ID (0x0000) @@ -188,26 +167,18 @@ #define ZCL_ON_TIME_ATTRIBUTE_ID (0x4001) #define ZCL_OFF_WAIT_TIME_ATTRIBUTE_ID (0x4002) #define ZCL_START_UP_ON_OFF_ATTRIBUTE_ID (0x4003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: On/off Switch Configuration // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_SWITCH_TYPE_ATTRIBUTE_ID (0x0000) #define ZCL_SWITCH_ACTIONS_ATTRIBUTE_ID (0x0010) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Level Control // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_CURRENT_LEVEL_ATTRIBUTE_ID (0x0000) @@ -219,25 +190,17 @@ #define ZCL_OFF_TRANSITION_TIME_ATTRIBUTE_ID (0x0013) #define ZCL_DEFAULT_MOVE_RATE_ATTRIBUTE_ID (0x0014) #define ZCL_START_UP_CURRENT_LEVEL_ATTRIBUTE_ID (0x4000) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Alarms // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_ALARM_COUNT_ATTRIBUTE_ID (0x0000) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Time // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_TIME_ATTRIBUTE_ID (0x0000) @@ -250,14 +213,10 @@ #define ZCL_LOCAL_TIME_ATTRIBUTE_ID (0x0007) #define ZCL_LAST_SET_TIME_ATTRIBUTE_ID (0x0008) #define ZCL_VALID_UNTIL_TIME_ATTRIBUTE_ID (0x0009) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: RSSI Location // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_LOCATION_TYPE_ATTRIBUTE_ID (0x0000) @@ -273,14 +232,10 @@ #define ZCL_REPORTING_PERIOD_ATTRIBUTE_ID (0x0015) #define ZCL_CALCULATION_PERIOD_ATTRIBUTE_ID (0x0016) #define ZCL_NUMBER_RSSI_MEASUREMENTS_ATTRIBUTE_ID (0x0017) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Binary Input (Basic) // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_ACTIVE_TEXT_ATTRIBUTE_ID (0x0004) @@ -292,14 +247,10 @@ #define ZCL_RELIABILITY_ATTRIBUTE_ID (0x0067) #define ZCL_STATUS_FLAGS_ATTRIBUTE_ID (0x006F) #define ZCL_APPLICATION_TYPE_ATTRIBUTE_ID (0x0100) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Commissioning // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_SHORT_ADDRESS_ATTRIBUTE_ID (0x0000) @@ -326,14 +277,10 @@ #define ZCL_CONCENTRATOR_FLAG_ATTRIBUTE_ID (0x0040) #define ZCL_CONCENTRATOR_RADIUS_ATTRIBUTE_ID (0x0041) #define ZCL_CONCENTRATOR_DISCOVERY_TIME_ATTRIBUTE_ID (0x0042) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Partition // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_PARTITION_MAXIMUM_INCOMING_TRANSFER_SIZE_ATTRIBUTE_ID (0x0000) @@ -346,8 +293,6 @@ #define ZCL_NUMBER_OF_SEND_RETRIES_ATTRIBUTE_ID (0x0007) #define ZCL_SENDER_TIMEOUT_ATTRIBUTE_ID (0x0008) #define ZCL_RECEIVER_TIMEOUT_ATTRIBUTE_ID (0x0009) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Over the Air Bootloading @@ -365,18 +310,12 @@ #define ZCL_IMAGE_STAMP_ATTRIBUTE_ID (0x000A) #define ZCL_UPGRADE_ACTIVATION_POLICY_ATTRIBUTE_ID (0x000B) #define ZCL_UPGRADE_TIMEOUT_POLICY_ATTRIBUTE_ID (0x000C) -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Power Profile // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_TOTAL_PROFILE_NUM_ATTRIBUTE_ID (0x0000) @@ -384,27 +323,19 @@ #define ZCL_ENERGY_FORMATTING_ATTRIBUTE_ID (0x0002) #define ZCL_ENERGY_REMOTE_ATTRIBUTE_ID (0x0003) #define ZCL_SCHEDULE_MODE_ATTRIBUTE_ID (0x0004) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Appliance Control // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_START_TIME_ATTRIBUTE_ID (0x0000) #define ZCL_FINISH_TIME_ATTRIBUTE_ID (0x0001) #define ZCL_REMAINING_TIME_ATTRIBUTE_ID (0x0002) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Poll Control // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_CHECK_IN_INTERVAL_ATTRIBUTE_ID (0x0000) @@ -414,8 +345,6 @@ #define ZCL_CHECK_IN_INTERVAL_MIN_ATTRIBUTE_ID (0x0004) #define ZCL_LONG_POLL_INTERVAL_MIN_ATTRIBUTE_ID (0x0005) #define ZCL_FAST_POLL_TIMEOUT_MAX_ATTRIBUTE_ID (0x0006) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Green Power @@ -431,8 +360,6 @@ #define ZCL_GP_CLIENT_GP_SHARED_SECURITY_KEY_TYPE_ATTRIBUTE_ID (0x0020) #define ZCL_GP_CLIENT_GP_SHARED_SECURITY_KEY_ATTRIBUTE_ID (0x0021) #define ZCL_GP_CLIENT_GP_LINK_KEY_ATTRIBUTE_ID (0x0022) -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_GP_SERVER_GPS_MAX_SINK_TABLE_ENTRIES_ATTRIBUTE_ID (0x0000) @@ -446,26 +373,18 @@ #define ZCL_GP_SERVER_GP_SHARED_SECURITY_KEY_TYPE_ATTRIBUTE_ID (0x0020) #define ZCL_GP_SERVER_GP_SHARED_SECURITY_KEY_ATTRIBUTE_ID (0x0021) #define ZCL_GP_SERVER_GP_LINK_KEY_ATTRIBUTE_ID (0x0022) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Keep-Alive // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_KEEPALIVE_BASE_ATTRIBUTE_ID (0x0000) #define ZCL_KEEPALIVE_JITTER_ATTRIBUTE_ID (0x0001) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Shade Configuration // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_SHADE_CONFIG_PHYSICAL_CLOSED_LIMIT_ATTRIBUTE_ID (0x0000) @@ -473,14 +392,10 @@ #define ZCL_SHADE_CONFIG_STATUS_ATTRIBUTE_ID (0x0002) #define ZCL_SHADE_CONFIG_CLOSED_LIMIT_ATTRIBUTE_ID (0x0010) #define ZCL_SHADE_CONFIG_MODE_ATTRIBUTE_ID (0x0011) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Door Lock // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_LOCK_STATE_ATTRIBUTE_ID (0x0000) @@ -526,14 +441,10 @@ #define ZCL_KEYPAD_PROGRAMMING_EVENT_MASK_ATTRIBUTE_ID (0x0045) #define ZCL_RF_PROGRAMMING_EVENT_MASK_ATTRIBUTE_ID (0x0046) #define ZCL_RFID_PROGRAMMING_EVENT_MASK_ATTRIBUTE_ID (0x0047) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Window Covering // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_COVERING_TYPE_ATTRIBUTE_ID (0x0000) @@ -556,14 +467,10 @@ #define ZCL_MODE_ATTRIBUTE_ID (0x0017) #define ZCL_SETPOINTS_LIFT_ATTRIBUTE_ID (0x0018) #define ZCL_SETPOINTS_TILT_ATTRIBUTE_ID (0x0019) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Barrier Control // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_BARRIER_MOVING_STATE_ATTRIBUTE_ID (0x0001) @@ -576,14 +483,10 @@ #define ZCL_BARRIER_OPEN_PERIOD_ATTRIBUTE_ID (0x0008) #define ZCL_BARRIER_CLOSE_PERIOD_ATTRIBUTE_ID (0x0009) #define ZCL_BARRIER_POSITION_ATTRIBUTE_ID (0x000A) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Pump Configuration and Control // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_MAX_PRESSURE_ATTRIBUTE_ID (0x0000) @@ -610,14 +513,10 @@ #define ZCL_OPERATION_MODE_ATTRIBUTE_ID (0x0020) #define ZCL_CONTROL_MODE_ATTRIBUTE_ID (0x0021) #define ZCL_PUMP_ALARM_MASK_ATTRIBUTE_ID (0x0022) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Thermostat // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_LOCAL_TEMPERATURE_ATTRIBUTE_ID (0x0000) @@ -663,26 +562,18 @@ #define ZCL_AC_LOUVER_POSITION_ATTRIBUTE_ID (0x0045) #define ZCL_AC_COIL_TEMPERATURE_ATTRIBUTE_ID (0x0046) #define ZCL_AC_CAPACITY_FORMAT_ATTRIBUTE_ID (0x0047) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Fan Control // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_FAN_CONTROL_FAN_MODE_ATTRIBUTE_ID (0x0000) #define ZCL_FAN_CONTROL_FAN_MODE_SEQUENCE_ATTRIBUTE_ID (0x0001) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Dehumidification Control // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_RELATIVE_HUMIDITY_ATTRIBUTE_ID (0x0000) @@ -693,27 +584,19 @@ #define ZCL_DEHUMIDIFICATION_HYSTERESIS_ATTRIBUTE_ID (0x0013) #define ZCL_DEHUMIDIFICATION_MAX_COOL_ATTRIBUTE_ID (0x0014) #define ZCL_RELATIVE_HUMIDITY_DISPLAY_ATTRIBUTE_ID (0x0015) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Thermostat User Interface Configuration // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_TEMPERATURE_DISPLAY_MODE_ATTRIBUTE_ID (0x0000) #define ZCL_KEYPAD_LOCKOUT_ATTRIBUTE_ID (0x0001) #define ZCL_SCHEDULE_PROGRAMMING_VISIBILITY_ATTRIBUTE_ID (0x0002) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Color Control // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_COLOR_CONTROL_CURRENT_HUE_ATTRIBUTE_ID (0x0000) @@ -768,14 +651,10 @@ #define ZCL_COLOR_CONTROL_COLOR_TEMP_PHYSICAL_MAX_ATTRIBUTE_ID (0x400C) #define ZCL_COLOR_CONTROL_TEMPERATURE_LEVEL_MIN_MIREDS_ATTRIBUTE_ID (0x400D) #define ZCL_START_UP_COLOR_TEMPERATURE_MIREDS_ATTRIBUTE_ID (0x4010) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Ballast Configuration // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_PHYSICAL_MIN_LEVEL_ATTRIBUTE_ID (0x0000) @@ -794,14 +673,10 @@ #define ZCL_LAMP_BURN_HOURS_ATTRIBUTE_ID (0x0033) #define ZCL_LAMP_ALARM_MODE_ATTRIBUTE_ID (0x0034) #define ZCL_LAMP_BURN_HOURS_TRIP_POINT_ATTRIBUTE_ID (0x0035) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Illuminance Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_ILLUM_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) @@ -809,41 +684,29 @@ #define ZCL_ILLUM_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_ILLUM_TOLERANCE_ATTRIBUTE_ID (0x0003) #define ZCL_MEASUREMENT_LIGHT_SENSOR_TYPE_ATTRIBUTE_ID (0x0004) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Illuminance Level Sensing // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_LEVEL_STATUS_ATTRIBUTE_ID (0x0000) #define ZCL_SENSING_LIGHT_SENSOR_TYPE_ATTRIBUTE_ID (0x0001) #define ZCL_ILLUMINANCE_TARGET_LEVEL_ATTRIBUTE_ID (0x0010) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Temperature Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_TEMP_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_TEMP_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_TEMP_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_TEMP_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Pressure Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_PRESSURE_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) @@ -855,42 +718,30 @@ #define ZCL_PRESSURE_MAX_SCALED_VALUE_ATTRIBUTE_ID (0x0012) #define ZCL_PRESSURE_SCALED_TOLERANCE_ATTRIBUTE_ID (0x0013) #define ZCL_PRESSURE_SCALE_ATTRIBUTE_ID (0x0014) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Flow Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_FLOW_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_FLOW_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_FLOW_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_FLOW_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Relative Humidity Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_RELATIVE_HUMIDITY_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_RELATIVE_HUMIDITY_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_RELATIVE_HUMIDITY_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_RELATIVE_HUMIDITY_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Occupancy Sensing // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_OCCUPANCY_ATTRIBUTE_ID (0x0000) @@ -905,434 +756,310 @@ #define ZCL_PHYSICAL_CONTACT_OCCUPIED_TO_UNOCCUPIED_DELAY_ATTRIBUTE_ID (0x0030) #define ZCL_PHYSICAL_CONTACT_UNOCCUPIED_TO_OCCUPIED_DELAY_ATTRIBUTE_ID (0x0031) #define ZCL_PHYSICAL_CONTACT_UNOCCUPIED_TO_OCCUPIED_THRESHOLD_ATTRIBUTE_ID (0x0032) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Carbon Monoxide Concentration Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_CARBON_MONOXIDE_CONCENTRATION_MEASUREMENT_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_CARBON_MONOXIDE_CONCENTRATION_MEASUREMENT_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_CARBON_MONOXIDE_CONCENTRATION_MEASUREMENT_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_CARBON_MONOXIDE_CONCENTRATION_MEASUREMENT_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Carbon Dioxide Concentration Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_CARBON_DIOXIDE_CONCENTRATION_MEASUREMENT_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_CARBON_DIOXIDE_CONCENTRATION_MEASUREMENT_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_CARBON_DIOXIDE_CONCENTRATION_MEASUREMENT_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_CARBON_DIOXIDE_CONCENTRATION_MEASUREMENT_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Ethylene Concentration Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_ETHYLENE_CONCENTRATION_MEASUREMENT_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_ETHYLENE_CONCENTRATION_MEASUREMENT_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_ETHYLENE_CONCENTRATION_MEASUREMENT_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_ETHYLENE_CONCENTRATION_MEASUREMENT_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Ethylene Oxide Concentration Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_ETHYLENE_OXIDE_CONCENTRATION_MEASUREMENT_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_ETHYLENE_OXIDE_CONCENTRATION_MEASUREMENT_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_ETHYLENE_OXIDE_CONCENTRATION_MEASUREMENT_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_ETHYLENE_OXIDE_CONCENTRATION_MEASUREMENT_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Hydrogen Concentration Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_HYDROGEN_CONCENTRATION_MEASUREMENT_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_HYDROGEN_CONCENTRATION_MEASUREMENT_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_HYDROGEN_CONCENTRATION_MEASUREMENT_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_HYDROGEN_CONCENTRATION_MEASUREMENT_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Hydrogen Sulphide Concentration Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_HYDROGEN_SULPHIDE_CONCENTRATION_MEASUREMENT_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_HYDROGEN_SULPHIDE_CONCENTRATION_MEASUREMENT_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_HYDROGEN_SULPHIDE_CONCENTRATION_MEASUREMENT_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_HYDROGEN_SULPHIDE_CONCENTRATION_MEASUREMENT_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Nitric Oxide Concentration Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_NITRIC_OXIDE_CONCENTRATION_MEASUREMENT_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_NITRIC_OXIDE_CONCENTRATION_MEASUREMENT_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_NITRIC_OXIDE_CONCENTRATION_MEASUREMENT_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_NITRIC_OXIDE_CONCENTRATION_MEASUREMENT_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Nitrogen Dioxide Concentration Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_NITROGEN_DIOXIDE_CONCENTRATION_MEASUREMENT_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_NITROGEN_DIOXIDE_CONCENTRATION_MEASUREMENT_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_NITROGEN_DIOXIDE_CONCENTRATION_MEASUREMENT_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_NITROGEN_DIOXIDE_CONCENTRATION_MEASUREMENT_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Oxygen Concentration Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_OXYGEN_CONCENTRATION_MEASUREMENT_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_OXYGEN_CONCENTRATION_MEASUREMENT_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_OXYGEN_CONCENTRATION_MEASUREMENT_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_OXYGEN_CONCENTRATION_MEASUREMENT_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Ozone Concentration Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_OZONE_CONCENTRATION_MEASUREMENT_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_OZONE_CONCENTRATION_MEASUREMENT_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_OZONE_CONCENTRATION_MEASUREMENT_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_OZONE_CONCENTRATION_MEASUREMENT_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Sulfur Dioxide Concentration Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_SULFUR_DIOXIDE_CONCENTRATION_MEASUREMENT_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_SULFUR_DIOXIDE_CONCENTRATION_MEASUREMENT_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_SULFUR_DIOXIDE_CONCENTRATION_MEASUREMENT_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_SULFUR_DIOXIDE_CONCENTRATION_MEASUREMENT_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Dissolved Oxygen Concentration Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_DISSOLVED_OXYGEN_CONCENTRATION_MEASUREMENT_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_DISSOLVED_OXYGEN_CONCENTRATION_MEASUREMENT_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_DISSOLVED_OXYGEN_CONCENTRATION_MEASUREMENT_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_DISSOLVED_OXYGEN_CONCENTRATION_MEASUREMENT_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Bromate Concentration Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_BROMATE_CONCENTRATION_MEASUREMENT_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_BROMATE_CONCENTRATION_MEASUREMENT_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_BROMATE_CONCENTRATION_MEASUREMENT_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_BROMATE_CONCENTRATION_MEASUREMENT_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Chloramines Concentration Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_CHLORAMINES_CONCENTRATION_MEASUREMENT_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_CHLORAMINES_CONCENTRATION_MEASUREMENT_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_CHLORAMINES_CONCENTRATION_MEASUREMENT_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_CHLORAMINES_CONCENTRATION_MEASUREMENT_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Chlorine Concentration Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_CHLORINE_CONCENTRATION_MEASUREMENT_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_CHLORINE_CONCENTRATION_MEASUREMENT_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_CHLORINE_CONCENTRATION_MEASUREMENT_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_CHLORINE_CONCENTRATION_MEASUREMENT_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Fecal coliform and E. Coli Concentration Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_FECAL_COLIFORM_AND_E_COLI_CONCENTRATION_MEASUREMENT_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_FECAL_COLIFORM_AND_E_COLI_CONCENTRATION_MEASUREMENT_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_FECAL_COLIFORM_AND_E_COLI_CONCENTRATION_MEASUREMENT_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_FECAL_COLIFORM_AND_E_COLI_CONCENTRATION_MEASUREMENT_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Fluoride Concentration Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_FLUORIDE_CONCENTRATION_MEASUREMENT_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_FLUORIDE_CONCENTRATION_MEASUREMENT_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_FLUORIDE_CONCENTRATION_MEASUREMENT_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_FLUORIDE_CONCENTRATION_MEASUREMENT_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Haloacetic Acids Concentration Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_HALOACETIC_ACIDS_CONCENTRATION_MEASUREMENT_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_HALOACETIC_ACIDS_CONCENTRATION_MEASUREMENT_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_HALOACETIC_ACIDS_CONCENTRATION_MEASUREMENT_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_HALOACETIC_ACIDS_CONCENTRATION_MEASUREMENT_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Total Trihalomethanes Concentration Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_TOTAL_TRIHALOMETHANES_CONCENTRATION_MEASUREMENT_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_TOTAL_TRIHALOMETHANES_CONCENTRATION_MEASUREMENT_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_TOTAL_TRIHALOMETHANES_CONCENTRATION_MEASUREMENT_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_TOTAL_TRIHALOMETHANES_CONCENTRATION_MEASUREMENT_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Total Coliform Bacteria Concentration Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_TOTAL_COLIFORM_BACTERIA_CONCENTRATION_MEASUREMENT_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_TOTAL_COLIFORM_BACTERIA_CONCENTRATION_MEASUREMENT_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_TOTAL_COLIFORM_BACTERIA_CONCENTRATION_MEASUREMENT_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_TOTAL_COLIFORM_BACTERIA_CONCENTRATION_MEASUREMENT_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Turbidity Concentration Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_TURBIDITY_CONCENTRATION_MEASUREMENT_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_TURBIDITY_CONCENTRATION_MEASUREMENT_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_TURBIDITY_CONCENTRATION_MEASUREMENT_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_TURBIDITY_CONCENTRATION_MEASUREMENT_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Copper Concentration Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_COPPER_CONCENTRATION_MEASUREMENT_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_COPPER_CONCENTRATION_MEASUREMENT_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_COPPER_CONCENTRATION_MEASUREMENT_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_COPPER_CONCENTRATION_MEASUREMENT_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Lead Concentration Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_LEAD_CONCENTRATION_MEASUREMENT_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_LEAD_CONCENTRATION_MEASUREMENT_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_LEAD_CONCENTRATION_MEASUREMENT_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_LEAD_CONCENTRATION_MEASUREMENT_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Manganese Concentration Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_MANGANESE_CONCENTRATION_MEASUREMENT_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_MANGANESE_CONCENTRATION_MEASUREMENT_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_MANGANESE_CONCENTRATION_MEASUREMENT_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_MANGANESE_CONCENTRATION_MEASUREMENT_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Sulfate Concentration Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_SULFATE_CONCENTRATION_MEASUREMENT_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_SULFATE_CONCENTRATION_MEASUREMENT_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_SULFATE_CONCENTRATION_MEASUREMENT_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_SULFATE_CONCENTRATION_MEASUREMENT_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Bromodichloromethane Concentration Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_BROMODICHLOROMETHANE_CONCENTRATION_MEASUREMENT_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_BROMODICHLOROMETHANE_CONCENTRATION_MEASUREMENT_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_BROMODICHLOROMETHANE_CONCENTRATION_MEASUREMENT_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_BROMODICHLOROMETHANE_CONCENTRATION_MEASUREMENT_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Bromoform Concentration Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_BROMOFORM_CONCENTRATION_MEASUREMENT_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_BROMOFORM_CONCENTRATION_MEASUREMENT_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_BROMOFORM_CONCENTRATION_MEASUREMENT_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_BROMOFORM_CONCENTRATION_MEASUREMENT_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Chlorodibromomethane Concentration Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_CHLORODIBROMOMETHANE_CONCENTRATION_MEASUREMENT_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_CHLORODIBROMOMETHANE_CONCENTRATION_MEASUREMENT_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_CHLORODIBROMOMETHANE_CONCENTRATION_MEASUREMENT_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_CHLORODIBROMOMETHANE_CONCENTRATION_MEASUREMENT_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Chloroform Concentration Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_CHLOROFORM_CONCENTRATION_MEASUREMENT_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_CHLOROFORM_CONCENTRATION_MEASUREMENT_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_CHLOROFORM_CONCENTRATION_MEASUREMENT_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_CHLOROFORM_CONCENTRATION_MEASUREMENT_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Sodium Concentration Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_SODIUM_CONCENTRATION_MEASUREMENT_MEASURED_VALUE_ATTRIBUTE_ID (0x0000) #define ZCL_SODIUM_CONCENTRATION_MEASUREMENT_MIN_MEASURED_VALUE_ATTRIBUTE_ID (0x0001) #define ZCL_SODIUM_CONCENTRATION_MEASUREMENT_MAX_MEASURED_VALUE_ATTRIBUTE_ID (0x0002) #define ZCL_SODIUM_CONCENTRATION_MEASUREMENT_TOLERANCE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: IAS Zone // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_ZONE_STATE_ATTRIBUTE_ID (0x0000) @@ -1342,58 +1069,38 @@ #define ZCL_ZONE_ID_ATTRIBUTE_ID (0x0011) #define ZCL_NUMBER_OF_ZONE_SENSITIVITY_LEVELS_SUPPORTED_ATTRIBUTE_ID (0x0012) #define ZCL_CURRENT_ZONE_SENSITIVITY_LEVEL_ATTRIBUTE_ID (0x0013) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: IAS ACE // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: IAS WD // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_MAX_DURATION_ATTRIBUTE_ID (0x0000) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Generic Tunnel // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_MAXIMUM_INCOMING_TRANSFER_SIZE_ATTRIBUTE_ID (0x0001) #define ZCL_MAXIMUM_OUTGOING_TRANSFER_SIZE_ATTRIBUTE_ID (0x0002) #define ZCL_PROTOCOL_ADDRESS_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: BACnet Protocol Tunnel // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: 11073 Protocol Tunnel // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_DEVICE_ID_LIST_ATTRIBUTE_ID (0x0000) @@ -1402,19 +1109,13 @@ #define ZCL_CONNECTED_ATTRIBUTE_ID (0x0003) #define ZCL_PREEMPTIBLE_ATTRIBUTE_ID (0x0004) #define ZCL_IDLE_TIMEOUT_ATTRIBUTE_ID (0x0005) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: ISO 7816 Protocol Tunnel // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_ISO7816_PROTOCOL_TUNNEL_STATUS_ATTRIBUTE_ID (0x0000) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Price @@ -1422,8 +1123,6 @@ #define ZCL_PRICE_INCREASE_RANDOMIZE_MINUTES_ATTRIBUTE_ID (0x0000) #define ZCL_PRICE_DECREASE_RANDOMIZE_MINUTES_ATTRIBUTE_ID (0x0001) #define ZCL_COMMODITY_TYPE_CLIENT_ATTRIBUTE_ID (0x0002) -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_TIER1_PRICE_LABEL_ATTRIBUTE_ID (0x0000) @@ -2438,8 +2137,6 @@ #define ZCL_RX_LAST_BILLING_PERIOD_START_ATTRIBUTE_ID (0x8702) #define ZCL_RX_LAST_BILLING_PERIOD_DURATION_ATTRIBUTE_ID (0x8703) #define ZCL_RX_LAST_BILLING_PERIOD_CONSOLIDATED_BILL_ATTRIBUTE_ID (0x8704) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Demand Response and Load Control @@ -2448,12 +2145,8 @@ #define ZCL_START_RANDOMIZATION_MINUTES_ATTRIBUTE_ID (0x0001) #define ZCL_DURATION_RANDOMIZATION_MINUTES_ATTRIBUTE_ID (0x0002) #define ZCL_DEVICE_CLASS_VALUE_ATTRIBUTE_ID (0x0003) -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Simple Metering @@ -2466,8 +2159,6 @@ #define ZCL_NOTIFICATION_FLAGS_6_ATTRIBUTE_ID (0x0005) #define ZCL_NOTIFICATION_FLAGS_7_ATTRIBUTE_ID (0x0006) #define ZCL_NOTIFICATION_FLAGS_8_ATTRIBUTE_ID (0x0007) -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_CURRENT_SUMMATION_DELIVERED_ATTRIBUTE_ID (0x0000) @@ -3354,35 +3045,23 @@ #define ZCL_CURRENT_REACTIVE_SUMMATION_Q2_ATTRIBUTE_ID (0x0D06) #define ZCL_CURRENT_REACTIVE_SUMMATION_Q3_ATTRIBUTE_ID (0x0D07) #define ZCL_CURRENT_REACTIVE_SUMMATION_Q4_ATTRIBUTE_ID (0x0D08) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Messaging // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Tunneling // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_CLOSE_TUNNEL_TIMEOUT_ATTRIBUTE_ID (0x0000) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Prepayment // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_PAYMENT_CONTROL_CONFIGURATION_ATTRIBUTE_ID (0x0000) @@ -3516,14 +3195,10 @@ #define ZCL_PREVIOUS_MONTH_13_COST_CONSUMPTION_DELIVERED_ATTRIBUTE_ID (0x055A) #define ZCL_PREVIOUS_MONTH_13_COST_CONSUMPTION_RECEIVED_ATTRIBUTE_ID (0x055B) #define ZCL_PREPAYMENT_HISTORICAL_FREEZE_TIME_ATTRIBUTE_ID (0x055C) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Energy Management // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_LOAD_CONTROL_STATE_ATTRIBUTE_ID (0x0000) @@ -3533,14 +3208,10 @@ #define ZCL_MINIMUM_OFF_TIME_ATTRIBUTE_ID (0x0004) #define ZCL_MINIMUM_ON_TIME_ATTRIBUTE_ID (0x0005) #define ZCL_MINIMUM_CYCLE_PERIOD_ATTRIBUTE_ID (0x0006) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Calendar // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_AUXILIARY_SWITCH_1_LABEL_ATTRIBUTE_ID (0x0000) @@ -3551,8 +3222,6 @@ #define ZCL_AUXILIARY_SWITCH_6_LABEL_ATTRIBUTE_ID (0x0005) #define ZCL_AUXILIARY_SWITCH_7_LABEL_ATTRIBUTE_ID (0x0006) #define ZCL_AUXILIARY_SWITCH_8_LABEL_ATTRIBUTE_ID (0x0007) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Device Management @@ -3991,8 +3660,6 @@ #define ZCL_QUERY_SPECIFIC_FILE_REQUEST_GENERATED_ATTRIBUTE_ID (0x08CC) #define ZCL_QUERY_SPECIFIC_FILE_RESPONSE_RECEIVED_ATTRIBUTE_ID (0x08CD) #define ZCL_QUERY_SPECIFIC_FILE_RESPONSE_REJECTED_ATTRIBUTE_ID (0x08CE) -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_PROVIDER_ID_SERVER_ATTRIBUTE_ID (0x0100) @@ -4014,34 +3681,22 @@ #define ZCL_WAN_STATUS_ATTRIBUTE_ID (0x0300) #define ZCL_LOW_MEDIUM_THRESHOLD_ATTRIBUTE_ID (0x0400) #define ZCL_MEDIUM_HIGH_THRESHOLD_ATTRIBUTE_ID (0x0401) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Events // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: MDU Pairing // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Sub-GHz // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_SUB_GHZ_CLUSTER_CHANNEL_CHANGE_ATTRIBUTE_ID (0x0000) @@ -4049,26 +3704,18 @@ #define ZCL_SUB_GHZ_CLUSTER_PAGE_29_CHANNEL_MASK_ATTRIBUTE_ID (0x0002) #define ZCL_SUB_GHZ_CLUSTER_PAGE_30_CHANNEL_MASK_ATTRIBUTE_ID (0x0003) #define ZCL_SUB_GHZ_CLUSTER_PAGE_31_CHANNEL_MASK_ATTRIBUTE_ID (0x0004) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Key Establishment // Client attributes #define ZCL_KEY_ESTABLISHMENT_SUITE_CLIENT_ATTRIBUTE_ID (0x0000) -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_KEY_ESTABLISHMENT_SUITE_SERVER_ATTRIBUTE_ID (0x0000) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Information // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_NODE_DESCRIPTION_ATTRIBUTE_ID (0x0000) @@ -4077,26 +3724,18 @@ #define ZCL_ENABLE_SECURE_CONFIGURATION_ATTRIBUTE_ID (0x0003) #define ZCL_NUMBER_OF_CONTENTS_ATTRIBUTE_ID (0x0010) #define ZCL_CONTENT_ROOT_ID_ATTRIBUTE_ID (0x0011) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Data Sharing // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_DEVICE_NAME_ATTRIBUTE_ID (0x0000) #define ZCL_DEVICE_DESCRIPTION_ATTRIBUTE_ID (0x0001) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Gaming // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_PLAYER_NAME_ATTRIBUTE_ID (0x0000) @@ -4119,27 +3758,19 @@ #define ZCL_COUNTER1_ATTRIBUTE_ID (0x001D) #define ZCL_COUNTER2_ATTRIBUTE_ID (0x001E) #define ZCL_DOWNLOADABLE_ATTRIBUTE_ID (0x001F) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Data Rate Control // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_AVERAGE_LATENCY_REQUIREMENT_ATTRIBUTE_ID (0x0000) #define ZCL_MAX_LATENCY_REQUIREMENT_ATTRIBUTE_ID (0x0001) #define ZCL_BANDWIDTH_REQUIREMENT_ATTRIBUTE_ID (0x0002) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Voice over ZigBee // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_CODEC_TYPE_ATTRIBUTE_ID (0x0000) @@ -4153,14 +3784,10 @@ #define ZCL_COMPRESSION_RATE_ATTRIBUTE_ID (0x0008) #define ZCL_OPTION_FLAGS_ATTRIBUTE_ID (0x0009) #define ZCL_THRESHOLD_ATTRIBUTE_ID (0x000A) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Chatting // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_U_ID_ATTRIBUTE_ID (0x0000) @@ -4168,14 +3795,10 @@ #define ZCL_C_ID_ATTRIBUTE_ID (0x0010) #define ZCL_NAME_ATTRIBUTE_ID (0x0011) #define ZCL_ENABLE_ADD_CHAT_ATTRIBUTE_ID (0x0020) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Payment // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_PAYMENT_USER_ID_ATTRIBUTE_ID (0x0000) @@ -4192,14 +3815,10 @@ #define ZCL_TRANS_ID_ATTRIBUTE_ID (0x0033) #define ZCL_TRANS_STATUS_ATTRIBUTE_ID (0x0034) #define ZCL_PAYMENT_STATUS_ATTRIBUTE_ID (0x0035) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Billing // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_USER_ID_ATTRIBUTE_ID (0x0000) @@ -4208,14 +3827,10 @@ #define ZCL_SESSION_INTERVAL_ATTRIBUTE_ID (0x0012) #define ZCL_TIMESTAMP_ATTRIBUTE_ID (0x0020) #define ZCL_DURATION_ATTRIBUTE_ID (0x0021) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Appliance Identification // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_BASIC_IDENTIFICATION_ATTRIBUTE_ID (0x0000) @@ -4230,14 +3845,10 @@ #define ZCL_PRODUCT_TYPE_NAME_ATTRIBUTE_ID (0x0018) #define ZCL_PRODUCT_TYPE_ID_ATTRIBUTE_ID (0x0019) #define ZCL_CECED_SPECIFICATION_VERSION_ATTRIBUTE_ID (0x001A) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Meter Identification // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_METER_COMPANY_NAME_ATTRIBUTE_ID (0x0000) @@ -4252,36 +3863,24 @@ #define ZCL_POD_ATTRIBUTE_ID (0x000C) #define ZCL_AVAILABLE_POWER_ATTRIBUTE_ID (0x000D) #define ZCL_POWER_THRESHOLD_ATTRIBUTE_ID (0x000E) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Appliance Events and Alert // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Appliance Statistics // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_LOG_MAX_SIZE_ATTRIBUTE_ID (0x0000) #define ZCL_LOG_QUEUE_MAX_SIZE_ATTRIBUTE_ID (0x0001) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Electrical Measurement // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_MEASUREMENT_TYPE_ATTRIBUTE_ID (0x0000) @@ -4412,14 +4011,10 @@ #define ZCL_RMS_EXTREME_UNDER_VOLTAGE_PERIOD_PHASE_C_ATTRIBUTE_ID (0x0A15) #define ZCL_RMS_VOLTAGE_SAG_PERIOD_PHASE_C_ATTRIBUTE_ID (0x0A16) #define ZCL_RMS_VOLTAGE_SWELL_PERIOD_PHASE_C_ATTRIBUTE_ID (0x0A17) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Diagnostics // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_NUMBER_OF_RESETS_ATTRIBUTE_ID (0x0000) @@ -4454,72 +4049,54 @@ #define ZCL_AVERAGE_MAC_RETRY_PER_APS_MSG_SENT_ATTRIBUTE_ID (0x011B) #define ZCL_LAST_MESSAGE_LQI_ATTRIBUTE_ID (0x011C) #define ZCL_LAST_MESSAGE_RSSI_ATTRIBUTE_ID (0x011D) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: ZLL Commissioning // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) + +// Attribute ids for cluster: Binding + +// Client attributes + +// Server attributes // Attribute ids for cluster: Sample Mfg Specific Cluster // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_ATTRIBUTE_ONE_ATTRIBUTE_ID (0x0000) #define ZCL_ATTRIBUTE_TWO_ATTRIBUTE_ID (0x0001) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Sample Mfg Specific Cluster 2 // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_ATTRIBUTE_THREE_ATTRIBUTE_ID (0x0000) #define ZCL_ATTRIBUTE_FOUR_ATTRIBUTE_ID (0x0001) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: Configuration Cluster // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_TOKENS_LOCKED_ATTRIBUTE_ID (0x0000) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: MFGLIB Cluster // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_PACKETS_RECEIVED_ATTRIBUTE_ID (0x0000) #define ZCL_SAVED_RSSI_ATTRIBUTE_ID (0x0001) #define ZCL_SAVED_LQI_ATTRIBUTE_ID (0x0002) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) // Attribute ids for cluster: SL Works With All Hubs // Client attributes -#define ZCL_CLUSTER_REVISION_CLIENT_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_CLIENT_ATTRIBUTE_ID (0xFFFE) // Server attributes #define ZCL_SL_DISABLE_OTA_DOWNGRADES_ATTRIBUTE_ID (0x0002) @@ -4540,5 +4117,3 @@ #define ZCL_SL_PENDING_NETWORK_UPDATE_CHANNEL_ATTRIBUTE_ID (0x0011) #define ZCL_SL_PENDING_NETWORK_UPDATE_PANID_ATTRIBUTE_ID (0x0012) #define ZCL_SL_OTA_MAX_OFFLINE_DURATION_ATTRIBUTE_ID (0x0013) -#define ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID (0xFFFD) -#define ZCL_REPORTING_STATUS_SERVER_ATTRIBUTE_ID (0xFFFE) diff --git a/examples/temperature-measurement-app/esp32/main/gen/attribute-size.h b/examples/temperature-measurement-app/esp32/main/gen/attribute-size.h index 8d8659ee7ece2e..f9ef9212244eca 100644 --- a/examples/temperature-measurement-app/esp32/main/gen/attribute-size.h +++ b/examples/temperature-measurement-app/esp32/main/gen/attribute-size.h @@ -1,4 +1,3 @@ - /* * * Copyright (c) 2020 Project CHIP Authors @@ -32,3 +31,5 @@ ZCL_DATA8_ATTRIBUTE_TYPE, 1, ZCL_DATA16_ATTRIBUTE_TYPE, 2, ZCL_DATA24_ATTRIBUTE_ ZCL_FLOAT_SINGLE_ATTRIBUTE_TYPE, 4, ZCL_FLOAT_DOUBLE_ATTRIBUTE_TYPE, 8, ZCL_TIME_OF_DAY_ATTRIBUTE_TYPE, 4, ZCL_DATE_ATTRIBUTE_TYPE, 4, ZCL_UTC_TIME_ATTRIBUTE_TYPE, 4, ZCL_CLUSTER_ID_ATTRIBUTE_TYPE, 2, ZCL_ATTRIBUTE_ID_ATTRIBUTE_TYPE, 2, ZCL_BACNET_OID_ATTRIBUTE_TYPE, 4, ZCL_IEEE_ADDRESS_ATTRIBUTE_TYPE, 8, ZCL_SECURITY_KEY_ATTRIBUTE_TYPE, 16, + ZCL_ENDPOINT_ID_ATTRIBUTE_TYPE, 1, ZCL_GROUP_ID_ATTRIBUTE_TYPE, 2, ZCL_COMMAND_ID_ATTRIBUTE_TYPE, 1, ZCL_NODE_ID_ATTRIBUTE_TYPE, + 8, diff --git a/examples/temperature-measurement-app/esp32/main/gen/attribute-type.h b/examples/temperature-measurement-app/esp32/main/gen/attribute-type.h index bc5d1bae34b365..225cbc68be49c2 100644 --- a/examples/temperature-measurement-app/esp32/main/gen/attribute-type.h +++ b/examples/temperature-measurement-app/esp32/main/gen/attribute-type.h @@ -1,4 +1,3 @@ - /* * * Copyright (c) 2020 Project CHIP Authors @@ -77,5 +76,9 @@ enum ZCL_BACNET_OID_ATTRIBUTE_TYPE = 0xEA, // BACnet OID ZCL_IEEE_ADDRESS_ATTRIBUTE_TYPE = 0xF0, // IEEE address ZCL_SECURITY_KEY_ATTRIBUTE_TYPE = 0xF1, // 128-bit security key + ZCL_ENDPOINT_ID_ATTRIBUTE_TYPE = 0xF2, // Endpoint Id + ZCL_GROUP_ID_ATTRIBUTE_TYPE = 0xF3, // Group Id + ZCL_COMMAND_ID_ATTRIBUTE_TYPE = 0xF4, // Command Id + ZCL_NODE_ID_ATTRIBUTE_TYPE = 0xF5, // Node Id ZCL_UNKNOWN_ATTRIBUTE_TYPE = 0xFF, // Unknown }; diff --git a/examples/temperature-measurement-app/esp32/main/gen/call-command-handler.cpp b/examples/temperature-measurement-app/esp32/main/gen/call-command-handler.cpp index 38afdd93327e0f..cba1ff3e46b4a7 100644 --- a/examples/temperature-measurement-app/esp32/main/gen/call-command-handler.cpp +++ b/examples/temperature-measurement-app/esp32/main/gen/call-command-handler.cpp @@ -1,4 +1,3 @@ - /* * * Copyright (c) 2020 Project CHIP Authors diff --git a/examples/temperature-measurement-app/esp32/main/gen/call-command-handler.h b/examples/temperature-measurement-app/esp32/main/gen/call-command-handler.h index c1b06642f07ac9..43164ad576bfa8 100644 --- a/examples/temperature-measurement-app/esp32/main/gen/call-command-handler.h +++ b/examples/temperature-measurement-app/esp32/main/gen/call-command-handler.h @@ -1,4 +1,3 @@ - /* * * Copyright (c) 2020 Project CHIP Authors diff --git a/examples/temperature-measurement-app/esp32/main/gen/callback-stub.cpp b/examples/temperature-measurement-app/esp32/main/gen/callback-stub.cpp index 83d63878f3d686..ac3b13aacbb381 100644 --- a/examples/temperature-measurement-app/esp32/main/gen/callback-stub.cpp +++ b/examples/temperature-measurement-app/esp32/main/gen/callback-stub.cpp @@ -1,4 +1,3 @@ - /* * * Copyright (c) 2020 Project CHIP Authors diff --git a/examples/temperature-measurement-app/esp32/main/gen/callback.h b/examples/temperature-measurement-app/esp32/main/gen/callback.h index 888e1699860951..7829b19e66d717 100644 --- a/examples/temperature-measurement-app/esp32/main/gen/callback.h +++ b/examples/temperature-measurement-app/esp32/main/gen/callback.h @@ -1,4 +1,3 @@ - /* * * Copyright (c) 2020 Project CHIP Authors diff --git a/examples/temperature-measurement-app/esp32/main/gen/client-command-macro.h b/examples/temperature-measurement-app/esp32/main/gen/client-command-macro.h index f1b0c4633a2b14..7116663d885eca 100644 --- a/examples/temperature-measurement-app/esp32/main/gen/client-command-macro.h +++ b/examples/temperature-measurement-app/esp32/main/gen/client-command-macro.h @@ -1,4 +1,3 @@ - /* * * Copyright (c) 2020 Project CHIP Authors @@ -5663,6 +5662,32 @@ ZCL_GET_ENDPOINT_LIST_REQUEST_COMMAND_ID, "uuuub", startIndex, total, startIndex, count, \ endpointInformationRecordList, endpointInformationRecordListLen); +/** @brief Command description for Bind + * + * Command: Bind + * @param nodeId NODE_ID + * @param groupId GROUP_ID + * @param endpointId ENDPOINT_ID + * @param clusterId CLUSTER_ID + */ +#define emberAfFillCommandBindingClusterBind(nodeId, groupId, endpointId, clusterId) \ + emberAfFillExternalBuffer(mask, \ + \ + ZCL_BIND_COMMAND_ID, "uuuu", nodeId, groupId, endpointId, clusterId); + +/** @brief Command description for Unbind + * + * Command: Unbind + * @param nodeId NODE_ID + * @param groupId GROUP_ID + * @param endpointId ENDPOINT_ID + * @param clusterId CLUSTER_ID + */ +#define emberAfFillCommandBindingClusterUnbind(nodeId, groupId, endpointId, clusterId) \ + emberAfFillExternalBuffer(mask, \ + \ + ZCL_UNBIND_COMMAND_ID, "uuuu", nodeId, groupId, endpointId, clusterId); + /** @brief Command description for CommandOne * * Command: CommandOne diff --git a/examples/temperature-measurement-app/esp32/main/gen/cluster-id.h b/examples/temperature-measurement-app/esp32/main/gen/cluster-id.h index c341b079be401d..4db65e9cad99d0 100644 --- a/examples/temperature-measurement-app/esp32/main/gen/cluster-id.h +++ b/examples/temperature-measurement-app/esp32/main/gen/cluster-id.h @@ -1,4 +1,3 @@ - /* * * Copyright (c) 2020 Project CHIP Authors @@ -331,6 +330,9 @@ // Definitions for cluster: ZLL Commissioning #define ZCL_ZLL_COMMISSIONING_CLUSTER_ID (0x1000) +// Definitions for cluster: Binding +#define ZCL_BINDING_CLUSTER_ID (0xF000) + // Definitions for cluster: Sample Mfg Specific Cluster #define ZCL_SAMPLE_MFG_SPECIFIC_CLUSTER_ID (0xFC00) diff --git a/examples/temperature-measurement-app/esp32/main/gen/command-id.h b/examples/temperature-measurement-app/esp32/main/gen/command-id.h index 940258f4527aa5..42dcc0e89c71f5 100644 --- a/examples/temperature-measurement-app/esp32/main/gen/command-id.h +++ b/examples/temperature-measurement-app/esp32/main/gen/command-id.h @@ -1,4 +1,3 @@ - /* * * Copyright (c) 2020 Project CHIP Authors @@ -46,6 +45,7 @@ // Commands for cluster: Basic #define ZCL_RESET_TO_FACTORY_DEFAULTS_COMMAND_ID (0x00) +#define ZCL_MFG_SPECIFIC_PING_COMMAND_ID (0x00) // Commands for cluster: Identify #define ZCL_IDENTIFY_COMMAND_ID (0x00) @@ -683,6 +683,10 @@ #define ZCL_GET_ENDPOINT_LIST_REQUEST_COMMAND_ID (0x42) #define ZCL_GET_ENDPOINT_LIST_RESPONSE_COMMAND_ID (0x42) +// Commands for cluster: Binding +#define ZCL_BIND_COMMAND_ID (0x00) +#define ZCL_UNBIND_COMMAND_ID (0x01) + // Commands for cluster: Sample Mfg Specific Cluster #define ZCL_COMMAND_ONE_COMMAND_ID (0x00) diff --git a/examples/temperature-measurement-app/esp32/main/gen/enums.h b/examples/temperature-measurement-app/esp32/main/gen/enums.h index 07c2881e641e97..eedb99290f59ce 100644 --- a/examples/temperature-measurement-app/esp32/main/gen/enums.h +++ b/examples/temperature-measurement-app/esp32/main/gen/enums.h @@ -1,4 +1,3 @@ - /* * * Copyright (c) 2020 Project CHIP Authors @@ -548,7 +547,7 @@ typedef enum EMBER_ZCL_DOOR_LOCK_OPERATING_MODE_PRIVACY_MODE = 0x02, EMBER_ZCL_DOOR_LOCK_OPERATING_MODE_NO_RF_LOCK_OR_UNLOCK = 0x03, EMBER_ZCL_DOOR_LOCK_OPERATING_MODE_LOCAL_PROGRAMMING_MODE = 0x04, - EMBER_ZCL_DOOR_LOCK_OPERATING_MODE_PASSAGE_MODE______ = 0x05, + EMBER_ZCL_DOOR_LOCK_OPERATING_MODE_PASSAGE_MODE = 0x05, } EmberAfDoorLockOperatingMode; // Enum for DoorLockOperationEventCode diff --git a/examples/temperature-measurement-app/esp32/main/gen/gen_config.h b/examples/temperature-measurement-app/esp32/main/gen/gen_config.h index 0466cf6b0e0045..f1ae11d45c4a52 100644 --- a/examples/temperature-measurement-app/esp32/main/gen/gen_config.h +++ b/examples/temperature-measurement-app/esp32/main/gen/gen_config.h @@ -1,4 +1,3 @@ - /* * * Copyright (c) 2020 Project CHIP Authors @@ -47,5 +46,5 @@ // Use this macro to check if Reporting plugin is included #define EMBER_AF_PLUGIN_REPORTING // User options for plugin Reporting -#define EMBER_AF_PLUGIN_REPORTING_TABLE_SIZE 5 +#define EMBER_AF_PLUGIN_REPORTING_TABLE_SIZE 20 #define EMBER_AF_PLUGIN_REPORTING_ENABLE_GROUP_BOUND_REPORTS diff --git a/examples/temperature-measurement-app/esp32/main/gen/print-cluster.h b/examples/temperature-measurement-app/esp32/main/gen/print-cluster.h index a37d7fb0495995..7155ccf0294122 100644 --- a/examples/temperature-measurement-app/esp32/main/gen/print-cluster.h +++ b/examples/temperature-measurement-app/esp32/main/gen/print-cluster.h @@ -1,4 +1,3 @@ - /* * * Copyright (c) 2020 Project CHIP Authors @@ -715,6 +714,12 @@ #define CHIP_PRINTCLUSTER_ZLL_COMMISSIONING_CLUSTER #endif +#if defined(ZCL_USING_BINDING_CLUSTER_SERVER) || defined(ZCL_USING_BINDING_CLUSTER_CLIENT) +#define CHIP_PRINTCLUSTER_BINDING_CLUSTER { ZCL_BINDING_CLUSTER_ID, 61440, "Binding" }, +#else +#define CHIP_PRINTCLUSTER_BINDING_CLUSTER +#endif + #if defined(ZCL_USING_SAMPLE_MFG_SPECIFIC_CLUSTER_SERVER) || defined(ZCL_USING_SAMPLE_MFG_SPECIFIC_CLUSTER_CLIENT) #define CHIP_PRINTCLUSTER_SAMPLE_MFG_SPECIFIC_CLUSTER { ZCL_SAMPLE_MFG_SPECIFIC_CLUSTER_ID, 64512, "Sample Mfg Specific Cluster" }, #else @@ -851,6 +856,7 @@ CHIP_PRINTCLUSTER_ELECTRICAL_MEASUREMENT_CLUSTER \ CHIP_PRINTCLUSTER_DIAGNOSTICS_CLUSTER \ CHIP_PRINTCLUSTER_ZLL_COMMISSIONING_CLUSTER \ + CHIP_PRINTCLUSTER_BINDING_CLUSTER \ CHIP_PRINTCLUSTER_SAMPLE_MFG_SPECIFIC_CLUSTER \ CHIP_PRINTCLUSTER_SAMPLE_MFG_SPECIFIC_CLUSTER_2 \ CHIP_PRINTCLUSTER_OTA_CONFIGURATION_CLUSTER \ diff --git a/integrations/docker/images/chip-cirque-device-base/Dockerfile b/integrations/docker/images/chip-cirque-device-base/Dockerfile index 408fe5ea355fd8..ed91b66f76412d 100644 --- a/integrations/docker/images/chip-cirque-device-base/Dockerfile +++ b/integrations/docker/images/chip-cirque-device-base/Dockerfile @@ -15,6 +15,7 @@ WORKDIR /app RUN apt-get update \ && apt-get install --no-install-recommends -y sudo git ca-certificates psmisc dhcpcd5 wpasupplicant wireless-tools \ + && apt-get install -y libglib2.0 avahi-daemon libavahi-client3 \ && ln -fs /usr/share/zoneinfo/UTC /etc/localtime \ && git clone https://github.com/openthread/ot-br-posix . \ && git checkout $OT_BR_POSIX_CHECKOUT \ diff --git a/scripts/requirements.in b/scripts/requirements.in index 1fd30bffaf7262..5b7a4df3a0e4d2 100644 --- a/scripts/requirements.in +++ b/scripts/requirements.in @@ -13,7 +13,7 @@ pyelftools>=0.22 requests>=2.24.0 # device controller wheel package -wheel>=0.34.2 +wheel==0.34.2 # mobly tests portpicker @@ -25,3 +25,9 @@ west>=0.8.0 # happy tests lockfile psutil >= 5.7.3 + +# pigweed +ipython +coloredlogs +watchdog +protobuf diff --git a/scripts/requirements.txt b/scripts/requirements.txt index b5abdfe0d83efb..cb352f22cdf517 100644 --- a/scripts/requirements.txt +++ b/scripts/requirements.txt @@ -4,33 +4,50 @@ # # pip-compile requirements.in # -certifi==2020.6.20 # via requests -cffi==1.14.3 # via cryptography +backcall==0.2.0 # via ipython +certifi==2020.12.5 # via requests +cffi==1.14.4 # via cryptography chardet==3.0.4 # via requests click==7.1.2 # via -r requirements.in, pip-tools colorama==0.4.4 # via west +coloredlogs==15.0 # via -r requirements.in configobj==5.0.6 # via west -cryptography==3.2.1 # via -r requirements.in +cryptography==3.3.1 # via -r requirements.in +decorator==4.4.2 # via ipython docopt==0.6.2 # via pykwalify future==0.18.2 # via -r requirements.in, mobly +humanfriendly==9.1 # via coloredlogs idna==2.10 # via requests +ipython-genutils==0.2.0 # via traitlets +ipython==7.19.0 # via -r requirements.in +jedi==0.17.2 # via ipython lockfile==0.12.2 # via -r requirements.in mobly==1.10 # via -r requirements.in -packaging==20.4 # via west -pip-tools==5.3.1 # via -r requirements.in +packaging==20.7 # via west +parso==0.7.1 # via jedi +pexpect==4.8.0 # via ipython +pickleshare==0.7.5 # via ipython +pip-tools==5.4.0 # via -r requirements.in portpicker==1.3.1 # via -r requirements.in, mobly +prompt-toolkit==3.0.8 # via ipython +protobuf==3.14.0 # via -r requirements.in psutil==5.7.3 # via -r requirements.in, mobly +ptyprocess==0.6.0 # via pexpect pycparser==2.20 # via cffi -pyelftools==0.26 # via -r requirements.in +pyelftools==0.27 # via -r requirements.in +pygments==2.7.3 # via ipython pykwalify==1.7.0 # via west pyparsing==2.3.1 # via -r requirements.in, packaging -pyserial==3.4 # via -r requirements.in, mobly +pyserial==3.5 # via -r requirements.in, mobly python-dateutil==2.8.1 # via pykwalify pyyaml==5.3.1 # via mobly, pykwalify, west -requests==2.24.0 # via -r requirements.in -six==1.15.0 # via configobj, cryptography, packaging, pip-tools, python-dateutil -timeout-decorator==0.4.1 # via mobly -urllib3==1.25.10 # via requests +requests==2.25.0 # via -r requirements.in +six==1.15.0 # via configobj, cryptography, pip-tools, protobuf, python-dateutil +timeout-decorator==0.5.0 # via mobly +traitlets==5.0.5 # via ipython +urllib3==1.26.2 # via requests +watchdog==1.0.1 # via -r requirements.in +wcwidth==0.2.5 # via prompt-toolkit west==0.8.0 # via -r requirements.in wheel==0.34.2 # via -r requirements.in diff --git a/scripts/tests/cirque_tests.sh b/scripts/tests/cirque_tests.sh index f350117aadae7f..654a47a4e824f7 100755 --- a/scripts/tests/cirque_tests.sh +++ b/scripts/tests/cirque_tests.sh @@ -25,6 +25,8 @@ LOG_DIR=${LOG_DIR:-$(mktemp -d)} # Append test name here to add more tests for run_all_tests CIRQUE_TESTS=( + "EchoTest" + "InteractionModelTest" "OnOffClusterTest" ) @@ -115,6 +117,7 @@ function cirquetest_run_test() { docker container prune -f >/dev/null 2>&1 docker network prune -f >/dev/null 2>&1 fi + echo "Test log can be found at $DEVICE_LOG_DIR" return "$exitcode" } diff --git a/scripts/tools/zap_configure.sh b/scripts/tools/zap_configure.sh index 7212aa3f216ba6..57d23a64db0b87 100755 --- a/scripts/tools/zap_configure.sh +++ b/scripts/tools/zap_configure.sh @@ -16,6 +16,7 @@ # limitations under the License. # +ZAP_TEMPLATES=$PWD/src/app/zap-templates cd ./third_party/zap/repo/ -node ./src-script/zap-start.js --logToStdout --gen ../../../src/app/zap-templates/chip-templates.json +node ./src-script/zap-start.js --logToStdout -z "$ZAP_TEMPLATES"/zcl/zcl.json --gen "$ZAP_TEMPLATES"/app-templates.json diff --git a/scripts/tools/zap_generate.sh b/scripts/tools/zap_generate.sh index b630b32cd848ee..0df32448785e1b 100755 --- a/scripts/tools/zap_generate.sh +++ b/scripts/tools/zap_generate.sh @@ -31,5 +31,11 @@ if [ ! -d "$OUTPUT_DIRECTORY" ]; then mkdir -p "$OUTPUT_DIRECTORY" fi +ZAP_TEMPLATES=$PWD/src/app/zap-templates cd ./third_party/zap/repo/ -node ./src-script/zap-generate.js -z ./zcl-builtin/silabs/zcl.json -g ../../../src/app/zap-templates/chip-templates.json -i "$FILE_PATH" -o "$OUTPUT_DIRECTORY" +node ./src-script/zap-generate.js -z "$ZAP_TEMPLATES"/zcl/zcl.json -g "$ZAP_TEMPLATES"/app-templates.json -i "$FILE_PATH" -o "$OUTPUT_DIRECTORY" + +# Check if clang-format is available +if command -v clang-format &>/dev/null; then + clang-format -i "$OUTPUT_DIRECTORY"* +fi diff --git a/scripts/tools/zap_generate_chip.sh b/scripts/tools/zap_generate_chip.sh new file mode 100755 index 00000000000000..af9334fa43afe0 --- /dev/null +++ b/scripts/tools/zap_generate_chip.sh @@ -0,0 +1,21 @@ +#!/usr/bin/env bash + +# +# 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. +# + +ZAP_TEMPLATES=$PWD/src/app/zap-templates +cd ./third_party/zap/repo/ +node ./src-script/zap-generate.js -z "$ZAP_TEMPLATES"/zcl/zcl.json -g "$ZAP_TEMPLATES"/chip-templates.json -i ../../../examples/all-clusters-app/all-clusters-common/all-clusters-app.zap -o ../../../ diff --git a/scripts/tools/zap_regen_all.py b/scripts/tools/zap_regen_all.py new file mode 100755 index 00000000000000..62c2e1551f2324 --- /dev/null +++ b/scripts/tools/zap_regen_all.py @@ -0,0 +1,37 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2020 Project CHIP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +import sys +import os +from pathlib import Path + +# Check python version +if sys.version_info[0] < 3: + print("Must use Python 3. Current version is " + str(sys.version_info[0])) + exit(1) + +# Check if we are in top of CHIP folder +scripts_path = os.path.join(os.getcwd(), 'scripts/tools/zap_regen_all.py') +if not os.path.exists(scripts_path): + print(os.getcwd()) + print('This script must be called from the root of the chip directory') + exit(1) + +os.system("./scripts/tools/zap_generate_chip.sh") + +for path in Path('./examples').rglob('*.zap'): + os.system("./scripts/tools/zap_generate.sh " + str(path)) diff --git a/src/BUILD.gn b/src/BUILD.gn index ef9cf26d4801a8..6d91bceddc3f82 100644 --- a/src/BUILD.gn +++ b/src/BUILD.gn @@ -39,6 +39,7 @@ if (chip_build_tests) { chip_test_group("tests") { deps = [ "${chip_root}/src/app/tests", + "${chip_root}/src/credentials/tests", "${chip_root}/src/crypto/tests", "${chip_root}/src/inet/tests", "${chip_root}/src/lib/asn1/tests", diff --git a/src/app/BUILD.gn b/src/app/BUILD.gn index b987da255b010a..b11be8911a1109 100644 --- a/src/app/BUILD.gn +++ b/src/app/BUILD.gn @@ -28,6 +28,11 @@ static_library("app") { output_name = "libCHIPDataModel" sources = [ + "Command.cpp", + "Command.h", + "CommandHandler.cpp", + "CommandSender.cpp", + "InteractionModelEngine.cpp", "MessageDef.cpp", "MessageDef.h", "decoder.cpp", @@ -37,6 +42,7 @@ static_library("app") { public_deps = [ ":codec_headers", "${chip_root}/src/lib/support", + "${chip_root}/src/messaging", "${chip_root}/src/system", "${nlio_root}:nlio", ] diff --git a/src/app/Command.cpp b/src/app/Command.cpp new file mode 100644 index 00000000000000..464f5562acfbcc --- /dev/null +++ b/src/app/Command.cpp @@ -0,0 +1,317 @@ +/* + * + * 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 + * This file defines Base class for a CHIP IM Command + * + */ + +#include "Command.h" +#include "CommandHandler.h" +#include "CommandSender.h" +#include "InteractionModelEngine.h" +#include + +namespace chip { +namespace app { + +CHIP_ERROR Command::Init(Messaging::ExchangeManager * apExchangeMgr) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + // Error if already initialized. + if (mpExchangeMgr != nullptr) + return CHIP_ERROR_INCORRECT_STATE; + + mpExchangeMgr = apExchangeMgr; + mpExchangeCtx = nullptr; + + err = Reset(); + SuccessOrExit(err); + +exit: + ChipLogFunctError(err); + return err; +} + +CHIP_ERROR Command::Reset() +{ + CHIP_ERROR err = CHIP_NO_ERROR; + + ClearExistingExchangeContext(); + + if (mCommandMessageBuf.IsNull()) + { + // TODO: Calculate the packet buffer size + mCommandMessageBuf = System::PacketBuffer::New(); + VerifyOrExit(!mCommandMessageBuf.IsNull(), err = CHIP_ERROR_NO_MEMORY); + } + + mCommandMessageWriter.Init(std::move(mCommandMessageBuf)); + err = mInvokeCommandBuilder.Init(&mCommandMessageWriter); + SuccessOrExit(err); + + mInvokeCommandBuilder.CreateCommandListBuilder(); + MoveToState(kState_Initialized); + +exit: + ChipLogFunctError(err); + + return err; +} + +CHIP_ERROR Command::ProcessCommandMessage(System::PacketBufferHandle payload, CommandRoleId aCommandRoleId) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + chip::System::PacketBufferTLVReader reader; + chip::TLV::TLVReader commandListReader; + InvokeCommand::Parser invokeCommandParser; + CommandList::Parser commandListParser; + + reader.Init(std::move(payload)); + err = reader.Next(); + SuccessOrExit(err); + + err = invokeCommandParser.Init(reader); + SuccessOrExit(err); + + err = invokeCommandParser.CheckSchemaValidity(); + SuccessOrExit(err); + + err = invokeCommandParser.GetCommandList(&commandListParser); + SuccessOrExit(err); + + commandListParser.GetReader(&commandListReader); + + while (CHIP_NO_ERROR == (err = commandListReader.Next())) + { + VerifyOrExit(chip::TLV::AnonymousTag == commandListReader.GetTag(), err = CHIP_ERROR_INVALID_TLV_TAG); + VerifyOrExit(chip::TLV::kTLVType_Structure == commandListReader.GetType(), err = CHIP_ERROR_WRONG_TLV_TYPE); + + CommandDataElement::Parser commandElement; + + err = commandElement.Init(commandListReader); + SuccessOrExit(err); + + err = commandElement.CheckSchemaValidity(); + SuccessOrExit(err); + + err = ProcessCommandDataElement(commandElement); + SuccessOrExit(err); + } + + // if we have exhausted this container + if (CHIP_END_OF_TLV == err) + { + err = CHIP_NO_ERROR; + } + +exit: + return err; +} + +void Command::Shutdown() +{ + VerifyOrExit(mState != kState_Uninitialized, ); + mCommandMessageWriter.Reset(); + mCommandMessageBuf = nullptr; + + if (mpExchangeCtx != nullptr) + { + mpExchangeCtx->Abort(); + mpExchangeCtx = nullptr; + } + mpExchangeMgr = nullptr; + MoveToState(kState_Uninitialized); + +exit: + return; +} + +chip::TLV::TLVWriter & Command::CreateCommandDataElementTLVWriter() +{ + mCommandDataBuf = chip::System::PacketBuffer::New(); + if (mCommandDataBuf.IsNull()) + { + ChipLogDetail(DataManagement, "Unable to allocate PacketBuffer"); + } + + mCommandDataWriter.Init(mCommandDataBuf.Retain()); + + return mCommandDataWriter; +} + +CHIP_ERROR Command::AddCommand(chip::EndpointId aEndpintId, chip::GroupId aGroupId, chip::ClusterId aClusterId, + chip::CommandId aCommandId, uint8_t aFlags) +{ + CommandParams commandParams; + + memset(&commandParams, 0, sizeof(CommandParams)); + + commandParams.EndpointId = aEndpintId; + commandParams.GroupId = aGroupId; + commandParams.ClusterId = aClusterId; + commandParams.CommandId = aCommandId; + commandParams.Flags = aFlags; + + return AddCommand(commandParams); +} + +CHIP_ERROR Command::AddCommand(CommandParams & aCommandParams) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + const uint8_t * apCommandData; + uint32_t apCommandLen; + + apCommandData = mCommandDataBuf->Start(); + apCommandLen = mCommandDataBuf->DataLength(); + + if (apCommandLen > 0) + { + VerifyOrExit(apCommandLen > 2, err = CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrExit(apCommandData[0] == chip::TLV::kTLVType_Structure, err = CHIP_ERROR_INVALID_ARGUMENT); + + apCommandData += 1; + apCommandLen -= 1; + } + + { + CommandDataElement::Builder commandDataElement = + mInvokeCommandBuilder.GetCommandListBuilder().CreateCommandDataElementBuilder(); + CommandPath::Builder commandPath = commandDataElement.CreateCommandPathBuilder(); + if (aCommandParams.Flags & kCommandPathFlag_EndpointIdValid) + { + commandPath.EndpointId(aCommandParams.EndpointId); + } + + if (aCommandParams.Flags & kCommandPathFlag_GroupIdValid) + { + commandPath.GroupId(aCommandParams.GroupId); + } + + commandPath.NamespacedClusterId(aCommandParams.ClusterId).CommandId(aCommandParams.CommandId).EndOfCommandPath(); + + err = commandPath.GetError(); + SuccessOrExit(err); + + if (apCommandLen > 0) + { + // Copy the application data into a new TLV structure field contained with the + // command structure. NOTE: The TLV writer will take care of moving the app data + // to the correct location within the buffer. + err = mInvokeCommandBuilder.GetWriter()->PutPreEncodedContainer( + chip::TLV::ContextTag(CommandDataElement::kCsTag_Data), chip::TLV::kTLVType_Structure, apCommandData, apCommandLen); + SuccessOrExit(err); + } + commandDataElement.EndOfCommandDataElement(); + + err = commandDataElement.GetError(); + SuccessOrExit(err); + } + MoveToState(kState_AddCommand); + +exit: + mCommandDataBuf = nullptr; + ChipLogFunctError(err); + return err; +} + +CHIP_ERROR Command::AddStatusCode(const uint16_t aGeneralCode, const uint32_t aProtocolId, const uint16_t aProtocolCode, + const chip::ClusterId aNamespacedClusterId) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + StatusElement::Builder statusElementBuilder; + + err = statusElementBuilder.Init(mInvokeCommandBuilder.GetWriter()); + SuccessOrExit(err); + + statusElementBuilder.EncodeStatusElement(aGeneralCode, aProtocolId, aProtocolCode, aProtocolCode).EndOfStatusElement(); + err = statusElementBuilder.GetError(); + + MoveToState(kState_AddCommand); + +exit: + ChipLogFunctError(err); + return err; +} + +CHIP_ERROR Command::ClearExistingExchangeContext() +{ + // Discard any existing exchange context. Effectively we can only have one Echo exchange with + // a single node at any one time. + if (mpExchangeCtx != nullptr) + { + mpExchangeCtx->Abort(); + mpExchangeCtx = nullptr; + } + + return CHIP_NO_ERROR; +} + +CHIP_ERROR Command::FinalizeCommandsMessage() +{ + CHIP_ERROR err = CHIP_NO_ERROR; + + mInvokeCommandBuilder.EndOfInvokeCommand(); + err = mInvokeCommandBuilder.GetError(); + SuccessOrExit(err); + + err = mCommandMessageWriter.Finalize(&mCommandMessageBuf); + SuccessOrExit(err); + + mCommandMessageBuf->EnsureReservedSize(CHIP_SYSTEM_CONFIG_HEADER_RESERVE_SIZE); + +exit: + ChipLogFunctError(err); + return err; +} + +#if CHIP_DETAIL_LOGGING +const char * Command::GetStateStr() const +{ + switch (mState) + { + case kState_Uninitialized: + return "Uninitialized"; + + case kState_Initialized: + return "Initialized"; + + case kState_AddCommand: + return "AddCommand"; + + case kState_Sending: + return "Sending"; + } + return "N/A"; +} +#endif // CHIP_DETAIL_LOGGING + +void Command::MoveToState(const CommandState aTargetState) +{ + mState = aTargetState; + ChipLogDetail(DataManagement, "ICR moving to [%10.10s]", GetStateStr()); +} + +void Command::ClearState(void) +{ + MoveToState(kState_Uninitialized); +} + +} // namespace app +} // namespace chip diff --git a/src/app/Command.h b/src/app/Command.h new file mode 100644 index 00000000000000..a224402e684a84 --- /dev/null +++ b/src/app/Command.h @@ -0,0 +1,152 @@ +/* + * + * 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 + * This file defines Base class for a CHIP IM Command + * + */ + +#pragma once + +#ifndef _CHIP_INTERACTION_MODEL_COMMAND_H +#define _CHIP_INTERACTION_MODEL_COMMAND_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace chip { +namespace app { + +class Command +{ +public: + enum CommandRoleId + { + kCommandSenderId = 0, + kCommandHandlerId = 1, + }; + + enum CommandState + { + kState_Uninitialized = 0, ///< The invoke command message has not been initialized + kState_Initialized, ///< The invoke command message has been initialized and is ready + kState_AddCommand, ///< The invoke command message has added Command + kState_Sending, ///< The invoke command message has sent out the invoke command + }; + + /** + * Encapsulates arguments to be passed into SendCommand(). + * + */ + struct CommandParams + { + chip::EndpointId EndpointId; + chip::GroupId GroupId; + chip::ClusterId ClusterId; + chip::CommandId CommandId; + uint8_t Flags; + }; + + enum CommandPathFlags + { + kCommandPathFlag_EndpointIdValid = 0x0001, /**< Set when the EndpointId field is valid */ + kCommandPathFlag_GroupIdValid = 0x0002, /**< Set when the GroupId field is valid */ + } CommandPathFlags; + + /** + * Initialize the CommandSender object. Within the lifetime + * of this instance, this method is invoked once after object + * construction until a call to Shutdown is made to terminate the + * instance. + * + * @param[in] apExchangeMgr A pointer to the ExchangeManager object. + * + * @retval #CHIP_ERROR_INCORRECT_STATE If the state is not equal to + * kState_NotInitialized. + * @retval #CHIP_NO_ERROR On success. + * + */ + CHIP_ERROR Init(Messaging::ExchangeManager * apExchangeMgr); + + /** + * Shutdown the CommandSender. This terminates this instance + * of the object and releases all held resources. + * + */ + void Shutdown(); + + /** + * Send an echo request to a CHIP node. + * + * @param nodeId The destination's nodeId + * @param payload A System::PacketBuffer with the payload. This function takes ownership of the System::PacketBuffer + * + * @return CHIP_ERROR_NO_MEMORY if no ExchangeContext is available. + * Other CHIPF_ERROR codes as returned by the lower layers. + * + */ + CHIP_ERROR FinalizeCommandsMessage(); + + chip::TLV::TLVWriter & CreateCommandDataElementTLVWriter(); + CHIP_ERROR AddCommand(chip::EndpointId aEndpintId, chip::GroupId aGroupId, chip::ClusterId aClusterId, + chip::CommandId aCommandId, uint8_t Flags); + CHIP_ERROR AddCommand(CommandParams & aCommandParams); + CHIP_ERROR AddStatusCode(const uint16_t aGeneralCode, const uint32_t aProtocolId, const uint16_t aProtocolCode, + const chip::ClusterId aNamespacedClusterId); + CHIP_ERROR ClearExistingExchangeContext(); + + CHIP_ERROR Reset(); + + virtual ~Command() = default; + + bool IsFree() { return (nullptr == mpExchangeCtx); }; + virtual CHIP_ERROR ProcessCommandDataElement(CommandDataElement::Parser & aCommandElement) = 0; + +protected: + void MoveToState(const CommandState aTargetState); + CHIP_ERROR ProcessCommandMessage(System::PacketBufferHandle payload, CommandRoleId aCommandRoleId); + void ClearState(); + const char * GetStateStr() const; + + Messaging::ExchangeManager * mpExchangeMgr = nullptr; + Messaging::ExchangeContext * mpExchangeCtx = nullptr; + chip::System::PacketBufferHandle mCommandMessageBuf; + +private: + chip::System::PacketBufferHandle mpBufHandle; + InvokeCommand::Builder mInvokeCommandBuilder; + CommandState mState; + + chip::System::PacketBufferHandle mCommandDataBuf; + chip::System::PacketBufferTLVWriter mCommandMessageWriter; + chip::System::PacketBufferTLVWriter mCommandDataWriter; +}; +} // namespace app +} // namespace chip + +#endif // _CHIP_INTERACTION_MODEL_COMMAND_H diff --git a/src/app/CommandHandler.cpp b/src/app/CommandHandler.cpp new file mode 100644 index 00000000000000..62df35cb0a5524 --- /dev/null +++ b/src/app/CommandHandler.cpp @@ -0,0 +1,107 @@ +/* + * + * 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 + * This file defines object for a CHIP IM Invoke Command Handler + * + */ + +#include "CommandHandler.h" +#include "Command.h" +#include "CommandSender.h" +#include "InteractionModelEngine.h" + +namespace chip { +namespace app { +void CommandHandler::OnMessageReceived(Messaging::ExchangeContext * ec, const PacketHeader & packetHeader, uint32_t protocolId, + uint8_t msgType, System::PacketBufferHandle payload) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + System::PacketBufferHandle response; + + // NOTE: we already know this is an InvokeCommand Request message because we explicitly registered with the + // Exchange Manager for unsolicited InvokeCommand Requests. + + mpExchangeCtx = ec; + + err = ProcessCommandMessage(std::move(payload), kCommandHandlerId); + SuccessOrExit(err); + + SendCommandResponse(); + +exit: + ChipLogFunctError(err); +} + +CHIP_ERROR CommandHandler::SendCommandResponse() +{ + CHIP_ERROR err = CHIP_NO_ERROR; + + err = FinalizeCommandsMessage(); + SuccessOrExit(err); + + VerifyOrExit(mpExchangeCtx != NULL, err = CHIP_ERROR_INCORRECT_STATE); + err = mpExchangeCtx->SendMessage(Protocols::kProtocol_InteractionModel, kMsgType_InvokeCommandResponse, + std::move(mCommandMessageBuf), Messaging::SendFlags(Messaging::SendMessageFlags::kNone)); + SuccessOrExit(err); + + MoveToState(kState_Sending); + +exit: + Shutdown(); + ChipLogFunctError(err); + return err; +} + +CHIP_ERROR CommandHandler::ProcessCommandDataElement(CommandDataElement::Parser & aCommandElement) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + CommandPath::Parser commandPath; + chip::TLV::TLVReader commandDataReader; + chip::ClusterId clusterId; + chip::CommandId commandId; + + err = aCommandElement.GetCommandPath(&commandPath); + SuccessOrExit(err); + + err = commandPath.GetNamespacedClusterId(&clusterId); + SuccessOrExit(err); + + err = commandPath.GetCommandId(&commandId); + SuccessOrExit(err); + + err = aCommandElement.GetData(&commandDataReader); + if (CHIP_END_OF_TLV == err) + { + // Empty Command, Add status code in invoke command response, notify cluster handler to hand it further. + err = CHIP_NO_ERROR; + ChipLogDetail(DataManagement, "Add Status code for empty command, cluster Id is %d", clusterId); + // Todo: Define ProtocolCode for StatusCode. + AddStatusCode(COMMON_STATUS_SUCCESS, chip::Protocols::kProtocol_Protocol_Common, 0, clusterId); + } + else if (CHIP_NO_ERROR == err) + { + InteractionModelEngine::GetInstance()->ProcessCommand(clusterId, commandId, commandDataReader, this, kCommandHandlerId); + } + +exit: + return err; +} +} // namespace app +} // namespace chip diff --git a/src/app/CommandHandler.h b/src/app/CommandHandler.h new file mode 100644 index 00000000000000..7144a2a140d9f9 --- /dev/null +++ b/src/app/CommandHandler.h @@ -0,0 +1,60 @@ +/* + * + * 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 + * This file defines object for a CHIP IM Invoke Command Handler + * + */ + +#pragma once + +#ifndef _CHIP_INTERACTION_MODEL_COMMAND_HANDLER_H +#define _CHIP_INTERACTION_MODEL_COMMAND_HANDLER_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace chip { +namespace app { + +class DLL_EXPORT CommandHandler : public Command +{ +public: + CHIP_ERROR SendCommandResponse(); + void OnMessageReceived(Messaging::ExchangeContext * ec, const PacketHeader & packetHeader, uint32_t protocolId, uint8_t msgType, + System::PacketBufferHandle payload); + +private: + CHIP_ERROR ProcessCommandDataElement(CommandDataElement::Parser & aCommandElement) override; +}; +} // namespace app +} // namespace chip + +#endif // _CHIP_INTERACTION_MODEL_COMMAND_HANDLER_H diff --git a/src/app/CommandSender.cpp b/src/app/CommandSender.cpp new file mode 100644 index 00000000000000..530af7e569f91b --- /dev/null +++ b/src/app/CommandSender.cpp @@ -0,0 +1,153 @@ +/* + * + * 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 + * This file defines objects for a CHIP IM Invoke Command Sender + * + */ + +#include "CommandSender.h" +#include "Command.h" +#include "CommandHandler.h" +#include "InteractionModelEngine.h" + +namespace chip { +namespace app { + +CHIP_ERROR CommandSender::SendCommandRequest(NodeId aNodeId) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + + err = FinalizeCommandsMessage(); + SuccessOrExit(err); + + ClearExistingExchangeContext(); + + // Create a new exchange context. + // TODO: temprary create a SecureSessionHandle from node id, will be fix in PR 3602 + mpExchangeCtx = mpExchangeMgr->NewContext({ aNodeId, Transport::kAnyKeyId }, this); + VerifyOrExit(mpExchangeCtx != nullptr, err = CHIP_ERROR_NO_MEMORY); + mpExchangeCtx->SetResponseTimeout(CHIP_INVOKE_COMMAND_RSP_TIMEOUT); + + err = mpExchangeCtx->SendMessage(Protocols::kProtocol_InteractionModel, kMsgType_InvokeCommandRequest, + std::move(mCommandMessageBuf), + Messaging::SendFlags(Messaging::SendMessageFlags::kExpectResponse)); + SuccessOrExit(err); + MoveToState(kState_Sending); + +exit: + if (err != CHIP_NO_ERROR) + { + ClearExistingExchangeContext(); + } + ChipLogFunctError(err); + + return err; +} + +void CommandSender::OnMessageReceived(Messaging::ExchangeContext * apEc, const PacketHeader & aPacketHeader, uint32_t aProtocolId, + uint8_t aMsgType, System::PacketBufferHandle aPayload) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + // Assert that the exchange context matches the client's current context. + // This should never fail because even if SendCommandRequest is called + // back-to-back, the second call will call Close() on the first exchange, + // which clears the OnMessageReceived callback. + + VerifyOrDie(apEc == mpExchangeCtx); + + // Verify that the message is an Invoke Command Response. + // If not, close the exchange and free the payload. + if (aProtocolId != Protocols::kProtocol_InteractionModel || aMsgType != kMsgType_InvokeCommandResponse) + { + apEc->Close(); + mpExchangeCtx = nullptr; + goto exit; + } + + // Remove the EC from the app state now. OnMessageReceived can call + // SendCommandRequest and install a new one. We abort rather than close + // because we no longer care whether the echo request message has been + // acknowledged at the transport layer. + ClearExistingExchangeContext(); + + err = ProcessCommandMessage(std::move(aPayload), kCommandSenderId); + SuccessOrExit(err); + +exit: + Reset(); + return; +} + +void CommandSender::OnResponseTimeout(Messaging::ExchangeContext * apEc) +{ + ChipLogProgress(DataManagement, "Time out! failed to receive invoke command response from Exchange: %d", apEc->GetExchangeId()); + Reset(); +} + +CHIP_ERROR CommandSender::ProcessCommandDataElement(CommandDataElement::Parser & aCommandElement) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + CommandPath::Parser commandPath; + chip::TLV::TLVReader commandDataReader; + chip::ClusterId clusterId; + chip::CommandId commandId; + uint16_t generalCode = 0; + uint32_t protocolId = 0; + uint16_t protocolCode = 0; + StatusElement::Parser statusElementParser; + + err = aCommandElement.GetStatusElement(&statusElementParser); + if (CHIP_NO_ERROR == err) + { + // Response has status element since either there is error in command response or it is empty response + err = statusElementParser.CheckSchemaValidity(); + SuccessOrExit(err); + + err = statusElementParser.DecodeStatusElement(&generalCode, &protocolId, &protocolCode, &clusterId); + SuccessOrExit(err); + } + else if (CHIP_END_OF_TLV == err) + { + err = aCommandElement.GetCommandPath(&commandPath); + SuccessOrExit(err); + + err = commandPath.GetNamespacedClusterId(&clusterId); + SuccessOrExit(err); + + err = commandPath.GetCommandId(&commandId); + SuccessOrExit(err); + + err = aCommandElement.GetData(&commandDataReader); + if (CHIP_END_OF_TLV == err) + { + err = CHIP_NO_ERROR; + ChipLogDetail(DataManagement, "Add Status code for empty command, cluster Id is %d", clusterId); + // Todo: Define protocol code for StatusCode + AddStatusCode(0, chip::Protocols::kProtocol_Protocol_Common, 0, clusterId); + } + InteractionModelEngine::GetInstance()->ProcessCommand(clusterId, commandId, commandDataReader, this, kCommandSenderId); + } + +exit: + return err; +} + +} // namespace app +} // namespace chip diff --git a/src/app/CommandSender.h b/src/app/CommandSender.h new file mode 100644 index 00000000000000..93d98cf5182b56 --- /dev/null +++ b/src/app/CommandSender.h @@ -0,0 +1,67 @@ +/* + * + * 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 + * This file defines objects for a CHIP IM Invoke Command Sender + * + */ + +#pragma once + +#ifndef _CHIP_INTERACTION_MODEL_COMMAND_SENDER_H +#define _CHIP_INTERACTION_MODEL_COMMAND_SENDER_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define CHIP_INVOKE_COMMAND_RSP_TIMEOUT 5 +#define COMMON_STATUS_SUCCESS 0 + +namespace chip { +namespace app { + +class DLL_EXPORT DLL_EXPORT CommandSender : public Command, public Messaging::ExchangeDelegate +{ +public: + CHIP_ERROR SendCommandRequest(NodeId aNodeId); + + void OnMessageReceived(Messaging::ExchangeContext * apEc, const PacketHeader & aPacketHeader, uint32_t aProtocolId, + uint8_t aMsgType, System::PacketBufferHandle aPayload) override; + void OnResponseTimeout(Messaging::ExchangeContext * apEc) override; + +private: + CHIP_ERROR ProcessCommandDataElement(CommandDataElement::Parser & aCommandElement) override; +}; + +} // namespace app +} // namespace chip + +#endif // _CHIP_INTERACTION_MODEL_COMMAND_SENDER_H diff --git a/src/app/InteractionModelEngine.cpp b/src/app/InteractionModelEngine.cpp new file mode 100644 index 00000000000000..090d8df19345a9 --- /dev/null +++ b/src/app/InteractionModelEngine.cpp @@ -0,0 +1,275 @@ +/* + * + * 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 + * This file defines objects for a CHIP Interaction Data model Engine which handle unsolicitied IM message, and + * manage different kinds of IM client and handlers. + * + */ + +#include "InteractionModelEngine.h" +#include "Command.h" +#include "CommandHandler.h" +#include "CommandSender.h" + +namespace chip { +namespace app { +InteractionModelEngine sInteractionModelEngine; + +InteractionModelEngine::InteractionModelEngine() {} + +InteractionModelEngine * InteractionModelEngine::GetInstance() +{ + return &sInteractionModelEngine; +} + +void InteractionModelEngine::SetEventCallback(void * apAppState, EventCallback aEventCallback) +{ + mpAppState = apAppState; + mEventCallback = aEventCallback; +} + +void InteractionModelEngine::DefaultEventHandler(EventID aEvent, const InEventParam & aInParam, OutEventParam & aOutParam) +{ + IgnoreUnusedVariable(aInParam); + IgnoreUnusedVariable(aOutParam); + + ChipLogDetail(DataManagement, "%s event: %d", __func__, aEvent); +} + +CHIP_ERROR InteractionModelEngine::Init(Messaging::ExchangeManager * apExchangeMgr) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + + // Error if already initialized. + if (mpExchangeMgr != nullptr) + return CHIP_ERROR_INCORRECT_STATE; + + mpExchangeMgr = apExchangeMgr; + + err = mpExchangeMgr->RegisterUnsolicitedMessageHandler(Protocols::kProtocol_InteractionModel, this); + SuccessOrExit(err); + +exit: + return err; +} + +void InteractionModelEngine::Shutdown() +{ + for (size_t i = 0; i < CHIP_MAX_NUM_COMMAND_HANDLER_OBJECTS; ++i) + { + mCommandHandlerObjs[i].Shutdown(); + } + mHandlersMap.clear(); +} + +CHIP_ERROR InteractionModelEngine::NewCommandSender(CommandSender ** const apComandSender) +{ + CHIP_ERROR err = CHIP_ERROR_NO_MEMORY; + *apComandSender = nullptr; + + for (size_t i = 0; i < CHIP_MAX_NUM_COMMAND_SENDER_OBJECTS; ++i) + { + if (mCommandHandlerObjs[i].IsFree()) + { + *apComandSender = &mCommandSenderObjs[i]; + err = mCommandSenderObjs[i].Init(mpExchangeMgr); + SuccessOrExit(err); + if (CHIP_NO_ERROR != err) + { + *apComandSender = nullptr; + ExitNow(); + } + break; + } + } + +exit: + return err; +} + +void InteractionModelEngine::OnUnknownMsgType(Messaging::ExchangeContext * apEc, const PacketHeader & aPacketHeader, + uint32_t aProtocolId, uint8_t aMsgType, System::PacketBufferHandle aPayload) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + + ChipLogDetail(DataManagement, "Msg type %d not supported", (int) aMsgType); + + // Todo: Add status report + // err = SendStatusReport(ec, kChipProfile_Common, kStatus_UnsupportedMessage); + // SuccessOrExit(err); + + apEc->Close(); + apEc = NULL; + + ChipLogFunctError(err); + + if (NULL != apEc) + { + apEc->Abort(); + apEc = NULL; + } +} + +void InteractionModelEngine::OnInvokeCommandRequest(Messaging::ExchangeContext * apEc, const PacketHeader & aPacketHeader, + uint32_t aProtocolId, uint8_t aMsgType, System::PacketBufferHandle aPayload) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + CommandHandler * commandServer = nullptr; + + if (nullptr != mEventCallback) + { + InEventParam inParam; + OutEventParam outParam; + inParam.Clear(); + outParam.Clear(); + outParam.mIncomingInvokeCommandRequest.mShouldContinueProcessing = true; + inParam.mIncomingInvokeCommandRequest.mpPacketHeader = &aPacketHeader; + + mEventCallback(mpAppState, kEvent_OnIncomingInvokeCommandRequest, inParam, outParam); + + if (!outParam.mIncomingInvokeCommandRequest.mShouldContinueProcessing) + { + ChipLogDetail(DataManagement, "Command not allowed"); + ExitNow(); + } + } + + for (size_t i = 0; i < CHIP_MAX_NUM_COMMAND_HANDLER_OBJECTS; ++i) + { + if (mCommandHandlerObjs[i].IsFree()) + { + commandServer = &mCommandHandlerObjs[i]; + err = commandServer->Init(mpExchangeMgr); + SuccessOrExit(err); + commandServer->OnMessageReceived(apEc, aPacketHeader, aProtocolId, aMsgType, std::move(aPayload)); + apEc = nullptr; + break; + } + } + +exit: + ChipLogFunctError(err); + + if (nullptr != apEc) + { + apEc->Abort(); + apEc = NULL; + } +} + +void InteractionModelEngine::OnMessageReceived(Messaging::ExchangeContext * apEc, const PacketHeader & aPacketHeader, + uint32_t aProtocolId, uint8_t aMsgType, System::PacketBufferHandle aPayload) +{ + switch (aMsgType) + { + case kMsgType_InvokeCommandRequest: + OnInvokeCommandRequest(apEc, aPacketHeader, aProtocolId, aMsgType, std::move(aPayload)); + break; + default: + OnUnknownMsgType(apEc, aPacketHeader, aProtocolId, aMsgType, std::move(aPayload)); + break; + } +} + +void InteractionModelEngine::OnResponseTimeout(Messaging::ExchangeContext * ec) +{ + ChipLogProgress(DataManagement, "Time out! failed to receive echo response from Exchange: %d", ec->GetExchangeId()); +} + +InteractionModelEngine::HandlerKey::HandlerKey(chip::ClusterId aClusterId, chip::CommandId aCommandId, + Command::CommandRoleId aCommandRoleId) : + mClusterId(aClusterId), + mCommandId(aCommandId), mCommandRoleId(aCommandRoleId) +{} + +inline bool InteractionModelEngine::HandlerKey::operator<(const HandlerKey & aOtherKey) const +{ + return ((mClusterId != aOtherKey.mClusterId) + ? (mClusterId < aOtherKey.mClusterId) + : ((mCommandId != aOtherKey.mCommandId) ? (mCommandId < aOtherKey.mCommandId) + : ((mCommandRoleId < aOtherKey.mCommandRoleId)))); +} + +CHIP_ERROR InteractionModelEngine::RegisterClusterCommandHandler(chip::ClusterId aClusterId, chip::CommandId aCommandId, + Command::CommandRoleId aCommandRoleId, CommandCbFunct aDispatcher) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + + std::pair insertResult = + mHandlersMap.insert(HandlersMapType::value_type(HandlerKey(aClusterId, aCommandId, aCommandRoleId), aDispatcher)); + + if (!insertResult.second) + { + err = CHIP_ERROR_INVALID_ARGUMENT; + } + else + { + ChipLogDetail(DataManagement, + "RegisterClusterCommandHandler registered handler for ClusterId = %d, CommandId = %d, CommandRoleId = " + "%d, Dispatcher = %p", + aClusterId, aCommandId, aCommandRoleId, (void *) aDispatcher); + } + + return err; +} + +CHIP_ERROR InteractionModelEngine::DeregisterClusterCommandHandler(chip::ClusterId aClusterId, chip::CommandId aCommandId, + Command::CommandRoleId aCommandRoleId) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + + HandlersMapType::iterator handlerIt = mHandlersMap.find(HandlerKey(aClusterId, aCommandId, aCommandRoleId)); + if (handlerIt != mHandlersMap.end()) + { + CommandCbFunct pDispatcher = handlerIt->second; + + ChipLogDetail(DataManagement, + "DeregisterClusterCommandHandler unregistered handler for ClusterId = %d, CommandId = %d, CommandRoleId " + "= %d, Dispatcher = %p", + aClusterId, aCommandId, aCommandRoleId, (void *) pDispatcher); + mHandlersMap.erase(handlerIt); + } + else + { + err = CHIP_ERROR_INVALID_ARGUMENT; + } + + return err; +} + +void InteractionModelEngine::ProcessCommand(chip::ClusterId aClusterId, chip::CommandId aCommandId, chip::TLV::TLVReader & aReader, + Command * apCommandObj, Command::CommandRoleId aCommandRoleId) +{ + HandlersMapType::iterator handlerIt; + + handlerIt = mHandlersMap.find(HandlerKey(aClusterId, aCommandId, aCommandRoleId)); + + ChipLogDetail(DataManagement, "ClusterId = %d, CommandId = %d, CommandRoleId = %d", (int) (aClusterId), (int) (aCommandId), + aCommandRoleId); + + if (handlerIt != mHandlersMap.end()) + { + handlerIt->second(aReader, apCommandObj); + } + + return; +} +} // namespace app +} // namespace chip diff --git a/src/app/InteractionModelEngine.h b/src/app/InteractionModelEngine.h new file mode 100644 index 00000000000000..533ec3c6c621b7 --- /dev/null +++ b/src/app/InteractionModelEngine.h @@ -0,0 +1,183 @@ +/* + * + * 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 + * This file defines objects for a CHIP Interaction Data model Engine which handle unsolicitied IM message, and + * manage different kinds of IM client and handlers. + * + */ + +#pragma once + +#ifndef _CHIP_INTERACTION_MODEL_ENGINE_H +#define _CHIP_INTERACTION_MODEL_ENGINE_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#define CHIP_MAX_NUM_COMMAND_HANDLER_OBJECTS 1 +#define CHIP_MAX_NUM_COMMAND_SENDER_OBJECTS 1 + +namespace chip { +namespace app { + +typedef void (*CommandCbFunct)(chip::TLV::TLVReader & aReader, Command * apCommandObj); + +/** + * @class InteractionModelEngine + * + * @brief This is a singleton hosting all CHIP unsolicited message processing and managing interaction model related clients and + * handlers + * + */ +class InteractionModelEngine : public Messaging::ExchangeDelegate +{ +public: + enum EventID + { + kEvent_OnIncomingInvokeCommandRequest = + 0, ///< Called when an incoming invoke command request has arrived before applying commands.. + }; + + /** + * Incoming parameters sent with events generated directly from this component + * + */ + union InEventParam + { + void Clear(void) { memset(this, 0, sizeof(*this)); } + struct + { + const PacketHeader * mpPacketHeader; ///< A pointer to the message information for the request + } mIncomingInvokeCommandRequest; + }; + + /** + * Outgoing parameters sent with events generated directly from this component + * + */ + union OutEventParam + { + void Clear(void) { memset(this, 0, sizeof(*this)); } + + struct + { + bool mShouldContinueProcessing; ///< Set to true if update is allowed. + } mIncomingInvokeCommandRequest; + }; + + /** + * @brief Set the event back function and pointer to associated state object for SubscriptionEngine specific call backs + * + * @param[in] apAppState A pointer to application layer supplied state object + * @param[in] aEvent A function pointer for event call back + * @param[in] aInParam A const reference to the input parameter for this event + * @param[out] aOutParam A reference to the output parameter for this event + */ + typedef void (*EventCallback)(void * apAppState, EventID aEvent, const InEventParam & aInParam, OutEventParam & aOutParam); + + /** + * @brief Set the event back function and pointer to associated state object for SubscriptionEngine specific call backs + * + * @param[in] apAppState A pointer to application layer supplied state object + * @param[in] aEventCallback A function pointer for event call back + */ + void SetEventCallback(void * apAppState, EventCallback aEventCallback); + + /** + * @brief This is the default event handler to be called by application layer for any ignored or unrecognized event + * + * @param[in] aEvent A function pointer for event call back + * @param[in] aInParam A const reference to the input parameter for this event + * @param[out] aOutParam A reference to the output parameter for this event + */ + static void DefaultEventHandler(EventID aEvent, const InEventParam & aInParam, OutEventParam & aOutParam); + + /** + * @brief Retrieve the singleton DataManagement Engine. Note this function should be implemented by the + * adoption layer. + * + * @return A pointer to the shared InteractionModel Engine + * + */ + static InteractionModelEngine * GetInstance(void); + + InteractionModelEngine(void); + + CHIP_ERROR Init(Messaging::ExchangeManager * apExchangeMgr); + + void Shutdown(); + + CHIP_ERROR DeregisterClusterCommandHandler(chip::ClusterId aClusterId, chip::CommandId aCommandId, + Command::CommandRoleId aCommandRoleId); + CHIP_ERROR RegisterClusterCommandHandler(chip::ClusterId aClusterId, chip::CommandId aCommandId, + Command::CommandRoleId aCommandRoleId, CommandCbFunct aDispatcher); + void ProcessCommand(chip::ClusterId aClusterId, chip::CommandId aCommandId, chip::TLV::TLVReader & aReader, + Command * apCommandObj, Command::CommandRoleId aCommandRoleId); + + Messaging::ExchangeManager * GetExchangeManager(void) const { return mpExchangeMgr; }; + + CHIP_ERROR NewCommandSender(CommandSender ** const apComandSender); + +private: + void OnUnknownMsgType(Messaging::ExchangeContext * apEc, const PacketHeader & aPacketHeader, uint32_t aProtocolId, + uint8_t aMsgType, System::PacketBufferHandle aPayload); + void OnInvokeCommandRequest(Messaging::ExchangeContext * apEc, const PacketHeader & aPacketHeader, uint32_t aProtocolId, + uint8_t aMsgType, System::PacketBufferHandle aPayload); + void OnMessageReceived(Messaging::ExchangeContext * apEc, const PacketHeader & aPacketHeader, uint32_t aProtocolId, + uint8_t aMsgType, System::PacketBufferHandle aPayload); + void OnResponseTimeout(Messaging::ExchangeContext * ec); + + struct HandlerKey + { + HandlerKey(chip::ClusterId aClusterId, chip::CommandId aCommandId, Command::CommandRoleId aCommandRoleId); + + chip::ClusterId mClusterId; + chip::CommandId mCommandId; + Command::CommandRoleId mCommandRoleId; + bool operator<(const HandlerKey & aOtherKey) const; + }; + + typedef std::map HandlersMapType; + + HandlersMapType mHandlersMap; + Messaging::ExchangeManager * mpExchangeMgr = nullptr; + void * mpAppState = nullptr; + EventCallback mEventCallback; + CommandHandler mCommandHandlerObjs[CHIP_MAX_NUM_COMMAND_HANDLER_OBJECTS]; + CommandSender mCommandSenderObjs[CHIP_MAX_NUM_COMMAND_SENDER_OBJECTS]; +}; + +} // namespace app +} // namespace chip + +#endif //_CHIP_INTERACTION_MODEL_ENGINE_H diff --git a/src/app/MessageDef.cpp b/src/app/MessageDef.cpp index 7c5f7cd544875c..4cc6c1fbe3f21d 100644 --- a/src/app/MessageDef.cpp +++ b/src/app/MessageDef.cpp @@ -142,6 +142,7 @@ static void PrettyPrintIM(bool aIsNewLine, const char * aFmt, ...) #define PRETTY_PRINT_CHECKPOINT() #define PRETTY_PRINT(fmt, ...) #define PRETTY_PRINT(fmt, ...) +#define PRETTY_PRINT_SAMELINE(fmt, ...) #define PRETTY_PRINT_INCDEPTH() #define PRETTY_PRINT_DECDEPTH() #endif // CHIP_DETAIL_LOGGING @@ -2898,15 +2899,19 @@ CHIP_ERROR CommandDataElement::Parser::CheckSchemaValidity() const // if we have exhausted this container if (CHIP_END_OF_TLV == err) { - // check for required fields: - const uint16_t RequiredFields = (1 << kCsTag_CommandPath); - if ((TagPresenceMask & RequiredFields) == RequiredFields) + // check for at most field: + const uint16_t CheckDataField = 1 << kCsTag_Data; + const uint16_t CheckStatusElementField = 1 << kCsTag_StatusElement; + + if ((TagPresenceMask & CheckDataField) == CheckDataField && + (TagPresenceMask & CheckStatusElementField) == CheckStatusElementField) { - err = CHIP_NO_ERROR; + // kCsTag_Data and kCsTag_StatusElement both exist + err = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; } else { - err = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; + err = CHIP_NO_ERROR; } } @@ -3495,6 +3500,11 @@ CommandList::Builder & InvokeCommand::Builder::CreateCommandListBuilder() return mCommandListBuilder; } +CommandList::Builder & InvokeCommand::Builder::GetCommandListBuilder() +{ + return mCommandListBuilder; +} + InvokeCommand::Builder & InvokeCommand::Builder::EndOfInvokeCommand() { EndOfContainer(); diff --git a/src/app/MessageDef.h b/src/app/MessageDef.h index 075692e7323859..568bfefb5be101 100644 --- a/src/app/MessageDef.h +++ b/src/app/MessageDef.h @@ -1842,10 +1842,17 @@ class Builder : public chip::app::Builder /** * @brief Initialize a CommandList::Builder for writing into the TLV stream * - * @return A reference to Path::Builder + * @return A reference to CommandList::Builder */ CommandList::Builder & CreateCommandListBuilder(); + /** + * @brief Get reference to CommandList::Builder + * + * @return A reference to CommandList::Builder + */ + CommandList::Builder & GetCommandListBuilder(); + /** * @brief Mark the end of this InvokeCommand * diff --git a/src/app/README.md b/src/app/README.md index ed31c46346887c..2c3dbfaafc9733 100644 --- a/src/app/README.md +++ b/src/app/README.md @@ -4,4 +4,4 @@ The purpose of this folder is to contain CHIP clusters and associated utilities. The cluster implementations live under the clusters/ directory. Utility files -live in the util/. +live in the util/. Server files live in the server/. diff --git a/src/app/chip-zcl-zpro-codec-api.h b/src/app/chip-zcl-zpro-codec-api.h index d7e3bbd2591c51..d935cb0440418d 100644 --- a/src/app/chip-zcl-zpro-codec-api.h +++ b/src/app/chip-zcl-zpro-codec-api.h @@ -1,4 +1,3 @@ - /* * * Copyright (c) 2020 Project CHIP Authors @@ -21,10 +20,7 @@ #include #include - -#ifdef __cplusplus -extern "C" { -#endif +#include /*----------------------------------------------------------------------------*\ | Cluster Name | ID | @@ -61,62 +57,56 @@ extern "C" { * @brief * Encode an BarrierControlGoToPercent command for Barrier Control server into buffer including the APS frame */ -uint16_t encodeBarrierControlClusterBarrierControlGoToPercentCommand(uint8_t * buffer, uint16_t buf_length, - chip::EndpointId destination_endpoint, uint8_t percentOpen); +chip::System::PacketBufferHandle encodeBarrierControlClusterBarrierControlGoToPercentCommand(chip::EndpointId destinationEndpoint, + uint8_t percentOpen); /** * @brief * Encode an BarrierControlStop command for Barrier Control server into buffer including the APS frame */ -uint16_t encodeBarrierControlClusterBarrierControlStopCommand(uint8_t * buffer, uint16_t buf_length, - chip::EndpointId destination_endpoint); +chip::System::PacketBufferHandle encodeBarrierControlClusterBarrierControlStopCommand(chip::EndpointId destinationEndpoint); /** * @brief * Encode a Barrier Control server discover command into buffer including the APS frame */ -uint16_t encodeBarrierControlClusterDiscoverAttributes(uint8_t * buffer, uint16_t buf_length, - chip::EndpointId destination_endpoint); +chip::System::PacketBufferHandle encodeBarrierControlClusterDiscoverAttributes(chip::EndpointId destinationEndpoint); /** * @brief * Encode a Barrier Control server read command for the barrier moving state attribute into buffer including the APS frame */ -uint16_t encodeBarrierControlClusterReadBarrierMovingStateAttribute(uint8_t * buffer, uint16_t buf_length, - chip::EndpointId destination_endpoint); +chip::System::PacketBufferHandle encodeBarrierControlClusterReadBarrierMovingStateAttribute(chip::EndpointId destinationEndpoint); /** * @brief * Encode a Barrier Control server read command for the barrier safety status attribute into buffer including the APS frame */ -uint16_t encodeBarrierControlClusterReadBarrierSafetyStatusAttribute(uint8_t * buffer, uint16_t buf_length, - chip::EndpointId destination_endpoint); +chip::System::PacketBufferHandle encodeBarrierControlClusterReadBarrierSafetyStatusAttribute(chip::EndpointId destinationEndpoint); /** * @brief * Encode a Barrier Control server read command for the barrier capabilities attribute into buffer including the APS frame */ -uint16_t encodeBarrierControlClusterReadBarrierCapabilitiesAttribute(uint8_t * buffer, uint16_t buf_length, - chip::EndpointId destination_endpoint); +chip::System::PacketBufferHandle encodeBarrierControlClusterReadBarrierCapabilitiesAttribute(chip::EndpointId destinationEndpoint); /** * @brief * Encode a Barrier Control server read command for the barrier position attribute into buffer including the APS frame */ -uint16_t encodeBarrierControlClusterReadBarrierPositionAttribute(uint8_t * buffer, uint16_t buf_length, - chip::EndpointId destination_endpoint); +chip::System::PacketBufferHandle encodeBarrierControlClusterReadBarrierPositionAttribute(chip::EndpointId destinationEndpoint); /** * @brief * Encode a Barrier Control server read command for the cluster revision attribute into buffer including the APS frame */ -uint16_t encodeBarrierControlClusterReadClusterRevisionAttribute(uint8_t * buffer, uint16_t buf_length, - chip::EndpointId destination_endpoint); +chip::System::PacketBufferHandle encodeBarrierControlClusterReadClusterRevisionAttribute(chip::EndpointId destinationEndpoint); /*----------------------------------------------------------------------------*\ | Cluster Basic | 0x0000 | |------------------------------------------------------------------------------| | Commands: | | +| * MfgSpecificPing | 0x00 | | * ResetToFactoryDefaults | 0x00 | |------------------------------------------------------------------------------| | Attributes: | | @@ -125,37 +115,41 @@ uint16_t encodeBarrierControlClusterReadClusterRevisionAttribute(uint8_t * buffe | * ClusterRevision | 0xFFFD | \*----------------------------------------------------------------------------*/ +/** + * @brief + * Encode an MfgSpecificPing command for Basic server into buffer including the APS frame + */ +chip::System::PacketBufferHandle encodeBasicClusterMfgSpecificPingCommand(chip::EndpointId destinationEndpoint); + /** * @brief * Encode an ResetToFactoryDefaults command for Basic server into buffer including the APS frame */ -uint16_t encodeBasicClusterResetToFactoryDefaultsCommand(uint8_t * buffer, uint16_t buf_length, - chip::EndpointId destination_endpoint); +chip::System::PacketBufferHandle encodeBasicClusterResetToFactoryDefaultsCommand(chip::EndpointId destinationEndpoint); /** * @brief * Encode a Basic server discover command into buffer including the APS frame */ -uint16_t encodeBasicClusterDiscoverAttributes(uint8_t * buffer, uint16_t buf_length, chip::EndpointId destination_endpoint); +chip::System::PacketBufferHandle encodeBasicClusterDiscoverAttributes(chip::EndpointId destinationEndpoint); /** * @brief * Encode a Basic server read command for the ZCL version attribute into buffer including the APS frame */ -uint16_t encodeBasicClusterReadZclVersionAttribute(uint8_t * buffer, uint16_t buf_length, chip::EndpointId destination_endpoint); +chip::System::PacketBufferHandle encodeBasicClusterReadZclVersionAttribute(chip::EndpointId destinationEndpoint); /** * @brief * Encode a Basic server read command for the power source attribute into buffer including the APS frame */ -uint16_t encodeBasicClusterReadPowerSourceAttribute(uint8_t * buffer, uint16_t buf_length, chip::EndpointId destination_endpoint); +chip::System::PacketBufferHandle encodeBasicClusterReadPowerSourceAttribute(chip::EndpointId destinationEndpoint); /** * @brief * Encode a Basic server read command for the cluster revision attribute into buffer including the APS frame */ -uint16_t encodeBasicClusterReadClusterRevisionAttribute(uint8_t * buffer, uint16_t buf_length, - chip::EndpointId destination_endpoint); +chip::System::PacketBufferHandle encodeBasicClusterReadClusterRevisionAttribute(chip::EndpointId destinationEndpoint); /*----------------------------------------------------------------------------*\ | Cluster ColorControl | 0x0300 | @@ -234,618 +228,564 @@ uint16_t encodeBasicClusterReadClusterRevisionAttribute(uint8_t * buffer, uint16 * @brief * Encode an MoveColor command for Color Control server into buffer including the APS frame */ -uint16_t encodeColorControlClusterMoveColorCommand(uint8_t * buffer, uint16_t buf_length, chip::EndpointId destination_endpoint, - int16_t rateX, int16_t rateY, uint8_t optionsMask, uint8_t optionsOverride); +chip::System::PacketBufferHandle encodeColorControlClusterMoveColorCommand(chip::EndpointId destinationEndpoint, int16_t rateX, + int16_t rateY, uint8_t optionsMask, + uint8_t optionsOverride); /** * @brief * Encode an MoveColorTemperature command for Color Control server into buffer including the APS frame */ -uint16_t encodeColorControlClusterMoveColorTemperatureCommand(uint8_t * buffer, uint16_t buf_length, - chip::EndpointId destination_endpoint, uint8_t moveMode, - uint16_t rate, uint16_t colorTemperatureMinimum, - uint16_t colorTemperatureMaximum, uint8_t optionsMask, - uint8_t optionsOverride); +chip::System::PacketBufferHandle encodeColorControlClusterMoveColorTemperatureCommand(chip::EndpointId destinationEndpoint, + uint8_t moveMode, uint16_t rate, + uint16_t colorTemperatureMinimum, + uint16_t colorTemperatureMaximum, + uint8_t optionsMask, uint8_t optionsOverride); /** * @brief * Encode an MoveHue command for Color Control server into buffer including the APS frame */ -uint16_t encodeColorControlClusterMoveHueCommand(uint8_t * buffer, uint16_t buf_length, chip::EndpointId destination_endpoint, - uint8_t moveMode, uint8_t rate, uint8_t optionsMask, uint8_t optionsOverride); +chip::System::PacketBufferHandle encodeColorControlClusterMoveHueCommand(chip::EndpointId destinationEndpoint, uint8_t moveMode, + uint8_t rate, uint8_t optionsMask, + uint8_t optionsOverride); /** * @brief * Encode an MoveSaturation command for Color Control server into buffer including the APS frame */ -uint16_t encodeColorControlClusterMoveSaturationCommand(uint8_t * buffer, uint16_t buf_length, - chip::EndpointId destination_endpoint, uint8_t moveMode, uint8_t rate, - uint8_t optionsMask, uint8_t optionsOverride); +chip::System::PacketBufferHandle encodeColorControlClusterMoveSaturationCommand(chip::EndpointId destinationEndpoint, + uint8_t moveMode, uint8_t rate, uint8_t optionsMask, + uint8_t optionsOverride); /** * @brief * Encode an MoveToColor command for Color Control server into buffer including the APS frame */ -uint16_t encodeColorControlClusterMoveToColorCommand(uint8_t * buffer, uint16_t buf_length, chip::EndpointId destination_endpoint, - uint16_t colorX, uint16_t colorY, uint16_t transitionTime, uint8_t optionsMask, - uint8_t optionsOverride); +chip::System::PacketBufferHandle encodeColorControlClusterMoveToColorCommand(chip::EndpointId destinationEndpoint, uint16_t colorX, + uint16_t colorY, uint16_t transitionTime, + uint8_t optionsMask, uint8_t optionsOverride); /** * @brief * Encode an MoveToColorTemperature command for Color Control server into buffer including the APS frame */ -uint16_t encodeColorControlClusterMoveToColorTemperatureCommand(uint8_t * buffer, uint16_t buf_length, - chip::EndpointId destination_endpoint, uint16_t colorTemperature, - uint16_t transitionTime, uint8_t optionsMask, - uint8_t optionsOverride); +chip::System::PacketBufferHandle +encodeColorControlClusterMoveToColorTemperatureCommand(chip::EndpointId destinationEndpoint, uint16_t colorTemperature, + uint16_t transitionTime, uint8_t optionsMask, uint8_t optionsOverride); /** * @brief * Encode an MoveToHue command for Color Control server into buffer including the APS frame */ -uint16_t encodeColorControlClusterMoveToHueCommand(uint8_t * buffer, uint16_t buf_length, chip::EndpointId destination_endpoint, - uint8_t hue, uint8_t direction, uint16_t transitionTime, uint8_t optionsMask, - uint8_t optionsOverride); +chip::System::PacketBufferHandle encodeColorControlClusterMoveToHueCommand(chip::EndpointId destinationEndpoint, uint8_t hue, + uint8_t direction, uint16_t transitionTime, + uint8_t optionsMask, uint8_t optionsOverride); /** * @brief * Encode an MoveToHueAndSaturation command for Color Control server into buffer including the APS frame */ -uint16_t encodeColorControlClusterMoveToHueAndSaturationCommand(uint8_t * buffer, uint16_t buf_length, - chip::EndpointId destination_endpoint, uint8_t hue, - uint8_t saturation, uint16_t transitionTime, uint8_t optionsMask, - uint8_t optionsOverride); +chip::System::PacketBufferHandle +encodeColorControlClusterMoveToHueAndSaturationCommand(chip::EndpointId destinationEndpoint, uint8_t hue, uint8_t saturation, + uint16_t transitionTime, uint8_t optionsMask, uint8_t optionsOverride); /** * @brief * Encode an MoveToSaturation command for Color Control server into buffer including the APS frame */ -uint16_t encodeColorControlClusterMoveToSaturationCommand(uint8_t * buffer, uint16_t buf_length, - chip::EndpointId destination_endpoint, uint8_t saturation, - uint16_t transitionTime, uint8_t optionsMask, uint8_t optionsOverride); +chip::System::PacketBufferHandle encodeColorControlClusterMoveToSaturationCommand(chip::EndpointId destinationEndpoint, + uint8_t saturation, uint16_t transitionTime, + uint8_t optionsMask, uint8_t optionsOverride); /** * @brief * Encode an StepColor command for Color Control server into buffer including the APS frame */ -uint16_t encodeColorControlClusterStepColorCommand(uint8_t * buffer, uint16_t buf_length, chip::EndpointId destination_endpoint, - int16_t stepX, int16_t stepY, uint16_t transitionTime, uint8_t optionsMask, - uint8_t optionsOverride); +chip::System::PacketBufferHandle encodeColorControlClusterStepColorCommand(chip::EndpointId destinationEndpoint, int16_t stepX, + int16_t stepY, uint16_t transitionTime, + uint8_t optionsMask, uint8_t optionsOverride); /** * @brief * Encode an StepColorTemperature command for Color Control server into buffer including the APS frame */ -uint16_t encodeColorControlClusterStepColorTemperatureCommand(uint8_t * buffer, uint16_t buf_length, - chip::EndpointId destination_endpoint, uint8_t stepMode, - uint16_t stepSize, uint16_t transitionTime, - uint16_t colorTemperatureMinimum, uint16_t colorTemperatureMaximum, - uint8_t optionsMask, uint8_t optionsOverride); +chip::System::PacketBufferHandle encodeColorControlClusterStepColorTemperatureCommand( + chip::EndpointId destinationEndpoint, uint8_t stepMode, uint16_t stepSize, uint16_t transitionTime, + uint16_t colorTemperatureMinimum, uint16_t colorTemperatureMaximum, uint8_t optionsMask, uint8_t optionsOverride); /** * @brief * Encode an StepHue command for Color Control server into buffer including the APS frame */ -uint16_t encodeColorControlClusterStepHueCommand(uint8_t * buffer, uint16_t buf_length, chip::EndpointId destination_endpoint, - uint8_t stepMode, uint8_t stepSize, uint8_t transitionTime, uint8_t optionsMask, - uint8_t optionsOverride); +chip::System::PacketBufferHandle encodeColorControlClusterStepHueCommand(chip::EndpointId destinationEndpoint, uint8_t stepMode, + uint8_t stepSize, uint8_t transitionTime, + uint8_t optionsMask, uint8_t optionsOverride); /** * @brief * Encode an StepSaturation command for Color Control server into buffer including the APS frame */ -uint16_t encodeColorControlClusterStepSaturationCommand(uint8_t * buffer, uint16_t buf_length, - chip::EndpointId destination_endpoint, uint8_t stepMode, uint8_t stepSize, - uint8_t transitionTime, uint8_t optionsMask, uint8_t optionsOverride); +chip::System::PacketBufferHandle encodeColorControlClusterStepSaturationCommand(chip::EndpointId destinationEndpoint, + uint8_t stepMode, uint8_t stepSize, + uint8_t transitionTime, uint8_t optionsMask, + uint8_t optionsOverride); /** * @brief * Encode an StopMoveStep command for Color Control server into buffer including the APS frame */ -uint16_t encodeColorControlClusterStopMoveStepCommand(uint8_t * buffer, uint16_t buf_length, chip::EndpointId destination_endpoint, - uint8_t optionsMask, uint8_t optionsOverride); +chip::System::PacketBufferHandle encodeColorControlClusterStopMoveStepCommand(chip::EndpointId destinationEndpoint, + uint8_t optionsMask, uint8_t optionsOverride); /** * @brief * Encode a Color Control server discover command into buffer including the APS frame */ -uint16_t encodeColorControlClusterDiscoverAttributes(uint8_t * buffer, uint16_t buf_length, chip::EndpointId destination_endpoint); +chip::System::PacketBufferHandle encodeColorControlClusterDiscoverAttributes(chip::EndpointId destinationEndpoint); /** * @brief * Encode a Color Control server read command for the current hue attribute into buffer including the APS frame */ -uint16_t encodeColorControlClusterReadCurrentHueAttribute(uint8_t * buffer, uint16_t buf_length, - chip::EndpointId destination_endpoint); +chip::System::PacketBufferHandle encodeColorControlClusterReadCurrentHueAttribute(chip::EndpointId destinationEndpoint); /** * @brief * Encode a Color Control server report command for the current hue attribute into buffer including the APS frame */ -uint16_t encodeColorControlClusterReportCurrentHueAttribute(uint8_t * buffer, uint16_t buf_length, - chip::EndpointId destination_endpoint, uint16_t min_interval, - uint16_t max_interval, uint8_t change); +chip::System::PacketBufferHandle encodeColorControlClusterReportCurrentHueAttribute(chip::EndpointId destinationEndpoint, + uint16_t minInterval, uint16_t maxInterval, + uint8_t change); /** * @brief * Encode a Color Control server read command for the current saturation attribute into buffer including the APS frame */ -uint16_t encodeColorControlClusterReadCurrentSaturationAttribute(uint8_t * buffer, uint16_t buf_length, - chip::EndpointId destination_endpoint); +chip::System::PacketBufferHandle encodeColorControlClusterReadCurrentSaturationAttribute(chip::EndpointId destinationEndpoint); /** * @brief * Encode a Color Control server report command for the current saturation attribute into buffer including the APS frame */ -uint16_t encodeColorControlClusterReportCurrentSaturationAttribute(uint8_t * buffer, uint16_t buf_length, - chip::EndpointId destination_endpoint, uint16_t min_interval, - uint16_t max_interval, uint8_t change); +chip::System::PacketBufferHandle encodeColorControlClusterReportCurrentSaturationAttribute(chip::EndpointId destinationEndpoint, + uint16_t minInterval, + uint16_t maxInterval, uint8_t change); /** * @brief * Encode a Color Control server read command for the remaining time attribute into buffer including the APS frame */ -uint16_t encodeColorControlClusterReadRemainingTimeAttribute(uint8_t * buffer, uint16_t buf_length, - chip::EndpointId destination_endpoint); +chip::System::PacketBufferHandle encodeColorControlClusterReadRemainingTimeAttribute(chip::EndpointId destinationEndpoint); /** * @brief * Encode a Color Control server read command for the current x attribute into buffer including the APS frame */ -uint16_t encodeColorControlClusterReadCurrentXAttribute(uint8_t * buffer, uint16_t buf_length, - chip::EndpointId destination_endpoint); +chip::System::PacketBufferHandle encodeColorControlClusterReadCurrentXAttribute(chip::EndpointId destinationEndpoint); /** * @brief * Encode a Color Control server report command for the current x attribute into buffer including the APS frame */ -uint16_t encodeColorControlClusterReportCurrentXAttribute(uint8_t * buffer, uint16_t buf_length, - chip::EndpointId destination_endpoint, uint16_t min_interval, - uint16_t max_interval, uint16_t change); +chip::System::PacketBufferHandle encodeColorControlClusterReportCurrentXAttribute(chip::EndpointId destinationEndpoint, + uint16_t minInterval, uint16_t maxInterval, + uint16_t change); /** * @brief * Encode a Color Control server read command for the current y attribute into buffer including the APS frame */ -uint16_t encodeColorControlClusterReadCurrentYAttribute(uint8_t * buffer, uint16_t buf_length, - chip::EndpointId destination_endpoint); +chip::System::PacketBufferHandle encodeColorControlClusterReadCurrentYAttribute(chip::EndpointId destinationEndpoint); /** * @brief * Encode a Color Control server report command for the current y attribute into buffer including the APS frame */ -uint16_t encodeColorControlClusterReportCurrentYAttribute(uint8_t * buffer, uint16_t buf_length, - chip::EndpointId destination_endpoint, uint16_t min_interval, - uint16_t max_interval, uint16_t change); +chip::System::PacketBufferHandle encodeColorControlClusterReportCurrentYAttribute(chip::EndpointId destinationEndpoint, + uint16_t minInterval, uint16_t maxInterval, + uint16_t change); /** * @brief * Encode a Color Control server read command for the drift compensation attribute into buffer including the APS frame */ -uint16_t encodeColorControlClusterReadDriftCompensationAttribute(uint8_t * buffer, uint16_t buf_length, - chip::EndpointId destination_endpoint); +chip::System::PacketBufferHandle encodeColorControlClusterReadDriftCompensationAttribute(chip::EndpointId destinationEndpoint); /** * @brief * Encode a Color Control server read command for the compensation text attribute into buffer including the APS frame */ -uint16_t encodeColorControlClusterReadCompensationTextAttribute(uint8_t * buffer, uint16_t buf_length, - chip::EndpointId destination_endpoint); +chip::System::PacketBufferHandle encodeColorControlClusterReadCompensationTextAttribute(chip::EndpointId destinationEndpoint); /** * @brief * Encode a Color Control server read command for the color temperature attribute into buffer including the APS frame */ -uint16_t encodeColorControlClusterReadColorTemperatureAttribute(uint8_t * buffer, uint16_t buf_length, - chip::EndpointId destination_endpoint); +chip::System::PacketBufferHandle encodeColorControlClusterReadColorTemperatureAttribute(chip::EndpointId destinationEndpoint); /** * @brief * Encode a Color Control server report command for the color temperature attribute into buffer including the APS frame */ -uint16_t encodeColorControlClusterReportColorTemperatureAttribute(uint8_t * buffer, uint16_t buf_length, - chip::EndpointId destination_endpoint, uint16_t min_interval, - uint16_t max_interval, uint16_t change); +chip::System::PacketBufferHandle encodeColorControlClusterReportColorTemperatureAttribute(chip::EndpointId destinationEndpoint, + uint16_t minInterval, + uint16_t maxInterval, uint16_t change); /** * @brief * Encode a Color Control server read command for the color mode attribute into buffer including the APS frame */ -uint16_t encodeColorControlClusterReadColorModeAttribute(uint8_t * buffer, uint16_t buf_length, - chip::EndpointId destination_endpoint); +chip::System::PacketBufferHandle encodeColorControlClusterReadColorModeAttribute(chip::EndpointId destinationEndpoint); /** * @brief * Encode a Color Control server read command for the color control options attribute into buffer including the APS frame */ -uint16_t encodeColorControlClusterReadColorControlOptionsAttribute(uint8_t * buffer, uint16_t buf_length, - chip::EndpointId destination_endpoint); +chip::System::PacketBufferHandle encodeColorControlClusterReadColorControlOptionsAttribute(chip::EndpointId destinationEndpoint); /** * @brief * Encode a Color Control server write command for the color control options attribute into buffer including the APS frame */ -uint16_t encodeColorControlClusterWriteColorControlOptionsAttribute(uint8_t * buffer, uint16_t buf_length, - chip::EndpointId destination_endpoint, - uint8_t colorControlOptions); +chip::System::PacketBufferHandle encodeColorControlClusterWriteColorControlOptionsAttribute(chip::EndpointId destinationEndpoint, + uint8_t colorControlOptions); /** * @brief * Encode a Color Control server read command for the number of primaries attribute into buffer including the APS frame */ -uint16_t encodeColorControlClusterReadNumberOfPrimariesAttribute(uint8_t * buffer, uint16_t buf_length, - chip::EndpointId destination_endpoint); +chip::System::PacketBufferHandle encodeColorControlClusterReadNumberOfPrimariesAttribute(chip::EndpointId destinationEndpoint); /** * @brief * Encode a Color Control server read command for the primary 1 x attribute into buffer including the APS frame */ -uint16_t encodeColorControlClusterReadPrimary1XAttribute(uint8_t * buffer, uint16_t buf_length, - chip::EndpointId destination_endpoint); +chip::System::PacketBufferHandle encodeColorControlClusterReadPrimary1XAttribute(chip::EndpointId destinationEndpoint); /** * @brief * Encode a Color Control server read command for the primary 1 y attribute into buffer including the APS frame */ -uint16_t encodeColorControlClusterReadPrimary1YAttribute(uint8_t * buffer, uint16_t buf_length, - chip::EndpointId destination_endpoint); +chip::System::PacketBufferHandle encodeColorControlClusterReadPrimary1YAttribute(chip::EndpointId destinationEndpoint); /** * @brief * Encode a Color Control server read command for the primary 1 intensity attribute into buffer including the APS frame */ -uint16_t encodeColorControlClusterReadPrimary1IntensityAttribute(uint8_t * buffer, uint16_t buf_length, - chip::EndpointId destination_endpoint); +chip::System::PacketBufferHandle encodeColorControlClusterReadPrimary1IntensityAttribute(chip::EndpointId destinationEndpoint); /** * @brief * Encode a Color Control server read command for the primary 2 x attribute into buffer including the APS frame */ -uint16_t encodeColorControlClusterReadPrimary2XAttribute(uint8_t * buffer, uint16_t buf_length, - chip::EndpointId destination_endpoint); +chip::System::PacketBufferHandle encodeColorControlClusterReadPrimary2XAttribute(chip::EndpointId destinationEndpoint); /** * @brief * Encode a Color Control server read command for the primary 2 y attribute into buffer including the APS frame */ -uint16_t encodeColorControlClusterReadPrimary2YAttribute(uint8_t * buffer, uint16_t buf_length, - chip::EndpointId destination_endpoint); +chip::System::PacketBufferHandle encodeColorControlClusterReadPrimary2YAttribute(chip::EndpointId destinationEndpoint); /** * @brief * Encode a Color Control server read command for the primary 2 intensity attribute into buffer including the APS frame */ -uint16_t encodeColorControlClusterReadPrimary2IntensityAttribute(uint8_t * buffer, uint16_t buf_length, - chip::EndpointId destination_endpoint); +chip::System::PacketBufferHandle encodeColorControlClusterReadPrimary2IntensityAttribute(chip::EndpointId destinationEndpoint); /** * @brief * Encode a Color Control server read command for the primary 3 x attribute into buffer including the APS frame */ -uint16_t encodeColorControlClusterReadPrimary3XAttribute(uint8_t * buffer, uint16_t buf_length, - chip::EndpointId destination_endpoint); +chip::System::PacketBufferHandle encodeColorControlClusterReadPrimary3XAttribute(chip::EndpointId destinationEndpoint); /** * @brief * Encode a Color Control server read command for the primary 3 y attribute into buffer including the APS frame */ -uint16_t encodeColorControlClusterReadPrimary3YAttribute(uint8_t * buffer, uint16_t buf_length, - chip::EndpointId destination_endpoint); +chip::System::PacketBufferHandle encodeColorControlClusterReadPrimary3YAttribute(chip::EndpointId destinationEndpoint); /** * @brief * Encode a Color Control server read command for the primary 3 intensity attribute into buffer including the APS frame */ -uint16_t encodeColorControlClusterReadPrimary3IntensityAttribute(uint8_t * buffer, uint16_t buf_length, - chip::EndpointId destination_endpoint); +chip::System::PacketBufferHandle encodeColorControlClusterReadPrimary3IntensityAttribute(chip::EndpointId destinationEndpoint); /** * @brief * Encode a Color Control server read command for the primary 4 x attribute into buffer including the APS frame */ -uint16_t encodeColorControlClusterReadPrimary4XAttribute(uint8_t * buffer, uint16_t buf_length, - chip::EndpointId destination_endpoint); +chip::System::PacketBufferHandle encodeColorControlClusterReadPrimary4XAttribute(chip::EndpointId destinationEndpoint); /** * @brief * Encode a Color Control server read command for the primary 4 y attribute into buffer including the APS frame */ -uint16_t encodeColorControlClusterReadPrimary4YAttribute(uint8_t * buffer, uint16_t buf_length, - chip::EndpointId destination_endpoint); +chip::System::PacketBufferHandle encodeColorControlClusterReadPrimary4YAttribute(chip::EndpointId destinationEndpoint); /** * @brief * Encode a Color Control server read command for the primary 4 intensity attribute into buffer including the APS frame */ -uint16_t encodeColorControlClusterReadPrimary4IntensityAttribute(uint8_t * buffer, uint16_t buf_length, - chip::EndpointId destination_endpoint); +chip::System::PacketBufferHandle encodeColorControlClusterReadPrimary4IntensityAttribute(chip::EndpointId destinationEndpoint); /** * @brief * Encode a Color Control server read command for the primary 5 x attribute into buffer including the APS frame */ -uint16_t encodeColorControlClusterReadPrimary5XAttribute(uint8_t * buffer, uint16_t buf_length, - chip::EndpointId destination_endpoint); +chip::System::PacketBufferHandle encodeColorControlClusterReadPrimary5XAttribute(chip::EndpointId destinationEndpoint); /** * @brief * Encode a Color Control server read command for the primary 5 y attribute into buffer including the APS frame */ -uint16_t encodeColorControlClusterReadPrimary5YAttribute(uint8_t * buffer, uint16_t buf_length, - chip::EndpointId destination_endpoint); +chip::System::PacketBufferHandle encodeColorControlClusterReadPrimary5YAttribute(chip::EndpointId destinationEndpoint); /** * @brief * Encode a Color Control server read command for the primary 5 intensity attribute into buffer including the APS frame */ -uint16_t encodeColorControlClusterReadPrimary5IntensityAttribute(uint8_t * buffer, uint16_t buf_length, - chip::EndpointId destination_endpoint); +chip::System::PacketBufferHandle encodeColorControlClusterReadPrimary5IntensityAttribute(chip::EndpointId destinationEndpoint); /** * @brief * Encode a Color Control server read command for the primary 6 x attribute into buffer including the APS frame */ -uint16_t encodeColorControlClusterReadPrimary6XAttribute(uint8_t * buffer, uint16_t buf_length, - chip::EndpointId destination_endpoint); +chip::System::PacketBufferHandle encodeColorControlClusterReadPrimary6XAttribute(chip::EndpointId destinationEndpoint); /** * @brief * Encode a Color Control server read command for the primary 6 y attribute into buffer including the APS frame */ -uint16_t encodeColorControlClusterReadPrimary6YAttribute(uint8_t * buffer, uint16_t buf_length, - chip::EndpointId destination_endpoint); +chip::System::PacketBufferHandle encodeColorControlClusterReadPrimary6YAttribute(chip::EndpointId destinationEndpoint); /** * @brief * Encode a Color Control server read command for the primary 6 intensity attribute into buffer including the APS frame */ -uint16_t encodeColorControlClusterReadPrimary6IntensityAttribute(uint8_t * buffer, uint16_t buf_length, - chip::EndpointId destination_endpoint); +chip::System::PacketBufferHandle encodeColorControlClusterReadPrimary6IntensityAttribute(chip::EndpointId destinationEndpoint); /** * @brief * Encode a Color Control server read command for the white point x attribute into buffer including the APS frame */ -uint16_t encodeColorControlClusterReadWhitePointXAttribute(uint8_t * buffer, uint16_t buf_length, - chip::EndpointId destination_endpoint); +chip::System::PacketBufferHandle encodeColorControlClusterReadWhitePointXAttribute(chip::EndpointId destinationEndpoint); /** * @brief * Encode a Color Control server write command for the white point x attribute into buffer including the APS frame */ -uint16_t encodeColorControlClusterWriteWhitePointXAttribute(uint8_t * buffer, uint16_t buf_length, - chip::EndpointId destination_endpoint, uint16_t whitePointX); +chip::System::PacketBufferHandle encodeColorControlClusterWriteWhitePointXAttribute(chip::EndpointId destinationEndpoint, + uint16_t whitePointX); /** * @brief * Encode a Color Control server read command for the white point y attribute into buffer including the APS frame */ -uint16_t encodeColorControlClusterReadWhitePointYAttribute(uint8_t * buffer, uint16_t buf_length, - chip::EndpointId destination_endpoint); +chip::System::PacketBufferHandle encodeColorControlClusterReadWhitePointYAttribute(chip::EndpointId destinationEndpoint); /** * @brief * Encode a Color Control server write command for the white point y attribute into buffer including the APS frame */ -uint16_t encodeColorControlClusterWriteWhitePointYAttribute(uint8_t * buffer, uint16_t buf_length, - chip::EndpointId destination_endpoint, uint16_t whitePointY); +chip::System::PacketBufferHandle encodeColorControlClusterWriteWhitePointYAttribute(chip::EndpointId destinationEndpoint, + uint16_t whitePointY); /** * @brief * Encode a Color Control server read command for the color point r x attribute into buffer including the APS frame */ -uint16_t encodeColorControlClusterReadColorPointRXAttribute(uint8_t * buffer, uint16_t buf_length, - chip::EndpointId destination_endpoint); +chip::System::PacketBufferHandle encodeColorControlClusterReadColorPointRXAttribute(chip::EndpointId destinationEndpoint); /** * @brief * Encode a Color Control server write command for the color point r x attribute into buffer including the APS frame */ -uint16_t encodeColorControlClusterWriteColorPointRXAttribute(uint8_t * buffer, uint16_t buf_length, - chip::EndpointId destination_endpoint, uint16_t colorPointRX); +chip::System::PacketBufferHandle encodeColorControlClusterWriteColorPointRXAttribute(chip::EndpointId destinationEndpoint, + uint16_t colorPointRX); /** * @brief * Encode a Color Control server read command for the color point r y attribute into buffer including the APS frame */ -uint16_t encodeColorControlClusterReadColorPointRYAttribute(uint8_t * buffer, uint16_t buf_length, - chip::EndpointId destination_endpoint); +chip::System::PacketBufferHandle encodeColorControlClusterReadColorPointRYAttribute(chip::EndpointId destinationEndpoint); /** * @brief * Encode a Color Control server write command for the color point r y attribute into buffer including the APS frame */ -uint16_t encodeColorControlClusterWriteColorPointRYAttribute(uint8_t * buffer, uint16_t buf_length, - chip::EndpointId destination_endpoint, uint16_t colorPointRY); +chip::System::PacketBufferHandle encodeColorControlClusterWriteColorPointRYAttribute(chip::EndpointId destinationEndpoint, + uint16_t colorPointRY); /** * @brief * Encode a Color Control server read command for the color point r intensity attribute into buffer including the APS frame */ -uint16_t encodeColorControlClusterReadColorPointRIntensityAttribute(uint8_t * buffer, uint16_t buf_length, - chip::EndpointId destination_endpoint); +chip::System::PacketBufferHandle encodeColorControlClusterReadColorPointRIntensityAttribute(chip::EndpointId destinationEndpoint); /** * @brief * Encode a Color Control server write command for the color point r intensity attribute into buffer including the APS frame */ -uint16_t encodeColorControlClusterWriteColorPointRIntensityAttribute(uint8_t * buffer, uint16_t buf_length, - chip::EndpointId destination_endpoint, - uint8_t colorPointRIntensity); +chip::System::PacketBufferHandle encodeColorControlClusterWriteColorPointRIntensityAttribute(chip::EndpointId destinationEndpoint, + uint8_t colorPointRIntensity); /** * @brief * Encode a Color Control server read command for the color point g x attribute into buffer including the APS frame */ -uint16_t encodeColorControlClusterReadColorPointGXAttribute(uint8_t * buffer, uint16_t buf_length, - chip::EndpointId destination_endpoint); +chip::System::PacketBufferHandle encodeColorControlClusterReadColorPointGXAttribute(chip::EndpointId destinationEndpoint); /** * @brief * Encode a Color Control server write command for the color point g x attribute into buffer including the APS frame */ -uint16_t encodeColorControlClusterWriteColorPointGXAttribute(uint8_t * buffer, uint16_t buf_length, - chip::EndpointId destination_endpoint, uint16_t colorPointGX); +chip::System::PacketBufferHandle encodeColorControlClusterWriteColorPointGXAttribute(chip::EndpointId destinationEndpoint, + uint16_t colorPointGX); /** * @brief * Encode a Color Control server read command for the color point g y attribute into buffer including the APS frame */ -uint16_t encodeColorControlClusterReadColorPointGYAttribute(uint8_t * buffer, uint16_t buf_length, - chip::EndpointId destination_endpoint); +chip::System::PacketBufferHandle encodeColorControlClusterReadColorPointGYAttribute(chip::EndpointId destinationEndpoint); /** * @brief * Encode a Color Control server write command for the color point g y attribute into buffer including the APS frame */ -uint16_t encodeColorControlClusterWriteColorPointGYAttribute(uint8_t * buffer, uint16_t buf_length, - chip::EndpointId destination_endpoint, uint16_t colorPointGY); +chip::System::PacketBufferHandle encodeColorControlClusterWriteColorPointGYAttribute(chip::EndpointId destinationEndpoint, + uint16_t colorPointGY); /** * @brief * Encode a Color Control server read command for the color point g intensity attribute into buffer including the APS frame */ -uint16_t encodeColorControlClusterReadColorPointGIntensityAttribute(uint8_t * buffer, uint16_t buf_length, - chip::EndpointId destination_endpoint); +chip::System::PacketBufferHandle encodeColorControlClusterReadColorPointGIntensityAttribute(chip::EndpointId destinationEndpoint); /** * @brief * Encode a Color Control server write command for the color point g intensity attribute into buffer including the APS frame */ -uint16_t encodeColorControlClusterWriteColorPointGIntensityAttribute(uint8_t * buffer, uint16_t buf_length, - chip::EndpointId destination_endpoint, - uint8_t colorPointGIntensity); +chip::System::PacketBufferHandle encodeColorControlClusterWriteColorPointGIntensityAttribute(chip::EndpointId destinationEndpoint, + uint8_t colorPointGIntensity); /** * @brief * Encode a Color Control server read command for the color point b x attribute into buffer including the APS frame */ -uint16_t encodeColorControlClusterReadColorPointBXAttribute(uint8_t * buffer, uint16_t buf_length, - chip::EndpointId destination_endpoint); +chip::System::PacketBufferHandle encodeColorControlClusterReadColorPointBXAttribute(chip::EndpointId destinationEndpoint); /** * @brief * Encode a Color Control server write command for the color point b x attribute into buffer including the APS frame */ -uint16_t encodeColorControlClusterWriteColorPointBXAttribute(uint8_t * buffer, uint16_t buf_length, - chip::EndpointId destination_endpoint, uint16_t colorPointBX); +chip::System::PacketBufferHandle encodeColorControlClusterWriteColorPointBXAttribute(chip::EndpointId destinationEndpoint, + uint16_t colorPointBX); /** * @brief * Encode a Color Control server read command for the color point b y attribute into buffer including the APS frame */ -uint16_t encodeColorControlClusterReadColorPointBYAttribute(uint8_t * buffer, uint16_t buf_length, - chip::EndpointId destination_endpoint); +chip::System::PacketBufferHandle encodeColorControlClusterReadColorPointBYAttribute(chip::EndpointId destinationEndpoint); /** * @brief * Encode a Color Control server write command for the color point b y attribute into buffer including the APS frame */ -uint16_t encodeColorControlClusterWriteColorPointBYAttribute(uint8_t * buffer, uint16_t buf_length, - chip::EndpointId destination_endpoint, uint16_t colorPointBY); +chip::System::PacketBufferHandle encodeColorControlClusterWriteColorPointBYAttribute(chip::EndpointId destinationEndpoint, + uint16_t colorPointBY); /** * @brief * Encode a Color Control server read command for the color point b intensity attribute into buffer including the APS frame */ -uint16_t encodeColorControlClusterReadColorPointBIntensityAttribute(uint8_t * buffer, uint16_t buf_length, - chip::EndpointId destination_endpoint); +chip::System::PacketBufferHandle encodeColorControlClusterReadColorPointBIntensityAttribute(chip::EndpointId destinationEndpoint); /** * @brief * Encode a Color Control server write command for the color point b intensity attribute into buffer including the APS frame */ -uint16_t encodeColorControlClusterWriteColorPointBIntensityAttribute(uint8_t * buffer, uint16_t buf_length, - chip::EndpointId destination_endpoint, - uint8_t colorPointBIntensity); +chip::System::PacketBufferHandle encodeColorControlClusterWriteColorPointBIntensityAttribute(chip::EndpointId destinationEndpoint, + uint8_t colorPointBIntensity); /** * @brief * Encode a Color Control server read command for the enhanced current hue attribute into buffer including the APS frame */ -uint16_t encodeColorControlClusterReadEnhancedCurrentHueAttribute(uint8_t * buffer, uint16_t buf_length, - chip::EndpointId destination_endpoint); +chip::System::PacketBufferHandle encodeColorControlClusterReadEnhancedCurrentHueAttribute(chip::EndpointId destinationEndpoint); /** * @brief * Encode a Color Control server read command for the enhanced color mode attribute into buffer including the APS frame */ -uint16_t encodeColorControlClusterReadEnhancedColorModeAttribute(uint8_t * buffer, uint16_t buf_length, - chip::EndpointId destination_endpoint); +chip::System::PacketBufferHandle encodeColorControlClusterReadEnhancedColorModeAttribute(chip::EndpointId destinationEndpoint); /** * @brief * Encode a Color Control server read command for the color loop active attribute into buffer including the APS frame */ -uint16_t encodeColorControlClusterReadColorLoopActiveAttribute(uint8_t * buffer, uint16_t buf_length, - chip::EndpointId destination_endpoint); +chip::System::PacketBufferHandle encodeColorControlClusterReadColorLoopActiveAttribute(chip::EndpointId destinationEndpoint); /** * @brief * Encode a Color Control server read command for the color loop direction attribute into buffer including the APS frame */ -uint16_t encodeColorControlClusterReadColorLoopDirectionAttribute(uint8_t * buffer, uint16_t buf_length, - chip::EndpointId destination_endpoint); +chip::System::PacketBufferHandle encodeColorControlClusterReadColorLoopDirectionAttribute(chip::EndpointId destinationEndpoint); /** * @brief * Encode a Color Control server read command for the color loop time attribute into buffer including the APS frame */ -uint16_t encodeColorControlClusterReadColorLoopTimeAttribute(uint8_t * buffer, uint16_t buf_length, - chip::EndpointId destination_endpoint); +chip::System::PacketBufferHandle encodeColorControlClusterReadColorLoopTimeAttribute(chip::EndpointId destinationEndpoint); /** * @brief * Encode a Color Control server read command for the color capabilities attribute into buffer including the APS frame */ -uint16_t encodeColorControlClusterReadColorCapabilitiesAttribute(uint8_t * buffer, uint16_t buf_length, - chip::EndpointId destination_endpoint); +chip::System::PacketBufferHandle encodeColorControlClusterReadColorCapabilitiesAttribute(chip::EndpointId destinationEndpoint); /** * @brief * Encode a Color Control server read command for the color temp physical min attribute into buffer including the APS frame */ -uint16_t encodeColorControlClusterReadColorTempPhysicalMinAttribute(uint8_t * buffer, uint16_t buf_length, - chip::EndpointId destination_endpoint); +chip::System::PacketBufferHandle encodeColorControlClusterReadColorTempPhysicalMinAttribute(chip::EndpointId destinationEndpoint); /** * @brief * Encode a Color Control server read command for the color temp physical max attribute into buffer including the APS frame */ -uint16_t encodeColorControlClusterReadColorTempPhysicalMaxAttribute(uint8_t * buffer, uint16_t buf_length, - chip::EndpointId destination_endpoint); +chip::System::PacketBufferHandle encodeColorControlClusterReadColorTempPhysicalMaxAttribute(chip::EndpointId destinationEndpoint); /** * @brief * Encode a Color Control server read command for the couple color temp to level min-mireds attribute into buffer including the * APS frame */ -uint16_t encodeColorControlClusterReadCoupleColorTempToLevelMinMiredsAttribute(uint8_t * buffer, uint16_t buf_length, - chip::EndpointId destination_endpoint); +chip::System::PacketBufferHandle +encodeColorControlClusterReadCoupleColorTempToLevelMinMiredsAttribute(chip::EndpointId destinationEndpoint); /** * @brief * Encode a Color Control server read command for the start up color temperature mireds attribute into buffer including the APS * frame */ -uint16_t encodeColorControlClusterReadStartUpColorTemperatureMiredsAttribute(uint8_t * buffer, uint16_t buf_length, - chip::EndpointId destination_endpoint); +chip::System::PacketBufferHandle +encodeColorControlClusterReadStartUpColorTemperatureMiredsAttribute(chip::EndpointId destinationEndpoint); /** * @brief * Encode a Color Control server write command for the start up color temperature mireds attribute into buffer including the APS * frame */ -uint16_t encodeColorControlClusterWriteStartUpColorTemperatureMiredsAttribute(uint8_t * buffer, uint16_t buf_length, - chip::EndpointId destination_endpoint, - uint16_t startUpColorTemperatureMireds); +chip::System::PacketBufferHandle +encodeColorControlClusterWriteStartUpColorTemperatureMiredsAttribute(chip::EndpointId destinationEndpoint, + uint16_t startUpColorTemperatureMireds); /** * @brief * Encode a Color Control server read command for the cluster revision attribute into buffer including the APS frame */ -uint16_t encodeColorControlClusterReadClusterRevisionAttribute(uint8_t * buffer, uint16_t buf_length, - chip::EndpointId destination_endpoint); +chip::System::PacketBufferHandle encodeColorControlClusterReadClusterRevisionAttribute(chip::EndpointId destinationEndpoint); /*----------------------------------------------------------------------------*\ | Cluster DoorLock | 0x0101 | @@ -886,206 +826,195 @@ uint16_t encodeColorControlClusterReadClusterRevisionAttribute(uint8_t * buffer, * @brief * Encode an ClearAllPins command for Door Lock server into buffer including the APS frame */ -uint16_t encodeDoorLockClusterClearAllPinsCommand(uint8_t * buffer, uint16_t buf_length, chip::EndpointId destination_endpoint); +chip::System::PacketBufferHandle encodeDoorLockClusterClearAllPinsCommand(chip::EndpointId destinationEndpoint); /** * @brief * Encode an ClearAllRfids command for Door Lock server into buffer including the APS frame */ -uint16_t encodeDoorLockClusterClearAllRfidsCommand(uint8_t * buffer, uint16_t buf_length, chip::EndpointId destination_endpoint); +chip::System::PacketBufferHandle encodeDoorLockClusterClearAllRfidsCommand(chip::EndpointId destinationEndpoint); /** * @brief * Encode an ClearHolidaySchedule command for Door Lock server into buffer including the APS frame */ -uint16_t encodeDoorLockClusterClearHolidayScheduleCommand(uint8_t * buffer, uint16_t buf_length, - chip::EndpointId destination_endpoint, uint8_t scheduleId); +chip::System::PacketBufferHandle encodeDoorLockClusterClearHolidayScheduleCommand(chip::EndpointId destinationEndpoint, + uint8_t scheduleId); /** * @brief * Encode an ClearPin command for Door Lock server into buffer including the APS frame */ -uint16_t encodeDoorLockClusterClearPinCommand(uint8_t * buffer, uint16_t buf_length, chip::EndpointId destination_endpoint, - uint16_t userId); +chip::System::PacketBufferHandle encodeDoorLockClusterClearPinCommand(chip::EndpointId destinationEndpoint, uint16_t userId); /** * @brief * Encode an ClearRfid command for Door Lock server into buffer including the APS frame */ -uint16_t encodeDoorLockClusterClearRfidCommand(uint8_t * buffer, uint16_t buf_length, chip::EndpointId destination_endpoint, - uint16_t userId); +chip::System::PacketBufferHandle encodeDoorLockClusterClearRfidCommand(chip::EndpointId destinationEndpoint, uint16_t userId); /** * @brief * Encode an ClearWeekdaySchedule command for Door Lock server into buffer including the APS frame */ -uint16_t encodeDoorLockClusterClearWeekdayScheduleCommand(uint8_t * buffer, uint16_t buf_length, - chip::EndpointId destination_endpoint, uint8_t scheduleId, - uint16_t userId); +chip::System::PacketBufferHandle encodeDoorLockClusterClearWeekdayScheduleCommand(chip::EndpointId destinationEndpoint, + uint8_t scheduleId, uint16_t userId); /** * @brief * Encode an ClearYeardaySchedule command for Door Lock server into buffer including the APS frame */ -uint16_t encodeDoorLockClusterClearYeardayScheduleCommand(uint8_t * buffer, uint16_t buf_length, - chip::EndpointId destination_endpoint, uint8_t scheduleId, - uint16_t userId); +chip::System::PacketBufferHandle encodeDoorLockClusterClearYeardayScheduleCommand(chip::EndpointId destinationEndpoint, + uint8_t scheduleId, uint16_t userId); /** * @brief * Encode an GetHolidaySchedule command for Door Lock server into buffer including the APS frame */ -uint16_t encodeDoorLockClusterGetHolidayScheduleCommand(uint8_t * buffer, uint16_t buf_length, - chip::EndpointId destination_endpoint, uint8_t scheduleId); +chip::System::PacketBufferHandle encodeDoorLockClusterGetHolidayScheduleCommand(chip::EndpointId destinationEndpoint, + uint8_t scheduleId); /** * @brief * Encode an GetLogRecord command for Door Lock server into buffer including the APS frame */ -uint16_t encodeDoorLockClusterGetLogRecordCommand(uint8_t * buffer, uint16_t buf_length, chip::EndpointId destination_endpoint, - uint16_t logIndex); +chip::System::PacketBufferHandle encodeDoorLockClusterGetLogRecordCommand(chip::EndpointId destinationEndpoint, uint16_t logIndex); /** * @brief * Encode an GetPin command for Door Lock server into buffer including the APS frame */ -uint16_t encodeDoorLockClusterGetPinCommand(uint8_t * buffer, uint16_t buf_length, chip::EndpointId destination_endpoint, - uint16_t userId); +chip::System::PacketBufferHandle encodeDoorLockClusterGetPinCommand(chip::EndpointId destinationEndpoint, uint16_t userId); /** * @brief * Encode an GetRfid command for Door Lock server into buffer including the APS frame */ -uint16_t encodeDoorLockClusterGetRfidCommand(uint8_t * buffer, uint16_t buf_length, chip::EndpointId destination_endpoint, - uint16_t userId); +chip::System::PacketBufferHandle encodeDoorLockClusterGetRfidCommand(chip::EndpointId destinationEndpoint, uint16_t userId); /** * @brief * Encode an GetUserType command for Door Lock server into buffer including the APS frame */ -uint16_t encodeDoorLockClusterGetUserTypeCommand(uint8_t * buffer, uint16_t buf_length, chip::EndpointId destination_endpoint, - uint16_t userId); +chip::System::PacketBufferHandle encodeDoorLockClusterGetUserTypeCommand(chip::EndpointId destinationEndpoint, uint16_t userId); /** * @brief * Encode an GetWeekdaySchedule command for Door Lock server into buffer including the APS frame */ -uint16_t encodeDoorLockClusterGetWeekdayScheduleCommand(uint8_t * buffer, uint16_t buf_length, - chip::EndpointId destination_endpoint, uint8_t scheduleId, uint16_t userId); +chip::System::PacketBufferHandle encodeDoorLockClusterGetWeekdayScheduleCommand(chip::EndpointId destinationEndpoint, + uint8_t scheduleId, uint16_t userId); /** * @brief * Encode an GetYeardaySchedule command for Door Lock server into buffer including the APS frame */ -uint16_t encodeDoorLockClusterGetYeardayScheduleCommand(uint8_t * buffer, uint16_t buf_length, - chip::EndpointId destination_endpoint, uint8_t scheduleId, uint16_t userId); +chip::System::PacketBufferHandle encodeDoorLockClusterGetYeardayScheduleCommand(chip::EndpointId destinationEndpoint, + uint8_t scheduleId, uint16_t userId); /** * @brief * Encode an LockDoor command for Door Lock server into buffer including the APS frame */ -uint16_t encodeDoorLockClusterLockDoorCommand(uint8_t * buffer, uint16_t buf_length, chip::EndpointId destination_endpoint, - char * pin); +chip::System::PacketBufferHandle encodeDoorLockClusterLockDoorCommand(chip::EndpointId destinationEndpoint, char * pin); /** * @brief * Encode an SetHolidaySchedule command for Door Lock server into buffer including the APS frame */ -uint16_t encodeDoorLockClusterSetHolidayScheduleCommand(uint8_t * buffer, uint16_t buf_length, - chip::EndpointId destination_endpoint, uint8_t scheduleId, - uint32_t localStartTime, uint32_t localEndTime, - uint8_t operatingModeDuringHoliday); +chip::System::PacketBufferHandle encodeDoorLockClusterSetHolidayScheduleCommand(chip::EndpointId destinationEndpoint, + uint8_t scheduleId, uint32_t localStartTime, + uint32_t localEndTime, + uint8_t operatingModeDuringHoliday); /** * @brief * Encode an SetPin command for Door Lock server into buffer including the APS frame */ -uint16_t encodeDoorLockClusterSetPinCommand(uint8_t * buffer, uint16_t buf_length, chip::EndpointId destination_endpoint, - uint16_t userId, uint8_t userStatus, uint8_t userType, char * pin); +chip::System::PacketBufferHandle encodeDoorLockClusterSetPinCommand(chip::EndpointId destinationEndpoint, uint16_t userId, + uint8_t userStatus, uint8_t userType, char * pin); /** * @brief * Encode an SetRfid command for Door Lock server into buffer including the APS frame */ -uint16_t encodeDoorLockClusterSetRfidCommand(uint8_t * buffer, uint16_t buf_length, chip::EndpointId destination_endpoint, - uint16_t userId, uint8_t userStatus, uint8_t userType, char * id); +chip::System::PacketBufferHandle encodeDoorLockClusterSetRfidCommand(chip::EndpointId destinationEndpoint, uint16_t userId, + uint8_t userStatus, uint8_t userType, char * id); /** * @brief * Encode an SetUserType command for Door Lock server into buffer including the APS frame */ -uint16_t encodeDoorLockClusterSetUserTypeCommand(uint8_t * buffer, uint16_t buf_length, chip::EndpointId destination_endpoint, - uint16_t userId, uint8_t userType); +chip::System::PacketBufferHandle encodeDoorLockClusterSetUserTypeCommand(chip::EndpointId destinationEndpoint, uint16_t userId, + uint8_t userType); /** * @brief * Encode an SetWeekdaySchedule command for Door Lock server into buffer including the APS frame */ -uint16_t encodeDoorLockClusterSetWeekdayScheduleCommand(uint8_t * buffer, uint16_t buf_length, - chip::EndpointId destination_endpoint, uint8_t scheduleId, uint16_t userId, - uint8_t daysMask, uint8_t startHour, uint8_t startMinute, uint8_t endHour, - uint8_t endMinute); +chip::System::PacketBufferHandle encodeDoorLockClusterSetWeekdayScheduleCommand(chip::EndpointId destinationEndpoint, + uint8_t scheduleId, uint16_t userId, + uint8_t daysMask, uint8_t startHour, + uint8_t startMinute, uint8_t endHour, + uint8_t endMinute); /** * @brief * Encode an SetYeardaySchedule command for Door Lock server into buffer including the APS frame */ -uint16_t encodeDoorLockClusterSetYeardayScheduleCommand(uint8_t * buffer, uint16_t buf_length, - chip::EndpointId destination_endpoint, uint8_t scheduleId, uint16_t userId, - uint32_t localStartTime, uint32_t localEndTime); +chip::System::PacketBufferHandle encodeDoorLockClusterSetYeardayScheduleCommand(chip::EndpointId destinationEndpoint, + uint8_t scheduleId, uint16_t userId, + uint32_t localStartTime, uint32_t localEndTime); /** * @brief * Encode an UnlockDoor command for Door Lock server into buffer including the APS frame */ -uint16_t encodeDoorLockClusterUnlockDoorCommand(uint8_t * buffer, uint16_t buf_length, chip::EndpointId destination_endpoint, - char * pin); +chip::System::PacketBufferHandle encodeDoorLockClusterUnlockDoorCommand(chip::EndpointId destinationEndpoint, char * pin); /** * @brief * Encode an UnlockWithTimeout command for Door Lock server into buffer including the APS frame */ -uint16_t encodeDoorLockClusterUnlockWithTimeoutCommand(uint8_t * buffer, uint16_t buf_length, chip::EndpointId destination_endpoint, - uint16_t timeoutInSeconds, char * pin); +chip::System::PacketBufferHandle encodeDoorLockClusterUnlockWithTimeoutCommand(chip::EndpointId destinationEndpoint, + uint16_t timeoutInSeconds, char * pin); /** * @brief * Encode a Door Lock server discover command into buffer including the APS frame */ -uint16_t encodeDoorLockClusterDiscoverAttributes(uint8_t * buffer, uint16_t buf_length, chip::EndpointId destination_endpoint); +chip::System::PacketBufferHandle encodeDoorLockClusterDiscoverAttributes(chip::EndpointId destinationEndpoint); /** * @brief * Encode a Door Lock server read command for the lock state attribute into buffer including the APS frame */ -uint16_t encodeDoorLockClusterReadLockStateAttribute(uint8_t * buffer, uint16_t buf_length, chip::EndpointId destination_endpoint); +chip::System::PacketBufferHandle encodeDoorLockClusterReadLockStateAttribute(chip::EndpointId destinationEndpoint); /** * @brief * Encode a Door Lock server report command for the lock state attribute into buffer including the APS frame */ -uint16_t encodeDoorLockClusterReportLockStateAttribute(uint8_t * buffer, uint16_t buf_length, chip::EndpointId destination_endpoint, - uint16_t min_interval, uint16_t max_interval); +chip::System::PacketBufferHandle encodeDoorLockClusterReportLockStateAttribute(chip::EndpointId destinationEndpoint, + uint16_t minInterval, uint16_t maxInterval); /** * @brief * Encode a Door Lock server read command for the lock type attribute into buffer including the APS frame */ -uint16_t encodeDoorLockClusterReadLockTypeAttribute(uint8_t * buffer, uint16_t buf_length, chip::EndpointId destination_endpoint); +chip::System::PacketBufferHandle encodeDoorLockClusterReadLockTypeAttribute(chip::EndpointId destinationEndpoint); /** * @brief * Encode a Door Lock server read command for the actuator enabled attribute into buffer including the APS frame */ -uint16_t encodeDoorLockClusterReadActuatorEnabledAttribute(uint8_t * buffer, uint16_t buf_length, - chip::EndpointId destination_endpoint); +chip::System::PacketBufferHandle encodeDoorLockClusterReadActuatorEnabledAttribute(chip::EndpointId destinationEndpoint); /** * @brief * Encode a Door Lock server read command for the cluster revision attribute into buffer including the APS frame */ -uint16_t encodeDoorLockClusterReadClusterRevisionAttribute(uint8_t * buffer, uint16_t buf_length, - chip::EndpointId destination_endpoint); +chip::System::PacketBufferHandle encodeDoorLockClusterReadClusterRevisionAttribute(chip::EndpointId destinationEndpoint); /*----------------------------------------------------------------------------*\ | Cluster Groups | 0x0004 | @@ -1107,61 +1036,58 @@ uint16_t encodeDoorLockClusterReadClusterRevisionAttribute(uint8_t * buffer, uin * @brief * Encode an AddGroup command for Groups server into buffer including the APS frame */ -uint16_t encodeGroupsClusterAddGroupCommand(uint8_t * buffer, uint16_t buf_length, chip::EndpointId destination_endpoint, - uint16_t groupId, char * groupName); +chip::System::PacketBufferHandle encodeGroupsClusterAddGroupCommand(chip::EndpointId destinationEndpoint, uint16_t groupId, + char * groupName); /** * @brief * Encode an AddGroupIfIdentifying command for Groups server into buffer including the APS frame */ -uint16_t encodeGroupsClusterAddGroupIfIdentifyingCommand(uint8_t * buffer, uint16_t buf_length, - chip::EndpointId destination_endpoint, uint16_t groupId, char * groupName); +chip::System::PacketBufferHandle encodeGroupsClusterAddGroupIfIdentifyingCommand(chip::EndpointId destinationEndpoint, + uint16_t groupId, char * groupName); /** * @brief * Encode an GetGroupMembership command for Groups server into buffer including the APS frame */ -uint16_t encodeGroupsClusterGetGroupMembershipCommand(uint8_t * buffer, uint16_t buf_length, chip::EndpointId destination_endpoint, - uint8_t groupCount, uint16_t groupList); +chip::System::PacketBufferHandle encodeGroupsClusterGetGroupMembershipCommand(chip::EndpointId destinationEndpoint, + uint8_t groupCount, uint16_t groupList); /** * @brief * Encode an RemoveAllGroups command for Groups server into buffer including the APS frame */ -uint16_t encodeGroupsClusterRemoveAllGroupsCommand(uint8_t * buffer, uint16_t buf_length, chip::EndpointId destination_endpoint); +chip::System::PacketBufferHandle encodeGroupsClusterRemoveAllGroupsCommand(chip::EndpointId destinationEndpoint); /** * @brief * Encode an RemoveGroup command for Groups server into buffer including the APS frame */ -uint16_t encodeGroupsClusterRemoveGroupCommand(uint8_t * buffer, uint16_t buf_length, chip::EndpointId destination_endpoint, - uint16_t groupId); +chip::System::PacketBufferHandle encodeGroupsClusterRemoveGroupCommand(chip::EndpointId destinationEndpoint, uint16_t groupId); /** * @brief * Encode an ViewGroup command for Groups server into buffer including the APS frame */ -uint16_t encodeGroupsClusterViewGroupCommand(uint8_t * buffer, uint16_t buf_length, chip::EndpointId destination_endpoint, - uint16_t groupId); +chip::System::PacketBufferHandle encodeGroupsClusterViewGroupCommand(chip::EndpointId destinationEndpoint, uint16_t groupId); /** * @brief * Encode a Groups server discover command into buffer including the APS frame */ -uint16_t encodeGroupsClusterDiscoverAttributes(uint8_t * buffer, uint16_t buf_length, chip::EndpointId destination_endpoint); +chip::System::PacketBufferHandle encodeGroupsClusterDiscoverAttributes(chip::EndpointId destinationEndpoint); /** * @brief * Encode a Groups server read command for the name support attribute into buffer including the APS frame */ -uint16_t encodeGroupsClusterReadNameSupportAttribute(uint8_t * buffer, uint16_t buf_length, chip::EndpointId destination_endpoint); +chip::System::PacketBufferHandle encodeGroupsClusterReadNameSupportAttribute(chip::EndpointId destinationEndpoint); /** * @brief * Encode a Groups server read command for the cluster revision attribute into buffer including the APS frame */ -uint16_t encodeGroupsClusterReadClusterRevisionAttribute(uint8_t * buffer, uint16_t buf_length, - chip::EndpointId destination_endpoint); +chip::System::PacketBufferHandle encodeGroupsClusterReadClusterRevisionAttribute(chip::EndpointId destinationEndpoint); /*----------------------------------------------------------------------------*\ | Cluster IasZone | 0x0500 | @@ -1181,52 +1107,50 @@ uint16_t encodeGroupsClusterReadClusterRevisionAttribute(uint8_t * buffer, uint1 * @brief * Encode a IAS Zone server discover command into buffer including the APS frame */ -uint16_t encodeIasZoneClusterDiscoverAttributes(uint8_t * buffer, uint16_t buf_length, chip::EndpointId destination_endpoint); +chip::System::PacketBufferHandle encodeIasZoneClusterDiscoverAttributes(chip::EndpointId destinationEndpoint); /** * @brief * Encode a IAS Zone server read command for the zone state attribute into buffer including the APS frame */ -uint16_t encodeIasZoneClusterReadZoneStateAttribute(uint8_t * buffer, uint16_t buf_length, chip::EndpointId destination_endpoint); +chip::System::PacketBufferHandle encodeIasZoneClusterReadZoneStateAttribute(chip::EndpointId destinationEndpoint); /** * @brief * Encode a IAS Zone server read command for the zone type attribute into buffer including the APS frame */ -uint16_t encodeIasZoneClusterReadZoneTypeAttribute(uint8_t * buffer, uint16_t buf_length, chip::EndpointId destination_endpoint); +chip::System::PacketBufferHandle encodeIasZoneClusterReadZoneTypeAttribute(chip::EndpointId destinationEndpoint); /** * @brief * Encode a IAS Zone server read command for the zone status attribute into buffer including the APS frame */ -uint16_t encodeIasZoneClusterReadZoneStatusAttribute(uint8_t * buffer, uint16_t buf_length, chip::EndpointId destination_endpoint); +chip::System::PacketBufferHandle encodeIasZoneClusterReadZoneStatusAttribute(chip::EndpointId destinationEndpoint); /** * @brief * Encode a IAS Zone server read command for the IAS CIE address attribute into buffer including the APS frame */ -uint16_t encodeIasZoneClusterReadIasCieAddressAttribute(uint8_t * buffer, uint16_t buf_length, - chip::EndpointId destination_endpoint); +chip::System::PacketBufferHandle encodeIasZoneClusterReadIasCieAddressAttribute(chip::EndpointId destinationEndpoint); /** * @brief * Encode a IAS Zone server write command for the IAS CIE address attribute into buffer including the APS frame */ -uint16_t encodeIasZoneClusterWriteIasCieAddressAttribute(uint8_t * buffer, uint16_t buf_length, - chip::EndpointId destination_endpoint, uint64_t iasCieAddress); +chip::System::PacketBufferHandle encodeIasZoneClusterWriteIasCieAddressAttribute(chip::EndpointId destinationEndpoint, + uint64_t iasCieAddress); /** * @brief * Encode a IAS Zone server read command for the Zone ID attribute into buffer including the APS frame */ -uint16_t encodeIasZoneClusterReadZoneIdAttribute(uint8_t * buffer, uint16_t buf_length, chip::EndpointId destination_endpoint); +chip::System::PacketBufferHandle encodeIasZoneClusterReadZoneIdAttribute(chip::EndpointId destinationEndpoint); /** * @brief * Encode a IAS Zone server read command for the cluster revision attribute into buffer including the APS frame */ -uint16_t encodeIasZoneClusterReadClusterRevisionAttribute(uint8_t * buffer, uint16_t buf_length, - chip::EndpointId destination_endpoint); +chip::System::PacketBufferHandle encodeIasZoneClusterReadClusterRevisionAttribute(chip::EndpointId destinationEndpoint); /*----------------------------------------------------------------------------*\ | Cluster Identify | 0x0003 | @@ -1244,41 +1168,38 @@ uint16_t encodeIasZoneClusterReadClusterRevisionAttribute(uint8_t * buffer, uint * @brief * Encode an Identify command for Identify server into buffer including the APS frame */ -uint16_t encodeIdentifyClusterIdentifyCommand(uint8_t * buffer, uint16_t buf_length, chip::EndpointId destination_endpoint, - uint16_t identifyTime); +chip::System::PacketBufferHandle encodeIdentifyClusterIdentifyCommand(chip::EndpointId destinationEndpoint, uint16_t identifyTime); /** * @brief * Encode an IdentifyQuery command for Identify server into buffer including the APS frame */ -uint16_t encodeIdentifyClusterIdentifyQueryCommand(uint8_t * buffer, uint16_t buf_length, chip::EndpointId destination_endpoint); +chip::System::PacketBufferHandle encodeIdentifyClusterIdentifyQueryCommand(chip::EndpointId destinationEndpoint); /** * @brief * Encode a Identify server discover command into buffer including the APS frame */ -uint16_t encodeIdentifyClusterDiscoverAttributes(uint8_t * buffer, uint16_t buf_length, chip::EndpointId destination_endpoint); +chip::System::PacketBufferHandle encodeIdentifyClusterDiscoverAttributes(chip::EndpointId destinationEndpoint); /** * @brief * Encode a Identify server read command for the identify time attribute into buffer including the APS frame */ -uint16_t encodeIdentifyClusterReadIdentifyTimeAttribute(uint8_t * buffer, uint16_t buf_length, - chip::EndpointId destination_endpoint); +chip::System::PacketBufferHandle encodeIdentifyClusterReadIdentifyTimeAttribute(chip::EndpointId destinationEndpoint); /** * @brief * Encode a Identify server write command for the identify time attribute into buffer including the APS frame */ -uint16_t encodeIdentifyClusterWriteIdentifyTimeAttribute(uint8_t * buffer, uint16_t buf_length, - chip::EndpointId destination_endpoint, uint16_t identifyTime); +chip::System::PacketBufferHandle encodeIdentifyClusterWriteIdentifyTimeAttribute(chip::EndpointId destinationEndpoint, + uint16_t identifyTime); /** * @brief * Encode a Identify server read command for the cluster revision attribute into buffer including the APS frame */ -uint16_t encodeIdentifyClusterReadClusterRevisionAttribute(uint8_t * buffer, uint16_t buf_length, - chip::EndpointId destination_endpoint); +chip::System::PacketBufferHandle encodeIdentifyClusterReadClusterRevisionAttribute(chip::EndpointId destinationEndpoint); /*----------------------------------------------------------------------------*\ | Cluster LevelControl | 0x0008 | @@ -1302,88 +1223,85 @@ uint16_t encodeIdentifyClusterReadClusterRevisionAttribute(uint8_t * buffer, uin * @brief * Encode an Move command for Level Control server into buffer including the APS frame */ -uint16_t encodeLevelControlClusterMoveCommand(uint8_t * buffer, uint16_t buf_length, chip::EndpointId destination_endpoint, - uint8_t moveMode, uint8_t rate, uint8_t optionMask, uint8_t optionOverride); +chip::System::PacketBufferHandle encodeLevelControlClusterMoveCommand(chip::EndpointId destinationEndpoint, uint8_t moveMode, + uint8_t rate, uint8_t optionMask, uint8_t optionOverride); /** * @brief * Encode an MoveToLevel command for Level Control server into buffer including the APS frame */ -uint16_t encodeLevelControlClusterMoveToLevelCommand(uint8_t * buffer, uint16_t buf_length, chip::EndpointId destination_endpoint, - uint8_t level, uint16_t transitionTime, uint8_t optionMask, - uint8_t optionOverride); +chip::System::PacketBufferHandle encodeLevelControlClusterMoveToLevelCommand(chip::EndpointId destinationEndpoint, uint8_t level, + uint16_t transitionTime, uint8_t optionMask, + uint8_t optionOverride); /** * @brief * Encode an MoveToLevelWithOnOff command for Level Control server into buffer including the APS frame */ -uint16_t encodeLevelControlClusterMoveToLevelWithOnOffCommand(uint8_t * buffer, uint16_t buf_length, - chip::EndpointId destination_endpoint, uint8_t level, - uint16_t transitionTime); +chip::System::PacketBufferHandle encodeLevelControlClusterMoveToLevelWithOnOffCommand(chip::EndpointId destinationEndpoint, + uint8_t level, uint16_t transitionTime); /** * @brief * Encode an MoveWithOnOff command for Level Control server into buffer including the APS frame */ -uint16_t encodeLevelControlClusterMoveWithOnOffCommand(uint8_t * buffer, uint16_t buf_length, chip::EndpointId destination_endpoint, - uint8_t moveMode, uint8_t rate); +chip::System::PacketBufferHandle encodeLevelControlClusterMoveWithOnOffCommand(chip::EndpointId destinationEndpoint, + uint8_t moveMode, uint8_t rate); /** * @brief * Encode an Step command for Level Control server into buffer including the APS frame */ -uint16_t encodeLevelControlClusterStepCommand(uint8_t * buffer, uint16_t buf_length, chip::EndpointId destination_endpoint, - uint8_t stepMode, uint8_t stepSize, uint16_t transitionTime, uint8_t optionMask, - uint8_t optionOverride); +chip::System::PacketBufferHandle encodeLevelControlClusterStepCommand(chip::EndpointId destinationEndpoint, uint8_t stepMode, + uint8_t stepSize, uint16_t transitionTime, uint8_t optionMask, + uint8_t optionOverride); /** * @brief * Encode an StepWithOnOff command for Level Control server into buffer including the APS frame */ -uint16_t encodeLevelControlClusterStepWithOnOffCommand(uint8_t * buffer, uint16_t buf_length, chip::EndpointId destination_endpoint, - uint8_t stepMode, uint8_t stepSize, uint16_t transitionTime); +chip::System::PacketBufferHandle encodeLevelControlClusterStepWithOnOffCommand(chip::EndpointId destinationEndpoint, + uint8_t stepMode, uint8_t stepSize, + uint16_t transitionTime); /** * @brief * Encode an Stop command for Level Control server into buffer including the APS frame */ -uint16_t encodeLevelControlClusterStopCommand(uint8_t * buffer, uint16_t buf_length, chip::EndpointId destination_endpoint, - uint8_t optionMask, uint8_t optionOverride); +chip::System::PacketBufferHandle encodeLevelControlClusterStopCommand(chip::EndpointId destinationEndpoint, uint8_t optionMask, + uint8_t optionOverride); /** * @brief * Encode an StopWithOnOff command for Level Control server into buffer including the APS frame */ -uint16_t encodeLevelControlClusterStopWithOnOffCommand(uint8_t * buffer, uint16_t buf_length, - chip::EndpointId destination_endpoint); +chip::System::PacketBufferHandle encodeLevelControlClusterStopWithOnOffCommand(chip::EndpointId destinationEndpoint); /** * @brief * Encode a Level Control server discover command into buffer including the APS frame */ -uint16_t encodeLevelControlClusterDiscoverAttributes(uint8_t * buffer, uint16_t buf_length, chip::EndpointId destination_endpoint); +chip::System::PacketBufferHandle encodeLevelControlClusterDiscoverAttributes(chip::EndpointId destinationEndpoint); /** * @brief * Encode a Level Control server read command for the current level attribute into buffer including the APS frame */ -uint16_t encodeLevelControlClusterReadCurrentLevelAttribute(uint8_t * buffer, uint16_t buf_length, - chip::EndpointId destination_endpoint); +chip::System::PacketBufferHandle encodeLevelControlClusterReadCurrentLevelAttribute(chip::EndpointId destinationEndpoint); /** * @brief * Encode a Level Control server report command for the current level attribute into buffer including the APS frame */ -uint16_t encodeLevelControlClusterReportCurrentLevelAttribute(uint8_t * buffer, uint16_t buf_length, - chip::EndpointId destination_endpoint, uint16_t min_interval, - uint16_t max_interval, uint8_t change); +chip::System::PacketBufferHandle encodeLevelControlClusterReportCurrentLevelAttribute(chip::EndpointId destinationEndpoint, + uint16_t minInterval, uint16_t maxInterval, + uint8_t change); /** * @brief * Encode a Level Control server read command for the cluster revision attribute into buffer including the APS frame */ -uint16_t encodeLevelControlClusterReadClusterRevisionAttribute(uint8_t * buffer, uint16_t buf_length, - chip::EndpointId destination_endpoint); +chip::System::PacketBufferHandle encodeLevelControlClusterReadClusterRevisionAttribute(chip::EndpointId destinationEndpoint); /*----------------------------------------------------------------------------*\ | Cluster OnOff | 0x0006 | @@ -1402,45 +1320,44 @@ uint16_t encodeLevelControlClusterReadClusterRevisionAttribute(uint8_t * buffer, * @brief * Encode an Off command for On/off server into buffer including the APS frame */ -uint16_t encodeOnOffClusterOffCommand(uint8_t * buffer, uint16_t buf_length, chip::EndpointId destination_endpoint); +chip::System::PacketBufferHandle encodeOnOffClusterOffCommand(chip::EndpointId destinationEndpoint); /** * @brief * Encode an On command for On/off server into buffer including the APS frame */ -uint16_t encodeOnOffClusterOnCommand(uint8_t * buffer, uint16_t buf_length, chip::EndpointId destination_endpoint); +chip::System::PacketBufferHandle encodeOnOffClusterOnCommand(chip::EndpointId destinationEndpoint); /** * @brief * Encode an Toggle command for On/off server into buffer including the APS frame */ -uint16_t encodeOnOffClusterToggleCommand(uint8_t * buffer, uint16_t buf_length, chip::EndpointId destination_endpoint); +chip::System::PacketBufferHandle encodeOnOffClusterToggleCommand(chip::EndpointId destinationEndpoint); /** * @brief * Encode a On/off server discover command into buffer including the APS frame */ -uint16_t encodeOnOffClusterDiscoverAttributes(uint8_t * buffer, uint16_t buf_length, chip::EndpointId destination_endpoint); +chip::System::PacketBufferHandle encodeOnOffClusterDiscoverAttributes(chip::EndpointId destinationEndpoint); /** * @brief * Encode a On/off server read command for the on/off attribute into buffer including the APS frame */ -uint16_t encodeOnOffClusterReadOnOffAttribute(uint8_t * buffer, uint16_t buf_length, chip::EndpointId destination_endpoint); +chip::System::PacketBufferHandle encodeOnOffClusterReadOnOffAttribute(chip::EndpointId destinationEndpoint); /** * @brief * Encode a On/off server report command for the on/off attribute into buffer including the APS frame */ -uint16_t encodeOnOffClusterReportOnOffAttribute(uint8_t * buffer, uint16_t buf_length, chip::EndpointId destination_endpoint, - uint16_t min_interval, uint16_t max_interval); +chip::System::PacketBufferHandle encodeOnOffClusterReportOnOffAttribute(chip::EndpointId destinationEndpoint, uint16_t minInterval, + uint16_t maxInterval); /** * @brief * Encode a On/off server read command for the cluster revision attribute into buffer including the APS frame */ -uint16_t encodeOnOffClusterReadClusterRevisionAttribute(uint8_t * buffer, uint16_t buf_length, - chip::EndpointId destination_endpoint); +chip::System::PacketBufferHandle encodeOnOffClusterReadClusterRevisionAttribute(chip::EndpointId destinationEndpoint); /*----------------------------------------------------------------------------*\ | Cluster Scenes | 0x0005 | @@ -1467,94 +1384,92 @@ uint16_t encodeOnOffClusterReadClusterRevisionAttribute(uint8_t * buffer, uint16 * @brief * Encode an AddScene command for Scenes server into buffer including the APS frame */ -uint16_t encodeScenesClusterAddSceneCommand(uint8_t * buffer, uint16_t buf_length, chip::EndpointId destination_endpoint, - uint16_t groupId, uint8_t sceneId, uint16_t transitionTime, char * sceneName, - chip::ClusterId clusterId, uint8_t length, uint8_t value); +chip::System::PacketBufferHandle encodeScenesClusterAddSceneCommand(chip::EndpointId destinationEndpoint, uint16_t groupId, + uint8_t sceneId, uint16_t transitionTime, char * sceneName, + chip::ClusterId clusterId, uint8_t length, uint8_t value); /** * @brief * Encode an GetSceneMembership command for Scenes server into buffer including the APS frame */ -uint16_t encodeScenesClusterGetSceneMembershipCommand(uint8_t * buffer, uint16_t buf_length, chip::EndpointId destination_endpoint, - uint16_t groupId); +chip::System::PacketBufferHandle encodeScenesClusterGetSceneMembershipCommand(chip::EndpointId destinationEndpoint, + uint16_t groupId); /** * @brief * Encode an RecallScene command for Scenes server into buffer including the APS frame */ -uint16_t encodeScenesClusterRecallSceneCommand(uint8_t * buffer, uint16_t buf_length, chip::EndpointId destination_endpoint, - uint16_t groupId, uint8_t sceneId, uint16_t transitionTime); +chip::System::PacketBufferHandle encodeScenesClusterRecallSceneCommand(chip::EndpointId destinationEndpoint, uint16_t groupId, + uint8_t sceneId, uint16_t transitionTime); /** * @brief * Encode an RemoveAllScenes command for Scenes server into buffer including the APS frame */ -uint16_t encodeScenesClusterRemoveAllScenesCommand(uint8_t * buffer, uint16_t buf_length, chip::EndpointId destination_endpoint, - uint16_t groupId); +chip::System::PacketBufferHandle encodeScenesClusterRemoveAllScenesCommand(chip::EndpointId destinationEndpoint, uint16_t groupId); /** * @brief * Encode an RemoveScene command for Scenes server into buffer including the APS frame */ -uint16_t encodeScenesClusterRemoveSceneCommand(uint8_t * buffer, uint16_t buf_length, chip::EndpointId destination_endpoint, - uint16_t groupId, uint8_t sceneId); +chip::System::PacketBufferHandle encodeScenesClusterRemoveSceneCommand(chip::EndpointId destinationEndpoint, uint16_t groupId, + uint8_t sceneId); /** * @brief * Encode an StoreScene command for Scenes server into buffer including the APS frame */ -uint16_t encodeScenesClusterStoreSceneCommand(uint8_t * buffer, uint16_t buf_length, chip::EndpointId destination_endpoint, - uint16_t groupId, uint8_t sceneId); +chip::System::PacketBufferHandle encodeScenesClusterStoreSceneCommand(chip::EndpointId destinationEndpoint, uint16_t groupId, + uint8_t sceneId); /** * @brief * Encode an ViewScene command for Scenes server into buffer including the APS frame */ -uint16_t encodeScenesClusterViewSceneCommand(uint8_t * buffer, uint16_t buf_length, chip::EndpointId destination_endpoint, - uint16_t groupId, uint8_t sceneId); +chip::System::PacketBufferHandle encodeScenesClusterViewSceneCommand(chip::EndpointId destinationEndpoint, uint16_t groupId, + uint8_t sceneId); /** * @brief * Encode a Scenes server discover command into buffer including the APS frame */ -uint16_t encodeScenesClusterDiscoverAttributes(uint8_t * buffer, uint16_t buf_length, chip::EndpointId destination_endpoint); +chip::System::PacketBufferHandle encodeScenesClusterDiscoverAttributes(chip::EndpointId destinationEndpoint); /** * @brief * Encode a Scenes server read command for the scene count attribute into buffer including the APS frame */ -uint16_t encodeScenesClusterReadSceneCountAttribute(uint8_t * buffer, uint16_t buf_length, chip::EndpointId destination_endpoint); +chip::System::PacketBufferHandle encodeScenesClusterReadSceneCountAttribute(chip::EndpointId destinationEndpoint); /** * @brief * Encode a Scenes server read command for the current scene attribute into buffer including the APS frame */ -uint16_t encodeScenesClusterReadCurrentSceneAttribute(uint8_t * buffer, uint16_t buf_length, chip::EndpointId destination_endpoint); +chip::System::PacketBufferHandle encodeScenesClusterReadCurrentSceneAttribute(chip::EndpointId destinationEndpoint); /** * @brief * Encode a Scenes server read command for the current group attribute into buffer including the APS frame */ -uint16_t encodeScenesClusterReadCurrentGroupAttribute(uint8_t * buffer, uint16_t buf_length, chip::EndpointId destination_endpoint); +chip::System::PacketBufferHandle encodeScenesClusterReadCurrentGroupAttribute(chip::EndpointId destinationEndpoint); /** * @brief * Encode a Scenes server read command for the scene valid attribute into buffer including the APS frame */ -uint16_t encodeScenesClusterReadSceneValidAttribute(uint8_t * buffer, uint16_t buf_length, chip::EndpointId destination_endpoint); +chip::System::PacketBufferHandle encodeScenesClusterReadSceneValidAttribute(chip::EndpointId destinationEndpoint); /** * @brief * Encode a Scenes server read command for the name support attribute into buffer including the APS frame */ -uint16_t encodeScenesClusterReadNameSupportAttribute(uint8_t * buffer, uint16_t buf_length, chip::EndpointId destination_endpoint); +chip::System::PacketBufferHandle encodeScenesClusterReadNameSupportAttribute(chip::EndpointId destinationEndpoint); /** * @brief * Encode a Scenes server read command for the cluster revision attribute into buffer including the APS frame */ -uint16_t encodeScenesClusterReadClusterRevisionAttribute(uint8_t * buffer, uint16_t buf_length, - chip::EndpointId destination_endpoint); +chip::System::PacketBufferHandle encodeScenesClusterReadClusterRevisionAttribute(chip::EndpointId destinationEndpoint); /*----------------------------------------------------------------------------*\ | Cluster TemperatureMeasurement | 0x0402 | @@ -1572,46 +1487,40 @@ uint16_t encodeScenesClusterReadClusterRevisionAttribute(uint8_t * buffer, uint1 * @brief * Encode a Temperature Measurement server discover command into buffer including the APS frame */ -uint16_t encodeTemperatureMeasurementClusterDiscoverAttributes(uint8_t * buffer, uint16_t buf_length, - chip::EndpointId destination_endpoint); +chip::System::PacketBufferHandle encodeTemperatureMeasurementClusterDiscoverAttributes(chip::EndpointId destinationEndpoint); /** * @brief * Encode a Temperature Measurement server read command for the measured value attribute into buffer including the APS frame */ -uint16_t encodeTemperatureMeasurementClusterReadMeasuredValueAttribute(uint8_t * buffer, uint16_t buf_length, - chip::EndpointId destination_endpoint); +chip::System::PacketBufferHandle +encodeTemperatureMeasurementClusterReadMeasuredValueAttribute(chip::EndpointId destinationEndpoint); /** * @brief * Encode a Temperature Measurement server report command for the measured value attribute into buffer including the APS frame */ -uint16_t encodeTemperatureMeasurementClusterReportMeasuredValueAttribute(uint8_t * buffer, uint16_t buf_length, - chip::EndpointId destination_endpoint, - uint16_t min_interval, uint16_t max_interval, - int16_t change); +chip::System::PacketBufferHandle +encodeTemperatureMeasurementClusterReportMeasuredValueAttribute(chip::EndpointId destinationEndpoint, uint16_t minInterval, + uint16_t maxInterval, int16_t change); /** * @brief * Encode a Temperature Measurement server read command for the min measured value attribute into buffer including the APS frame */ -uint16_t encodeTemperatureMeasurementClusterReadMinMeasuredValueAttribute(uint8_t * buffer, uint16_t buf_length, - chip::EndpointId destination_endpoint); +chip::System::PacketBufferHandle +encodeTemperatureMeasurementClusterReadMinMeasuredValueAttribute(chip::EndpointId destinationEndpoint); /** * @brief * Encode a Temperature Measurement server read command for the max measured value attribute into buffer including the APS frame */ -uint16_t encodeTemperatureMeasurementClusterReadMaxMeasuredValueAttribute(uint8_t * buffer, uint16_t buf_length, - chip::EndpointId destination_endpoint); +chip::System::PacketBufferHandle +encodeTemperatureMeasurementClusterReadMaxMeasuredValueAttribute(chip::EndpointId destinationEndpoint); /** * @brief * Encode a Temperature Measurement server read command for the cluster revision attribute into buffer including the APS frame */ -uint16_t encodeTemperatureMeasurementClusterReadClusterRevisionAttribute(uint8_t * buffer, uint16_t buf_length, - chip::EndpointId destination_endpoint); - -#ifdef __cplusplus -} // extern "C" -#endif +chip::System::PacketBufferHandle +encodeTemperatureMeasurementClusterReadClusterRevisionAttribute(chip::EndpointId destinationEndpoint); diff --git a/src/app/clusters/bindings/bindings.cpp b/src/app/clusters/bindings/bindings.cpp new file mode 100644 index 00000000000000..b54242bbd0d3df --- /dev/null +++ b/src/app/clusters/bindings/bindings.cpp @@ -0,0 +1,140 @@ +/* + * + * 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 + * @brief Implementation for the Binding Server Cluster + ***************************************************************************/ + +#include "af.h" + +#include +#include + +using namespace chip; + +EmberStatus prepareBinding(EmberBindingTableEntry & binding, NodeId nodeId, GroupId groupId, EndpointId endpointId, + ClusterId clusterId) +{ + if (groupId && nodeId) + { + return EMBER_BAD_ARGUMENT; + } + + binding.clusterId = clusterId; + binding.local = emberAfCurrentCommand()->apsFrame->destinationEndpoint; + binding.networkIndex = 0; + + if (groupId) + { + binding.type = EMBER_MULTICAST_BINDING; + binding.groupId = groupId; + binding.remote = 0; + } + else + { + binding.type = EMBER_UNICAST_BINDING; + binding.nodeId = nodeId; + binding.remote = endpointId; + } + + return EMBER_SUCCESS; +} + +EmberStatus getBindingIndex(EmberBindingTableEntry & newEntry, uint8_t * bindingIndex) +{ + EmberBindingTableEntry currentEntry; + for (uint8_t i = 0; i < EMBER_BINDING_TABLE_SIZE; i++) + { + emberGetBinding(i, ¤tEntry); + if (currentEntry.type != EMBER_UNUSED_BINDING && currentEntry == newEntry) + { + *bindingIndex = i; + return EMBER_SUCCESS; + } + } + + return EMBER_NOT_FOUND; +} + +EmberStatus getUnusedBindingIndex(uint8_t * bindingIndex) +{ + EmberBindingTableEntry currentEntry; + for (uint8_t i = 0; i < EMBER_BINDING_TABLE_SIZE; i++) + { + emberGetBinding(i, ¤tEntry); + if (currentEntry.type == EMBER_UNUSED_BINDING) + { + *bindingIndex = i; + return EMBER_SUCCESS; + } + } + + return EMBER_NOT_FOUND; +} + +bool emberAfBindingClusterBindCallback(NodeId nodeId, GroupId groupId, EndpointId endpointId, ClusterId clusterId) +{ + ChipLogDetail(Zcl, "RX: BindCallback"); + + EmberBindingTableEntry bindingEntry; + if (prepareBinding(bindingEntry, nodeId, groupId, endpointId, clusterId) != EMBER_SUCCESS) + { + emberAfSendImmediateDefaultResponse(EMBER_ZCL_STATUS_MALFORMED_COMMAND); + return true; + } + + uint8_t bindingIndex; + if (getBindingIndex(bindingEntry, &bindingIndex) != EMBER_NOT_FOUND) + { + emberAfSendImmediateDefaultResponse(EMBER_ZCL_STATUS_DUPLICATE_EXISTS); + return true; + } + + if (getUnusedBindingIndex(&bindingIndex) != EMBER_SUCCESS) + { + emberAfSendImmediateDefaultResponse(EMBER_ZCL_STATUS_INSUFFICIENT_SPACE); + return true; + } + + emberSetBinding(bindingIndex, &bindingEntry); + emberAfSendImmediateDefaultResponse(EMBER_ZCL_STATUS_SUCCESS); + return true; +} + +bool emberAfBindingClusterUnbindCallback(NodeId nodeId, GroupId groupId, EndpointId endpointId, ClusterId clusterId) +{ + ChipLogDetail(Zcl, "RX: UnbindCallback"); + + EmberBindingTableEntry bindingEntry; + if (prepareBinding(bindingEntry, nodeId, groupId, endpointId, clusterId) != EMBER_SUCCESS) + { + emberAfSendImmediateDefaultResponse(EMBER_ZCL_STATUS_MALFORMED_COMMAND); + return true; + } + + uint8_t bindingIndex; + if (getBindingIndex(bindingEntry, &bindingIndex) != EMBER_SUCCESS) + { + emberAfSendImmediateDefaultResponse(EMBER_ZCL_STATUS_NOT_FOUND); + return true; + } + + emberDeleteBinding(bindingIndex); + emberAfSendImmediateDefaultResponse(EMBER_ZCL_STATUS_SUCCESS); + return true; +} diff --git a/src/app/clusters/temperature-measurement-server/temperature-measurement-server.cpp b/src/app/clusters/temperature-measurement-server/temperature-measurement-server.cpp index c8a000f2f5af7e..f1e2f7a233e480 100644 --- a/src/app/clusters/temperature-measurement-server/temperature-measurement-server.cpp +++ b/src/app/clusters/temperature-measurement-server/temperature-measurement-server.cpp @@ -52,6 +52,8 @@ EmberEventControl emberAfPluginTemperatureMeasurementServerReadEventControl; // https://github.com/project-chip/connectedhomeip/issues/3619 void emberAfPluginTemperatureMeasurementServerReadEventHandler() {} +void emberAfPluginTemperatureMeasurementServerStackStatusCallback(EmberStatus status) {} + // ------------------------------------------------------------------------- // ****** callback section ******* diff --git a/src/app/clusters/zll-identify-server/zll-identify-server.c b/src/app/clusters/zll-identify-server/zll-identify-server.c new file mode 100644 index 00000000000000..e76abf6ea8c1ff --- /dev/null +++ b/src/app/clusters/zll-identify-server/zll-identify-server.c @@ -0,0 +1,254 @@ +/** + * + * 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. + */ + +/** + * + * Copyright (c) 2020 Silicon Labs + * + * 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 + * @brief Routines for the ZLL Identify Server plugin, + * which contains additions to the Identify server + * cluster. + ******************************************************************************* + * # License + * Copyright 2018 Silicon Laboratories Inc. www.silabs.com + ******************************************************************************* + * + * The licensor of this software is Silicon + * Laboratories Inc. Your use of this software is + * governed by the terms of Silicon Labs Master + * Software License Agreement (MSLA) available at + * www.silabs.com/about-us/legal/master-software-license-agreement. + * This software is distributed to you in Source Code + * format and is governed by the sections of the MSLA + * applicable to Source Code. + * + ******************************************************************************/ + +// this file contains all the common includes for clusters in the util +#include "app/framework/include/af.h" +#include "app/framework/util/common.h" + +#ifndef EZSP_HOST +#include "hal/hal.h" +#endif + +typedef struct +{ + bool active; + bool cancel; + EmberAfIdentifyEffectIdentifier effectId; + EmberAfIdentifyEffectVariant commandVariant; + uint8_t eventsRemaining; + uint16_t eventDelay; +} EmAfZllIdentifyState; + +void emAfPluginZllIdentifyServerBlinkEffect(uint8_t endpoint); + +void emAfPluginZllIdentifyServerBreatheEffect(uint8_t endpoint); + +void emAfPluginZllIdentifyServerOkayEffect(uint8_t endpoint); + +void emAfPluginZllIdentifyServerChannelChangeEffect(uint8_t endpoint); + +extern EmberEventControl emberAfPluginZllIdentifyServerTriggerEffectEndpointEventControls[]; + +static EmAfZllIdentifyState stateTable[EMBER_AF_IDENTIFY_CLUSTER_SERVER_ENDPOINT_COUNT]; + +static EmAfZllIdentifyState * getZllIdentifyState(uint8_t endpoint); + +static void deactivateZllIdentify(EmAfZllIdentifyState * state, uint8_t endpoint); + +static EmAfZllIdentifyState * getZllIdentifyState(uint8_t endpoint) +{ + uint8_t index = emberAfFindClusterServerEndpointIndex(endpoint, ZCL_IDENTIFY_CLUSTER_ID); + return (index == 0xFF ? NULL : &stateTable[index]); +} + +static void deactivateZllIdentify(EmAfZllIdentifyState * state, uint8_t endpoint) +{ + if (state == NULL) + { + return; + } + + state->active = false; + state->cancel = false; + + emberAfEndpointEventControlSetInactive(emberAfPluginZllIdentifyServerTriggerEffectEndpointEventControls, endpoint); +} + +void emberAfPluginZllIdentifyServerTriggerEffectEndpointEventHandler(uint8_t endpoint) +{ + EmAfZllIdentifyState * state = getZllIdentifyState(endpoint); + + if (state == NULL) + { + return; + } + + switch (state->effectId) + { + case EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_BLINK: + emAfPluginZllIdentifyServerBlinkEffect(endpoint); + break; + case EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_BREATHE: + emAfPluginZllIdentifyServerBreatheEffect(endpoint); + break; + case EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_OKAY: + emAfPluginZllIdentifyServerOkayEffect(endpoint); + break; + case EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_CHANNEL_CHANGE: + emAfPluginZllIdentifyServerChannelChangeEffect(endpoint); + break; + case EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_FINISH_EFFECT: // At this point, these are functionally equivalent + case EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_STOP_EFFECT: + default: + deactivateZllIdentify(state, endpoint); + return; + } + if (state->cancel) + { + deactivateZllIdentify(state, endpoint); + return; + } + + if (state->active) + { + emberAfEndpointEventControlSetDelayMS(emberAfPluginZllIdentifyServerTriggerEffectEndpointEventControls, endpoint, + state->eventDelay); + } +} + +bool emberAfIdentifyClusterTriggerEffectCallback(uint8_t effectId, uint8_t effectVariant) +{ + uint8_t endpoint = emberAfCurrentEndpoint(); + EmAfZllIdentifyState * state = getZllIdentifyState(endpoint); + EmberAfStatus status; + + if (state == NULL) + { + status = EMBER_ZCL_STATUS_FAILURE; + goto default_response; + } + + emberAfIdentifyClusterPrintln("RX identify:trigger effect 0x%x variant 0x%x", effectId, effectVariant); + + if (state->active) + { + switch (state->effectId) + { + case EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_FINISH_EFFECT: + state->cancel = true; + status = EMBER_ZCL_STATUS_SUCCESS; + break; + case EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_STOP_EFFECT: + deactivateZllIdentify(state, endpoint); + status = EMBER_ZCL_STATUS_SUCCESS; + goto default_response; + default: + status = EMBER_ZCL_STATUS_FAILURE; + break; + } + } + else + { + switch (effectId) + { + case EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_BLINK: + state->eventsRemaining = EMBER_AF_PLUGIN_ZLL_IDENTIFY_SERVER_BLINK_EVENTS; + break; + case EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_BREATHE: + state->eventsRemaining = EMBER_AF_PLUGIN_ZLL_IDENTIFY_SERVER_BREATHE_EVENTS; + break; + case EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_OKAY: + state->eventsRemaining = EMBER_AF_PLUGIN_ZLL_IDENTIFY_SERVER_OKAY_EVENTS; + break; + case EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_CHANNEL_CHANGE: + state->eventsRemaining = EMBER_AF_PLUGIN_ZLL_IDENTIFY_SERVER_CHANNEL_CHANGE_EVENTS; + break; + case EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_FINISH_EFFECT: // At this point, these are functionally equivalent + case EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_STOP_EFFECT: + status = EMBER_ZCL_STATUS_SUCCESS; + goto default_response; + default: + status = EMBER_ZCL_STATUS_FAILURE; + goto default_response; + } + state->active = true; + state->cancel = false; + state->effectId = (EmberAfIdentifyEffectIdentifier) effectId; + state->commandVariant = (EmberAfIdentifyEffectVariant) effectVariant; + state->eventDelay = EMBER_AF_PLUGIN_ZLL_IDENTIFY_SERVER_EVENT_DELAY; + emberAfEndpointEventControlSetDelayMS(emberAfPluginZllIdentifyServerTriggerEffectEndpointEventControls, endpoint, + state->eventDelay); + status = EMBER_ZCL_STATUS_SUCCESS; + } + +default_response: + emberAfSendImmediateDefaultResponse(status); + return true; +} + +void emAfPluginZllIdentifyServerBlinkEffect(uint8_t endpoint) +{ + EmAfZllIdentifyState * state = getZllIdentifyState(endpoint); + + if (state == NULL || state->eventsRemaining == 0) + { + deactivateZllIdentify(state, endpoint); + return; + } + +#ifndef EZSP_HOST + halToggleLed(BOARDLED0); + halToggleLed(BOARDLED1); + halToggleLed(BOARDLED2); + halToggleLed(BOARDLED3); +#endif + + state->eventsRemaining = state->eventsRemaining - 1; +} + +void emAfPluginZllIdentifyServerBreatheEffect(uint8_t endpoint) +{ + emAfPluginZllIdentifyServerBlinkEffect(endpoint); +} + +void emAfPluginZllIdentifyServerOkayEffect(uint8_t endpoint) +{ + emAfPluginZllIdentifyServerBlinkEffect(endpoint); +} + +void emAfPluginZllIdentifyServerChannelChangeEffect(uint8_t endpoint) +{ + emAfPluginZllIdentifyServerBlinkEffect(endpoint); +} diff --git a/src/app/clusters/zll-level-control-server/zll-level-control-server.c b/src/app/clusters/zll-level-control-server/zll-level-control-server.c new file mode 100644 index 00000000000000..8837ec9d51d4cc --- /dev/null +++ b/src/app/clusters/zll-level-control-server/zll-level-control-server.c @@ -0,0 +1,91 @@ +/** + * + * Copyright (c) 2020 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * + * Copyright (c) 2020 Silicon Labs + * + * 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 + * @brief Routines for the ZLL Level Control Server plugin. + ******************************************************************************* + * # License + * Copyright 2018 Silicon Laboratories Inc. + * www.silabs.com + ******************************************************************************* + * + * The licensor of this software is Silicon + * Laboratories Inc. Your use of this software is + * governed by the terms of Silicon Labs Master + * Software License Agreement (MSLA) available at + * www.silabs.com/about-us/legal/master-software-license-agreement. + * This software is distributed to you in Source Code + * format and is governed by the sections of the MSLA + * applicable to Source Code. + * + ******************************************************************************/ + +#include "zll-level-control-server.h" +#include "../../include/af.h" + +EmberAfStatus emberAfPluginZllLevelControlServerMoveToLevelWithOnOffZllExtensions(const EmberAfClusterCommand * cmd) +{ + bool globalSceneControl = true; + EmberAfStatus status = emberAfWriteServerAttribute(cmd->apsFrame->destinationEndpoint, ZCL_ON_OFF_CLUSTER_ID, + ZCL_GLOBAL_SCENE_CONTROL_ATTRIBUTE_ID, (uint8_t *) &globalSceneControl, + ZCL_BOOLEAN_ATTRIBUTE_TYPE); + if (status != EMBER_ZCL_STATUS_SUCCESS) + { + emberAfLevelControlClusterPrintln("ERR: writing global scene control %x", status); + } + return status; +} + +bool emberAfPluginZllLevelControlServerIgnoreMoveToLevelMoveStepStop(uint8_t endpoint, uint8_t commandId) +{ + // If a MoveToLevel, Move, Step, or Stop command is received while the device + // is in its off state (i.e., the OnOff attribute of the On/Off cluster is + // equal to false), the command shall be ignored. + bool onOff = true; +#ifdef ZCL_USING_ON_OFF_CLUSTER_SERVER + if ((commandId == ZCL_MOVE_TO_LEVEL_COMMAND_ID || commandId == ZCL_MOVE_COMMAND_ID || commandId == ZCL_STEP_COMMAND_ID || + commandId == ZCL_STOP_COMMAND_ID) && + emberAfContainsServer(endpoint, ZCL_ON_OFF_CLUSTER_ID)) + { + EmberAfStatus status = + emberAfReadServerAttribute(endpoint, ZCL_ON_OFF_CLUSTER_ID, ZCL_ON_OFF_ATTRIBUTE_ID, (uint8_t *) &onOff, sizeof(onOff)); + if (status != EMBER_ZCL_STATUS_SUCCESS) + { + emberAfLevelControlClusterPrintln("ERR: reading on/off %x", status); + } + } +#endif + return !onOff; +} diff --git a/src/app/clusters/zll-level-control-server/zll-level-control-server.h b/src/app/clusters/zll-level-control-server/zll-level-control-server.h new file mode 100644 index 00000000000000..11510d085e02ee --- /dev/null +++ b/src/app/clusters/zll-level-control-server/zll-level-control-server.h @@ -0,0 +1,59 @@ +/** + * + * 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. + */ + +/** + * + * Copyright (c) 2020 Silicon Labs + * + * 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 + * @brief Definitions for the ZLL Level Control Server plugin. + ******************************************************************************* + * # License + * Copyright 2018 Silicon Laboratories Inc. + * www.silabs.com + ******************************************************************************* + * + * The licensor of this software is Silicon + * Laboratories Inc. Your use of this software is + * governed by the terms of Silicon Labs Master + * Software License Agreement (MSLA) available at + * www.silabs.com/about-us/legal/master-software-license-agreement. + * This software is distributed to you in Source Code + * format and is governed by the sections of the MSLA + * applicable to Source Code. + * + ******************************************************************************/ + +#define EMBER_AF_PLUGIN_ZLL_LEVEL_CONTROL_SERVER_MINIMUM_LEVEL 0x01 +#define EMBER_AF_PLUGIN_ZLL_LEVEL_CONTROL_SERVER_MAXIMUM_LEVEL 0xFE + +EmberAfStatus emberAfPluginZllLevelControlServerMoveToLevelWithOnOffZllExtensions(const EmberAfClusterCommand * cmd); +bool emberAfPluginZllLevelControlServerIgnoreMoveToLevelMoveStepStop(uint8_t endpoint, uint8_t commandId); diff --git a/src/app/clusters/zll-on-off-server/zll-on-off-server.c b/src/app/clusters/zll-on-off-server/zll-on-off-server.c new file mode 100644 index 00000000000000..f168b34366bfa7 --- /dev/null +++ b/src/app/clusters/zll-on-off-server/zll-on-off-server.c @@ -0,0 +1,481 @@ +/** + * + * 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. + */ + +/** + * + * Copyright (c) 2020 Silicon Labs + * + * 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 + * @brief Routines for the ZLL On Off Server plugin. + ******************************************************************************* + * # License + * Copyright 2018 Silicon Laboratories Inc. + * www.silabs.com + ******************************************************************************* + * + * The licensor of this software is Silicon + * Laboratories Inc. Your use of this software is + * governed by the terms of Silicon Labs Master + * Software License Agreement (MSLA) available at + * www.silabs.com/about-us/legal/master-software-license-agreement. + * This software is distributed to you in Source Code + * format and is governed by the sections of the MSLA + * applicable to Source Code. + * + ******************************************************************************/ + +#include "zll-on-off-server.h" +#include "../../include/af.h" + +#define ZLL_ON_OFF_CLUSTER_ON_OFF_CONTROL_ACCEPT_ONLY_WHEN_ON_MASK BIT(0) + +#define readOnOff(endpoint, onOff) readBoolean((endpoint), ZCL_ON_OFF_ATTRIBUTE_ID, "on/off", (onOff)) +#define writeOnOff(endpoint, onOff) writeBoolean((endpoint), ZCL_ON_OFF_ATTRIBUTE_ID, "on/off", (onOff)) +#define readGlobalSceneControl(endpoint, globalSceneControl) \ + readBoolean((endpoint), ZCL_GLOBAL_SCENE_CONTROL_ATTRIBUTE_ID, "global scene control", (globalSceneControl)) +#define writeGlobalSceneControl(endpoint, globalSceneControl) \ + writeBoolean((endpoint), ZCL_GLOBAL_SCENE_CONTROL_ATTRIBUTE_ID, "global scene control", (globalSceneControl)) +#define readOnTime(endpoint, onTime) readInt16u((endpoint), ZCL_ON_TIME_ATTRIBUTE_ID, "on time", (onTime)) +#define writeOnTime(endpoint, onTime) writeInt16u((endpoint), ZCL_ON_TIME_ATTRIBUTE_ID, "on time", (onTime)) +#define readOffWaitTime(endpoint, offWaitTime) \ + readInt16u((endpoint), ZCL_OFF_WAIT_TIME_ATTRIBUTE_ID, "off wait time", (offWaitTime)) +#define writeOffWaitTime(endpoint, offWaitTime) \ + writeInt16u((endpoint), ZCL_OFF_WAIT_TIME_ATTRIBUTE_ID, "off wait time", (offWaitTime)) + +static EmberAfStatus readBoolean(uint8_t endpoint, EmberAfAttributeId attribute, const char * name, bool * value) +{ + EmberAfStatus status = emberAfReadServerAttribute(endpoint, ZCL_ON_OFF_CLUSTER_ID, attribute, (uint8_t *) value, sizeof(bool)); + if (status != EMBER_ZCL_STATUS_SUCCESS) + { + emberAfOnOffClusterPrintln("ERR: %ping %p %x", "read", name, status); + } + return status; +} + +static EmberAfStatus writeBoolean(uint8_t endpoint, EmberAfAttributeId attribute, const char * name, bool value) +{ + EmberAfStatus status = + emberAfWriteServerAttribute(endpoint, ZCL_ON_OFF_CLUSTER_ID, attribute, (uint8_t *) &value, ZCL_BOOLEAN_ATTRIBUTE_TYPE); + if (status != EMBER_ZCL_STATUS_SUCCESS) + { + emberAfOnOffClusterPrintln("ERR: %ping %p %x", "writ", name, status); + } + return status; +} + +static EmberAfStatus readInt16u(uint8_t endpoint, EmberAfAttributeId attribute, const char * name, uint16_t * value) +{ + EmberAfStatus status = + emberAfReadServerAttribute(endpoint, ZCL_ON_OFF_CLUSTER_ID, attribute, (uint8_t *) value, sizeof(uint16_t)); + if (status != EMBER_ZCL_STATUS_SUCCESS) + { + emberAfOnOffClusterPrintln("ERR: %ping %p %x", "read", name, status); + } + return status; +} + +static EmberAfStatus writeInt16u(uint8_t endpoint, EmberAfAttributeId attribute, const char * name, uint16_t value) +{ + EmberAfStatus status = + emberAfWriteServerAttribute(endpoint, ZCL_ON_OFF_CLUSTER_ID, attribute, (uint8_t *) &value, ZCL_INT16U_ATTRIBUTE_TYPE); + if (status != EMBER_ZCL_STATUS_SUCCESS) + { + emberAfOnOffClusterPrintln("ERR: %ping %p %x", "writ", name, status); + } + return status; +} + +void emberAfOnOffClusterServerTickCallback(uint8_t endpoint) +{ + uint16_t onTime, offWaitTime; + bool onOff; + + if (readOnOff(endpoint, &onOff) != EMBER_ZCL_STATUS_SUCCESS || readOnTime(endpoint, &onTime) != EMBER_ZCL_STATUS_SUCCESS || + readOffWaitTime(endpoint, &offWaitTime) != EMBER_ZCL_STATUS_SUCCESS) + { + return; + } + + // If the values of the OnTime and OffWaitTime attributes are both less than + // 0xFFFF, the device shall then update the device every 1/10th second until + // both the OnTime and OffWaitTime attributes are equal to 0x0000, as + // follows: + // + // If the value of the OnOff attribute is equal to 0x01 (on) and the value + // of the OnTime attribute is greater than zero, the device shall decrement + // the value of the OnTime attribute. If the value of the OnTime attribute + // reaches 0x0000, the device shall set the OffWaitTime and OnOff + // attributes to 0x0000 and 0x00, respectively. + // + // If the value of the OnOff attribute is equal to 0x00 (off) and the value + // of the OffWaitTime attribute is greater than zero, the device shall + // decrement the value of the OffWaitTime attribute. If the value of the + // OffWaitTime attribute reaches 0x0000, the device shall terminate the + // update. + if (onOff && 0x0000 < onTime) + { + onTime--; + writeOnTime(endpoint, onTime); + if (onTime == 0x0000) + { + offWaitTime = 0x0000; + writeOffWaitTime(endpoint, offWaitTime); + onOff = false; + writeOnOff(endpoint, onOff); + return; + } + } + else if (!onOff && 0x0000 < offWaitTime) + { + offWaitTime--; + writeOffWaitTime(endpoint, offWaitTime); + if (offWaitTime == 0x0000) + { + return; + } + } + + emberAfScheduleServerTick(endpoint, ZCL_ON_OFF_CLUSTER_ID, MILLISECOND_TICKS_PER_SECOND / 10); +} + +bool emberAfOnOffClusterOffWithEffectCallback(uint8_t effectId, uint8_t effectVariant) +{ + EmberAfStatus status = EMBER_ZCL_STATUS_INVALID_VALUE; + bool globalSceneControl; + uint8_t endpoint = emberAfCurrentEndpoint(); + + // Ensure parameters have values withing proper range. + if (effectId > EMBER_ZCL_ON_OFF_EFFECT_IDENTIFIER_DYING_LIGHT || + effectVariant > + EMBER_ZCL_ON_OFF_DELAYED_ALL_OFF_EFFECT_VARIANT_50_PERCENT_DIM_DOWN_IN_0P8_SECONDS_THEN_FADE_TO_OFF_IN_12_SECONDS || + (effectId == EMBER_ZCL_ON_OFF_EFFECT_IDENTIFIER_DYING_LIGHT && + effectVariant > + EMBER_ZCL_ON_OFF_DYING_LIGHT_EFFECT_VARIANT_20_PERCENTER_DIM_UP_IN_0P5_SECONDS_THEN_FADE_TO_OFF_IN_1_SECOND)) + { + goto kickout; + } + + // If the GlobalSceneControl attribute is equal to true, the application on + // the associated endpoint shall store its settings in its global scene then + // set the GlobalSceneControl attribute to false. + status = readGlobalSceneControl(endpoint, &globalSceneControl); + if (status != EMBER_ZCL_STATUS_SUCCESS) + { + goto kickout; + } + else if (globalSceneControl) + { + status = emberAfScenesClusterStoreCurrentSceneCallback(endpoint, ZCL_SCENES_GLOBAL_SCENE_GROUP_ID, + ZCL_SCENES_GLOBAL_SCENE_SCENE_ID); + if (status != EMBER_ZCL_STATUS_SUCCESS) + { + emberAfOnOffClusterPrintln("ERR: %ping %p %x", "stor", "global scene", status); + goto kickout; + } + globalSceneControl = false; + status = writeGlobalSceneControl(endpoint, globalSceneControl); + if (status != EMBER_ZCL_STATUS_SUCCESS) + { + goto kickout; + } + } + + // The application will handle the actual effect and variant. + status = emberAfPluginZllOnOffServerOffWithEffectCallback(endpoint, effectId, effectVariant); + if (status == EMBER_ZCL_STATUS_SUCCESS) + { + // If the application handled the effect, the endpoint shall enter its + // "off" state, update the OnOff attribute accordingly, and set the OnTime + // attribute to 0x0000. + status = emberAfOnOffClusterSetValueCallback(endpoint, ZCL_OFF_COMMAND_ID, false); + if (status == EMBER_ZCL_STATUS_SUCCESS) + { + status = writeOnTime(endpoint, 0x0000); + } + } + +kickout: + emberAfSendImmediateDefaultResponse(status); + return true; +} + +bool emberAfOnOffClusterOnWithRecallGlobalSceneCallback(void) +{ + EmberAfStatus status; + bool globalSceneControl; + uint8_t endpoint = emberAfCurrentEndpoint(); + + status = readGlobalSceneControl(endpoint, &globalSceneControl); + if (status != EMBER_ZCL_STATUS_SUCCESS) + { + goto kickout; + } + else if (!globalSceneControl) + { + uint16_t onTime; + status = emberAfScenesClusterRecallSavedSceneCallback(endpoint, ZCL_SCENES_GLOBAL_SCENE_GROUP_ID, + ZCL_SCENES_GLOBAL_SCENE_SCENE_ID); + if (status != EMBER_ZCL_STATUS_SUCCESS) + { + emberAfOnOffClusterPrintln("ERR: %ping %p %x", "recall", "global scene", status); + goto kickout; + } + globalSceneControl = true; + status = writeGlobalSceneControl(endpoint, globalSceneControl); + if (status != EMBER_ZCL_STATUS_SUCCESS) + { + goto kickout; + } + status = readOnTime(endpoint, &onTime); + if (status != EMBER_ZCL_STATUS_SUCCESS) + { + goto kickout; + } + if (onTime == 0x0000) + { + status = writeOffWaitTime(endpoint, 0x0000); + if (status != EMBER_ZCL_STATUS_SUCCESS) + { + goto kickout; + } + } + } + else + { + goto kickout; + } + +kickout: + emberAfSendImmediateDefaultResponse(status); + return true; +} + +bool emberAfOnOffClusterOnWithTimedOffCallback(uint8_t onOffControl, uint16_t onTime, uint16_t offWaitTime) +{ + EmberAfStatus status; + uint16_t onTimeAttribute, offWaitTimeAttribute; + bool onOffAttribute; + uint8_t endpoint = emberAfCurrentEndpoint(); + + // The valid range of the OnTime and OffWaitTime fields is 0x0000 to 0xFFFF. + if (onTime == 0xFFFF || offWaitTime == 0xFFFF) + { + status = EMBER_ZCL_STATUS_INVALID_FIELD; + goto kickout; + } + + // On receipt of this command, if the accept only when on sub-field of the + // on/off control field is set to 1 and the value of the OnOff attribute is + // equal to 0x00 (off), the command shall be discarded. + status = readOnOff(endpoint, &onOffAttribute); + if (status != EMBER_ZCL_STATUS_SUCCESS) + { + goto kickout; + } + else if ((onOffControl & ZLL_ON_OFF_CLUSTER_ON_OFF_CONTROL_ACCEPT_ONLY_WHEN_ON_MASK) && !onOffAttribute) + { + goto kickout; + } + + status = readOnTime(endpoint, &onTimeAttribute); + if (status != EMBER_ZCL_STATUS_SUCCESS) + { + goto kickout; + } + status = readOffWaitTime(endpoint, &offWaitTimeAttribute); + if (status != EMBER_ZCL_STATUS_SUCCESS) + { + goto kickout; + } + + // If the value of the OffWaitTime attribute is greater than zero and the + // value of the OnOff attribute is equal to 0x00, then the device shall set + // the OffWaitTime attribute to the minimum of the OffWaitTime attribute and + // the value specified in the off wait time field. In all other cases, the + // device shall set the OnTime attribute to the maximum of the OnTime + // attribute and the value specified in the on time field, set the + // OffWaitTime attribute to the value specified in the off wait time field + // and set the OnOff attribute to 0x01 (on). + if (0x0000 < offWaitTimeAttribute && !onOffAttribute) + { + if (offWaitTime < offWaitTimeAttribute) + { + offWaitTimeAttribute = offWaitTime; + } + status = writeOffWaitTime(endpoint, offWaitTimeAttribute); + if (status != EMBER_ZCL_STATUS_SUCCESS) + { + goto kickout; + } + } + else + { + if (onTimeAttribute < onTime) + { + onTimeAttribute = onTime; + } + status = writeOnTime(endpoint, onTimeAttribute); + if (status != EMBER_ZCL_STATUS_SUCCESS) + { + goto kickout; + } + offWaitTimeAttribute = offWaitTime; + status = writeOffWaitTime(endpoint, offWaitTimeAttribute); + if (status != EMBER_ZCL_STATUS_SUCCESS) + { + goto kickout; + } + onOffAttribute = true; + status = writeOnOff(endpoint, onOffAttribute); + if (status != EMBER_ZCL_STATUS_SUCCESS) + { + goto kickout; + } + } + + // If the values of the OnTime and OffWaitTime attributes are both less than + // 0xFFFF, the device shall then update the device every 1/10th second until + // both the OnTime and OffWaitTime attributes are equal to 0x0000. + if (onTimeAttribute < 0xFFFF && offWaitTimeAttribute < 0xFFFF) + { + emberAfScheduleServerTick(endpoint, ZCL_ON_OFF_CLUSTER_ID, MILLISECOND_TICKS_PER_SECOND / 10); + } + else + { + emberAfDeactivateServerTick(endpoint, ZCL_ON_OFF_CLUSTER_ID); + } + +kickout: + emberAfSendImmediateDefaultResponse(status); + return true; +} + +EmberAfStatus emberAfPluginZllOnOffServerOffZllExtensions(const EmberAfClusterCommand * cmd) +{ + // On receipt of the off command, the OnTime attribute shall be set to + // 0x0000. + return writeOnTime(cmd->apsFrame->destinationEndpoint, 0x0000); +} + +EmberAfStatus emberAfPluginZllOnOffServerOnZllExtensions(const EmberAfClusterCommand * cmd) +{ + // On receipt of the on command, if the value of the OnTime attribute is + // equal to 0x0000, the device shall set the OffWaitTime attribute to 0x0000. + uint16_t onTime; + uint8_t endpoint = cmd->apsFrame->destinationEndpoint; + EmberAfStatus status = readOnTime(endpoint, &onTime); + if (status != EMBER_ZCL_STATUS_SUCCESS) + { + return status; + } + else if (onTime == 0x0000) + { + status = writeOffWaitTime(endpoint, 0x0000); + if (status != EMBER_ZCL_STATUS_SUCCESS) + { + return status; + } + } + + // The GlobalSceneControl attribute shall be set to true after the reception + // of a standard ZCL on command. + return writeGlobalSceneControl(endpoint, true); +} + +EmberAfStatus emberAfPluginZllOnOffServerToggleZllExtensions(const EmberAfClusterCommand * cmd) +{ + // On receipt of the toggle command, if the value of the OnOff attribute is + // equal to 0x00 and if the value of the OnTime attribute is equal to 0x0000, + // the device shall set the OffWaitTime attribute to 0x0000. If the value of + // the OnOff attribute is equal to 0x01, the OnTime attribute shall be set to + // 0x0000. When this function is called, the OnOff attribute has already + // been toggled, so the logic is reversed. + // + // The GlobalSceneControl attribute shall be set to true after the + // receiption of a command which causes the OnOff attribute to be set to + // true, e.g. ZCL toggle command + bool onOff; + uint8_t endpoint = cmd->apsFrame->destinationEndpoint; + EmberAfStatus status = readOnOff(endpoint, &onOff); + if (status != EMBER_ZCL_STATUS_SUCCESS) + { + return status; + } + else if (onOff) + { + uint16_t onTime; + status = readOnTime(endpoint, &onTime); + if (status == EMBER_ZCL_STATUS_SUCCESS && onTime == 0x0000) + { + status = writeOffWaitTime(endpoint, 0x0000); + } + + if (status == EMBER_ZCL_STATUS_SUCCESS) + { + status = writeGlobalSceneControl(endpoint, true); + } + + return status; + } + else + { + return writeOnTime(endpoint, 0x0000); + } +} + +EmberAfStatus emberAfPluginZllOnOffServerLevelControlZllExtensions(uint8_t endpoint) +{ + // On receipt of a level control cluster command that causes the OnOff + // attribute to be set to 0x00, the OnTime attribute shall be set to 0x0000. + // On receipt of a level control cluster command that causes the OnOff + // attribute to be set to 0x01, if the value of the OnTime attribute is equal + // to 0x0000, the device shall set the OffWaitTime attribute to 0x0000. + bool onOff; + EmberAfStatus status = readOnOff(endpoint, &onOff); + if (status != EMBER_ZCL_STATUS_SUCCESS) + { + return status; + } + else if (!onOff) + { + return writeOnTime(endpoint, 0x0000); + } + else + { + uint16_t onTime; + status = readOnTime(endpoint, &onTime); + if (status == EMBER_ZCL_STATUS_SUCCESS && onTime == 0x0000) + { + status = writeOffWaitTime(endpoint, 0x0000); + } + return status; + } +} diff --git a/src/app/clusters/zll-on-off-server/zll-on-off-server.h b/src/app/clusters/zll-on-off-server/zll-on-off-server.h new file mode 100644 index 00000000000000..aa08e6809d7548 --- /dev/null +++ b/src/app/clusters/zll-on-off-server/zll-on-off-server.h @@ -0,0 +1,59 @@ +/** + * + * 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. + */ + +/** + * + * Copyright (c) 2020 Silicon Labs + * + * 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 + * @brief Definitions for the ZLL On Off Server plugin. + ******************************************************************************* + * # License + * Copyright 2018 Silicon Laboratories Inc. + * www.silabs.com + ******************************************************************************* + * + * The licensor of this software is Silicon + * Laboratories Inc. Your use of this software is + * governed by the terms of Silicon Labs Master + * Software License Agreement (MSLA) available at + * www.silabs.com/about-us/legal/master-software-license-agreement. + * This software is distributed to you in Source Code + * format and is governed by the sections of the MSLA + * applicable to Source Code. + * + ******************************************************************************/ + +EmberAfStatus emberAfPluginZllOnOffServerOffZllExtensions(const EmberAfClusterCommand * cmd); +EmberAfStatus emberAfPluginZllOnOffServerOnZllExtensions(const EmberAfClusterCommand * cmd); +EmberAfStatus emberAfPluginZllOnOffServerToggleZllExtensions(const EmberAfClusterCommand * cmd); + +EmberAfStatus emberAfPluginZllOnOffServerLevelControlZllExtensions(uint8_t endpoint); diff --git a/src/app/clusters/zll-scenes-client/zll-scenes-client.c b/src/app/clusters/zll-scenes-client/zll-scenes-client.c new file mode 100644 index 00000000000000..f521a41544e687 --- /dev/null +++ b/src/app/clusters/zll-scenes-client/zll-scenes-client.c @@ -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. + */ + +/** + * + * Copyright (c) 2020 Silicon Labs + * + * 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 + * @brief Routines for the ZLL Scenes Client plugin. + ******************************************************************************* + * # License + * Copyright 2018 Silicon Laboratories Inc. + * www.silabs.com + ******************************************************************************* + * + * The licensor of this software is Silicon + * Laboratories Inc. Your use of this software is + * governed by the terms of Silicon Labs Master + * Software License Agreement (MSLA) available at + * www.silabs.com/about-us/legal/master-software-license-agreement. + * This software is distributed to you in Source Code + * format and is governed by the sections of the MSLA + * applicable to Source Code. + * + ******************************************************************************/ + +#include "../../include/af.h" +#include "../scenes-client/scenes-client.h" + +bool emberAfScenesClusterEnhancedAddSceneResponseCallback(uint8_t status, uint16_t groupId, uint8_t sceneId) +{ + return emberAfPluginScenesClientParseAddSceneResponse(emberAfCurrentCommand(), status, groupId, sceneId); +} + +bool emberAfScenesClusterEnhancedViewSceneResponseCallback(uint8_t status, uint16_t groupId, uint8_t sceneId, + uint16_t transitionTime, uint8_t * sceneName, + uint8_t * extensionFieldSets) +{ + return emberAfPluginScenesClientParseViewSceneResponse(emberAfCurrentCommand(), status, groupId, sceneId, transitionTime, + sceneName, extensionFieldSets); +} + +bool emberAfScenesClusterCopySceneResponseCallback(uint8_t status, uint16_t groupIdFrom, uint8_t sceneIdFrom) +{ + emberAfScenesClusterPrintln("RX: CopySceneResponse 0x%x, 0x%2x, 0x%x", status, groupIdFrom, sceneIdFrom); + emberAfSendImmediateDefaultResponse(EMBER_ZCL_STATUS_SUCCESS); + return true; +} diff --git a/src/app/clusters/zll-scenes-server/zll-scenes-server.c b/src/app/clusters/zll-scenes-server/zll-scenes-server.c new file mode 100644 index 00000000000000..a70d563703e624 --- /dev/null +++ b/src/app/clusters/zll-scenes-server/zll-scenes-server.c @@ -0,0 +1,177 @@ +/** + * + * 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. + */ + +/** + * + * Copyright (c) 2020 Silicon Labs + * + * 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 + * @brief Routines for the ZLL Scenes Server plugin. + ******************************************************************************* + * # License + * Copyright 2018 Silicon Laboratories Inc. + * www.silabs.com + ******************************************************************************* + * + * The licensor of this software is Silicon + * Laboratories Inc. Your use of this software is + * governed by the terms of Silicon Labs Master + * Software License Agreement (MSLA) available at + * www.silabs.com/about-us/legal/master-software-license-agreement. + * This software is distributed to you in Source Code + * format and is governed by the sections of the MSLA + * applicable to Source Code. + * + ******************************************************************************/ + +#include "../../include/af.h" +#include "../scenes/scenes.h" + +#define ZCL_SCENES_CLUSTER_MODE_COPY_ALL_SCENES_MASK BIT(0) + +bool emberAfScenesClusterEnhancedAddSceneCallback(uint16_t groupId, uint8_t sceneId, uint16_t transitionTime, uint8_t * sceneName, + uint8_t * extensionFieldSets) +{ + return emberAfPluginScenesServerParseAddScene(emberAfCurrentCommand(), groupId, sceneId, transitionTime, sceneName, + extensionFieldSets); +} + +bool emberAfScenesClusterEnhancedViewSceneCallback(uint16_t groupId, uint8_t sceneId) +{ + return emberAfPluginScenesServerParseViewScene(emberAfCurrentCommand(), groupId, sceneId); +} + +bool emberAfScenesClusterCopySceneCallback(uint8_t mode, uint16_t groupIdFrom, uint8_t sceneIdFrom, uint16_t groupIdTo, + uint8_t sceneIdTo) +{ + EmberStatus sendStatus; + EmberAfStatus status = EMBER_ZCL_STATUS_INVALID_FIELD; + bool copyAllScenes = (mode & ZCL_SCENES_CLUSTER_MODE_COPY_ALL_SCENES_MASK); + uint8_t i; + + emberAfScenesClusterPrintln("RX: CopyScene 0x%x, 0x%2x, 0x%x, 0x%2x, 0x%x", mode, groupIdFrom, sceneIdFrom, groupIdTo, + sceneIdTo); + + // If a group id is specified but this endpoint isn't in it, take no action. + if ((groupIdFrom != ZCL_SCENES_GLOBAL_SCENE_GROUP_ID && + !emberAfGroupsClusterEndpointInGroupCallback(emberAfCurrentEndpoint(), groupIdFrom)) || + (groupIdTo != ZCL_SCENES_GLOBAL_SCENE_GROUP_ID && + !emberAfGroupsClusterEndpointInGroupCallback(emberAfCurrentEndpoint(), groupIdTo))) + { + status = EMBER_ZCL_STATUS_INVALID_FIELD; + goto kickout; + } + + for (i = 0; i < EMBER_AF_PLUGIN_SCENES_TABLE_SIZE; i++) + { + EmberAfSceneTableEntry from; + emberAfPluginScenesServerRetrieveSceneEntry(from, i); + if (from.endpoint == emberAfCurrentEndpoint() && from.groupId == groupIdFrom && + (copyAllScenes || from.sceneId == sceneIdFrom)) + { + uint8_t j, index = EMBER_AF_SCENE_TABLE_NULL_INDEX; + for (j = 0; j < EMBER_AF_PLUGIN_SCENES_TABLE_SIZE; j++) + { + EmberAfSceneTableEntry to; + if (i == j) + { + continue; + } + emberAfPluginScenesServerRetrieveSceneEntry(to, j); + if (to.endpoint == emberAfCurrentEndpoint() && to.groupId == groupIdTo && + to.sceneId == (copyAllScenes ? from.sceneId : sceneIdTo)) + { + index = j; + break; + } + else if (index == EMBER_AF_SCENE_TABLE_NULL_INDEX && to.endpoint == EMBER_AF_SCENE_TABLE_UNUSED_ENDPOINT_ID) + { + index = j; + } + } + + // If the target index is still zero, the table is full. + if (index == EMBER_AF_SCENE_TABLE_NULL_INDEX) + { + status = EMBER_ZCL_STATUS_INSUFFICIENT_SPACE; + goto kickout; + } + + // Save the "from" entry to the "to" index. This makes a copy of "from" + // with the correct group and scene ids and leaves the original in tact. + from.groupId = groupIdTo; + if (!copyAllScenes) + { + from.sceneId = sceneIdTo; + } + emberAfPluginScenesServerSaveSceneEntry(from, index); + + if (j != index) + { + emberAfPluginScenesServerIncrNumSceneEntriesInUse(); + emberAfScenesSetSceneCountAttribute(emberAfCurrentEndpoint(), emberAfPluginScenesServerNumSceneEntriesInUse()); + } + + // If we aren't copying all scenes, we can stop here. + status = EMBER_ZCL_STATUS_SUCCESS; + if (!copyAllScenes) + { + goto kickout; + } + } + } + +kickout: + // Copy Scene commands are only responded to when they are addressed to a + // single device. + if (emberAfCurrentCommand()->type == EMBER_INCOMING_UNICAST || emberAfCurrentCommand()->type == EMBER_INCOMING_UNICAST_REPLY) + { + emberAfFillCommandScenesClusterCopySceneResponse(status, groupIdFrom, sceneIdFrom); + sendStatus = emberAfSendResponse(); + if (EMBER_SUCCESS != sendStatus) + { + emberAfScenesClusterPrintln("Scenes: failed to send %s response: 0x%x", "copy_scene", sendStatus); + } + } + return true; +} + +EmberAfStatus emberAfPluginZllScenesServerRecallSceneZllExtensions(uint8_t endpoint) +{ + bool globalSceneControl = true; + EmberAfStatus status = emberAfWriteServerAttribute(endpoint, ZCL_ON_OFF_CLUSTER_ID, ZCL_GLOBAL_SCENE_CONTROL_ATTRIBUTE_ID, + (uint8_t *) &globalSceneControl, ZCL_BOOLEAN_ATTRIBUTE_TYPE); + if (status != EMBER_ZCL_STATUS_SUCCESS) + { + emberAfScenesClusterPrintln("ERR: writing global scene control %x", status); + } + return status; +} diff --git a/src/app/clusters/zll-scenes-server/zll-scenes-server.h b/src/app/clusters/zll-scenes-server/zll-scenes-server.h new file mode 100644 index 00000000000000..f2e37d46b25d23 --- /dev/null +++ b/src/app/clusters/zll-scenes-server/zll-scenes-server.h @@ -0,0 +1,55 @@ +/** + * + * 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. + */ + +/** + * + * Copyright (c) 2020 Silicon Labs + * + * 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 + * @brief Definitions for the ZLL Scenes Server plugin. + ******************************************************************************* + * # License + * Copyright 2018 Silicon Laboratories Inc. + * www.silabs.com + ******************************************************************************* + * + * The licensor of this software is Silicon + * Laboratories Inc. Your use of this software is + * governed by the terms of Silicon Labs Master + * Software License Agreement (MSLA) available at + * www.silabs.com/about-us/legal/master-software-license-agreement. + * This software is distributed to you in Source Code + * format and is governed by the sections of the MSLA + * applicable to Source Code. + * + ******************************************************************************/ + +EmberAfStatus emberAfPluginZllScenesServerRecallSceneZllExtensions(uint8_t endpoint); diff --git a/src/app/encoder.cpp b/src/app/encoder.cpp index 0b4e124368a3e6..2369e9f848440b 100644 --- a/src/app/encoder.cpp +++ b/src/app/encoder.cpp @@ -1,4 +1,3 @@ - /* * * Copyright (c) 2020 Project CHIP Authors @@ -25,149 +24,78 @@ #include using namespace chip; +using namespace chip::System; -#define CHECK_FRAME_LENGTH(value, name) \ - if (value == 0) \ - { \ - ChipLogError(Zcl, "Error encoding APS Frame: %s", name); \ - return 0; \ +static uint16_t doEncodeApsFrame(BufBound & buf, ClusterId clusterId, EndpointId sourceEndpoint, EndpointId destinationEndpoint, + EmberApsOption options, GroupId groupId, uint8_t sequence, uint8_t radius, bool isMeasuring) +{ + + uint8_t control_byte = 0; + buf.Put(control_byte) // Put in a control byte + .Put16(clusterId) + .Put8(sourceEndpoint) + .Put8(destinationEndpoint) + .Put(options, sizeof(EmberApsOption)) + .Put16(groupId) + .Put8(sequence) + .Put8(radius); + + size_t result = buf.Needed(); + if (isMeasuring) + { + ChipLogDetail(Zcl, "Measured APS frame size %d", result); + } + else if (buf.Fit()) + { + ChipLogDetail(Zcl, "Successfully encoded %d bytes", result); + } + else + { + ChipLogError(Zcl, "Error encoding APS Frame: Buffer too small"); + result = 0; } -#define READ_ATTRIBUTES(name, cluster_id) \ - uint16_t attr_id_count = sizeof(attr_ids) / sizeof(attr_ids[0]); \ - uint16_t result = encodeReadAttributesCommand(buffer, buf_length, destination_endpoint, cluster_id, attr_ids, attr_id_count); \ - if (result == 0) \ - { \ - ChipLogError(Zcl, "Error encoding %s command", name); \ - return 0; \ - } \ - return result; + if (!CanCastTo(result)) + { + ChipLogError(Zcl, "Can't fit our measured size in uint16_t"); + result = 0; + } -#define WRITE_ATTRIBUTE(name, cluster_id, value) \ - BufBound buf = BufBound(buffer, buf_length); \ - if (_encodeGlobalCommand(buf, destination_endpoint, cluster_id, 0x02)) \ - { \ - buf.Put16(attr_id); \ - buf.Put(attr_type); \ - switch (attr_type) \ - { \ - case 0x21: \ - buf.Put16(static_cast(value)); \ - break; \ - case 0x18: \ - buf.Put(static_cast(value)); \ - break; \ - case 0x20: \ - buf.Put(static_cast(value)); \ - break; \ - case 0xF0: \ - buf.Put64(static_cast(value)); \ - break; \ - default: \ - ChipLogError(Zcl, "Error encoding %s command", name); \ - return 0; \ - } \ - } \ - \ - uint16_t result = buf.Fit() && CanCastTo(buf.Needed()) ? static_cast(buf.Needed()) : 0; \ - if (result == 0) \ - { \ - ChipLogError(Zcl, "Error encoding %s command", name); \ - return 0; \ - } \ - return result; + return static_cast(result); +} -#define REPORT_ATTRIBUTE(name, cluster_id, isAnalog, value) \ - BufBound buf = BufBound(buffer, buf_length); \ - if (_encodeGlobalCommand(buf, destination_endpoint, cluster_id, 0x06)) \ - { \ - uint8_t direction = 0x00; \ - buf.Put(direction); \ - buf.Put16(attr_id); \ - buf.Put(attr_type); \ - buf.Put16(min_interval); \ - buf.Put16(max_interval); \ - if (isAnalog) \ - { \ - switch (attr_type) \ - { \ - case 0x20: \ - buf.Put(static_cast(value)); \ - break; \ - case 0x21: \ - buf.Put16(static_cast(value)); \ - break; \ - case 0x29: \ - buf.Put16(static_cast(value)); \ - break; \ - default: \ - ChipLogError(Zcl, "Type is not supported for report attribute: '0x%02x'", attr_type); \ - break; \ - } \ - } \ - } \ +uint16_t encodeApsFrame(uint8_t * buffer, uint16_t buf_length, EmberApsFrame * apsFrame) +{ + BufBound buf = BufBound(buffer, buf_length); + return doEncodeApsFrame(buf, apsFrame->clusterId, apsFrame->sourceEndpoint, apsFrame->destinationEndpoint, apsFrame->options, + apsFrame->groupId, apsFrame->sequence, apsFrame->radius, !buffer); +} + +#define COMMAND_HEADER(name, clusterId) \ + const char * kName = name; \ \ - uint16_t result = buf.Fit() && CanCastTo(buf.Needed()) ? static_cast(buf.Needed()) : 0; \ - if (result == 0) \ + PacketBufferHandle payload = PacketBuffer::NewWithAvailableSize(kMaxBufferSize); \ + if (payload.IsNull()) \ { \ - ChipLogError(Zcl, "Error encoding %s command", name); \ - return 0; \ + ChipLogError(Zcl, "Could not allocate PacketBuffer while trying to encode %s command", kName); \ + return payload; \ } \ - return result; + \ + BufBound buf = BufBound(payload->Start(), kMaxBufferSize); \ + if (doEncodeApsFrame(buf, clusterId, kSourceEndpoint, destinationEndpoint, 0, 0, 0, 0, false)) \ + { -#define DISCOVER_ATTRIBUTES(name, cluster_id) \ - BufBound buf = BufBound(buffer, buf_length); \ - if (_encodeGlobalCommand(buf, destination_endpoint, cluster_id, 0x0c)) \ - { \ - /* Discover all attributes */ \ - buf.Put16(0x0000); \ - buf.Put(0xFF); \ +#define COMMAND_FOOTER() \ } \ - \ uint16_t result = buf.Fit() && CanCastTo(buf.Needed()) ? static_cast(buf.Needed()) : 0; \ if (result == 0) \ { \ - ChipLogError(Zcl, "Error encoding %s command", name); \ - return 0; \ - } \ - return result; - -#define COMMAND_HEADER(name, cluster_id, command_id) \ - BufBound buf = BufBound(buffer, buf_length); \ - uint16_t result = _encodeClusterSpecificCommand(buf, destination_endpoint, cluster_id, command_id); \ - if (result == 0) \ - { \ - ChipLogError(Zcl, "Error encoding %s command", name); \ - return 0; \ - } - -#define COMMAND_FOOTER(name) \ - result = buf.Fit() && CanCastTo(buf.Needed()) ? static_cast(buf.Needed()) : 0; \ - if (result == 0) \ - { \ - ChipLogError(Zcl, "Error encoding %s command", name); \ - return 0; \ + ChipLogError(Zcl, "Command %s can't fit in the allocated buffer", kName); \ + return PacketBufferHandle(); \ } \ - return result; - -#define COMMAND_INSERT_STRING(name, str) \ - { \ - size_t str_length = strlen(str); \ - if (!CanCastTo(str_length)) \ - { \ - ChipLogError(Zcl, "Error encoding %s command. String too long: %d", name, str_length); \ - return 0; \ - } \ - buf.Put(static_cast(str_length)); \ - buf.Put(str); \ - } - -#define COMMAND(name, cluster_id, command_id) \ - COMMAND_HEADER(name, cluster_id, command_id); \ - COMMAND_FOOTER(name); - -using namespace chip; -extern "C" { + \ + payload->SetDataLength(result); \ + return payload; /*----------------------------------------------------------------------------*\ | Cluster Name | ID | @@ -185,113 +113,140 @@ extern "C" { | TemperatureMeasurement | 0x0402 | \*----------------------------------------------------------------------------*/ +#define EMBER_ZCL_REPORTING_DIRECTION_REPORTED 0x00 + +#define ZCL_READ_ATTRIBUTES_COMMAND_ID (0x00) +#define ZCL_READ_ATTRIBUTES_RESPONSE_COMMAND_ID (0x01) +#define ZCL_WRITE_ATTRIBUTES_COMMAND_ID (0x02) +#define ZCL_WRITE_ATTRIBUTES_UNDIVIDED_COMMAND_ID (0x03) +#define ZCL_WRITE_ATTRIBUTES_RESPONSE_COMMAND_ID (0x04) +#define ZCL_WRITE_ATTRIBUTES_NO_RESPONSE_COMMAND_ID (0x05) +#define ZCL_CONFIGURE_REPORTING_COMMAND_ID (0x06) +#define ZCL_CONFIGURE_REPORTING_RESPONSE_COMMAND_ID (0x07) +#define ZCL_READ_REPORTING_CONFIGURATION_COMMAND_ID (0x08) +#define ZCL_READ_REPORTING_CONFIGURATION_RESPONSE_COMMAND_ID (0x09) +#define ZCL_REPORT_ATTRIBUTES_COMMAND_ID (0x0A) +#define ZCL_DEFAULT_RESPONSE_COMMAND_ID (0x0B) +#define ZCL_DISCOVER_ATTRIBUTES_COMMAND_ID (0x0C) +#define ZCL_DISCOVER_ATTRIBUTES_RESPONSE_COMMAND_ID (0x0D) +#define ZCL_READ_ATTRIBUTES_STRUCTURED_COMMAND_ID (0x0E) +#define ZCL_WRITE_ATTRIBUTES_STRUCTURED_COMMAND_ID (0x0F) +#define ZCL_WRITE_ATTRIBUTES_STRUCTURED_RESPONSE_COMMAND_ID (0x10) +#define ZCL_DISCOVER_COMMANDS_RECEIVED_COMMAND_ID (0x11) +#define ZCL_DISCOVER_COMMANDS_RECEIVED_RESPONSE_COMMAND_ID (0x12) +#define ZCL_DISCOVER_COMMANDS_GENERATED_COMMAND_ID (0x13) +#define ZCL_DISCOVER_COMMANDS_GENERATED_RESPONSE_COMMAND_ID (0x14) +#define ZCL_DISCOVER_ATTRIBUTES_EXTENDED_COMMAND_ID (0x15) +#define ZCL_DISCOVER_ATTRIBUTES_EXTENDED_RESPONSE_COMMAND_ID (0x16) + #define BARRIER_CONTROL_CLUSTER_ID 0x0103 -#define BASIC_CLUSTER_ID 0x0000 -#define COLOR_CONTROL_CLUSTER_ID 0x0300 -#define DOOR_LOCK_CLUSTER_ID 0x0101 -#define GROUPS_CLUSTER_ID 0x0004 -#define IAS_ZONE_CLUSTER_ID 0x0500 -#define IDENTIFY_CLUSTER_ID 0x0003 -#define LEVEL_CONTROL_CLUSTER_ID 0x0008 -#define ON_OFF_CLUSTER_ID 0x0006 -#define SCENES_CLUSTER_ID 0x0005 -#define TEMP_MEASUREMENT_CLUSTER_ID 0x0402 +#define ZCL_BARRIER_CONTROL_GO_TO_PERCENT_COMMAND_ID (0x00) +#define ZCL_BARRIER_CONTROL_STOP_COMMAND_ID (0x01) -static uint16_t doEncodeApsFrame(BufBound & buf, ClusterId clusterId, EndpointId sourceEndpoint, EndpointId destinationEndpoint, - EmberApsOption options, GroupId groupId, uint8_t sequence, uint8_t radius, bool isMeasuring) -{ +#define BASIC_CLUSTER_ID 0x0000 +#define ZCL_MFG_SPECIFIC_PING_COMMAND_ID (0x00) +#define ZCL_RESET_TO_FACTORY_DEFAULTS_COMMAND_ID (0x00) - uint8_t control_byte = 0; - buf.Put(control_byte) // Put in a control byte - .Put16(clusterId) - .Put(sourceEndpoint) - .Put(destinationEndpoint) - .Put(options, sizeof(EmberApsOption)) - .Put16(groupId) - .Put(sequence) - .Put(radius); +#define COLOR_CONTROL_CLUSTER_ID 0x0300 +#define ZCL_MOVE_COLOR_COMMAND_ID (0x08) +#define ZCL_MOVE_COLOR_TEMPERATURE_COMMAND_ID (0x4B) +#define ZCL_MOVE_HUE_COMMAND_ID (0x01) +#define ZCL_MOVE_SATURATION_COMMAND_ID (0x04) +#define ZCL_MOVE_TO_COLOR_COMMAND_ID (0x07) +#define ZCL_MOVE_TO_COLOR_TEMPERATURE_COMMAND_ID (0x0A) +#define ZCL_MOVE_TO_HUE_COMMAND_ID (0x00) +#define ZCL_MOVE_TO_HUE_AND_SATURATION_COMMAND_ID (0x06) +#define ZCL_MOVE_TO_SATURATION_COMMAND_ID (0x03) +#define ZCL_STEP_COLOR_COMMAND_ID (0x09) +#define ZCL_STEP_COLOR_TEMPERATURE_COMMAND_ID (0x4C) +#define ZCL_STEP_HUE_COMMAND_ID (0x02) +#define ZCL_STEP_SATURATION_COMMAND_ID (0x05) +#define ZCL_STOP_MOVE_STEP_COMMAND_ID (0x47) - size_t result = 0; - if (isMeasuring) - { - result = buf.Needed(); - ChipLogDetail(Zcl, "Measured APS frame size %d", result); - } - else - { - result = buf.Fit() ? buf.Needed() : 0; - CHECK_FRAME_LENGTH(result, "Buffer too small"); - ChipLogDetail(Zcl, "Successfully encoded %d bytes", result); - } - if (!CanCastTo(result)) - { - ChipLogError(Zcl, "Can't fit our measured size in uint16_t"); - result = 0; - } +#define DOOR_LOCK_CLUSTER_ID 0x0101 +#define ZCL_CLEAR_ALL_PINS_COMMAND_ID (0x08) +#define ZCL_CLEAR_ALL_RFIDS_COMMAND_ID (0x19) +#define ZCL_CLEAR_HOLIDAY_SCHEDULE_COMMAND_ID (0x13) +#define ZCL_CLEAR_PIN_COMMAND_ID (0x07) +#define ZCL_CLEAR_RFID_COMMAND_ID (0x18) +#define ZCL_CLEAR_WEEKDAY_SCHEDULE_COMMAND_ID (0x0D) +#define ZCL_CLEAR_YEARDAY_SCHEDULE_COMMAND_ID (0x10) +#define ZCL_GET_HOLIDAY_SCHEDULE_COMMAND_ID (0x12) +#define ZCL_GET_LOG_RECORD_COMMAND_ID (0x04) +#define ZCL_GET_PIN_COMMAND_ID (0x06) +#define ZCL_GET_RFID_COMMAND_ID (0x17) +#define ZCL_GET_USER_TYPE_COMMAND_ID (0x15) +#define ZCL_GET_WEEKDAY_SCHEDULE_COMMAND_ID (0x0C) +#define ZCL_GET_YEARDAY_SCHEDULE_COMMAND_ID (0x0F) +#define ZCL_LOCK_DOOR_COMMAND_ID (0x00) +#define ZCL_SET_HOLIDAY_SCHEDULE_COMMAND_ID (0x11) +#define ZCL_SET_PIN_COMMAND_ID (0x05) +#define ZCL_SET_RFID_COMMAND_ID (0x16) +#define ZCL_SET_USER_TYPE_COMMAND_ID (0x14) +#define ZCL_SET_WEEKDAY_SCHEDULE_COMMAND_ID (0x0B) +#define ZCL_SET_YEARDAY_SCHEDULE_COMMAND_ID (0x0E) +#define ZCL_UNLOCK_DOOR_COMMAND_ID (0x01) +#define ZCL_UNLOCK_WITH_TIMEOUT_COMMAND_ID (0x03) - return static_cast(result); -} +#define GROUPS_CLUSTER_ID 0x0004 +#define ZCL_ADD_GROUP_COMMAND_ID (0x00) +#define ZCL_ADD_GROUP_IF_IDENTIFYING_COMMAND_ID (0x05) +#define ZCL_GET_GROUP_MEMBERSHIP_COMMAND_ID (0x02) +#define ZCL_REMOVE_ALL_GROUPS_COMMAND_ID (0x04) +#define ZCL_REMOVE_GROUP_COMMAND_ID (0x03) +#define ZCL_VIEW_GROUP_COMMAND_ID (0x01) -uint16_t encodeApsFrame(uint8_t * buffer, uint16_t buf_length, EmberApsFrame * apsFrame) -{ - BufBound buf = BufBound(buffer, buf_length); - return doEncodeApsFrame(buf, apsFrame->clusterId, apsFrame->sourceEndpoint, apsFrame->destinationEndpoint, apsFrame->options, - apsFrame->groupId, apsFrame->sequence, apsFrame->radius, !buffer); -} +#define IAS_ZONE_CLUSTER_ID 0x0500 -uint16_t _encodeCommand(BufBound & buf, EndpointId destination_endpoint, ClusterId cluster_id, CommandId command, - uint8_t frame_control) -{ - CHECK_FRAME_LENGTH(buf.Size(), "Buffer is empty"); +#define IDENTIFY_CLUSTER_ID 0x0003 +#define ZCL_IDENTIFY_COMMAND_ID (0x00) +#define ZCL_IDENTIFY_QUERY_COMMAND_ID (0x01) - uint8_t seq_num = 1; // Transaction sequence number. Just pick something. - EndpointId source_endpoint = 1; // Pick source endpoint as 1 for now. +#define LEVEL_CONTROL_CLUSTER_ID 0x0008 +#define ZCL_MOVE_COMMAND_ID (0x01) +#define ZCL_MOVE_TO_LEVEL_COMMAND_ID (0x00) +#define ZCL_MOVE_TO_LEVEL_WITH_ON_OFF_COMMAND_ID (0x04) +#define ZCL_MOVE_WITH_ON_OFF_COMMAND_ID (0x05) +#define ZCL_STEP_COMMAND_ID (0x02) +#define ZCL_STEP_WITH_ON_OFF_COMMAND_ID (0x06) +#define ZCL_STOP_COMMAND_ID (0x03) +#define ZCL_STOP_WITH_ON_OFF_COMMAND_ID (0x07) - if (doEncodeApsFrame(buf, cluster_id, source_endpoint, destination_endpoint, 0, 0, 0, 0, false)) - { - buf.Put(frame_control); - buf.Put(seq_num); - buf.Put(command); - } +#define ON_OFF_CLUSTER_ID 0x0006 +#define ZCL_OFF_COMMAND_ID (0x00) +#define ZCL_ON_COMMAND_ID (0x01) +#define ZCL_TOGGLE_COMMAND_ID (0x02) - return buf.Fit() && CanCastTo(buf.Needed()) ? static_cast(buf.Needed()) : 0; -} +#define SCENES_CLUSTER_ID 0x0005 +#define ZCL_ADD_SCENE_COMMAND_ID (0x00) +#define ZCL_GET_SCENE_MEMBERSHIP_COMMAND_ID (0x06) +#define ZCL_RECALL_SCENE_COMMAND_ID (0x05) +#define ZCL_REMOVE_ALL_SCENES_COMMAND_ID (0x03) +#define ZCL_REMOVE_SCENE_COMMAND_ID (0x02) +#define ZCL_STORE_SCENE_COMMAND_ID (0x04) +#define ZCL_VIEW_SCENE_COMMAND_ID (0x01) -uint16_t _encodeClusterSpecificCommand(BufBound & buf, EndpointId destination_endpoint, ClusterId cluster_id, CommandId command) -{ - // This is a cluster-specific command so low two bits are 0b01. The command - // is standard, so does not need a manufacturer code, and we're sending - // client to server, so all the remaining bits are 0. - uint8_t frame_control = 0x01; +#define TEMP_MEASUREMENT_CLUSTER_ID 0x0402 - return _encodeCommand(buf, destination_endpoint, cluster_id, command, frame_control); -} +// TODO: Find a way to calculate maximum message length for clusters +// https://github.com/project-chip/connectedhomeip/issues/965 +constexpr uint16_t kMaxBufferSize = 1024; -uint16_t _encodeGlobalCommand(BufBound & buf, EndpointId destination_endpoint, ClusterId cluster_id, CommandId command) -{ - // This is a global command, so the low bits are 0b00. The command is - // standard, so does not need a manufacturer code, and we're sending client - // to server, so all the remaining bits are 0. - uint8_t frame_control = 0x00; +// This is a cluster-specific command so low two bits are 0b01. The command +// is standard, so does not need a manufacturer code, and we're sending +// client to server, so all the remaining bits are 0. +constexpr uint8_t kFrameControlClusterSpecificCommand = 0x01; - return _encodeCommand(buf, destination_endpoint, cluster_id, command, frame_control); -} +// This is a global command, so the low bits are 0b00. The command is +// standard, so does not need a manufacturer code, and we're sending client +// to server, so all the remaining bits are 0. +constexpr uint8_t kFrameControlGlobalCommand = 0x00; -uint16_t encodeReadAttributesCommand(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint, ClusterId cluster_id, - const uint16_t * attr_ids, uint16_t attr_id_count) -{ - BufBound buf = BufBound(buffer, buf_length); - if (_encodeGlobalCommand(buf, destination_endpoint, cluster_id, 0x00)) - { - for (uint16_t i = 0; i < attr_id_count; ++i) - { - uint16_t attr_id = attr_ids[i]; - buf.Put16(attr_id); - } - } +// Pick source endpoint as 1 for now +constexpr EndpointId kSourceEndpoint = 1; - return buf.Fit() && CanCastTo(buf.Needed()) ? static_cast(buf.Needed()) : 0; -} +// Transaction sequence number. Just pick something for now. +constexpr uint8_t kSeqNum = 1; /*----------------------------------------------------------------------------*\ | Cluster BarrierControl | 0x0103 | @@ -311,85 +266,88 @@ uint16_t encodeReadAttributesCommand(uint8_t * buffer, uint16_t buf_length, Endp /* * Command BarrierControlGoToPercent */ -uint16_t encodeBarrierControlClusterBarrierControlGoToPercentCommand(uint8_t * buffer, uint16_t buf_length, - EndpointId destination_endpoint, uint8_t percentOpen) +PacketBufferHandle encodeBarrierControlClusterBarrierControlGoToPercentCommand(EndpointId destinationEndpoint, uint8_t percentOpen) { - const char * kName = "BarrierControlBarrierControlGoToPercent"; - COMMAND_HEADER(kName, BARRIER_CONTROL_CLUSTER_ID, 0x00); - buf.Put(percentOpen); - COMMAND_FOOTER(kName); + COMMAND_HEADER("BarrierControlGoToPercent", BARRIER_CONTROL_CLUSTER_ID); + buf.Put8(kFrameControlClusterSpecificCommand) + .Put8(kSeqNum) + .Put8(ZCL_BARRIER_CONTROL_GO_TO_PERCENT_COMMAND_ID) + .Put8(percentOpen); + COMMAND_FOOTER(); } /* * Command BarrierControlStop */ -uint16_t encodeBarrierControlClusterBarrierControlStopCommand(uint8_t * buffer, uint16_t buf_length, - EndpointId destination_endpoint) +PacketBufferHandle encodeBarrierControlClusterBarrierControlStopCommand(EndpointId destinationEndpoint) { - const char * kName = "BarrierControlBarrierControlStop"; - COMMAND_HEADER(kName, BARRIER_CONTROL_CLUSTER_ID, 0x01); - COMMAND_FOOTER(kName); + COMMAND_HEADER("BarrierControlStop", BARRIER_CONTROL_CLUSTER_ID); + buf.Put8(kFrameControlClusterSpecificCommand).Put8(kSeqNum).Put8(ZCL_BARRIER_CONTROL_STOP_COMMAND_ID); + COMMAND_FOOTER(); } -uint16_t encodeBarrierControlClusterDiscoverAttributes(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint) +PacketBufferHandle encodeBarrierControlClusterDiscoverAttributes(EndpointId destinationEndpoint) { - DISCOVER_ATTRIBUTES("DiscoverBarrierControlAttributes", BARRIER_CONTROL_CLUSTER_ID); + COMMAND_HEADER("DiscoverBarrierControlAttributes", BARRIER_CONTROL_CLUSTER_ID); + buf.Put8(kFrameControlGlobalCommand).Put8(kSeqNum).Put8(ZCL_DISCOVER_ATTRIBUTES_COMMAND_ID).Put16(0x0000).Put8(0xFF); + COMMAND_FOOTER(); } /* * Attribute BarrierMovingState */ -uint16_t encodeBarrierControlClusterReadBarrierMovingStateAttribute(uint8_t * buffer, uint16_t buf_length, - EndpointId destination_endpoint) +PacketBufferHandle encodeBarrierControlClusterReadBarrierMovingStateAttribute(EndpointId destinationEndpoint) { - uint16_t attr_ids[] = { 0x0001 }; - READ_ATTRIBUTES("ReadBarrierControlBarrierMovingState", BARRIER_CONTROL_CLUSTER_ID); + COMMAND_HEADER("ReadBarrierControlBarrierMovingState", BARRIER_CONTROL_CLUSTER_ID); + buf.Put8(kFrameControlGlobalCommand).Put8(kSeqNum).Put8(ZCL_READ_ATTRIBUTES_COMMAND_ID).Put16(0x0001); + COMMAND_FOOTER(); } /* * Attribute BarrierSafetyStatus */ -uint16_t encodeBarrierControlClusterReadBarrierSafetyStatusAttribute(uint8_t * buffer, uint16_t buf_length, - EndpointId destination_endpoint) +PacketBufferHandle encodeBarrierControlClusterReadBarrierSafetyStatusAttribute(EndpointId destinationEndpoint) { - uint16_t attr_ids[] = { 0x0002 }; - READ_ATTRIBUTES("ReadBarrierControlBarrierSafetyStatus", BARRIER_CONTROL_CLUSTER_ID); + COMMAND_HEADER("ReadBarrierControlBarrierSafetyStatus", BARRIER_CONTROL_CLUSTER_ID); + buf.Put8(kFrameControlGlobalCommand).Put8(kSeqNum).Put8(ZCL_READ_ATTRIBUTES_COMMAND_ID).Put16(0x0002); + COMMAND_FOOTER(); } /* * Attribute BarrierCapabilities */ -uint16_t encodeBarrierControlClusterReadBarrierCapabilitiesAttribute(uint8_t * buffer, uint16_t buf_length, - EndpointId destination_endpoint) +PacketBufferHandle encodeBarrierControlClusterReadBarrierCapabilitiesAttribute(EndpointId destinationEndpoint) { - uint16_t attr_ids[] = { 0x0003 }; - READ_ATTRIBUTES("ReadBarrierControlBarrierCapabilities", BARRIER_CONTROL_CLUSTER_ID); + COMMAND_HEADER("ReadBarrierControlBarrierCapabilities", BARRIER_CONTROL_CLUSTER_ID); + buf.Put8(kFrameControlGlobalCommand).Put8(kSeqNum).Put8(ZCL_READ_ATTRIBUTES_COMMAND_ID).Put16(0x0003); + COMMAND_FOOTER(); } /* * Attribute BarrierPosition */ -uint16_t encodeBarrierControlClusterReadBarrierPositionAttribute(uint8_t * buffer, uint16_t buf_length, - EndpointId destination_endpoint) +PacketBufferHandle encodeBarrierControlClusterReadBarrierPositionAttribute(EndpointId destinationEndpoint) { - uint16_t attr_ids[] = { 0x000A }; - READ_ATTRIBUTES("ReadBarrierControlBarrierPosition", BARRIER_CONTROL_CLUSTER_ID); + COMMAND_HEADER("ReadBarrierControlBarrierPosition", BARRIER_CONTROL_CLUSTER_ID); + buf.Put8(kFrameControlGlobalCommand).Put8(kSeqNum).Put8(ZCL_READ_ATTRIBUTES_COMMAND_ID).Put16(0x000A); + COMMAND_FOOTER(); } /* * Attribute ClusterRevision */ -uint16_t encodeBarrierControlClusterReadClusterRevisionAttribute(uint8_t * buffer, uint16_t buf_length, - EndpointId destination_endpoint) +PacketBufferHandle encodeBarrierControlClusterReadClusterRevisionAttribute(EndpointId destinationEndpoint) { - uint16_t attr_ids[] = { 0xFFFD }; - READ_ATTRIBUTES("ReadBarrierControlClusterRevision", BARRIER_CONTROL_CLUSTER_ID); + COMMAND_HEADER("ReadBarrierControlClusterRevision", BARRIER_CONTROL_CLUSTER_ID); + buf.Put8(kFrameControlGlobalCommand).Put8(kSeqNum).Put8(ZCL_READ_ATTRIBUTES_COMMAND_ID).Put16(0xFFFD); + COMMAND_FOOTER(); } /*----------------------------------------------------------------------------*\ | Cluster Basic | 0x0000 | |------------------------------------------------------------------------------| | Commands: | | +| * MfgSpecificPing | 0x00 | | * ResetToFactoryDefaults | 0x00 | |------------------------------------------------------------------------------| | Attributes: | | @@ -398,46 +356,61 @@ uint16_t encodeBarrierControlClusterReadClusterRevisionAttribute(uint8_t * buffe | * ClusterRevision | 0xFFFD | \*----------------------------------------------------------------------------*/ +/* + * Command MfgSpecificPing + */ +PacketBufferHandle encodeBasicClusterMfgSpecificPingCommand(EndpointId destinationEndpoint) +{ + COMMAND_HEADER("MfgSpecificPing", BASIC_CLUSTER_ID); + buf.Put8(kFrameControlClusterSpecificCommand | (1u << 2)).Put16(0x1002).Put8(kSeqNum).Put8(ZCL_MFG_SPECIFIC_PING_COMMAND_ID); + COMMAND_FOOTER(); +} + /* * Command ResetToFactoryDefaults */ -uint16_t encodeBasicClusterResetToFactoryDefaultsCommand(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint) +PacketBufferHandle encodeBasicClusterResetToFactoryDefaultsCommand(EndpointId destinationEndpoint) { - const char * kName = "BasicResetToFactoryDefaults"; - COMMAND_HEADER(kName, BASIC_CLUSTER_ID, 0x00); - COMMAND_FOOTER(kName); + COMMAND_HEADER("ResetToFactoryDefaults", BASIC_CLUSTER_ID); + buf.Put8(kFrameControlClusterSpecificCommand).Put8(kSeqNum).Put8(ZCL_RESET_TO_FACTORY_DEFAULTS_COMMAND_ID); + COMMAND_FOOTER(); } -uint16_t encodeBasicClusterDiscoverAttributes(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint) +PacketBufferHandle encodeBasicClusterDiscoverAttributes(EndpointId destinationEndpoint) { - DISCOVER_ATTRIBUTES("DiscoverBasicAttributes", BASIC_CLUSTER_ID); + COMMAND_HEADER("DiscoverBasicAttributes", BASIC_CLUSTER_ID); + buf.Put8(kFrameControlGlobalCommand).Put8(kSeqNum).Put8(ZCL_DISCOVER_ATTRIBUTES_COMMAND_ID).Put16(0x0000).Put8(0xFF); + COMMAND_FOOTER(); } /* * Attribute ZclVersion */ -uint16_t encodeBasicClusterReadZclVersionAttribute(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint) +PacketBufferHandle encodeBasicClusterReadZclVersionAttribute(EndpointId destinationEndpoint) { - uint16_t attr_ids[] = { 0x0000 }; - READ_ATTRIBUTES("ReadBasicZclVersion", BASIC_CLUSTER_ID); + COMMAND_HEADER("ReadBasicZclVersion", BASIC_CLUSTER_ID); + buf.Put8(kFrameControlGlobalCommand).Put8(kSeqNum).Put8(ZCL_READ_ATTRIBUTES_COMMAND_ID).Put16(0x0000); + COMMAND_FOOTER(); } /* * Attribute PowerSource */ -uint16_t encodeBasicClusterReadPowerSourceAttribute(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint) +PacketBufferHandle encodeBasicClusterReadPowerSourceAttribute(EndpointId destinationEndpoint) { - uint16_t attr_ids[] = { 0x0007 }; - READ_ATTRIBUTES("ReadBasicPowerSource", BASIC_CLUSTER_ID); + COMMAND_HEADER("ReadBasicPowerSource", BASIC_CLUSTER_ID); + buf.Put8(kFrameControlGlobalCommand).Put8(kSeqNum).Put8(ZCL_READ_ATTRIBUTES_COMMAND_ID).Put16(0x0007); + COMMAND_FOOTER(); } /* * Attribute ClusterRevision */ -uint16_t encodeBasicClusterReadClusterRevisionAttribute(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint) +PacketBufferHandle encodeBasicClusterReadClusterRevisionAttribute(EndpointId destinationEndpoint) { - uint16_t attr_ids[] = { 0xFFFD }; - READ_ATTRIBUTES("ReadBasicClusterRevision", BASIC_CLUSTER_ID); + COMMAND_HEADER("ReadBasicClusterRevision", BASIC_CLUSTER_ID); + buf.Put8(kFrameControlGlobalCommand).Put8(kSeqNum).Put8(ZCL_READ_ATTRIBUTES_COMMAND_ID).Put16(0xFFFD); + COMMAND_FOOTER(); } /*----------------------------------------------------------------------------*\ @@ -516,872 +489,1016 @@ uint16_t encodeBasicClusterReadClusterRevisionAttribute(uint8_t * buffer, uint16 /* * Command MoveColor */ -uint16_t encodeColorControlClusterMoveColorCommand(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint, - int16_t rateX, int16_t rateY, uint8_t optionsMask, uint8_t optionsOverride) +PacketBufferHandle encodeColorControlClusterMoveColorCommand(EndpointId destinationEndpoint, int16_t rateX, int16_t rateY, + uint8_t optionsMask, uint8_t optionsOverride) { - const char * kName = "ColorControlMoveColor"; - COMMAND_HEADER(kName, COLOR_CONTROL_CLUSTER_ID, 0x08); - buf.Put16(static_cast(rateX)); - buf.Put16(static_cast(rateY)); - buf.Put(optionsMask); - buf.Put(optionsOverride); - COMMAND_FOOTER(kName); + COMMAND_HEADER("MoveColor", COLOR_CONTROL_CLUSTER_ID); + buf.Put8(kFrameControlClusterSpecificCommand) + .Put8(kSeqNum) + .Put8(ZCL_MOVE_COLOR_COMMAND_ID) + .Put16(static_cast(rateX)) + .Put16(static_cast(rateY)) + .Put8(optionsMask) + .Put8(optionsOverride); + COMMAND_FOOTER(); } /* * Command MoveColorTemperature */ -uint16_t encodeColorControlClusterMoveColorTemperatureCommand(uint8_t * buffer, uint16_t buf_length, - EndpointId destination_endpoint, uint8_t moveMode, uint16_t rate, - uint16_t colorTemperatureMinimum, uint16_t colorTemperatureMaximum, - uint8_t optionsMask, uint8_t optionsOverride) +PacketBufferHandle encodeColorControlClusterMoveColorTemperatureCommand(EndpointId destinationEndpoint, uint8_t moveMode, + uint16_t rate, uint16_t colorTemperatureMinimum, + uint16_t colorTemperatureMaximum, uint8_t optionsMask, + uint8_t optionsOverride) { - const char * kName = "ColorControlMoveColorTemperature"; - COMMAND_HEADER(kName, COLOR_CONTROL_CLUSTER_ID, 0x4B); - buf.Put(moveMode); - buf.Put16(rate); - buf.Put16(colorTemperatureMinimum); - buf.Put16(colorTemperatureMaximum); - buf.Put(optionsMask); - buf.Put(optionsOverride); - COMMAND_FOOTER(kName); + COMMAND_HEADER("MoveColorTemperature", COLOR_CONTROL_CLUSTER_ID); + buf.Put8(kFrameControlClusterSpecificCommand) + .Put8(kSeqNum) + .Put8(ZCL_MOVE_COLOR_TEMPERATURE_COMMAND_ID) + .Put8(moveMode) + .Put16(rate) + .Put16(colorTemperatureMinimum) + .Put16(colorTemperatureMaximum) + .Put8(optionsMask) + .Put8(optionsOverride); + COMMAND_FOOTER(); } /* * Command MoveHue */ -uint16_t encodeColorControlClusterMoveHueCommand(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint, - uint8_t moveMode, uint8_t rate, uint8_t optionsMask, uint8_t optionsOverride) +PacketBufferHandle encodeColorControlClusterMoveHueCommand(EndpointId destinationEndpoint, uint8_t moveMode, uint8_t rate, + uint8_t optionsMask, uint8_t optionsOverride) { - const char * kName = "ColorControlMoveHue"; - COMMAND_HEADER(kName, COLOR_CONTROL_CLUSTER_ID, 0x01); - buf.Put(moveMode); - buf.Put(rate); - buf.Put(optionsMask); - buf.Put(optionsOverride); - COMMAND_FOOTER(kName); + COMMAND_HEADER("MoveHue", COLOR_CONTROL_CLUSTER_ID); + buf.Put8(kFrameControlClusterSpecificCommand) + .Put8(kSeqNum) + .Put8(ZCL_MOVE_HUE_COMMAND_ID) + .Put8(moveMode) + .Put8(rate) + .Put8(optionsMask) + .Put8(optionsOverride); + COMMAND_FOOTER(); } /* * Command MoveSaturation */ -uint16_t encodeColorControlClusterMoveSaturationCommand(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint, - uint8_t moveMode, uint8_t rate, uint8_t optionsMask, - uint8_t optionsOverride) +PacketBufferHandle encodeColorControlClusterMoveSaturationCommand(EndpointId destinationEndpoint, uint8_t moveMode, uint8_t rate, + uint8_t optionsMask, uint8_t optionsOverride) { - const char * kName = "ColorControlMoveSaturation"; - COMMAND_HEADER(kName, COLOR_CONTROL_CLUSTER_ID, 0x04); - buf.Put(moveMode); - buf.Put(rate); - buf.Put(optionsMask); - buf.Put(optionsOverride); - COMMAND_FOOTER(kName); + COMMAND_HEADER("MoveSaturation", COLOR_CONTROL_CLUSTER_ID); + buf.Put8(kFrameControlClusterSpecificCommand) + .Put8(kSeqNum) + .Put8(ZCL_MOVE_SATURATION_COMMAND_ID) + .Put8(moveMode) + .Put8(rate) + .Put8(optionsMask) + .Put8(optionsOverride); + COMMAND_FOOTER(); } /* * Command MoveToColor */ -uint16_t encodeColorControlClusterMoveToColorCommand(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint, - uint16_t colorX, uint16_t colorY, uint16_t transitionTime, uint8_t optionsMask, - uint8_t optionsOverride) +PacketBufferHandle encodeColorControlClusterMoveToColorCommand(EndpointId destinationEndpoint, uint16_t colorX, uint16_t colorY, + uint16_t transitionTime, uint8_t optionsMask, + uint8_t optionsOverride) { - const char * kName = "ColorControlMoveToColor"; - COMMAND_HEADER(kName, COLOR_CONTROL_CLUSTER_ID, 0x07); - buf.Put16(colorX); - buf.Put16(colorY); - buf.Put16(transitionTime); - buf.Put(optionsMask); - buf.Put(optionsOverride); - COMMAND_FOOTER(kName); + COMMAND_HEADER("MoveToColor", COLOR_CONTROL_CLUSTER_ID); + buf.Put8(kFrameControlClusterSpecificCommand) + .Put8(kSeqNum) + .Put8(ZCL_MOVE_TO_COLOR_COMMAND_ID) + .Put16(colorX) + .Put16(colorY) + .Put16(transitionTime) + .Put8(optionsMask) + .Put8(optionsOverride); + COMMAND_FOOTER(); } /* * Command MoveToColorTemperature */ -uint16_t encodeColorControlClusterMoveToColorTemperatureCommand(uint8_t * buffer, uint16_t buf_length, - EndpointId destination_endpoint, uint16_t colorTemperature, - uint16_t transitionTime, uint8_t optionsMask, - uint8_t optionsOverride) +PacketBufferHandle encodeColorControlClusterMoveToColorTemperatureCommand(EndpointId destinationEndpoint, uint16_t colorTemperature, + uint16_t transitionTime, uint8_t optionsMask, + uint8_t optionsOverride) { - const char * kName = "ColorControlMoveToColorTemperature"; - COMMAND_HEADER(kName, COLOR_CONTROL_CLUSTER_ID, 0x0A); - buf.Put16(colorTemperature); - buf.Put16(transitionTime); - buf.Put(optionsMask); - buf.Put(optionsOverride); - COMMAND_FOOTER(kName); + COMMAND_HEADER("MoveToColorTemperature", COLOR_CONTROL_CLUSTER_ID); + buf.Put8(kFrameControlClusterSpecificCommand) + .Put8(kSeqNum) + .Put8(ZCL_MOVE_TO_COLOR_TEMPERATURE_COMMAND_ID) + .Put16(colorTemperature) + .Put16(transitionTime) + .Put8(optionsMask) + .Put8(optionsOverride); + COMMAND_FOOTER(); } /* * Command MoveToHue */ -uint16_t encodeColorControlClusterMoveToHueCommand(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint, - uint8_t hue, uint8_t direction, uint16_t transitionTime, uint8_t optionsMask, - uint8_t optionsOverride) +PacketBufferHandle encodeColorControlClusterMoveToHueCommand(EndpointId destinationEndpoint, uint8_t hue, uint8_t direction, + uint16_t transitionTime, uint8_t optionsMask, uint8_t optionsOverride) { - const char * kName = "ColorControlMoveToHue"; - COMMAND_HEADER(kName, COLOR_CONTROL_CLUSTER_ID, 0x00); - buf.Put(hue); - buf.Put(direction); - buf.Put16(transitionTime); - buf.Put(optionsMask); - buf.Put(optionsOverride); - COMMAND_FOOTER(kName); + COMMAND_HEADER("MoveToHue", COLOR_CONTROL_CLUSTER_ID); + buf.Put8(kFrameControlClusterSpecificCommand) + .Put8(kSeqNum) + .Put8(ZCL_MOVE_TO_HUE_COMMAND_ID) + .Put8(hue) + .Put8(direction) + .Put16(transitionTime) + .Put8(optionsMask) + .Put8(optionsOverride); + COMMAND_FOOTER(); } /* * Command MoveToHueAndSaturation */ -uint16_t encodeColorControlClusterMoveToHueAndSaturationCommand(uint8_t * buffer, uint16_t buf_length, - EndpointId destination_endpoint, uint8_t hue, uint8_t saturation, - uint16_t transitionTime, uint8_t optionsMask, - uint8_t optionsOverride) +PacketBufferHandle encodeColorControlClusterMoveToHueAndSaturationCommand(EndpointId destinationEndpoint, uint8_t hue, + uint8_t saturation, uint16_t transitionTime, + uint8_t optionsMask, uint8_t optionsOverride) { - const char * kName = "ColorControlMoveToHueAndSaturation"; - COMMAND_HEADER(kName, COLOR_CONTROL_CLUSTER_ID, 0x06); - buf.Put(hue); - buf.Put(saturation); - buf.Put16(transitionTime); - buf.Put(optionsMask); - buf.Put(optionsOverride); - COMMAND_FOOTER(kName); + COMMAND_HEADER("MoveToHueAndSaturation", COLOR_CONTROL_CLUSTER_ID); + buf.Put8(kFrameControlClusterSpecificCommand) + .Put8(kSeqNum) + .Put8(ZCL_MOVE_TO_HUE_AND_SATURATION_COMMAND_ID) + .Put8(hue) + .Put8(saturation) + .Put16(transitionTime) + .Put8(optionsMask) + .Put8(optionsOverride); + COMMAND_FOOTER(); } /* * Command MoveToSaturation */ -uint16_t encodeColorControlClusterMoveToSaturationCommand(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint, - uint8_t saturation, uint16_t transitionTime, uint8_t optionsMask, - uint8_t optionsOverride) +PacketBufferHandle encodeColorControlClusterMoveToSaturationCommand(EndpointId destinationEndpoint, uint8_t saturation, + uint16_t transitionTime, uint8_t optionsMask, + uint8_t optionsOverride) { - const char * kName = "ColorControlMoveToSaturation"; - COMMAND_HEADER(kName, COLOR_CONTROL_CLUSTER_ID, 0x03); - buf.Put(saturation); - buf.Put16(transitionTime); - buf.Put(optionsMask); - buf.Put(optionsOverride); - COMMAND_FOOTER(kName); + COMMAND_HEADER("MoveToSaturation", COLOR_CONTROL_CLUSTER_ID); + buf.Put8(kFrameControlClusterSpecificCommand) + .Put8(kSeqNum) + .Put8(ZCL_MOVE_TO_SATURATION_COMMAND_ID) + .Put8(saturation) + .Put16(transitionTime) + .Put8(optionsMask) + .Put8(optionsOverride); + COMMAND_FOOTER(); } /* * Command StepColor */ -uint16_t encodeColorControlClusterStepColorCommand(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint, - int16_t stepX, int16_t stepY, uint16_t transitionTime, uint8_t optionsMask, - uint8_t optionsOverride) +PacketBufferHandle encodeColorControlClusterStepColorCommand(EndpointId destinationEndpoint, int16_t stepX, int16_t stepY, + uint16_t transitionTime, uint8_t optionsMask, uint8_t optionsOverride) { - const char * kName = "ColorControlStepColor"; - COMMAND_HEADER(kName, COLOR_CONTROL_CLUSTER_ID, 0x09); - buf.Put16(static_cast(stepX)); - buf.Put16(static_cast(stepY)); - buf.Put16(transitionTime); - buf.Put(optionsMask); - buf.Put(optionsOverride); - COMMAND_FOOTER(kName); + COMMAND_HEADER("StepColor", COLOR_CONTROL_CLUSTER_ID); + buf.Put8(kFrameControlClusterSpecificCommand) + .Put8(kSeqNum) + .Put8(ZCL_STEP_COLOR_COMMAND_ID) + .Put16(static_cast(stepX)) + .Put16(static_cast(stepY)) + .Put16(transitionTime) + .Put8(optionsMask) + .Put8(optionsOverride); + COMMAND_FOOTER(); } /* * Command StepColorTemperature */ -uint16_t encodeColorControlClusterStepColorTemperatureCommand(uint8_t * buffer, uint16_t buf_length, - EndpointId destination_endpoint, uint8_t stepMode, uint16_t stepSize, - uint16_t transitionTime, uint16_t colorTemperatureMinimum, - uint16_t colorTemperatureMaximum, uint8_t optionsMask, - uint8_t optionsOverride) +PacketBufferHandle encodeColorControlClusterStepColorTemperatureCommand(EndpointId destinationEndpoint, uint8_t stepMode, + uint16_t stepSize, uint16_t transitionTime, + uint16_t colorTemperatureMinimum, + uint16_t colorTemperatureMaximum, uint8_t optionsMask, + uint8_t optionsOverride) { - const char * kName = "ColorControlStepColorTemperature"; - COMMAND_HEADER(kName, COLOR_CONTROL_CLUSTER_ID, 0x4C); - buf.Put(stepMode); - buf.Put16(stepSize); - buf.Put16(transitionTime); - buf.Put16(colorTemperatureMinimum); - buf.Put16(colorTemperatureMaximum); - buf.Put(optionsMask); - buf.Put(optionsOverride); - COMMAND_FOOTER(kName); + COMMAND_HEADER("StepColorTemperature", COLOR_CONTROL_CLUSTER_ID); + buf.Put8(kFrameControlClusterSpecificCommand) + .Put8(kSeqNum) + .Put8(ZCL_STEP_COLOR_TEMPERATURE_COMMAND_ID) + .Put8(stepMode) + .Put16(stepSize) + .Put16(transitionTime) + .Put16(colorTemperatureMinimum) + .Put16(colorTemperatureMaximum) + .Put8(optionsMask) + .Put8(optionsOverride); + COMMAND_FOOTER(); } /* * Command StepHue */ -uint16_t encodeColorControlClusterStepHueCommand(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint, - uint8_t stepMode, uint8_t stepSize, uint8_t transitionTime, uint8_t optionsMask, - uint8_t optionsOverride) +PacketBufferHandle encodeColorControlClusterStepHueCommand(EndpointId destinationEndpoint, uint8_t stepMode, uint8_t stepSize, + uint8_t transitionTime, uint8_t optionsMask, uint8_t optionsOverride) { - const char * kName = "ColorControlStepHue"; - COMMAND_HEADER(kName, COLOR_CONTROL_CLUSTER_ID, 0x02); - buf.Put(stepMode); - buf.Put(stepSize); - buf.Put(transitionTime); - buf.Put(optionsMask); - buf.Put(optionsOverride); - COMMAND_FOOTER(kName); + COMMAND_HEADER("StepHue", COLOR_CONTROL_CLUSTER_ID); + buf.Put8(kFrameControlClusterSpecificCommand) + .Put8(kSeqNum) + .Put8(ZCL_STEP_HUE_COMMAND_ID) + .Put8(stepMode) + .Put8(stepSize) + .Put8(transitionTime) + .Put8(optionsMask) + .Put8(optionsOverride); + COMMAND_FOOTER(); } /* * Command StepSaturation */ -uint16_t encodeColorControlClusterStepSaturationCommand(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint, - uint8_t stepMode, uint8_t stepSize, uint8_t transitionTime, - uint8_t optionsMask, uint8_t optionsOverride) +PacketBufferHandle encodeColorControlClusterStepSaturationCommand(EndpointId destinationEndpoint, uint8_t stepMode, + uint8_t stepSize, uint8_t transitionTime, uint8_t optionsMask, + uint8_t optionsOverride) { - const char * kName = "ColorControlStepSaturation"; - COMMAND_HEADER(kName, COLOR_CONTROL_CLUSTER_ID, 0x05); - buf.Put(stepMode); - buf.Put(stepSize); - buf.Put(transitionTime); - buf.Put(optionsMask); - buf.Put(optionsOverride); - COMMAND_FOOTER(kName); + COMMAND_HEADER("StepSaturation", COLOR_CONTROL_CLUSTER_ID); + buf.Put8(kFrameControlClusterSpecificCommand) + .Put8(kSeqNum) + .Put8(ZCL_STEP_SATURATION_COMMAND_ID) + .Put8(stepMode) + .Put8(stepSize) + .Put8(transitionTime) + .Put8(optionsMask) + .Put8(optionsOverride); + COMMAND_FOOTER(); } /* * Command StopMoveStep */ -uint16_t encodeColorControlClusterStopMoveStepCommand(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint, - uint8_t optionsMask, uint8_t optionsOverride) +PacketBufferHandle encodeColorControlClusterStopMoveStepCommand(EndpointId destinationEndpoint, uint8_t optionsMask, + uint8_t optionsOverride) { - const char * kName = "ColorControlStopMoveStep"; - COMMAND_HEADER(kName, COLOR_CONTROL_CLUSTER_ID, 0x47); - buf.Put(optionsMask); - buf.Put(optionsOverride); - COMMAND_FOOTER(kName); + COMMAND_HEADER("StopMoveStep", COLOR_CONTROL_CLUSTER_ID); + buf.Put8(kFrameControlClusterSpecificCommand) + .Put8(kSeqNum) + .Put8(ZCL_STOP_MOVE_STEP_COMMAND_ID) + .Put8(optionsMask) + .Put8(optionsOverride); + COMMAND_FOOTER(); } -uint16_t encodeColorControlClusterDiscoverAttributes(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint) +PacketBufferHandle encodeColorControlClusterDiscoverAttributes(EndpointId destinationEndpoint) { - DISCOVER_ATTRIBUTES("DiscoverColorControlAttributes", COLOR_CONTROL_CLUSTER_ID); + COMMAND_HEADER("DiscoverColorControlAttributes", COLOR_CONTROL_CLUSTER_ID); + buf.Put8(kFrameControlGlobalCommand).Put8(kSeqNum).Put8(ZCL_DISCOVER_ATTRIBUTES_COMMAND_ID).Put16(0x0000).Put8(0xFF); + COMMAND_FOOTER(); } /* * Attribute CurrentHue */ -uint16_t encodeColorControlClusterReadCurrentHueAttribute(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint) +PacketBufferHandle encodeColorControlClusterReadCurrentHueAttribute(EndpointId destinationEndpoint) { - uint16_t attr_ids[] = { 0x0000 }; - READ_ATTRIBUTES("ReadColorControlCurrentHue", COLOR_CONTROL_CLUSTER_ID); + COMMAND_HEADER("ReadColorControlCurrentHue", COLOR_CONTROL_CLUSTER_ID); + buf.Put8(kFrameControlGlobalCommand).Put8(kSeqNum).Put8(ZCL_READ_ATTRIBUTES_COMMAND_ID).Put16(0x0000); + COMMAND_FOOTER(); } -uint16_t encodeColorControlClusterReportCurrentHueAttribute(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint, - uint16_t min_interval, uint16_t max_interval, uint8_t change) +PacketBufferHandle encodeColorControlClusterReportCurrentHueAttribute(EndpointId destinationEndpoint, uint16_t minInterval, + uint16_t maxInterval, uint8_t change) { - uint16_t attr_id = 0x0000; - uint8_t attr_type = { 0x20 }; - REPORT_ATTRIBUTE("ReportColorControlCurrentHue", COLOR_CONTROL_CLUSTER_ID, true, change); + COMMAND_HEADER("ReportColorControlCurrentHue", COLOR_CONTROL_CLUSTER_ID); + buf.Put8(kFrameControlGlobalCommand) + .Put8(kSeqNum) + .Put8(ZCL_CONFIGURE_REPORTING_COMMAND_ID) + .Put8(EMBER_ZCL_REPORTING_DIRECTION_REPORTED) + .Put16(0x0000) + .Put8(0x20) + .Put16(minInterval) + .Put16(maxInterval); + buf.Put8(static_cast(change)); + COMMAND_FOOTER(); } /* * Attribute CurrentSaturation */ -uint16_t encodeColorControlClusterReadCurrentSaturationAttribute(uint8_t * buffer, uint16_t buf_length, - EndpointId destination_endpoint) +PacketBufferHandle encodeColorControlClusterReadCurrentSaturationAttribute(EndpointId destinationEndpoint) { - uint16_t attr_ids[] = { 0x0001 }; - READ_ATTRIBUTES("ReadColorControlCurrentSaturation", COLOR_CONTROL_CLUSTER_ID); + COMMAND_HEADER("ReadColorControlCurrentSaturation", COLOR_CONTROL_CLUSTER_ID); + buf.Put8(kFrameControlGlobalCommand).Put8(kSeqNum).Put8(ZCL_READ_ATTRIBUTES_COMMAND_ID).Put16(0x0001); + COMMAND_FOOTER(); } -uint16_t encodeColorControlClusterReportCurrentSaturationAttribute(uint8_t * buffer, uint16_t buf_length, - EndpointId destination_endpoint, uint16_t min_interval, - uint16_t max_interval, uint8_t change) +PacketBufferHandle encodeColorControlClusterReportCurrentSaturationAttribute(EndpointId destinationEndpoint, uint16_t minInterval, + uint16_t maxInterval, uint8_t change) { - uint16_t attr_id = 0x0001; - uint8_t attr_type = { 0x20 }; - REPORT_ATTRIBUTE("ReportColorControlCurrentSaturation", COLOR_CONTROL_CLUSTER_ID, true, change); + COMMAND_HEADER("ReportColorControlCurrentSaturation", COLOR_CONTROL_CLUSTER_ID); + buf.Put8(kFrameControlGlobalCommand) + .Put8(kSeqNum) + .Put8(ZCL_CONFIGURE_REPORTING_COMMAND_ID) + .Put8(EMBER_ZCL_REPORTING_DIRECTION_REPORTED) + .Put16(0x0001) + .Put8(0x20) + .Put16(minInterval) + .Put16(maxInterval); + buf.Put8(static_cast(change)); + COMMAND_FOOTER(); } /* * Attribute RemainingTime */ -uint16_t encodeColorControlClusterReadRemainingTimeAttribute(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint) +PacketBufferHandle encodeColorControlClusterReadRemainingTimeAttribute(EndpointId destinationEndpoint) { - uint16_t attr_ids[] = { 0x0002 }; - READ_ATTRIBUTES("ReadColorControlRemainingTime", COLOR_CONTROL_CLUSTER_ID); + COMMAND_HEADER("ReadColorControlRemainingTime", COLOR_CONTROL_CLUSTER_ID); + buf.Put8(kFrameControlGlobalCommand).Put8(kSeqNum).Put8(ZCL_READ_ATTRIBUTES_COMMAND_ID).Put16(0x0002); + COMMAND_FOOTER(); } /* * Attribute CurrentX */ -uint16_t encodeColorControlClusterReadCurrentXAttribute(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint) +PacketBufferHandle encodeColorControlClusterReadCurrentXAttribute(EndpointId destinationEndpoint) { - uint16_t attr_ids[] = { 0x0003 }; - READ_ATTRIBUTES("ReadColorControlCurrentX", COLOR_CONTROL_CLUSTER_ID); + COMMAND_HEADER("ReadColorControlCurrentX", COLOR_CONTROL_CLUSTER_ID); + buf.Put8(kFrameControlGlobalCommand).Put8(kSeqNum).Put8(ZCL_READ_ATTRIBUTES_COMMAND_ID).Put16(0x0003); + COMMAND_FOOTER(); } -uint16_t encodeColorControlClusterReportCurrentXAttribute(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint, - uint16_t min_interval, uint16_t max_interval, uint16_t change) +PacketBufferHandle encodeColorControlClusterReportCurrentXAttribute(EndpointId destinationEndpoint, uint16_t minInterval, + uint16_t maxInterval, uint16_t change) { - uint16_t attr_id = 0x0003; - uint8_t attr_type = { 0x21 }; - REPORT_ATTRIBUTE("ReportColorControlCurrentX", COLOR_CONTROL_CLUSTER_ID, true, change); + COMMAND_HEADER("ReportColorControlCurrentX", COLOR_CONTROL_CLUSTER_ID); + buf.Put8(kFrameControlGlobalCommand) + .Put8(kSeqNum) + .Put8(ZCL_CONFIGURE_REPORTING_COMMAND_ID) + .Put8(EMBER_ZCL_REPORTING_DIRECTION_REPORTED) + .Put16(0x0003) + .Put8(0x21) + .Put16(minInterval) + .Put16(maxInterval); + buf.Put16(static_cast(change)); + COMMAND_FOOTER(); } /* * Attribute CurrentY */ -uint16_t encodeColorControlClusterReadCurrentYAttribute(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint) +PacketBufferHandle encodeColorControlClusterReadCurrentYAttribute(EndpointId destinationEndpoint) { - uint16_t attr_ids[] = { 0x0004 }; - READ_ATTRIBUTES("ReadColorControlCurrentY", COLOR_CONTROL_CLUSTER_ID); + COMMAND_HEADER("ReadColorControlCurrentY", COLOR_CONTROL_CLUSTER_ID); + buf.Put8(kFrameControlGlobalCommand).Put8(kSeqNum).Put8(ZCL_READ_ATTRIBUTES_COMMAND_ID).Put16(0x0004); + COMMAND_FOOTER(); } -uint16_t encodeColorControlClusterReportCurrentYAttribute(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint, - uint16_t min_interval, uint16_t max_interval, uint16_t change) +PacketBufferHandle encodeColorControlClusterReportCurrentYAttribute(EndpointId destinationEndpoint, uint16_t minInterval, + uint16_t maxInterval, uint16_t change) { - uint16_t attr_id = 0x0004; - uint8_t attr_type = { 0x21 }; - REPORT_ATTRIBUTE("ReportColorControlCurrentY", COLOR_CONTROL_CLUSTER_ID, true, change); + COMMAND_HEADER("ReportColorControlCurrentY", COLOR_CONTROL_CLUSTER_ID); + buf.Put8(kFrameControlGlobalCommand) + .Put8(kSeqNum) + .Put8(ZCL_CONFIGURE_REPORTING_COMMAND_ID) + .Put8(EMBER_ZCL_REPORTING_DIRECTION_REPORTED) + .Put16(0x0004) + .Put8(0x21) + .Put16(minInterval) + .Put16(maxInterval); + buf.Put16(static_cast(change)); + COMMAND_FOOTER(); } /* * Attribute DriftCompensation */ -uint16_t encodeColorControlClusterReadDriftCompensationAttribute(uint8_t * buffer, uint16_t buf_length, - EndpointId destination_endpoint) +PacketBufferHandle encodeColorControlClusterReadDriftCompensationAttribute(EndpointId destinationEndpoint) { - uint16_t attr_ids[] = { 0x0005 }; - READ_ATTRIBUTES("ReadColorControlDriftCompensation", COLOR_CONTROL_CLUSTER_ID); + COMMAND_HEADER("ReadColorControlDriftCompensation", COLOR_CONTROL_CLUSTER_ID); + buf.Put8(kFrameControlGlobalCommand).Put8(kSeqNum).Put8(ZCL_READ_ATTRIBUTES_COMMAND_ID).Put16(0x0005); + COMMAND_FOOTER(); } /* * Attribute CompensationText */ -uint16_t encodeColorControlClusterReadCompensationTextAttribute(uint8_t * buffer, uint16_t buf_length, - EndpointId destination_endpoint) +PacketBufferHandle encodeColorControlClusterReadCompensationTextAttribute(EndpointId destinationEndpoint) { - uint16_t attr_ids[] = { 0x0006 }; - READ_ATTRIBUTES("ReadColorControlCompensationText", COLOR_CONTROL_CLUSTER_ID); + COMMAND_HEADER("ReadColorControlCompensationText", COLOR_CONTROL_CLUSTER_ID); + buf.Put8(kFrameControlGlobalCommand).Put8(kSeqNum).Put8(ZCL_READ_ATTRIBUTES_COMMAND_ID).Put16(0x0006); + COMMAND_FOOTER(); } /* * Attribute ColorTemperature */ -uint16_t encodeColorControlClusterReadColorTemperatureAttribute(uint8_t * buffer, uint16_t buf_length, - EndpointId destination_endpoint) +PacketBufferHandle encodeColorControlClusterReadColorTemperatureAttribute(EndpointId destinationEndpoint) { - uint16_t attr_ids[] = { 0x0007 }; - READ_ATTRIBUTES("ReadColorControlColorTemperature", COLOR_CONTROL_CLUSTER_ID); + COMMAND_HEADER("ReadColorControlColorTemperature", COLOR_CONTROL_CLUSTER_ID); + buf.Put8(kFrameControlGlobalCommand).Put8(kSeqNum).Put8(ZCL_READ_ATTRIBUTES_COMMAND_ID).Put16(0x0007); + COMMAND_FOOTER(); } -uint16_t encodeColorControlClusterReportColorTemperatureAttribute(uint8_t * buffer, uint16_t buf_length, - EndpointId destination_endpoint, uint16_t min_interval, - uint16_t max_interval, uint16_t change) +PacketBufferHandle encodeColorControlClusterReportColorTemperatureAttribute(EndpointId destinationEndpoint, uint16_t minInterval, + uint16_t maxInterval, uint16_t change) { - uint16_t attr_id = 0x0007; - uint8_t attr_type = { 0x21 }; - REPORT_ATTRIBUTE("ReportColorControlColorTemperature", COLOR_CONTROL_CLUSTER_ID, true, change); + COMMAND_HEADER("ReportColorControlColorTemperature", COLOR_CONTROL_CLUSTER_ID); + buf.Put8(kFrameControlGlobalCommand) + .Put8(kSeqNum) + .Put8(ZCL_CONFIGURE_REPORTING_COMMAND_ID) + .Put8(EMBER_ZCL_REPORTING_DIRECTION_REPORTED) + .Put16(0x0007) + .Put8(0x21) + .Put16(minInterval) + .Put16(maxInterval); + buf.Put16(static_cast(change)); + COMMAND_FOOTER(); } /* * Attribute ColorMode */ -uint16_t encodeColorControlClusterReadColorModeAttribute(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint) +PacketBufferHandle encodeColorControlClusterReadColorModeAttribute(EndpointId destinationEndpoint) { - uint16_t attr_ids[] = { 0x0008 }; - READ_ATTRIBUTES("ReadColorControlColorMode", COLOR_CONTROL_CLUSTER_ID); + COMMAND_HEADER("ReadColorControlColorMode", COLOR_CONTROL_CLUSTER_ID); + buf.Put8(kFrameControlGlobalCommand).Put8(kSeqNum).Put8(ZCL_READ_ATTRIBUTES_COMMAND_ID).Put16(0x0008); + COMMAND_FOOTER(); } /* * Attribute ColorControlOptions */ -uint16_t encodeColorControlClusterReadColorControlOptionsAttribute(uint8_t * buffer, uint16_t buf_length, - EndpointId destination_endpoint) +PacketBufferHandle encodeColorControlClusterReadColorControlOptionsAttribute(EndpointId destinationEndpoint) { - uint16_t attr_ids[] = { 0x000F }; - READ_ATTRIBUTES("ReadColorControlColorControlOptions", COLOR_CONTROL_CLUSTER_ID); + COMMAND_HEADER("ReadColorControlColorControlOptions", COLOR_CONTROL_CLUSTER_ID); + buf.Put8(kFrameControlGlobalCommand).Put8(kSeqNum).Put8(ZCL_READ_ATTRIBUTES_COMMAND_ID).Put16(0x000F); + COMMAND_FOOTER(); } -uint16_t encodeColorControlClusterWriteColorControlOptionsAttribute(uint8_t * buffer, uint16_t buf_length, - EndpointId destination_endpoint, uint8_t colorControlOptions) +PacketBufferHandle encodeColorControlClusterWriteColorControlOptionsAttribute(EndpointId destinationEndpoint, + uint8_t colorControlOptions) { - uint16_t attr_id = 0x000F; - uint8_t attr_type = { 0x18 }; - WRITE_ATTRIBUTE("WriteColorControlColorControlOptions", COLOR_CONTROL_CLUSTER_ID, colorControlOptions); + COMMAND_HEADER("WriteColorControlColorControlOptions", COLOR_CONTROL_CLUSTER_ID); + buf.Put8(kFrameControlGlobalCommand) + .Put8(kSeqNum) + .Put8(ZCL_WRITE_ATTRIBUTES_COMMAND_ID) + .Put16(0x000F) + .Put8(0x18) + .Put8(static_cast(colorControlOptions)); + COMMAND_FOOTER(); } /* * Attribute NumberOfPrimaries */ -uint16_t encodeColorControlClusterReadNumberOfPrimariesAttribute(uint8_t * buffer, uint16_t buf_length, - EndpointId destination_endpoint) +PacketBufferHandle encodeColorControlClusterReadNumberOfPrimariesAttribute(EndpointId destinationEndpoint) { - uint16_t attr_ids[] = { 0x0010 }; - READ_ATTRIBUTES("ReadColorControlNumberOfPrimaries", COLOR_CONTROL_CLUSTER_ID); + COMMAND_HEADER("ReadColorControlNumberOfPrimaries", COLOR_CONTROL_CLUSTER_ID); + buf.Put8(kFrameControlGlobalCommand).Put8(kSeqNum).Put8(ZCL_READ_ATTRIBUTES_COMMAND_ID).Put16(0x0010); + COMMAND_FOOTER(); } /* * Attribute Primary1X */ -uint16_t encodeColorControlClusterReadPrimary1XAttribute(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint) +PacketBufferHandle encodeColorControlClusterReadPrimary1XAttribute(EndpointId destinationEndpoint) { - uint16_t attr_ids[] = { 0x0011 }; - READ_ATTRIBUTES("ReadColorControlPrimary1X", COLOR_CONTROL_CLUSTER_ID); + COMMAND_HEADER("ReadColorControlPrimary1X", COLOR_CONTROL_CLUSTER_ID); + buf.Put8(kFrameControlGlobalCommand).Put8(kSeqNum).Put8(ZCL_READ_ATTRIBUTES_COMMAND_ID).Put16(0x0011); + COMMAND_FOOTER(); } /* * Attribute Primary1Y */ -uint16_t encodeColorControlClusterReadPrimary1YAttribute(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint) +PacketBufferHandle encodeColorControlClusterReadPrimary1YAttribute(EndpointId destinationEndpoint) { - uint16_t attr_ids[] = { 0x0012 }; - READ_ATTRIBUTES("ReadColorControlPrimary1Y", COLOR_CONTROL_CLUSTER_ID); + COMMAND_HEADER("ReadColorControlPrimary1Y", COLOR_CONTROL_CLUSTER_ID); + buf.Put8(kFrameControlGlobalCommand).Put8(kSeqNum).Put8(ZCL_READ_ATTRIBUTES_COMMAND_ID).Put16(0x0012); + COMMAND_FOOTER(); } /* * Attribute Primary1Intensity */ -uint16_t encodeColorControlClusterReadPrimary1IntensityAttribute(uint8_t * buffer, uint16_t buf_length, - EndpointId destination_endpoint) +PacketBufferHandle encodeColorControlClusterReadPrimary1IntensityAttribute(EndpointId destinationEndpoint) { - uint16_t attr_ids[] = { 0x0013 }; - READ_ATTRIBUTES("ReadColorControlPrimary1Intensity", COLOR_CONTROL_CLUSTER_ID); + COMMAND_HEADER("ReadColorControlPrimary1Intensity", COLOR_CONTROL_CLUSTER_ID); + buf.Put8(kFrameControlGlobalCommand).Put8(kSeqNum).Put8(ZCL_READ_ATTRIBUTES_COMMAND_ID).Put16(0x0013); + COMMAND_FOOTER(); } /* * Attribute Primary2X */ -uint16_t encodeColorControlClusterReadPrimary2XAttribute(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint) +PacketBufferHandle encodeColorControlClusterReadPrimary2XAttribute(EndpointId destinationEndpoint) { - uint16_t attr_ids[] = { 0x0015 }; - READ_ATTRIBUTES("ReadColorControlPrimary2X", COLOR_CONTROL_CLUSTER_ID); + COMMAND_HEADER("ReadColorControlPrimary2X", COLOR_CONTROL_CLUSTER_ID); + buf.Put8(kFrameControlGlobalCommand).Put8(kSeqNum).Put8(ZCL_READ_ATTRIBUTES_COMMAND_ID).Put16(0x0015); + COMMAND_FOOTER(); } /* * Attribute Primary2Y */ -uint16_t encodeColorControlClusterReadPrimary2YAttribute(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint) +PacketBufferHandle encodeColorControlClusterReadPrimary2YAttribute(EndpointId destinationEndpoint) { - uint16_t attr_ids[] = { 0x0016 }; - READ_ATTRIBUTES("ReadColorControlPrimary2Y", COLOR_CONTROL_CLUSTER_ID); + COMMAND_HEADER("ReadColorControlPrimary2Y", COLOR_CONTROL_CLUSTER_ID); + buf.Put8(kFrameControlGlobalCommand).Put8(kSeqNum).Put8(ZCL_READ_ATTRIBUTES_COMMAND_ID).Put16(0x0016); + COMMAND_FOOTER(); } /* * Attribute Primary2Intensity */ -uint16_t encodeColorControlClusterReadPrimary2IntensityAttribute(uint8_t * buffer, uint16_t buf_length, - EndpointId destination_endpoint) +PacketBufferHandle encodeColorControlClusterReadPrimary2IntensityAttribute(EndpointId destinationEndpoint) { - uint16_t attr_ids[] = { 0x0017 }; - READ_ATTRIBUTES("ReadColorControlPrimary2Intensity", COLOR_CONTROL_CLUSTER_ID); + COMMAND_HEADER("ReadColorControlPrimary2Intensity", COLOR_CONTROL_CLUSTER_ID); + buf.Put8(kFrameControlGlobalCommand).Put8(kSeqNum).Put8(ZCL_READ_ATTRIBUTES_COMMAND_ID).Put16(0x0017); + COMMAND_FOOTER(); } /* * Attribute Primary3X */ -uint16_t encodeColorControlClusterReadPrimary3XAttribute(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint) +PacketBufferHandle encodeColorControlClusterReadPrimary3XAttribute(EndpointId destinationEndpoint) { - uint16_t attr_ids[] = { 0x0019 }; - READ_ATTRIBUTES("ReadColorControlPrimary3X", COLOR_CONTROL_CLUSTER_ID); + COMMAND_HEADER("ReadColorControlPrimary3X", COLOR_CONTROL_CLUSTER_ID); + buf.Put8(kFrameControlGlobalCommand).Put8(kSeqNum).Put8(ZCL_READ_ATTRIBUTES_COMMAND_ID).Put16(0x0019); + COMMAND_FOOTER(); } /* * Attribute Primary3Y */ -uint16_t encodeColorControlClusterReadPrimary3YAttribute(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint) +PacketBufferHandle encodeColorControlClusterReadPrimary3YAttribute(EndpointId destinationEndpoint) { - uint16_t attr_ids[] = { 0x001A }; - READ_ATTRIBUTES("ReadColorControlPrimary3Y", COLOR_CONTROL_CLUSTER_ID); + COMMAND_HEADER("ReadColorControlPrimary3Y", COLOR_CONTROL_CLUSTER_ID); + buf.Put8(kFrameControlGlobalCommand).Put8(kSeqNum).Put8(ZCL_READ_ATTRIBUTES_COMMAND_ID).Put16(0x001A); + COMMAND_FOOTER(); } /* * Attribute Primary3Intensity */ -uint16_t encodeColorControlClusterReadPrimary3IntensityAttribute(uint8_t * buffer, uint16_t buf_length, - EndpointId destination_endpoint) +PacketBufferHandle encodeColorControlClusterReadPrimary3IntensityAttribute(EndpointId destinationEndpoint) { - uint16_t attr_ids[] = { 0x001B }; - READ_ATTRIBUTES("ReadColorControlPrimary3Intensity", COLOR_CONTROL_CLUSTER_ID); + COMMAND_HEADER("ReadColorControlPrimary3Intensity", COLOR_CONTROL_CLUSTER_ID); + buf.Put8(kFrameControlGlobalCommand).Put8(kSeqNum).Put8(ZCL_READ_ATTRIBUTES_COMMAND_ID).Put16(0x001B); + COMMAND_FOOTER(); } /* * Attribute Primary4X */ -uint16_t encodeColorControlClusterReadPrimary4XAttribute(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint) +PacketBufferHandle encodeColorControlClusterReadPrimary4XAttribute(EndpointId destinationEndpoint) { - uint16_t attr_ids[] = { 0x0020 }; - READ_ATTRIBUTES("ReadColorControlPrimary4X", COLOR_CONTROL_CLUSTER_ID); + COMMAND_HEADER("ReadColorControlPrimary4X", COLOR_CONTROL_CLUSTER_ID); + buf.Put8(kFrameControlGlobalCommand).Put8(kSeqNum).Put8(ZCL_READ_ATTRIBUTES_COMMAND_ID).Put16(0x0020); + COMMAND_FOOTER(); } /* * Attribute Primary4Y */ -uint16_t encodeColorControlClusterReadPrimary4YAttribute(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint) +PacketBufferHandle encodeColorControlClusterReadPrimary4YAttribute(EndpointId destinationEndpoint) { - uint16_t attr_ids[] = { 0x0021 }; - READ_ATTRIBUTES("ReadColorControlPrimary4Y", COLOR_CONTROL_CLUSTER_ID); + COMMAND_HEADER("ReadColorControlPrimary4Y", COLOR_CONTROL_CLUSTER_ID); + buf.Put8(kFrameControlGlobalCommand).Put8(kSeqNum).Put8(ZCL_READ_ATTRIBUTES_COMMAND_ID).Put16(0x0021); + COMMAND_FOOTER(); } /* * Attribute Primary4Intensity */ -uint16_t encodeColorControlClusterReadPrimary4IntensityAttribute(uint8_t * buffer, uint16_t buf_length, - EndpointId destination_endpoint) +PacketBufferHandle encodeColorControlClusterReadPrimary4IntensityAttribute(EndpointId destinationEndpoint) { - uint16_t attr_ids[] = { 0x0022 }; - READ_ATTRIBUTES("ReadColorControlPrimary4Intensity", COLOR_CONTROL_CLUSTER_ID); + COMMAND_HEADER("ReadColorControlPrimary4Intensity", COLOR_CONTROL_CLUSTER_ID); + buf.Put8(kFrameControlGlobalCommand).Put8(kSeqNum).Put8(ZCL_READ_ATTRIBUTES_COMMAND_ID).Put16(0x0022); + COMMAND_FOOTER(); } /* * Attribute Primary5X */ -uint16_t encodeColorControlClusterReadPrimary5XAttribute(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint) +PacketBufferHandle encodeColorControlClusterReadPrimary5XAttribute(EndpointId destinationEndpoint) { - uint16_t attr_ids[] = { 0x0024 }; - READ_ATTRIBUTES("ReadColorControlPrimary5X", COLOR_CONTROL_CLUSTER_ID); + COMMAND_HEADER("ReadColorControlPrimary5X", COLOR_CONTROL_CLUSTER_ID); + buf.Put8(kFrameControlGlobalCommand).Put8(kSeqNum).Put8(ZCL_READ_ATTRIBUTES_COMMAND_ID).Put16(0x0024); + COMMAND_FOOTER(); } /* * Attribute Primary5Y */ -uint16_t encodeColorControlClusterReadPrimary5YAttribute(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint) +PacketBufferHandle encodeColorControlClusterReadPrimary5YAttribute(EndpointId destinationEndpoint) { - uint16_t attr_ids[] = { 0x0025 }; - READ_ATTRIBUTES("ReadColorControlPrimary5Y", COLOR_CONTROL_CLUSTER_ID); + COMMAND_HEADER("ReadColorControlPrimary5Y", COLOR_CONTROL_CLUSTER_ID); + buf.Put8(kFrameControlGlobalCommand).Put8(kSeqNum).Put8(ZCL_READ_ATTRIBUTES_COMMAND_ID).Put16(0x0025); + COMMAND_FOOTER(); } /* * Attribute Primary5Intensity */ -uint16_t encodeColorControlClusterReadPrimary5IntensityAttribute(uint8_t * buffer, uint16_t buf_length, - EndpointId destination_endpoint) +PacketBufferHandle encodeColorControlClusterReadPrimary5IntensityAttribute(EndpointId destinationEndpoint) { - uint16_t attr_ids[] = { 0x0026 }; - READ_ATTRIBUTES("ReadColorControlPrimary5Intensity", COLOR_CONTROL_CLUSTER_ID); + COMMAND_HEADER("ReadColorControlPrimary5Intensity", COLOR_CONTROL_CLUSTER_ID); + buf.Put8(kFrameControlGlobalCommand).Put8(kSeqNum).Put8(ZCL_READ_ATTRIBUTES_COMMAND_ID).Put16(0x0026); + COMMAND_FOOTER(); } /* * Attribute Primary6X */ -uint16_t encodeColorControlClusterReadPrimary6XAttribute(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint) +PacketBufferHandle encodeColorControlClusterReadPrimary6XAttribute(EndpointId destinationEndpoint) { - uint16_t attr_ids[] = { 0x0028 }; - READ_ATTRIBUTES("ReadColorControlPrimary6X", COLOR_CONTROL_CLUSTER_ID); + COMMAND_HEADER("ReadColorControlPrimary6X", COLOR_CONTROL_CLUSTER_ID); + buf.Put8(kFrameControlGlobalCommand).Put8(kSeqNum).Put8(ZCL_READ_ATTRIBUTES_COMMAND_ID).Put16(0x0028); + COMMAND_FOOTER(); } /* * Attribute Primary6Y */ -uint16_t encodeColorControlClusterReadPrimary6YAttribute(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint) +PacketBufferHandle encodeColorControlClusterReadPrimary6YAttribute(EndpointId destinationEndpoint) { - uint16_t attr_ids[] = { 0x0029 }; - READ_ATTRIBUTES("ReadColorControlPrimary6Y", COLOR_CONTROL_CLUSTER_ID); + COMMAND_HEADER("ReadColorControlPrimary6Y", COLOR_CONTROL_CLUSTER_ID); + buf.Put8(kFrameControlGlobalCommand).Put8(kSeqNum).Put8(ZCL_READ_ATTRIBUTES_COMMAND_ID).Put16(0x0029); + COMMAND_FOOTER(); } /* * Attribute Primary6Intensity */ -uint16_t encodeColorControlClusterReadPrimary6IntensityAttribute(uint8_t * buffer, uint16_t buf_length, - EndpointId destination_endpoint) +PacketBufferHandle encodeColorControlClusterReadPrimary6IntensityAttribute(EndpointId destinationEndpoint) { - uint16_t attr_ids[] = { 0x002A }; - READ_ATTRIBUTES("ReadColorControlPrimary6Intensity", COLOR_CONTROL_CLUSTER_ID); + COMMAND_HEADER("ReadColorControlPrimary6Intensity", COLOR_CONTROL_CLUSTER_ID); + buf.Put8(kFrameControlGlobalCommand).Put8(kSeqNum).Put8(ZCL_READ_ATTRIBUTES_COMMAND_ID).Put16(0x002A); + COMMAND_FOOTER(); } /* * Attribute WhitePointX */ -uint16_t encodeColorControlClusterReadWhitePointXAttribute(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint) +PacketBufferHandle encodeColorControlClusterReadWhitePointXAttribute(EndpointId destinationEndpoint) { - uint16_t attr_ids[] = { 0x0030 }; - READ_ATTRIBUTES("ReadColorControlWhitePointX", COLOR_CONTROL_CLUSTER_ID); + COMMAND_HEADER("ReadColorControlWhitePointX", COLOR_CONTROL_CLUSTER_ID); + buf.Put8(kFrameControlGlobalCommand).Put8(kSeqNum).Put8(ZCL_READ_ATTRIBUTES_COMMAND_ID).Put16(0x0030); + COMMAND_FOOTER(); } -uint16_t encodeColorControlClusterWriteWhitePointXAttribute(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint, - uint16_t whitePointX) +PacketBufferHandle encodeColorControlClusterWriteWhitePointXAttribute(EndpointId destinationEndpoint, uint16_t whitePointX) { - uint16_t attr_id = 0x0030; - uint8_t attr_type = { 0x21 }; - WRITE_ATTRIBUTE("WriteColorControlWhitePointX", COLOR_CONTROL_CLUSTER_ID, whitePointX); + COMMAND_HEADER("WriteColorControlWhitePointX", COLOR_CONTROL_CLUSTER_ID); + buf.Put8(kFrameControlGlobalCommand) + .Put8(kSeqNum) + .Put8(ZCL_WRITE_ATTRIBUTES_COMMAND_ID) + .Put16(0x0030) + .Put8(0x21) + .Put16(static_cast(whitePointX)); + COMMAND_FOOTER(); } /* * Attribute WhitePointY */ -uint16_t encodeColorControlClusterReadWhitePointYAttribute(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint) +PacketBufferHandle encodeColorControlClusterReadWhitePointYAttribute(EndpointId destinationEndpoint) { - uint16_t attr_ids[] = { 0x0031 }; - READ_ATTRIBUTES("ReadColorControlWhitePointY", COLOR_CONTROL_CLUSTER_ID); + COMMAND_HEADER("ReadColorControlWhitePointY", COLOR_CONTROL_CLUSTER_ID); + buf.Put8(kFrameControlGlobalCommand).Put8(kSeqNum).Put8(ZCL_READ_ATTRIBUTES_COMMAND_ID).Put16(0x0031); + COMMAND_FOOTER(); } -uint16_t encodeColorControlClusterWriteWhitePointYAttribute(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint, - uint16_t whitePointY) +PacketBufferHandle encodeColorControlClusterWriteWhitePointYAttribute(EndpointId destinationEndpoint, uint16_t whitePointY) { - uint16_t attr_id = 0x0031; - uint8_t attr_type = { 0x21 }; - WRITE_ATTRIBUTE("WriteColorControlWhitePointY", COLOR_CONTROL_CLUSTER_ID, whitePointY); + COMMAND_HEADER("WriteColorControlWhitePointY", COLOR_CONTROL_CLUSTER_ID); + buf.Put8(kFrameControlGlobalCommand) + .Put8(kSeqNum) + .Put8(ZCL_WRITE_ATTRIBUTES_COMMAND_ID) + .Put16(0x0031) + .Put8(0x21) + .Put16(static_cast(whitePointY)); + COMMAND_FOOTER(); } /* * Attribute ColorPointRX */ -uint16_t encodeColorControlClusterReadColorPointRXAttribute(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint) +PacketBufferHandle encodeColorControlClusterReadColorPointRXAttribute(EndpointId destinationEndpoint) { - uint16_t attr_ids[] = { 0x0032 }; - READ_ATTRIBUTES("ReadColorControlColorPointRX", COLOR_CONTROL_CLUSTER_ID); + COMMAND_HEADER("ReadColorControlColorPointRX", COLOR_CONTROL_CLUSTER_ID); + buf.Put8(kFrameControlGlobalCommand).Put8(kSeqNum).Put8(ZCL_READ_ATTRIBUTES_COMMAND_ID).Put16(0x0032); + COMMAND_FOOTER(); } -uint16_t encodeColorControlClusterWriteColorPointRXAttribute(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint, - uint16_t colorPointRX) +PacketBufferHandle encodeColorControlClusterWriteColorPointRXAttribute(EndpointId destinationEndpoint, uint16_t colorPointRX) { - uint16_t attr_id = 0x0032; - uint8_t attr_type = { 0x21 }; - WRITE_ATTRIBUTE("WriteColorControlColorPointRX", COLOR_CONTROL_CLUSTER_ID, colorPointRX); + COMMAND_HEADER("WriteColorControlColorPointRX", COLOR_CONTROL_CLUSTER_ID); + buf.Put8(kFrameControlGlobalCommand) + .Put8(kSeqNum) + .Put8(ZCL_WRITE_ATTRIBUTES_COMMAND_ID) + .Put16(0x0032) + .Put8(0x21) + .Put16(static_cast(colorPointRX)); + COMMAND_FOOTER(); } /* * Attribute ColorPointRY */ -uint16_t encodeColorControlClusterReadColorPointRYAttribute(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint) +PacketBufferHandle encodeColorControlClusterReadColorPointRYAttribute(EndpointId destinationEndpoint) { - uint16_t attr_ids[] = { 0x0033 }; - READ_ATTRIBUTES("ReadColorControlColorPointRY", COLOR_CONTROL_CLUSTER_ID); + COMMAND_HEADER("ReadColorControlColorPointRY", COLOR_CONTROL_CLUSTER_ID); + buf.Put8(kFrameControlGlobalCommand).Put8(kSeqNum).Put8(ZCL_READ_ATTRIBUTES_COMMAND_ID).Put16(0x0033); + COMMAND_FOOTER(); } -uint16_t encodeColorControlClusterWriteColorPointRYAttribute(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint, - uint16_t colorPointRY) +PacketBufferHandle encodeColorControlClusterWriteColorPointRYAttribute(EndpointId destinationEndpoint, uint16_t colorPointRY) { - uint16_t attr_id = 0x0033; - uint8_t attr_type = { 0x21 }; - WRITE_ATTRIBUTE("WriteColorControlColorPointRY", COLOR_CONTROL_CLUSTER_ID, colorPointRY); + COMMAND_HEADER("WriteColorControlColorPointRY", COLOR_CONTROL_CLUSTER_ID); + buf.Put8(kFrameControlGlobalCommand) + .Put8(kSeqNum) + .Put8(ZCL_WRITE_ATTRIBUTES_COMMAND_ID) + .Put16(0x0033) + .Put8(0x21) + .Put16(static_cast(colorPointRY)); + COMMAND_FOOTER(); } /* * Attribute ColorPointRIntensity */ -uint16_t encodeColorControlClusterReadColorPointRIntensityAttribute(uint8_t * buffer, uint16_t buf_length, - EndpointId destination_endpoint) +PacketBufferHandle encodeColorControlClusterReadColorPointRIntensityAttribute(EndpointId destinationEndpoint) { - uint16_t attr_ids[] = { 0x0034 }; - READ_ATTRIBUTES("ReadColorControlColorPointRIntensity", COLOR_CONTROL_CLUSTER_ID); + COMMAND_HEADER("ReadColorControlColorPointRIntensity", COLOR_CONTROL_CLUSTER_ID); + buf.Put8(kFrameControlGlobalCommand).Put8(kSeqNum).Put8(ZCL_READ_ATTRIBUTES_COMMAND_ID).Put16(0x0034); + COMMAND_FOOTER(); } -uint16_t encodeColorControlClusterWriteColorPointRIntensityAttribute(uint8_t * buffer, uint16_t buf_length, - EndpointId destination_endpoint, uint8_t colorPointRIntensity) +PacketBufferHandle encodeColorControlClusterWriteColorPointRIntensityAttribute(EndpointId destinationEndpoint, + uint8_t colorPointRIntensity) { - uint16_t attr_id = 0x0034; - uint8_t attr_type = { 0x20 }; - WRITE_ATTRIBUTE("WriteColorControlColorPointRIntensity", COLOR_CONTROL_CLUSTER_ID, colorPointRIntensity); + COMMAND_HEADER("WriteColorControlColorPointRIntensity", COLOR_CONTROL_CLUSTER_ID); + buf.Put8(kFrameControlGlobalCommand) + .Put8(kSeqNum) + .Put8(ZCL_WRITE_ATTRIBUTES_COMMAND_ID) + .Put16(0x0034) + .Put8(0x20) + .Put8(static_cast(colorPointRIntensity)); + COMMAND_FOOTER(); } /* * Attribute ColorPointGX */ -uint16_t encodeColorControlClusterReadColorPointGXAttribute(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint) +PacketBufferHandle encodeColorControlClusterReadColorPointGXAttribute(EndpointId destinationEndpoint) { - uint16_t attr_ids[] = { 0x0036 }; - READ_ATTRIBUTES("ReadColorControlColorPointGX", COLOR_CONTROL_CLUSTER_ID); + COMMAND_HEADER("ReadColorControlColorPointGX", COLOR_CONTROL_CLUSTER_ID); + buf.Put8(kFrameControlGlobalCommand).Put8(kSeqNum).Put8(ZCL_READ_ATTRIBUTES_COMMAND_ID).Put16(0x0036); + COMMAND_FOOTER(); } -uint16_t encodeColorControlClusterWriteColorPointGXAttribute(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint, - uint16_t colorPointGX) +PacketBufferHandle encodeColorControlClusterWriteColorPointGXAttribute(EndpointId destinationEndpoint, uint16_t colorPointGX) { - uint16_t attr_id = 0x0036; - uint8_t attr_type = { 0x21 }; - WRITE_ATTRIBUTE("WriteColorControlColorPointGX", COLOR_CONTROL_CLUSTER_ID, colorPointGX); + COMMAND_HEADER("WriteColorControlColorPointGX", COLOR_CONTROL_CLUSTER_ID); + buf.Put8(kFrameControlGlobalCommand) + .Put8(kSeqNum) + .Put8(ZCL_WRITE_ATTRIBUTES_COMMAND_ID) + .Put16(0x0036) + .Put8(0x21) + .Put16(static_cast(colorPointGX)); + COMMAND_FOOTER(); } /* * Attribute ColorPointGY */ -uint16_t encodeColorControlClusterReadColorPointGYAttribute(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint) +PacketBufferHandle encodeColorControlClusterReadColorPointGYAttribute(EndpointId destinationEndpoint) { - uint16_t attr_ids[] = { 0x0037 }; - READ_ATTRIBUTES("ReadColorControlColorPointGY", COLOR_CONTROL_CLUSTER_ID); + COMMAND_HEADER("ReadColorControlColorPointGY", COLOR_CONTROL_CLUSTER_ID); + buf.Put8(kFrameControlGlobalCommand).Put8(kSeqNum).Put8(ZCL_READ_ATTRIBUTES_COMMAND_ID).Put16(0x0037); + COMMAND_FOOTER(); } -uint16_t encodeColorControlClusterWriteColorPointGYAttribute(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint, - uint16_t colorPointGY) +PacketBufferHandle encodeColorControlClusterWriteColorPointGYAttribute(EndpointId destinationEndpoint, uint16_t colorPointGY) { - uint16_t attr_id = 0x0037; - uint8_t attr_type = { 0x21 }; - WRITE_ATTRIBUTE("WriteColorControlColorPointGY", COLOR_CONTROL_CLUSTER_ID, colorPointGY); + COMMAND_HEADER("WriteColorControlColorPointGY", COLOR_CONTROL_CLUSTER_ID); + buf.Put8(kFrameControlGlobalCommand) + .Put8(kSeqNum) + .Put8(ZCL_WRITE_ATTRIBUTES_COMMAND_ID) + .Put16(0x0037) + .Put8(0x21) + .Put16(static_cast(colorPointGY)); + COMMAND_FOOTER(); } /* * Attribute ColorPointGIntensity */ -uint16_t encodeColorControlClusterReadColorPointGIntensityAttribute(uint8_t * buffer, uint16_t buf_length, - EndpointId destination_endpoint) +PacketBufferHandle encodeColorControlClusterReadColorPointGIntensityAttribute(EndpointId destinationEndpoint) { - uint16_t attr_ids[] = { 0x0038 }; - READ_ATTRIBUTES("ReadColorControlColorPointGIntensity", COLOR_CONTROL_CLUSTER_ID); + COMMAND_HEADER("ReadColorControlColorPointGIntensity", COLOR_CONTROL_CLUSTER_ID); + buf.Put8(kFrameControlGlobalCommand).Put8(kSeqNum).Put8(ZCL_READ_ATTRIBUTES_COMMAND_ID).Put16(0x0038); + COMMAND_FOOTER(); } -uint16_t encodeColorControlClusterWriteColorPointGIntensityAttribute(uint8_t * buffer, uint16_t buf_length, - EndpointId destination_endpoint, uint8_t colorPointGIntensity) +PacketBufferHandle encodeColorControlClusterWriteColorPointGIntensityAttribute(EndpointId destinationEndpoint, + uint8_t colorPointGIntensity) { - uint16_t attr_id = 0x0038; - uint8_t attr_type = { 0x20 }; - WRITE_ATTRIBUTE("WriteColorControlColorPointGIntensity", COLOR_CONTROL_CLUSTER_ID, colorPointGIntensity); + COMMAND_HEADER("WriteColorControlColorPointGIntensity", COLOR_CONTROL_CLUSTER_ID); + buf.Put8(kFrameControlGlobalCommand) + .Put8(kSeqNum) + .Put8(ZCL_WRITE_ATTRIBUTES_COMMAND_ID) + .Put16(0x0038) + .Put8(0x20) + .Put8(static_cast(colorPointGIntensity)); + COMMAND_FOOTER(); } /* * Attribute ColorPointBX */ -uint16_t encodeColorControlClusterReadColorPointBXAttribute(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint) +PacketBufferHandle encodeColorControlClusterReadColorPointBXAttribute(EndpointId destinationEndpoint) { - uint16_t attr_ids[] = { 0x003A }; - READ_ATTRIBUTES("ReadColorControlColorPointBX", COLOR_CONTROL_CLUSTER_ID); + COMMAND_HEADER("ReadColorControlColorPointBX", COLOR_CONTROL_CLUSTER_ID); + buf.Put8(kFrameControlGlobalCommand).Put8(kSeqNum).Put8(ZCL_READ_ATTRIBUTES_COMMAND_ID).Put16(0x003A); + COMMAND_FOOTER(); } -uint16_t encodeColorControlClusterWriteColorPointBXAttribute(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint, - uint16_t colorPointBX) +PacketBufferHandle encodeColorControlClusterWriteColorPointBXAttribute(EndpointId destinationEndpoint, uint16_t colorPointBX) { - uint16_t attr_id = 0x003A; - uint8_t attr_type = { 0x21 }; - WRITE_ATTRIBUTE("WriteColorControlColorPointBX", COLOR_CONTROL_CLUSTER_ID, colorPointBX); + COMMAND_HEADER("WriteColorControlColorPointBX", COLOR_CONTROL_CLUSTER_ID); + buf.Put8(kFrameControlGlobalCommand) + .Put8(kSeqNum) + .Put8(ZCL_WRITE_ATTRIBUTES_COMMAND_ID) + .Put16(0x003A) + .Put8(0x21) + .Put16(static_cast(colorPointBX)); + COMMAND_FOOTER(); } /* * Attribute ColorPointBY */ -uint16_t encodeColorControlClusterReadColorPointBYAttribute(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint) +PacketBufferHandle encodeColorControlClusterReadColorPointBYAttribute(EndpointId destinationEndpoint) { - uint16_t attr_ids[] = { 0x003B }; - READ_ATTRIBUTES("ReadColorControlColorPointBY", COLOR_CONTROL_CLUSTER_ID); + COMMAND_HEADER("ReadColorControlColorPointBY", COLOR_CONTROL_CLUSTER_ID); + buf.Put8(kFrameControlGlobalCommand).Put8(kSeqNum).Put8(ZCL_READ_ATTRIBUTES_COMMAND_ID).Put16(0x003B); + COMMAND_FOOTER(); } -uint16_t encodeColorControlClusterWriteColorPointBYAttribute(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint, - uint16_t colorPointBY) +PacketBufferHandle encodeColorControlClusterWriteColorPointBYAttribute(EndpointId destinationEndpoint, uint16_t colorPointBY) { - uint16_t attr_id = 0x003B; - uint8_t attr_type = { 0x21 }; - WRITE_ATTRIBUTE("WriteColorControlColorPointBY", COLOR_CONTROL_CLUSTER_ID, colorPointBY); + COMMAND_HEADER("WriteColorControlColorPointBY", COLOR_CONTROL_CLUSTER_ID); + buf.Put8(kFrameControlGlobalCommand) + .Put8(kSeqNum) + .Put8(ZCL_WRITE_ATTRIBUTES_COMMAND_ID) + .Put16(0x003B) + .Put8(0x21) + .Put16(static_cast(colorPointBY)); + COMMAND_FOOTER(); } /* * Attribute ColorPointBIntensity */ -uint16_t encodeColorControlClusterReadColorPointBIntensityAttribute(uint8_t * buffer, uint16_t buf_length, - EndpointId destination_endpoint) +PacketBufferHandle encodeColorControlClusterReadColorPointBIntensityAttribute(EndpointId destinationEndpoint) { - uint16_t attr_ids[] = { 0x003C }; - READ_ATTRIBUTES("ReadColorControlColorPointBIntensity", COLOR_CONTROL_CLUSTER_ID); + COMMAND_HEADER("ReadColorControlColorPointBIntensity", COLOR_CONTROL_CLUSTER_ID); + buf.Put8(kFrameControlGlobalCommand).Put8(kSeqNum).Put8(ZCL_READ_ATTRIBUTES_COMMAND_ID).Put16(0x003C); + COMMAND_FOOTER(); } -uint16_t encodeColorControlClusterWriteColorPointBIntensityAttribute(uint8_t * buffer, uint16_t buf_length, - EndpointId destination_endpoint, uint8_t colorPointBIntensity) +PacketBufferHandle encodeColorControlClusterWriteColorPointBIntensityAttribute(EndpointId destinationEndpoint, + uint8_t colorPointBIntensity) { - uint16_t attr_id = 0x003C; - uint8_t attr_type = { 0x20 }; - WRITE_ATTRIBUTE("WriteColorControlColorPointBIntensity", COLOR_CONTROL_CLUSTER_ID, colorPointBIntensity); + COMMAND_HEADER("WriteColorControlColorPointBIntensity", COLOR_CONTROL_CLUSTER_ID); + buf.Put8(kFrameControlGlobalCommand) + .Put8(kSeqNum) + .Put8(ZCL_WRITE_ATTRIBUTES_COMMAND_ID) + .Put16(0x003C) + .Put8(0x20) + .Put8(static_cast(colorPointBIntensity)); + COMMAND_FOOTER(); } /* * Attribute EnhancedCurrentHue */ -uint16_t encodeColorControlClusterReadEnhancedCurrentHueAttribute(uint8_t * buffer, uint16_t buf_length, - EndpointId destination_endpoint) +PacketBufferHandle encodeColorControlClusterReadEnhancedCurrentHueAttribute(EndpointId destinationEndpoint) { - uint16_t attr_ids[] = { 0x4000 }; - READ_ATTRIBUTES("ReadColorControlEnhancedCurrentHue", COLOR_CONTROL_CLUSTER_ID); + COMMAND_HEADER("ReadColorControlEnhancedCurrentHue", COLOR_CONTROL_CLUSTER_ID); + buf.Put8(kFrameControlGlobalCommand).Put8(kSeqNum).Put8(ZCL_READ_ATTRIBUTES_COMMAND_ID).Put16(0x4000); + COMMAND_FOOTER(); } /* * Attribute EnhancedColorMode */ -uint16_t encodeColorControlClusterReadEnhancedColorModeAttribute(uint8_t * buffer, uint16_t buf_length, - EndpointId destination_endpoint) +PacketBufferHandle encodeColorControlClusterReadEnhancedColorModeAttribute(EndpointId destinationEndpoint) { - uint16_t attr_ids[] = { 0x4001 }; - READ_ATTRIBUTES("ReadColorControlEnhancedColorMode", COLOR_CONTROL_CLUSTER_ID); + COMMAND_HEADER("ReadColorControlEnhancedColorMode", COLOR_CONTROL_CLUSTER_ID); + buf.Put8(kFrameControlGlobalCommand).Put8(kSeqNum).Put8(ZCL_READ_ATTRIBUTES_COMMAND_ID).Put16(0x4001); + COMMAND_FOOTER(); } /* * Attribute ColorLoopActive */ -uint16_t encodeColorControlClusterReadColorLoopActiveAttribute(uint8_t * buffer, uint16_t buf_length, - EndpointId destination_endpoint) +PacketBufferHandle encodeColorControlClusterReadColorLoopActiveAttribute(EndpointId destinationEndpoint) { - uint16_t attr_ids[] = { 0x4002 }; - READ_ATTRIBUTES("ReadColorControlColorLoopActive", COLOR_CONTROL_CLUSTER_ID); + COMMAND_HEADER("ReadColorControlColorLoopActive", COLOR_CONTROL_CLUSTER_ID); + buf.Put8(kFrameControlGlobalCommand).Put8(kSeqNum).Put8(ZCL_READ_ATTRIBUTES_COMMAND_ID).Put16(0x4002); + COMMAND_FOOTER(); } /* * Attribute ColorLoopDirection */ -uint16_t encodeColorControlClusterReadColorLoopDirectionAttribute(uint8_t * buffer, uint16_t buf_length, - EndpointId destination_endpoint) +PacketBufferHandle encodeColorControlClusterReadColorLoopDirectionAttribute(EndpointId destinationEndpoint) { - uint16_t attr_ids[] = { 0x4003 }; - READ_ATTRIBUTES("ReadColorControlColorLoopDirection", COLOR_CONTROL_CLUSTER_ID); + COMMAND_HEADER("ReadColorControlColorLoopDirection", COLOR_CONTROL_CLUSTER_ID); + buf.Put8(kFrameControlGlobalCommand).Put8(kSeqNum).Put8(ZCL_READ_ATTRIBUTES_COMMAND_ID).Put16(0x4003); + COMMAND_FOOTER(); } /* * Attribute ColorLoopTime */ -uint16_t encodeColorControlClusterReadColorLoopTimeAttribute(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint) +PacketBufferHandle encodeColorControlClusterReadColorLoopTimeAttribute(EndpointId destinationEndpoint) { - uint16_t attr_ids[] = { 0x4004 }; - READ_ATTRIBUTES("ReadColorControlColorLoopTime", COLOR_CONTROL_CLUSTER_ID); + COMMAND_HEADER("ReadColorControlColorLoopTime", COLOR_CONTROL_CLUSTER_ID); + buf.Put8(kFrameControlGlobalCommand).Put8(kSeqNum).Put8(ZCL_READ_ATTRIBUTES_COMMAND_ID).Put16(0x4004); + COMMAND_FOOTER(); } /* * Attribute ColorCapabilities */ -uint16_t encodeColorControlClusterReadColorCapabilitiesAttribute(uint8_t * buffer, uint16_t buf_length, - EndpointId destination_endpoint) +PacketBufferHandle encodeColorControlClusterReadColorCapabilitiesAttribute(EndpointId destinationEndpoint) { - uint16_t attr_ids[] = { 0x400A }; - READ_ATTRIBUTES("ReadColorControlColorCapabilities", COLOR_CONTROL_CLUSTER_ID); + COMMAND_HEADER("ReadColorControlColorCapabilities", COLOR_CONTROL_CLUSTER_ID); + buf.Put8(kFrameControlGlobalCommand).Put8(kSeqNum).Put8(ZCL_READ_ATTRIBUTES_COMMAND_ID).Put16(0x400A); + COMMAND_FOOTER(); } /* * Attribute ColorTempPhysicalMin */ -uint16_t encodeColorControlClusterReadColorTempPhysicalMinAttribute(uint8_t * buffer, uint16_t buf_length, - EndpointId destination_endpoint) +PacketBufferHandle encodeColorControlClusterReadColorTempPhysicalMinAttribute(EndpointId destinationEndpoint) { - uint16_t attr_ids[] = { 0x400B }; - READ_ATTRIBUTES("ReadColorControlColorTempPhysicalMin", COLOR_CONTROL_CLUSTER_ID); + COMMAND_HEADER("ReadColorControlColorTempPhysicalMin", COLOR_CONTROL_CLUSTER_ID); + buf.Put8(kFrameControlGlobalCommand).Put8(kSeqNum).Put8(ZCL_READ_ATTRIBUTES_COMMAND_ID).Put16(0x400B); + COMMAND_FOOTER(); } /* * Attribute ColorTempPhysicalMax */ -uint16_t encodeColorControlClusterReadColorTempPhysicalMaxAttribute(uint8_t * buffer, uint16_t buf_length, - EndpointId destination_endpoint) +PacketBufferHandle encodeColorControlClusterReadColorTempPhysicalMaxAttribute(EndpointId destinationEndpoint) { - uint16_t attr_ids[] = { 0x400C }; - READ_ATTRIBUTES("ReadColorControlColorTempPhysicalMax", COLOR_CONTROL_CLUSTER_ID); + COMMAND_HEADER("ReadColorControlColorTempPhysicalMax", COLOR_CONTROL_CLUSTER_ID); + buf.Put8(kFrameControlGlobalCommand).Put8(kSeqNum).Put8(ZCL_READ_ATTRIBUTES_COMMAND_ID).Put16(0x400C); + COMMAND_FOOTER(); } /* * Attribute CoupleColorTempToLevelMinMireds */ -uint16_t encodeColorControlClusterReadCoupleColorTempToLevelMinMiredsAttribute(uint8_t * buffer, uint16_t buf_length, - EndpointId destination_endpoint) +PacketBufferHandle encodeColorControlClusterReadCoupleColorTempToLevelMinMiredsAttribute(EndpointId destinationEndpoint) { - uint16_t attr_ids[] = { 0x400D }; - READ_ATTRIBUTES("ReadColorControlCoupleColorTempToLevelMinMireds", COLOR_CONTROL_CLUSTER_ID); + COMMAND_HEADER("ReadColorControlCoupleColorTempToLevelMinMireds", COLOR_CONTROL_CLUSTER_ID); + buf.Put8(kFrameControlGlobalCommand).Put8(kSeqNum).Put8(ZCL_READ_ATTRIBUTES_COMMAND_ID).Put16(0x400D); + COMMAND_FOOTER(); } /* * Attribute StartUpColorTemperatureMireds */ -uint16_t encodeColorControlClusterReadStartUpColorTemperatureMiredsAttribute(uint8_t * buffer, uint16_t buf_length, - EndpointId destination_endpoint) +PacketBufferHandle encodeColorControlClusterReadStartUpColorTemperatureMiredsAttribute(EndpointId destinationEndpoint) { - uint16_t attr_ids[] = { 0x4010 }; - READ_ATTRIBUTES("ReadColorControlStartUpColorTemperatureMireds", COLOR_CONTROL_CLUSTER_ID); + COMMAND_HEADER("ReadColorControlStartUpColorTemperatureMireds", COLOR_CONTROL_CLUSTER_ID); + buf.Put8(kFrameControlGlobalCommand).Put8(kSeqNum).Put8(ZCL_READ_ATTRIBUTES_COMMAND_ID).Put16(0x4010); + COMMAND_FOOTER(); } -uint16_t encodeColorControlClusterWriteStartUpColorTemperatureMiredsAttribute(uint8_t * buffer, uint16_t buf_length, - EndpointId destination_endpoint, - uint16_t startUpColorTemperatureMireds) +PacketBufferHandle encodeColorControlClusterWriteStartUpColorTemperatureMiredsAttribute(EndpointId destinationEndpoint, + uint16_t startUpColorTemperatureMireds) { - uint16_t attr_id = 0x4010; - uint8_t attr_type = { 0x21 }; - WRITE_ATTRIBUTE("WriteColorControlStartUpColorTemperatureMireds", COLOR_CONTROL_CLUSTER_ID, startUpColorTemperatureMireds); + COMMAND_HEADER("WriteColorControlStartUpColorTemperatureMireds", COLOR_CONTROL_CLUSTER_ID); + buf.Put8(kFrameControlGlobalCommand) + .Put8(kSeqNum) + .Put8(ZCL_WRITE_ATTRIBUTES_COMMAND_ID) + .Put16(0x4010) + .Put8(0x21) + .Put16(static_cast(startUpColorTemperatureMireds)); + COMMAND_FOOTER(); } /* * Attribute ClusterRevision */ -uint16_t encodeColorControlClusterReadClusterRevisionAttribute(uint8_t * buffer, uint16_t buf_length, - EndpointId destination_endpoint) +PacketBufferHandle encodeColorControlClusterReadClusterRevisionAttribute(EndpointId destinationEndpoint) { - uint16_t attr_ids[] = { 0xFFFD }; - READ_ATTRIBUTES("ReadColorControlClusterRevision", COLOR_CONTROL_CLUSTER_ID); + COMMAND_HEADER("ReadColorControlClusterRevision", COLOR_CONTROL_CLUSTER_ID); + buf.Put8(kFrameControlGlobalCommand).Put8(kSeqNum).Put8(ZCL_READ_ATTRIBUTES_COMMAND_ID).Put16(0xFFFD); + COMMAND_FOOTER(); } /*----------------------------------------------------------------------------*\ @@ -1422,346 +1539,399 @@ uint16_t encodeColorControlClusterReadClusterRevisionAttribute(uint8_t * buffer, /* * Command ClearAllPins */ -uint16_t encodeDoorLockClusterClearAllPinsCommand(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint) +PacketBufferHandle encodeDoorLockClusterClearAllPinsCommand(EndpointId destinationEndpoint) { - const char * kName = "DoorLockClearAllPins"; - COMMAND_HEADER(kName, DOOR_LOCK_CLUSTER_ID, 0x08); - COMMAND_FOOTER(kName); + COMMAND_HEADER("ClearAllPins", DOOR_LOCK_CLUSTER_ID); + buf.Put8(kFrameControlClusterSpecificCommand).Put8(kSeqNum).Put8(ZCL_CLEAR_ALL_PINS_COMMAND_ID); + COMMAND_FOOTER(); } /* * Command ClearAllRfids */ -uint16_t encodeDoorLockClusterClearAllRfidsCommand(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint) +PacketBufferHandle encodeDoorLockClusterClearAllRfidsCommand(EndpointId destinationEndpoint) { - const char * kName = "DoorLockClearAllRfids"; - COMMAND_HEADER(kName, DOOR_LOCK_CLUSTER_ID, 0x19); - COMMAND_FOOTER(kName); + COMMAND_HEADER("ClearAllRfids", DOOR_LOCK_CLUSTER_ID); + buf.Put8(kFrameControlClusterSpecificCommand).Put8(kSeqNum).Put8(ZCL_CLEAR_ALL_RFIDS_COMMAND_ID); + COMMAND_FOOTER(); } /* * Command ClearHolidaySchedule */ -uint16_t encodeDoorLockClusterClearHolidayScheduleCommand(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint, - uint8_t scheduleId) +PacketBufferHandle encodeDoorLockClusterClearHolidayScheduleCommand(EndpointId destinationEndpoint, uint8_t scheduleId) { - const char * kName = "DoorLockClearHolidaySchedule"; - COMMAND_HEADER(kName, DOOR_LOCK_CLUSTER_ID, 0x13); - buf.Put(scheduleId); - COMMAND_FOOTER(kName); + COMMAND_HEADER("ClearHolidaySchedule", DOOR_LOCK_CLUSTER_ID); + buf.Put8(kFrameControlClusterSpecificCommand).Put8(kSeqNum).Put8(ZCL_CLEAR_HOLIDAY_SCHEDULE_COMMAND_ID).Put8(scheduleId); + COMMAND_FOOTER(); } /* * Command ClearPin */ -uint16_t encodeDoorLockClusterClearPinCommand(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint, - uint16_t userId) +PacketBufferHandle encodeDoorLockClusterClearPinCommand(EndpointId destinationEndpoint, uint16_t userId) { - const char * kName = "DoorLockClearPin"; - COMMAND_HEADER(kName, DOOR_LOCK_CLUSTER_ID, 0x07); - buf.Put16(userId); - COMMAND_FOOTER(kName); + COMMAND_HEADER("ClearPin", DOOR_LOCK_CLUSTER_ID); + buf.Put8(kFrameControlClusterSpecificCommand).Put8(kSeqNum).Put8(ZCL_CLEAR_PIN_COMMAND_ID).Put16(userId); + COMMAND_FOOTER(); } /* * Command ClearRfid */ -uint16_t encodeDoorLockClusterClearRfidCommand(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint, - uint16_t userId) +PacketBufferHandle encodeDoorLockClusterClearRfidCommand(EndpointId destinationEndpoint, uint16_t userId) { - const char * kName = "DoorLockClearRfid"; - COMMAND_HEADER(kName, DOOR_LOCK_CLUSTER_ID, 0x18); - buf.Put16(userId); - COMMAND_FOOTER(kName); + COMMAND_HEADER("ClearRfid", DOOR_LOCK_CLUSTER_ID); + buf.Put8(kFrameControlClusterSpecificCommand).Put8(kSeqNum).Put8(ZCL_CLEAR_RFID_COMMAND_ID).Put16(userId); + COMMAND_FOOTER(); } /* * Command ClearWeekdaySchedule */ -uint16_t encodeDoorLockClusterClearWeekdayScheduleCommand(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint, - uint8_t scheduleId, uint16_t userId) +PacketBufferHandle encodeDoorLockClusterClearWeekdayScheduleCommand(EndpointId destinationEndpoint, uint8_t scheduleId, + uint16_t userId) { - const char * kName = "DoorLockClearWeekdaySchedule"; - COMMAND_HEADER(kName, DOOR_LOCK_CLUSTER_ID, 0x0D); - buf.Put(scheduleId); - buf.Put16(userId); - COMMAND_FOOTER(kName); + COMMAND_HEADER("ClearWeekdaySchedule", DOOR_LOCK_CLUSTER_ID); + buf.Put8(kFrameControlClusterSpecificCommand) + .Put8(kSeqNum) + .Put8(ZCL_CLEAR_WEEKDAY_SCHEDULE_COMMAND_ID) + .Put8(scheduleId) + .Put16(userId); + COMMAND_FOOTER(); } /* * Command ClearYeardaySchedule */ -uint16_t encodeDoorLockClusterClearYeardayScheduleCommand(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint, - uint8_t scheduleId, uint16_t userId) +PacketBufferHandle encodeDoorLockClusterClearYeardayScheduleCommand(EndpointId destinationEndpoint, uint8_t scheduleId, + uint16_t userId) { - const char * kName = "DoorLockClearYeardaySchedule"; - COMMAND_HEADER(kName, DOOR_LOCK_CLUSTER_ID, 0x10); - buf.Put(scheduleId); - buf.Put16(userId); - COMMAND_FOOTER(kName); + COMMAND_HEADER("ClearYeardaySchedule", DOOR_LOCK_CLUSTER_ID); + buf.Put8(kFrameControlClusterSpecificCommand) + .Put8(kSeqNum) + .Put8(ZCL_CLEAR_YEARDAY_SCHEDULE_COMMAND_ID) + .Put8(scheduleId) + .Put16(userId); + COMMAND_FOOTER(); } /* * Command GetHolidaySchedule */ -uint16_t encodeDoorLockClusterGetHolidayScheduleCommand(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint, - uint8_t scheduleId) +PacketBufferHandle encodeDoorLockClusterGetHolidayScheduleCommand(EndpointId destinationEndpoint, uint8_t scheduleId) { - const char * kName = "DoorLockGetHolidaySchedule"; - COMMAND_HEADER(kName, DOOR_LOCK_CLUSTER_ID, 0x12); - buf.Put(scheduleId); - COMMAND_FOOTER(kName); + COMMAND_HEADER("GetHolidaySchedule", DOOR_LOCK_CLUSTER_ID); + buf.Put8(kFrameControlClusterSpecificCommand).Put8(kSeqNum).Put8(ZCL_GET_HOLIDAY_SCHEDULE_COMMAND_ID).Put8(scheduleId); + COMMAND_FOOTER(); } /* * Command GetLogRecord */ -uint16_t encodeDoorLockClusterGetLogRecordCommand(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint, - uint16_t logIndex) +PacketBufferHandle encodeDoorLockClusterGetLogRecordCommand(EndpointId destinationEndpoint, uint16_t logIndex) { - const char * kName = "DoorLockGetLogRecord"; - COMMAND_HEADER(kName, DOOR_LOCK_CLUSTER_ID, 0x04); - buf.Put16(logIndex); - COMMAND_FOOTER(kName); + COMMAND_HEADER("GetLogRecord", DOOR_LOCK_CLUSTER_ID); + buf.Put8(kFrameControlClusterSpecificCommand).Put8(kSeqNum).Put8(ZCL_GET_LOG_RECORD_COMMAND_ID).Put16(logIndex); + COMMAND_FOOTER(); } /* * Command GetPin */ -uint16_t encodeDoorLockClusterGetPinCommand(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint, uint16_t userId) +PacketBufferHandle encodeDoorLockClusterGetPinCommand(EndpointId destinationEndpoint, uint16_t userId) { - const char * kName = "DoorLockGetPin"; - COMMAND_HEADER(kName, DOOR_LOCK_CLUSTER_ID, 0x06); - buf.Put16(userId); - COMMAND_FOOTER(kName); + COMMAND_HEADER("GetPin", DOOR_LOCK_CLUSTER_ID); + buf.Put8(kFrameControlClusterSpecificCommand).Put8(kSeqNum).Put8(ZCL_GET_PIN_COMMAND_ID).Put16(userId); + COMMAND_FOOTER(); } /* * Command GetRfid */ -uint16_t encodeDoorLockClusterGetRfidCommand(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint, - uint16_t userId) +PacketBufferHandle encodeDoorLockClusterGetRfidCommand(EndpointId destinationEndpoint, uint16_t userId) { - const char * kName = "DoorLockGetRfid"; - COMMAND_HEADER(kName, DOOR_LOCK_CLUSTER_ID, 0x17); - buf.Put16(userId); - COMMAND_FOOTER(kName); + COMMAND_HEADER("GetRfid", DOOR_LOCK_CLUSTER_ID); + buf.Put8(kFrameControlClusterSpecificCommand).Put8(kSeqNum).Put8(ZCL_GET_RFID_COMMAND_ID).Put16(userId); + COMMAND_FOOTER(); } /* * Command GetUserType */ -uint16_t encodeDoorLockClusterGetUserTypeCommand(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint, - uint16_t userId) +PacketBufferHandle encodeDoorLockClusterGetUserTypeCommand(EndpointId destinationEndpoint, uint16_t userId) { - const char * kName = "DoorLockGetUserType"; - COMMAND_HEADER(kName, DOOR_LOCK_CLUSTER_ID, 0x15); - buf.Put16(userId); - COMMAND_FOOTER(kName); + COMMAND_HEADER("GetUserType", DOOR_LOCK_CLUSTER_ID); + buf.Put8(kFrameControlClusterSpecificCommand).Put8(kSeqNum).Put8(ZCL_GET_USER_TYPE_COMMAND_ID).Put16(userId); + COMMAND_FOOTER(); } /* * Command GetWeekdaySchedule */ -uint16_t encodeDoorLockClusterGetWeekdayScheduleCommand(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint, - uint8_t scheduleId, uint16_t userId) +PacketBufferHandle encodeDoorLockClusterGetWeekdayScheduleCommand(EndpointId destinationEndpoint, uint8_t scheduleId, + uint16_t userId) { - const char * kName = "DoorLockGetWeekdaySchedule"; - COMMAND_HEADER(kName, DOOR_LOCK_CLUSTER_ID, 0x0C); - buf.Put(scheduleId); - buf.Put16(userId); - COMMAND_FOOTER(kName); + COMMAND_HEADER("GetWeekdaySchedule", DOOR_LOCK_CLUSTER_ID); + buf.Put8(kFrameControlClusterSpecificCommand) + .Put8(kSeqNum) + .Put8(ZCL_GET_WEEKDAY_SCHEDULE_COMMAND_ID) + .Put8(scheduleId) + .Put16(userId); + COMMAND_FOOTER(); } /* * Command GetYeardaySchedule */ -uint16_t encodeDoorLockClusterGetYeardayScheduleCommand(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint, - uint8_t scheduleId, uint16_t userId) +PacketBufferHandle encodeDoorLockClusterGetYeardayScheduleCommand(EndpointId destinationEndpoint, uint8_t scheduleId, + uint16_t userId) { - const char * kName = "DoorLockGetYeardaySchedule"; - COMMAND_HEADER(kName, DOOR_LOCK_CLUSTER_ID, 0x0F); - buf.Put(scheduleId); - buf.Put16(userId); - COMMAND_FOOTER(kName); + COMMAND_HEADER("GetYeardaySchedule", DOOR_LOCK_CLUSTER_ID); + buf.Put8(kFrameControlClusterSpecificCommand) + .Put8(kSeqNum) + .Put8(ZCL_GET_YEARDAY_SCHEDULE_COMMAND_ID) + .Put8(scheduleId) + .Put16(userId); + COMMAND_FOOTER(); } /* * Command LockDoor */ -uint16_t encodeDoorLockClusterLockDoorCommand(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint, char * pin) +PacketBufferHandle encodeDoorLockClusterLockDoorCommand(EndpointId destinationEndpoint, char * pin) { - const char * kName = "DoorLockLockDoor"; - COMMAND_HEADER(kName, DOOR_LOCK_CLUSTER_ID, 0x00); - COMMAND_INSERT_STRING(kName, pin); - COMMAND_FOOTER(kName); + COMMAND_HEADER("LockDoor", DOOR_LOCK_CLUSTER_ID); + size_t pinStrLen = strlen(pin); + if (!CanCastTo(pinStrLen)) + { + ChipLogError(Zcl, "Error encoding %s command. String too long: %d", kName, pinStrLen); + return PacketBufferHandle(); + } + buf.Put8(kFrameControlClusterSpecificCommand) + .Put8(kSeqNum) + .Put8(ZCL_LOCK_DOOR_COMMAND_ID) + .Put(static_cast(pinStrLen)) + .Put(pin); + COMMAND_FOOTER(); } /* * Command SetHolidaySchedule */ -uint16_t encodeDoorLockClusterSetHolidayScheduleCommand(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint, - uint8_t scheduleId, uint32_t localStartTime, uint32_t localEndTime, - uint8_t operatingModeDuringHoliday) +PacketBufferHandle encodeDoorLockClusterSetHolidayScheduleCommand(EndpointId destinationEndpoint, uint8_t scheduleId, + uint32_t localStartTime, uint32_t localEndTime, + uint8_t operatingModeDuringHoliday) { - const char * kName = "DoorLockSetHolidaySchedule"; - COMMAND_HEADER(kName, DOOR_LOCK_CLUSTER_ID, 0x11); - buf.Put(scheduleId); - buf.Put32(localStartTime); - buf.Put32(localEndTime); - buf.Put(operatingModeDuringHoliday); - COMMAND_FOOTER(kName); + COMMAND_HEADER("SetHolidaySchedule", DOOR_LOCK_CLUSTER_ID); + buf.Put8(kFrameControlClusterSpecificCommand) + .Put8(kSeqNum) + .Put8(ZCL_SET_HOLIDAY_SCHEDULE_COMMAND_ID) + .Put8(scheduleId) + .Put32(localStartTime) + .Put32(localEndTime) + .Put8(operatingModeDuringHoliday); + COMMAND_FOOTER(); } /* * Command SetPin */ -uint16_t encodeDoorLockClusterSetPinCommand(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint, uint16_t userId, - uint8_t userStatus, uint8_t userType, char * pin) +PacketBufferHandle encodeDoorLockClusterSetPinCommand(EndpointId destinationEndpoint, uint16_t userId, uint8_t userStatus, + uint8_t userType, char * pin) { - const char * kName = "DoorLockSetPin"; - COMMAND_HEADER(kName, DOOR_LOCK_CLUSTER_ID, 0x05); - buf.Put16(userId); - buf.Put(userStatus); - buf.Put(userType); - COMMAND_INSERT_STRING(kName, pin); - COMMAND_FOOTER(kName); + COMMAND_HEADER("SetPin", DOOR_LOCK_CLUSTER_ID); + size_t pinStrLen = strlen(pin); + if (!CanCastTo(pinStrLen)) + { + ChipLogError(Zcl, "Error encoding %s command. String too long: %d", kName, pinStrLen); + return PacketBufferHandle(); + } + buf.Put8(kFrameControlClusterSpecificCommand) + .Put8(kSeqNum) + .Put8(ZCL_SET_PIN_COMMAND_ID) + .Put16(userId) + .Put8(userStatus) + .Put8(userType) + .Put(static_cast(pinStrLen)) + .Put(pin); + COMMAND_FOOTER(); } /* * Command SetRfid */ -uint16_t encodeDoorLockClusterSetRfidCommand(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint, - uint16_t userId, uint8_t userStatus, uint8_t userType, char * id) +PacketBufferHandle encodeDoorLockClusterSetRfidCommand(EndpointId destinationEndpoint, uint16_t userId, uint8_t userStatus, + uint8_t userType, char * id) { - const char * kName = "DoorLockSetRfid"; - COMMAND_HEADER(kName, DOOR_LOCK_CLUSTER_ID, 0x16); - buf.Put16(userId); - buf.Put(userStatus); - buf.Put(userType); - COMMAND_INSERT_STRING(kName, id); - COMMAND_FOOTER(kName); + COMMAND_HEADER("SetRfid", DOOR_LOCK_CLUSTER_ID); + size_t idStrLen = strlen(id); + if (!CanCastTo(idStrLen)) + { + ChipLogError(Zcl, "Error encoding %s command. String too long: %d", kName, idStrLen); + return PacketBufferHandle(); + } + buf.Put8(kFrameControlClusterSpecificCommand) + .Put8(kSeqNum) + .Put8(ZCL_SET_RFID_COMMAND_ID) + .Put16(userId) + .Put8(userStatus) + .Put8(userType) + .Put(static_cast(idStrLen)) + .Put(id); + COMMAND_FOOTER(); } /* * Command SetUserType */ -uint16_t encodeDoorLockClusterSetUserTypeCommand(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint, - uint16_t userId, uint8_t userType) +PacketBufferHandle encodeDoorLockClusterSetUserTypeCommand(EndpointId destinationEndpoint, uint16_t userId, uint8_t userType) { - const char * kName = "DoorLockSetUserType"; - COMMAND_HEADER(kName, DOOR_LOCK_CLUSTER_ID, 0x14); - buf.Put16(userId); - buf.Put(userType); - COMMAND_FOOTER(kName); + COMMAND_HEADER("SetUserType", DOOR_LOCK_CLUSTER_ID); + buf.Put8(kFrameControlClusterSpecificCommand).Put8(kSeqNum).Put8(ZCL_SET_USER_TYPE_COMMAND_ID).Put16(userId).Put8(userType); + COMMAND_FOOTER(); } /* * Command SetWeekdaySchedule */ -uint16_t encodeDoorLockClusterSetWeekdayScheduleCommand(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint, - uint8_t scheduleId, uint16_t userId, uint8_t daysMask, uint8_t startHour, - uint8_t startMinute, uint8_t endHour, uint8_t endMinute) +PacketBufferHandle encodeDoorLockClusterSetWeekdayScheduleCommand(EndpointId destinationEndpoint, uint8_t scheduleId, + uint16_t userId, uint8_t daysMask, uint8_t startHour, + uint8_t startMinute, uint8_t endHour, uint8_t endMinute) { - const char * kName = "DoorLockSetWeekdaySchedule"; - COMMAND_HEADER(kName, DOOR_LOCK_CLUSTER_ID, 0x0B); - buf.Put(scheduleId); - buf.Put16(userId); - buf.Put(daysMask); - buf.Put(startHour); - buf.Put(startMinute); - buf.Put(endHour); - buf.Put(endMinute); - COMMAND_FOOTER(kName); + COMMAND_HEADER("SetWeekdaySchedule", DOOR_LOCK_CLUSTER_ID); + buf.Put8(kFrameControlClusterSpecificCommand) + .Put8(kSeqNum) + .Put8(ZCL_SET_WEEKDAY_SCHEDULE_COMMAND_ID) + .Put8(scheduleId) + .Put16(userId) + .Put8(daysMask) + .Put8(startHour) + .Put8(startMinute) + .Put8(endHour) + .Put8(endMinute); + COMMAND_FOOTER(); } /* * Command SetYeardaySchedule */ -uint16_t encodeDoorLockClusterSetYeardayScheduleCommand(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint, - uint8_t scheduleId, uint16_t userId, uint32_t localStartTime, - uint32_t localEndTime) +PacketBufferHandle encodeDoorLockClusterSetYeardayScheduleCommand(EndpointId destinationEndpoint, uint8_t scheduleId, + uint16_t userId, uint32_t localStartTime, uint32_t localEndTime) { - const char * kName = "DoorLockSetYeardaySchedule"; - COMMAND_HEADER(kName, DOOR_LOCK_CLUSTER_ID, 0x0E); - buf.Put(scheduleId); - buf.Put16(userId); - buf.Put32(localStartTime); - buf.Put32(localEndTime); - COMMAND_FOOTER(kName); + COMMAND_HEADER("SetYeardaySchedule", DOOR_LOCK_CLUSTER_ID); + buf.Put8(kFrameControlClusterSpecificCommand) + .Put8(kSeqNum) + .Put8(ZCL_SET_YEARDAY_SCHEDULE_COMMAND_ID) + .Put8(scheduleId) + .Put16(userId) + .Put32(localStartTime) + .Put32(localEndTime); + COMMAND_FOOTER(); } /* * Command UnlockDoor */ -uint16_t encodeDoorLockClusterUnlockDoorCommand(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint, char * pin) +PacketBufferHandle encodeDoorLockClusterUnlockDoorCommand(EndpointId destinationEndpoint, char * pin) { - const char * kName = "DoorLockUnlockDoor"; - COMMAND_HEADER(kName, DOOR_LOCK_CLUSTER_ID, 0x01); - COMMAND_INSERT_STRING(kName, pin); - COMMAND_FOOTER(kName); + COMMAND_HEADER("UnlockDoor", DOOR_LOCK_CLUSTER_ID); + size_t pinStrLen = strlen(pin); + if (!CanCastTo(pinStrLen)) + { + ChipLogError(Zcl, "Error encoding %s command. String too long: %d", kName, pinStrLen); + return PacketBufferHandle(); + } + buf.Put8(kFrameControlClusterSpecificCommand) + .Put8(kSeqNum) + .Put8(ZCL_UNLOCK_DOOR_COMMAND_ID) + .Put(static_cast(pinStrLen)) + .Put(pin); + COMMAND_FOOTER(); } /* * Command UnlockWithTimeout */ -uint16_t encodeDoorLockClusterUnlockWithTimeoutCommand(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint, - uint16_t timeoutInSeconds, char * pin) +PacketBufferHandle encodeDoorLockClusterUnlockWithTimeoutCommand(EndpointId destinationEndpoint, uint16_t timeoutInSeconds, + char * pin) { - const char * kName = "DoorLockUnlockWithTimeout"; - COMMAND_HEADER(kName, DOOR_LOCK_CLUSTER_ID, 0x03); - buf.Put16(timeoutInSeconds); - COMMAND_INSERT_STRING(kName, pin); - COMMAND_FOOTER(kName); + COMMAND_HEADER("UnlockWithTimeout", DOOR_LOCK_CLUSTER_ID); + size_t pinStrLen = strlen(pin); + if (!CanCastTo(pinStrLen)) + { + ChipLogError(Zcl, "Error encoding %s command. String too long: %d", kName, pinStrLen); + return PacketBufferHandle(); + } + buf.Put8(kFrameControlClusterSpecificCommand) + .Put8(kSeqNum) + .Put8(ZCL_UNLOCK_WITH_TIMEOUT_COMMAND_ID) + .Put16(timeoutInSeconds) + .Put(static_cast(pinStrLen)) + .Put(pin); + COMMAND_FOOTER(); } -uint16_t encodeDoorLockClusterDiscoverAttributes(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint) +PacketBufferHandle encodeDoorLockClusterDiscoverAttributes(EndpointId destinationEndpoint) { - DISCOVER_ATTRIBUTES("DiscoverDoorLockAttributes", DOOR_LOCK_CLUSTER_ID); + COMMAND_HEADER("DiscoverDoorLockAttributes", DOOR_LOCK_CLUSTER_ID); + buf.Put8(kFrameControlGlobalCommand).Put8(kSeqNum).Put8(ZCL_DISCOVER_ATTRIBUTES_COMMAND_ID).Put16(0x0000).Put8(0xFF); + COMMAND_FOOTER(); } /* * Attribute LockState */ -uint16_t encodeDoorLockClusterReadLockStateAttribute(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint) +PacketBufferHandle encodeDoorLockClusterReadLockStateAttribute(EndpointId destinationEndpoint) { - uint16_t attr_ids[] = { 0x0000 }; - READ_ATTRIBUTES("ReadDoorLockLockState", DOOR_LOCK_CLUSTER_ID); + COMMAND_HEADER("ReadDoorLockLockState", DOOR_LOCK_CLUSTER_ID); + buf.Put8(kFrameControlGlobalCommand).Put8(kSeqNum).Put8(ZCL_READ_ATTRIBUTES_COMMAND_ID).Put16(0x0000); + COMMAND_FOOTER(); } -uint16_t encodeDoorLockClusterReportLockStateAttribute(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint, - uint16_t min_interval, uint16_t max_interval) +PacketBufferHandle encodeDoorLockClusterReportLockStateAttribute(EndpointId destinationEndpoint, uint16_t minInterval, + uint16_t maxInterval) { - uint16_t attr_id = 0x0000; - uint8_t attr_type = { 0x30 }; - REPORT_ATTRIBUTE("ReportDoorLockLockState", DOOR_LOCK_CLUSTER_ID, false, 0); + COMMAND_HEADER("ReportDoorLockLockState", DOOR_LOCK_CLUSTER_ID); + buf.Put8(kFrameControlGlobalCommand) + .Put8(kSeqNum) + .Put8(ZCL_CONFIGURE_REPORTING_COMMAND_ID) + .Put8(EMBER_ZCL_REPORTING_DIRECTION_REPORTED) + .Put16(0x0000) + .Put8(0x30) + .Put16(minInterval) + .Put16(maxInterval); + COMMAND_FOOTER(); } /* * Attribute LockType */ -uint16_t encodeDoorLockClusterReadLockTypeAttribute(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint) +PacketBufferHandle encodeDoorLockClusterReadLockTypeAttribute(EndpointId destinationEndpoint) { - uint16_t attr_ids[] = { 0x0001 }; - READ_ATTRIBUTES("ReadDoorLockLockType", DOOR_LOCK_CLUSTER_ID); + COMMAND_HEADER("ReadDoorLockLockType", DOOR_LOCK_CLUSTER_ID); + buf.Put8(kFrameControlGlobalCommand).Put8(kSeqNum).Put8(ZCL_READ_ATTRIBUTES_COMMAND_ID).Put16(0x0001); + COMMAND_FOOTER(); } /* * Attribute ActuatorEnabled */ -uint16_t encodeDoorLockClusterReadActuatorEnabledAttribute(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint) +PacketBufferHandle encodeDoorLockClusterReadActuatorEnabledAttribute(EndpointId destinationEndpoint) { - uint16_t attr_ids[] = { 0x0002 }; - READ_ATTRIBUTES("ReadDoorLockActuatorEnabled", DOOR_LOCK_CLUSTER_ID); + COMMAND_HEADER("ReadDoorLockActuatorEnabled", DOOR_LOCK_CLUSTER_ID); + buf.Put8(kFrameControlGlobalCommand).Put8(kSeqNum).Put8(ZCL_READ_ATTRIBUTES_COMMAND_ID).Put16(0x0002); + COMMAND_FOOTER(); } /* * Attribute ClusterRevision */ -uint16_t encodeDoorLockClusterReadClusterRevisionAttribute(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint) +PacketBufferHandle encodeDoorLockClusterReadClusterRevisionAttribute(EndpointId destinationEndpoint) { - uint16_t attr_ids[] = { 0xFFFD }; - READ_ATTRIBUTES("ReadDoorLockClusterRevision", DOOR_LOCK_CLUSTER_ID); + COMMAND_HEADER("ReadDoorLockClusterRevision", DOOR_LOCK_CLUSTER_ID); + buf.Put8(kFrameControlGlobalCommand).Put8(kSeqNum).Put8(ZCL_READ_ATTRIBUTES_COMMAND_ID).Put16(0xFFFD); + COMMAND_FOOTER(); } /*----------------------------------------------------------------------------*\ @@ -1783,97 +1953,116 @@ uint16_t encodeDoorLockClusterReadClusterRevisionAttribute(uint8_t * buffer, uin /* * Command AddGroup */ -uint16_t encodeGroupsClusterAddGroupCommand(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint, - uint16_t groupId, char * groupName) +PacketBufferHandle encodeGroupsClusterAddGroupCommand(EndpointId destinationEndpoint, uint16_t groupId, char * groupName) { - const char * kName = "GroupsAddGroup"; - COMMAND_HEADER(kName, GROUPS_CLUSTER_ID, 0x00); - buf.Put16(groupId); - COMMAND_INSERT_STRING(kName, groupName); - COMMAND_FOOTER(kName); + COMMAND_HEADER("AddGroup", GROUPS_CLUSTER_ID); + size_t groupNameStrLen = strlen(groupName); + if (!CanCastTo(groupNameStrLen)) + { + ChipLogError(Zcl, "Error encoding %s command. String too long: %d", kName, groupNameStrLen); + return PacketBufferHandle(); + } + buf.Put8(kFrameControlClusterSpecificCommand) + .Put8(kSeqNum) + .Put8(ZCL_ADD_GROUP_COMMAND_ID) + .Put16(groupId) + .Put(static_cast(groupNameStrLen)) + .Put(groupName); + COMMAND_FOOTER(); } /* * Command AddGroupIfIdentifying */ -uint16_t encodeGroupsClusterAddGroupIfIdentifyingCommand(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint, - uint16_t groupId, char * groupName) +PacketBufferHandle encodeGroupsClusterAddGroupIfIdentifyingCommand(EndpointId destinationEndpoint, uint16_t groupId, + char * groupName) { - const char * kName = "GroupsAddGroupIfIdentifying"; - COMMAND_HEADER(kName, GROUPS_CLUSTER_ID, 0x05); - buf.Put16(groupId); - COMMAND_INSERT_STRING(kName, groupName); - COMMAND_FOOTER(kName); + COMMAND_HEADER("AddGroupIfIdentifying", GROUPS_CLUSTER_ID); + size_t groupNameStrLen = strlen(groupName); + if (!CanCastTo(groupNameStrLen)) + { + ChipLogError(Zcl, "Error encoding %s command. String too long: %d", kName, groupNameStrLen); + return PacketBufferHandle(); + } + buf.Put8(kFrameControlClusterSpecificCommand) + .Put8(kSeqNum) + .Put8(ZCL_ADD_GROUP_IF_IDENTIFYING_COMMAND_ID) + .Put16(groupId) + .Put(static_cast(groupNameStrLen)) + .Put(groupName); + COMMAND_FOOTER(); } /* * Command GetGroupMembership */ -uint16_t encodeGroupsClusterGetGroupMembershipCommand(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint, - uint8_t groupCount, uint16_t groupList) +PacketBufferHandle encodeGroupsClusterGetGroupMembershipCommand(EndpointId destinationEndpoint, uint8_t groupCount, + uint16_t groupList) { - const char * kName = "GroupsGetGroupMembership"; - COMMAND_HEADER(kName, GROUPS_CLUSTER_ID, 0x02); - buf.Put(groupCount); - buf.Put16(groupList); - COMMAND_FOOTER(kName); + COMMAND_HEADER("GetGroupMembership", GROUPS_CLUSTER_ID); + buf.Put8(kFrameControlClusterSpecificCommand) + .Put8(kSeqNum) + .Put8(ZCL_GET_GROUP_MEMBERSHIP_COMMAND_ID) + .Put8(groupCount) + .Put16(groupList); + COMMAND_FOOTER(); } /* * Command RemoveAllGroups */ -uint16_t encodeGroupsClusterRemoveAllGroupsCommand(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint) +PacketBufferHandle encodeGroupsClusterRemoveAllGroupsCommand(EndpointId destinationEndpoint) { - const char * kName = "GroupsRemoveAllGroups"; - COMMAND_HEADER(kName, GROUPS_CLUSTER_ID, 0x04); - COMMAND_FOOTER(kName); + COMMAND_HEADER("RemoveAllGroups", GROUPS_CLUSTER_ID); + buf.Put8(kFrameControlClusterSpecificCommand).Put8(kSeqNum).Put8(ZCL_REMOVE_ALL_GROUPS_COMMAND_ID); + COMMAND_FOOTER(); } /* * Command RemoveGroup */ -uint16_t encodeGroupsClusterRemoveGroupCommand(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint, - uint16_t groupId) +PacketBufferHandle encodeGroupsClusterRemoveGroupCommand(EndpointId destinationEndpoint, uint16_t groupId) { - const char * kName = "GroupsRemoveGroup"; - COMMAND_HEADER(kName, GROUPS_CLUSTER_ID, 0x03); - buf.Put16(groupId); - COMMAND_FOOTER(kName); + COMMAND_HEADER("RemoveGroup", GROUPS_CLUSTER_ID); + buf.Put8(kFrameControlClusterSpecificCommand).Put8(kSeqNum).Put8(ZCL_REMOVE_GROUP_COMMAND_ID).Put16(groupId); + COMMAND_FOOTER(); } /* * Command ViewGroup */ -uint16_t encodeGroupsClusterViewGroupCommand(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint, - uint16_t groupId) +PacketBufferHandle encodeGroupsClusterViewGroupCommand(EndpointId destinationEndpoint, uint16_t groupId) { - const char * kName = "GroupsViewGroup"; - COMMAND_HEADER(kName, GROUPS_CLUSTER_ID, 0x01); - buf.Put16(groupId); - COMMAND_FOOTER(kName); + COMMAND_HEADER("ViewGroup", GROUPS_CLUSTER_ID); + buf.Put8(kFrameControlClusterSpecificCommand).Put8(kSeqNum).Put8(ZCL_VIEW_GROUP_COMMAND_ID).Put16(groupId); + COMMAND_FOOTER(); } -uint16_t encodeGroupsClusterDiscoverAttributes(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint) +PacketBufferHandle encodeGroupsClusterDiscoverAttributes(EndpointId destinationEndpoint) { - DISCOVER_ATTRIBUTES("DiscoverGroupsAttributes", GROUPS_CLUSTER_ID); + COMMAND_HEADER("DiscoverGroupsAttributes", GROUPS_CLUSTER_ID); + buf.Put8(kFrameControlGlobalCommand).Put8(kSeqNum).Put8(ZCL_DISCOVER_ATTRIBUTES_COMMAND_ID).Put16(0x0000).Put8(0xFF); + COMMAND_FOOTER(); } /* * Attribute NameSupport */ -uint16_t encodeGroupsClusterReadNameSupportAttribute(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint) +PacketBufferHandle encodeGroupsClusterReadNameSupportAttribute(EndpointId destinationEndpoint) { - uint16_t attr_ids[] = { 0x0000 }; - READ_ATTRIBUTES("ReadGroupsNameSupport", GROUPS_CLUSTER_ID); + COMMAND_HEADER("ReadGroupsNameSupport", GROUPS_CLUSTER_ID); + buf.Put8(kFrameControlGlobalCommand).Put8(kSeqNum).Put8(ZCL_READ_ATTRIBUTES_COMMAND_ID).Put16(0x0000); + COMMAND_FOOTER(); } /* * Attribute ClusterRevision */ -uint16_t encodeGroupsClusterReadClusterRevisionAttribute(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint) +PacketBufferHandle encodeGroupsClusterReadClusterRevisionAttribute(EndpointId destinationEndpoint) { - uint16_t attr_ids[] = { 0xFFFD }; - READ_ATTRIBUTES("ReadGroupsClusterRevision", GROUPS_CLUSTER_ID); + COMMAND_HEADER("ReadGroupsClusterRevision", GROUPS_CLUSTER_ID); + buf.Put8(kFrameControlGlobalCommand).Put8(kSeqNum).Put8(ZCL_READ_ATTRIBUTES_COMMAND_ID).Put16(0xFFFD); + COMMAND_FOOTER(); } /*----------------------------------------------------------------------------*\ @@ -1890,71 +2079,83 @@ uint16_t encodeGroupsClusterReadClusterRevisionAttribute(uint8_t * buffer, uint1 | * ClusterRevision | 0xFFFD | \*----------------------------------------------------------------------------*/ -uint16_t encodeIasZoneClusterDiscoverAttributes(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint) +PacketBufferHandle encodeIasZoneClusterDiscoverAttributes(EndpointId destinationEndpoint) { - DISCOVER_ATTRIBUTES("DiscoverIasZoneAttributes", IAS_ZONE_CLUSTER_ID); + COMMAND_HEADER("DiscoverIasZoneAttributes", IAS_ZONE_CLUSTER_ID); + buf.Put8(kFrameControlGlobalCommand).Put8(kSeqNum).Put8(ZCL_DISCOVER_ATTRIBUTES_COMMAND_ID).Put16(0x0000).Put8(0xFF); + COMMAND_FOOTER(); } /* * Attribute ZoneState */ -uint16_t encodeIasZoneClusterReadZoneStateAttribute(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint) +PacketBufferHandle encodeIasZoneClusterReadZoneStateAttribute(EndpointId destinationEndpoint) { - uint16_t attr_ids[] = { 0x0000 }; - READ_ATTRIBUTES("ReadIasZoneZoneState", IAS_ZONE_CLUSTER_ID); + COMMAND_HEADER("ReadIasZoneZoneState", IAS_ZONE_CLUSTER_ID); + buf.Put8(kFrameControlGlobalCommand).Put8(kSeqNum).Put8(ZCL_READ_ATTRIBUTES_COMMAND_ID).Put16(0x0000); + COMMAND_FOOTER(); } /* * Attribute ZoneType */ -uint16_t encodeIasZoneClusterReadZoneTypeAttribute(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint) +PacketBufferHandle encodeIasZoneClusterReadZoneTypeAttribute(EndpointId destinationEndpoint) { - uint16_t attr_ids[] = { 0x0001 }; - READ_ATTRIBUTES("ReadIasZoneZoneType", IAS_ZONE_CLUSTER_ID); + COMMAND_HEADER("ReadIasZoneZoneType", IAS_ZONE_CLUSTER_ID); + buf.Put8(kFrameControlGlobalCommand).Put8(kSeqNum).Put8(ZCL_READ_ATTRIBUTES_COMMAND_ID).Put16(0x0001); + COMMAND_FOOTER(); } /* * Attribute ZoneStatus */ -uint16_t encodeIasZoneClusterReadZoneStatusAttribute(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint) +PacketBufferHandle encodeIasZoneClusterReadZoneStatusAttribute(EndpointId destinationEndpoint) { - uint16_t attr_ids[] = { 0x0002 }; - READ_ATTRIBUTES("ReadIasZoneZoneStatus", IAS_ZONE_CLUSTER_ID); + COMMAND_HEADER("ReadIasZoneZoneStatus", IAS_ZONE_CLUSTER_ID); + buf.Put8(kFrameControlGlobalCommand).Put8(kSeqNum).Put8(ZCL_READ_ATTRIBUTES_COMMAND_ID).Put16(0x0002); + COMMAND_FOOTER(); } /* * Attribute IasCieAddress */ -uint16_t encodeIasZoneClusterReadIasCieAddressAttribute(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint) +PacketBufferHandle encodeIasZoneClusterReadIasCieAddressAttribute(EndpointId destinationEndpoint) { - uint16_t attr_ids[] = { 0x0010 }; - READ_ATTRIBUTES("ReadIasZoneIasCieAddress", IAS_ZONE_CLUSTER_ID); + COMMAND_HEADER("ReadIasZoneIasCieAddress", IAS_ZONE_CLUSTER_ID); + buf.Put8(kFrameControlGlobalCommand).Put8(kSeqNum).Put8(ZCL_READ_ATTRIBUTES_COMMAND_ID).Put16(0x0010); + COMMAND_FOOTER(); } -uint16_t encodeIasZoneClusterWriteIasCieAddressAttribute(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint, - uint64_t iasCieAddress) +PacketBufferHandle encodeIasZoneClusterWriteIasCieAddressAttribute(EndpointId destinationEndpoint, uint64_t iasCieAddress) { - uint16_t attr_id = 0x0010; - uint8_t attr_type = { 0xF0 }; - WRITE_ATTRIBUTE("WriteIasZoneIasCieAddress", IAS_ZONE_CLUSTER_ID, iasCieAddress); + COMMAND_HEADER("WriteIasZoneIasCieAddress", IAS_ZONE_CLUSTER_ID); + buf.Put8(kFrameControlGlobalCommand) + .Put8(kSeqNum) + .Put8(ZCL_WRITE_ATTRIBUTES_COMMAND_ID) + .Put16(0x0010) + .Put8(0xF0) + .Put64(static_cast(iasCieAddress)); + COMMAND_FOOTER(); } /* * Attribute ZoneId */ -uint16_t encodeIasZoneClusterReadZoneIdAttribute(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint) +PacketBufferHandle encodeIasZoneClusterReadZoneIdAttribute(EndpointId destinationEndpoint) { - uint16_t attr_ids[] = { 0x0011 }; - READ_ATTRIBUTES("ReadIasZoneZoneId", IAS_ZONE_CLUSTER_ID); + COMMAND_HEADER("ReadIasZoneZoneId", IAS_ZONE_CLUSTER_ID); + buf.Put8(kFrameControlGlobalCommand).Put8(kSeqNum).Put8(ZCL_READ_ATTRIBUTES_COMMAND_ID).Put16(0x0011); + COMMAND_FOOTER(); } /* * Attribute ClusterRevision */ -uint16_t encodeIasZoneClusterReadClusterRevisionAttribute(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint) +PacketBufferHandle encodeIasZoneClusterReadClusterRevisionAttribute(EndpointId destinationEndpoint) { - uint16_t attr_ids[] = { 0xFFFD }; - READ_ATTRIBUTES("ReadIasZoneClusterRevision", IAS_ZONE_CLUSTER_ID); + COMMAND_HEADER("ReadIasZoneClusterRevision", IAS_ZONE_CLUSTER_ID); + buf.Put8(kFrameControlGlobalCommand).Put8(kSeqNum).Put8(ZCL_READ_ATTRIBUTES_COMMAND_ID).Put16(0xFFFD); + COMMAND_FOOTER(); } /*----------------------------------------------------------------------------*\ @@ -1972,54 +2173,60 @@ uint16_t encodeIasZoneClusterReadClusterRevisionAttribute(uint8_t * buffer, uint /* * Command Identify */ -uint16_t encodeIdentifyClusterIdentifyCommand(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint, - uint16_t identifyTime) +PacketBufferHandle encodeIdentifyClusterIdentifyCommand(EndpointId destinationEndpoint, uint16_t identifyTime) { - const char * kName = "IdentifyIdentify"; - COMMAND_HEADER(kName, IDENTIFY_CLUSTER_ID, 0x00); - buf.Put16(identifyTime); - COMMAND_FOOTER(kName); + COMMAND_HEADER("Identify", IDENTIFY_CLUSTER_ID); + buf.Put8(kFrameControlClusterSpecificCommand).Put8(kSeqNum).Put8(ZCL_IDENTIFY_COMMAND_ID).Put16(identifyTime); + COMMAND_FOOTER(); } /* * Command IdentifyQuery */ -uint16_t encodeIdentifyClusterIdentifyQueryCommand(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint) +PacketBufferHandle encodeIdentifyClusterIdentifyQueryCommand(EndpointId destinationEndpoint) { - const char * kName = "IdentifyIdentifyQuery"; - COMMAND_HEADER(kName, IDENTIFY_CLUSTER_ID, 0x01); - COMMAND_FOOTER(kName); + COMMAND_HEADER("IdentifyQuery", IDENTIFY_CLUSTER_ID); + buf.Put8(kFrameControlClusterSpecificCommand).Put8(kSeqNum).Put8(ZCL_IDENTIFY_QUERY_COMMAND_ID); + COMMAND_FOOTER(); } -uint16_t encodeIdentifyClusterDiscoverAttributes(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint) +PacketBufferHandle encodeIdentifyClusterDiscoverAttributes(EndpointId destinationEndpoint) { - DISCOVER_ATTRIBUTES("DiscoverIdentifyAttributes", IDENTIFY_CLUSTER_ID); + COMMAND_HEADER("DiscoverIdentifyAttributes", IDENTIFY_CLUSTER_ID); + buf.Put8(kFrameControlGlobalCommand).Put8(kSeqNum).Put8(ZCL_DISCOVER_ATTRIBUTES_COMMAND_ID).Put16(0x0000).Put8(0xFF); + COMMAND_FOOTER(); } /* * Attribute IdentifyTime */ -uint16_t encodeIdentifyClusterReadIdentifyTimeAttribute(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint) +PacketBufferHandle encodeIdentifyClusterReadIdentifyTimeAttribute(EndpointId destinationEndpoint) { - uint16_t attr_ids[] = { 0x0000 }; - READ_ATTRIBUTES("ReadIdentifyIdentifyTime", IDENTIFY_CLUSTER_ID); + COMMAND_HEADER("ReadIdentifyIdentifyTime", IDENTIFY_CLUSTER_ID); + buf.Put8(kFrameControlGlobalCommand).Put8(kSeqNum).Put8(ZCL_READ_ATTRIBUTES_COMMAND_ID).Put16(0x0000); + COMMAND_FOOTER(); } -uint16_t encodeIdentifyClusterWriteIdentifyTimeAttribute(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint, - uint16_t identifyTime) +PacketBufferHandle encodeIdentifyClusterWriteIdentifyTimeAttribute(EndpointId destinationEndpoint, uint16_t identifyTime) { - uint16_t attr_id = 0x0000; - uint8_t attr_type = { 0x21 }; - WRITE_ATTRIBUTE("WriteIdentifyIdentifyTime", IDENTIFY_CLUSTER_ID, identifyTime); + COMMAND_HEADER("WriteIdentifyIdentifyTime", IDENTIFY_CLUSTER_ID); + buf.Put8(kFrameControlGlobalCommand) + .Put8(kSeqNum) + .Put8(ZCL_WRITE_ATTRIBUTES_COMMAND_ID) + .Put16(0x0000) + .Put8(0x21) + .Put16(static_cast(identifyTime)); + COMMAND_FOOTER(); } /* * Attribute ClusterRevision */ -uint16_t encodeIdentifyClusterReadClusterRevisionAttribute(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint) +PacketBufferHandle encodeIdentifyClusterReadClusterRevisionAttribute(EndpointId destinationEndpoint) { - uint16_t attr_ids[] = { 0xFFFD }; - READ_ATTRIBUTES("ReadIdentifyClusterRevision", IDENTIFY_CLUSTER_ID); + COMMAND_HEADER("ReadIdentifyClusterRevision", IDENTIFY_CLUSTER_ID); + buf.Put8(kFrameControlGlobalCommand).Put8(kSeqNum).Put8(ZCL_READ_ATTRIBUTES_COMMAND_ID).Put16(0xFFFD); + COMMAND_FOOTER(); } /*----------------------------------------------------------------------------*\ @@ -2043,146 +2250,157 @@ uint16_t encodeIdentifyClusterReadClusterRevisionAttribute(uint8_t * buffer, uin /* * Command Move */ -uint16_t encodeLevelControlClusterMoveCommand(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint, - uint8_t moveMode, uint8_t rate, uint8_t optionMask, uint8_t optionOverride) +PacketBufferHandle encodeLevelControlClusterMoveCommand(EndpointId destinationEndpoint, uint8_t moveMode, uint8_t rate, + uint8_t optionMask, uint8_t optionOverride) { - const char * kName = "LevelControlMove"; - COMMAND_HEADER(kName, LEVEL_CONTROL_CLUSTER_ID, 0x01); - buf.Put(moveMode); - buf.Put(rate); - buf.Put(optionMask); - buf.Put(optionOverride); - COMMAND_FOOTER(kName); + COMMAND_HEADER("Move", LEVEL_CONTROL_CLUSTER_ID); + buf.Put8(kFrameControlClusterSpecificCommand) + .Put8(kSeqNum) + .Put8(ZCL_MOVE_COMMAND_ID) + .Put8(moveMode) + .Put8(rate) + .Put8(optionMask) + .Put8(optionOverride); + COMMAND_FOOTER(); } /* * Command MoveToLevel */ -uint16_t encodeLevelControlClusterMoveToLevelCommand(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint, - uint8_t level, uint16_t transitionTime, uint8_t optionMask, - uint8_t optionOverride) +PacketBufferHandle encodeLevelControlClusterMoveToLevelCommand(EndpointId destinationEndpoint, uint8_t level, + uint16_t transitionTime, uint8_t optionMask, uint8_t optionOverride) { - const char * kName = "LevelControlMoveToLevel"; - COMMAND_HEADER(kName, LEVEL_CONTROL_CLUSTER_ID, 0x00); - buf.Put(level); - buf.Put16(transitionTime); - buf.Put(optionMask); - buf.Put(optionOverride); - COMMAND_FOOTER(kName); + COMMAND_HEADER("MoveToLevel", LEVEL_CONTROL_CLUSTER_ID); + buf.Put8(kFrameControlClusterSpecificCommand) + .Put8(kSeqNum) + .Put8(ZCL_MOVE_TO_LEVEL_COMMAND_ID) + .Put8(level) + .Put16(transitionTime) + .Put8(optionMask) + .Put8(optionOverride); + COMMAND_FOOTER(); } /* * Command MoveToLevelWithOnOff */ -uint16_t encodeLevelControlClusterMoveToLevelWithOnOffCommand(uint8_t * buffer, uint16_t buf_length, - EndpointId destination_endpoint, uint8_t level, - uint16_t transitionTime) +PacketBufferHandle encodeLevelControlClusterMoveToLevelWithOnOffCommand(EndpointId destinationEndpoint, uint8_t level, + uint16_t transitionTime) { - const char * kName = "LevelControlMoveToLevelWithOnOff"; - COMMAND_HEADER(kName, LEVEL_CONTROL_CLUSTER_ID, 0x04); - buf.Put(level); - buf.Put16(transitionTime); - COMMAND_FOOTER(kName); + COMMAND_HEADER("MoveToLevelWithOnOff", LEVEL_CONTROL_CLUSTER_ID); + buf.Put8(kFrameControlClusterSpecificCommand) + .Put8(kSeqNum) + .Put8(ZCL_MOVE_TO_LEVEL_WITH_ON_OFF_COMMAND_ID) + .Put8(level) + .Put16(transitionTime); + COMMAND_FOOTER(); } /* * Command MoveWithOnOff */ -uint16_t encodeLevelControlClusterMoveWithOnOffCommand(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint, - uint8_t moveMode, uint8_t rate) +PacketBufferHandle encodeLevelControlClusterMoveWithOnOffCommand(EndpointId destinationEndpoint, uint8_t moveMode, uint8_t rate) { - const char * kName = "LevelControlMoveWithOnOff"; - COMMAND_HEADER(kName, LEVEL_CONTROL_CLUSTER_ID, 0x05); - buf.Put(moveMode); - buf.Put(rate); - COMMAND_FOOTER(kName); + COMMAND_HEADER("MoveWithOnOff", LEVEL_CONTROL_CLUSTER_ID); + buf.Put8(kFrameControlClusterSpecificCommand).Put8(kSeqNum).Put8(ZCL_MOVE_WITH_ON_OFF_COMMAND_ID).Put8(moveMode).Put8(rate); + COMMAND_FOOTER(); } /* * Command Step */ -uint16_t encodeLevelControlClusterStepCommand(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint, - uint8_t stepMode, uint8_t stepSize, uint16_t transitionTime, uint8_t optionMask, - uint8_t optionOverride) +PacketBufferHandle encodeLevelControlClusterStepCommand(EndpointId destinationEndpoint, uint8_t stepMode, uint8_t stepSize, + uint16_t transitionTime, uint8_t optionMask, uint8_t optionOverride) { - const char * kName = "LevelControlStep"; - COMMAND_HEADER(kName, LEVEL_CONTROL_CLUSTER_ID, 0x02); - buf.Put(stepMode); - buf.Put(stepSize); - buf.Put16(transitionTime); - buf.Put(optionMask); - buf.Put(optionOverride); - COMMAND_FOOTER(kName); + COMMAND_HEADER("Step", LEVEL_CONTROL_CLUSTER_ID); + buf.Put8(kFrameControlClusterSpecificCommand) + .Put8(kSeqNum) + .Put8(ZCL_STEP_COMMAND_ID) + .Put8(stepMode) + .Put8(stepSize) + .Put16(transitionTime) + .Put8(optionMask) + .Put8(optionOverride); + COMMAND_FOOTER(); } /* * Command StepWithOnOff */ -uint16_t encodeLevelControlClusterStepWithOnOffCommand(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint, - uint8_t stepMode, uint8_t stepSize, uint16_t transitionTime) +PacketBufferHandle encodeLevelControlClusterStepWithOnOffCommand(EndpointId destinationEndpoint, uint8_t stepMode, uint8_t stepSize, + uint16_t transitionTime) { - const char * kName = "LevelControlStepWithOnOff"; - COMMAND_HEADER(kName, LEVEL_CONTROL_CLUSTER_ID, 0x06); - buf.Put(stepMode); - buf.Put(stepSize); - buf.Put16(transitionTime); - COMMAND_FOOTER(kName); + COMMAND_HEADER("StepWithOnOff", LEVEL_CONTROL_CLUSTER_ID); + buf.Put8(kFrameControlClusterSpecificCommand) + .Put8(kSeqNum) + .Put8(ZCL_STEP_WITH_ON_OFF_COMMAND_ID) + .Put8(stepMode) + .Put8(stepSize) + .Put16(transitionTime); + COMMAND_FOOTER(); } /* * Command Stop */ -uint16_t encodeLevelControlClusterStopCommand(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint, - uint8_t optionMask, uint8_t optionOverride) +PacketBufferHandle encodeLevelControlClusterStopCommand(EndpointId destinationEndpoint, uint8_t optionMask, uint8_t optionOverride) { - const char * kName = "LevelControlStop"; - COMMAND_HEADER(kName, LEVEL_CONTROL_CLUSTER_ID, 0x03); - buf.Put(optionMask); - buf.Put(optionOverride); - COMMAND_FOOTER(kName); + COMMAND_HEADER("Stop", LEVEL_CONTROL_CLUSTER_ID); + buf.Put8(kFrameControlClusterSpecificCommand).Put8(kSeqNum).Put8(ZCL_STOP_COMMAND_ID).Put8(optionMask).Put8(optionOverride); + COMMAND_FOOTER(); } /* * Command StopWithOnOff */ -uint16_t encodeLevelControlClusterStopWithOnOffCommand(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint) +PacketBufferHandle encodeLevelControlClusterStopWithOnOffCommand(EndpointId destinationEndpoint) { - const char * kName = "LevelControlStopWithOnOff"; - COMMAND_HEADER(kName, LEVEL_CONTROL_CLUSTER_ID, 0x07); - COMMAND_FOOTER(kName); + COMMAND_HEADER("StopWithOnOff", LEVEL_CONTROL_CLUSTER_ID); + buf.Put8(kFrameControlClusterSpecificCommand).Put8(kSeqNum).Put8(ZCL_STOP_WITH_ON_OFF_COMMAND_ID); + COMMAND_FOOTER(); } -uint16_t encodeLevelControlClusterDiscoverAttributes(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint) +PacketBufferHandle encodeLevelControlClusterDiscoverAttributes(EndpointId destinationEndpoint) { - DISCOVER_ATTRIBUTES("DiscoverLevelControlAttributes", LEVEL_CONTROL_CLUSTER_ID); + COMMAND_HEADER("DiscoverLevelControlAttributes", LEVEL_CONTROL_CLUSTER_ID); + buf.Put8(kFrameControlGlobalCommand).Put8(kSeqNum).Put8(ZCL_DISCOVER_ATTRIBUTES_COMMAND_ID).Put16(0x0000).Put8(0xFF); + COMMAND_FOOTER(); } /* * Attribute CurrentLevel */ -uint16_t encodeLevelControlClusterReadCurrentLevelAttribute(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint) +PacketBufferHandle encodeLevelControlClusterReadCurrentLevelAttribute(EndpointId destinationEndpoint) { - uint16_t attr_ids[] = { 0x0000 }; - READ_ATTRIBUTES("ReadLevelControlCurrentLevel", LEVEL_CONTROL_CLUSTER_ID); + COMMAND_HEADER("ReadLevelControlCurrentLevel", LEVEL_CONTROL_CLUSTER_ID); + buf.Put8(kFrameControlGlobalCommand).Put8(kSeqNum).Put8(ZCL_READ_ATTRIBUTES_COMMAND_ID).Put16(0x0000); + COMMAND_FOOTER(); } -uint16_t encodeLevelControlClusterReportCurrentLevelAttribute(uint8_t * buffer, uint16_t buf_length, - EndpointId destination_endpoint, uint16_t min_interval, - uint16_t max_interval, uint8_t change) +PacketBufferHandle encodeLevelControlClusterReportCurrentLevelAttribute(EndpointId destinationEndpoint, uint16_t minInterval, + uint16_t maxInterval, uint8_t change) { - uint16_t attr_id = 0x0000; - uint8_t attr_type = { 0x20 }; - REPORT_ATTRIBUTE("ReportLevelControlCurrentLevel", LEVEL_CONTROL_CLUSTER_ID, true, change); + COMMAND_HEADER("ReportLevelControlCurrentLevel", LEVEL_CONTROL_CLUSTER_ID); + buf.Put8(kFrameControlGlobalCommand) + .Put8(kSeqNum) + .Put8(ZCL_CONFIGURE_REPORTING_COMMAND_ID) + .Put8(EMBER_ZCL_REPORTING_DIRECTION_REPORTED) + .Put16(0x0000) + .Put8(0x20) + .Put16(minInterval) + .Put16(maxInterval); + buf.Put8(static_cast(change)); + COMMAND_FOOTER(); } /* * Attribute ClusterRevision */ -uint16_t encodeLevelControlClusterReadClusterRevisionAttribute(uint8_t * buffer, uint16_t buf_length, - EndpointId destination_endpoint) +PacketBufferHandle encodeLevelControlClusterReadClusterRevisionAttribute(EndpointId destinationEndpoint) { - uint16_t attr_ids[] = { 0xFFFD }; - READ_ATTRIBUTES("ReadLevelControlClusterRevision", LEVEL_CONTROL_CLUSTER_ID); + COMMAND_HEADER("ReadLevelControlClusterRevision", LEVEL_CONTROL_CLUSTER_ID); + buf.Put8(kFrameControlGlobalCommand).Put8(kSeqNum).Put8(ZCL_READ_ATTRIBUTES_COMMAND_ID).Put16(0xFFFD); + COMMAND_FOOTER(); } /*----------------------------------------------------------------------------*\ @@ -2201,62 +2419,73 @@ uint16_t encodeLevelControlClusterReadClusterRevisionAttribute(uint8_t * buffer, /* * Command Off */ -uint16_t encodeOnOffClusterOffCommand(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint) +PacketBufferHandle encodeOnOffClusterOffCommand(EndpointId destinationEndpoint) { - const char * kName = "OnOffOff"; - COMMAND_HEADER(kName, ON_OFF_CLUSTER_ID, 0x00); - COMMAND_FOOTER(kName); + COMMAND_HEADER("Off", ON_OFF_CLUSTER_ID); + buf.Put8(kFrameControlClusterSpecificCommand).Put8(kSeqNum).Put8(ZCL_OFF_COMMAND_ID); + COMMAND_FOOTER(); } /* * Command On */ -uint16_t encodeOnOffClusterOnCommand(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint) +PacketBufferHandle encodeOnOffClusterOnCommand(EndpointId destinationEndpoint) { - const char * kName = "OnOffOn"; - COMMAND_HEADER(kName, ON_OFF_CLUSTER_ID, 0x01); - COMMAND_FOOTER(kName); + COMMAND_HEADER("On", ON_OFF_CLUSTER_ID); + buf.Put8(kFrameControlClusterSpecificCommand).Put8(kSeqNum).Put8(ZCL_ON_COMMAND_ID); + COMMAND_FOOTER(); } /* * Command Toggle */ -uint16_t encodeOnOffClusterToggleCommand(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint) +PacketBufferHandle encodeOnOffClusterToggleCommand(EndpointId destinationEndpoint) { - const char * kName = "OnOffToggle"; - COMMAND_HEADER(kName, ON_OFF_CLUSTER_ID, 0x02); - COMMAND_FOOTER(kName); + COMMAND_HEADER("Toggle", ON_OFF_CLUSTER_ID); + buf.Put8(kFrameControlClusterSpecificCommand).Put8(kSeqNum).Put8(ZCL_TOGGLE_COMMAND_ID); + COMMAND_FOOTER(); } -uint16_t encodeOnOffClusterDiscoverAttributes(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint) +PacketBufferHandle encodeOnOffClusterDiscoverAttributes(EndpointId destinationEndpoint) { - DISCOVER_ATTRIBUTES("DiscoverOnOffAttributes", ON_OFF_CLUSTER_ID); + COMMAND_HEADER("DiscoverOnOffAttributes", ON_OFF_CLUSTER_ID); + buf.Put8(kFrameControlGlobalCommand).Put8(kSeqNum).Put8(ZCL_DISCOVER_ATTRIBUTES_COMMAND_ID).Put16(0x0000).Put8(0xFF); + COMMAND_FOOTER(); } /* * Attribute OnOff */ -uint16_t encodeOnOffClusterReadOnOffAttribute(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint) +PacketBufferHandle encodeOnOffClusterReadOnOffAttribute(EndpointId destinationEndpoint) { - uint16_t attr_ids[] = { 0x0000 }; - READ_ATTRIBUTES("ReadOnOffOnOff", ON_OFF_CLUSTER_ID); + COMMAND_HEADER("ReadOnOffOnOff", ON_OFF_CLUSTER_ID); + buf.Put8(kFrameControlGlobalCommand).Put8(kSeqNum).Put8(ZCL_READ_ATTRIBUTES_COMMAND_ID).Put16(0x0000); + COMMAND_FOOTER(); } -uint16_t encodeOnOffClusterReportOnOffAttribute(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint, - uint16_t min_interval, uint16_t max_interval) +PacketBufferHandle encodeOnOffClusterReportOnOffAttribute(EndpointId destinationEndpoint, uint16_t minInterval, + uint16_t maxInterval) { - uint16_t attr_id = 0x0000; - uint8_t attr_type = { 0x10 }; - REPORT_ATTRIBUTE("ReportOnOffOnOff", ON_OFF_CLUSTER_ID, false, 0); + COMMAND_HEADER("ReportOnOffOnOff", ON_OFF_CLUSTER_ID); + buf.Put8(kFrameControlGlobalCommand) + .Put8(kSeqNum) + .Put8(ZCL_CONFIGURE_REPORTING_COMMAND_ID) + .Put8(EMBER_ZCL_REPORTING_DIRECTION_REPORTED) + .Put16(0x0000) + .Put8(0x10) + .Put16(minInterval) + .Put16(maxInterval); + COMMAND_FOOTER(); } /* * Attribute ClusterRevision */ -uint16_t encodeOnOffClusterReadClusterRevisionAttribute(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint) +PacketBufferHandle encodeOnOffClusterReadClusterRevisionAttribute(EndpointId destinationEndpoint) { - uint16_t attr_ids[] = { 0xFFFD }; - READ_ATTRIBUTES("ReadOnOffClusterRevision", ON_OFF_CLUSTER_ID); + COMMAND_HEADER("ReadOnOffClusterRevision", ON_OFF_CLUSTER_ID); + buf.Put8(kFrameControlGlobalCommand).Put8(kSeqNum).Put8(ZCL_READ_ATTRIBUTES_COMMAND_ID).Put16(0xFFFD); + COMMAND_FOOTER(); } /*----------------------------------------------------------------------------*\ @@ -2283,156 +2512,162 @@ uint16_t encodeOnOffClusterReadClusterRevisionAttribute(uint8_t * buffer, uint16 /* * Command AddScene */ -uint16_t encodeScenesClusterAddSceneCommand(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint, - uint16_t groupId, uint8_t sceneId, uint16_t transitionTime, char * sceneName, - chip::ClusterId clusterId, uint8_t length, uint8_t value) +PacketBufferHandle encodeScenesClusterAddSceneCommand(EndpointId destinationEndpoint, uint16_t groupId, uint8_t sceneId, + uint16_t transitionTime, char * sceneName, chip::ClusterId clusterId, + uint8_t length, uint8_t value) { - const char * kName = "ScenesAddScene"; - COMMAND_HEADER(kName, SCENES_CLUSTER_ID, 0x00); - buf.Put16(groupId); - buf.Put(sceneId); - buf.Put16(transitionTime); - COMMAND_INSERT_STRING(kName, sceneName); - buf.Put16(clusterId); - buf.Put(length); - buf.Put(value); - COMMAND_FOOTER(kName); + COMMAND_HEADER("AddScene", SCENES_CLUSTER_ID); + size_t sceneNameStrLen = strlen(sceneName); + if (!CanCastTo(sceneNameStrLen)) + { + ChipLogError(Zcl, "Error encoding %s command. String too long: %d", kName, sceneNameStrLen); + return PacketBufferHandle(); + } + buf.Put8(kFrameControlClusterSpecificCommand) + .Put8(kSeqNum) + .Put8(ZCL_ADD_SCENE_COMMAND_ID) + .Put16(groupId) + .Put8(sceneId) + .Put16(transitionTime) + .Put(static_cast(sceneNameStrLen)) + .Put(sceneName) + .Put16(clusterId) + .Put8(length) + .Put8(value); + COMMAND_FOOTER(); } /* * Command GetSceneMembership */ -uint16_t encodeScenesClusterGetSceneMembershipCommand(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint, - uint16_t groupId) +PacketBufferHandle encodeScenesClusterGetSceneMembershipCommand(EndpointId destinationEndpoint, uint16_t groupId) { - const char * kName = "ScenesGetSceneMembership"; - COMMAND_HEADER(kName, SCENES_CLUSTER_ID, 0x06); - buf.Put16(groupId); - COMMAND_FOOTER(kName); + COMMAND_HEADER("GetSceneMembership", SCENES_CLUSTER_ID); + buf.Put8(kFrameControlClusterSpecificCommand).Put8(kSeqNum).Put8(ZCL_GET_SCENE_MEMBERSHIP_COMMAND_ID).Put16(groupId); + COMMAND_FOOTER(); } /* * Command RecallScene */ -uint16_t encodeScenesClusterRecallSceneCommand(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint, - uint16_t groupId, uint8_t sceneId, uint16_t transitionTime) +PacketBufferHandle encodeScenesClusterRecallSceneCommand(EndpointId destinationEndpoint, uint16_t groupId, uint8_t sceneId, + uint16_t transitionTime) { - const char * kName = "ScenesRecallScene"; - COMMAND_HEADER(kName, SCENES_CLUSTER_ID, 0x05); - buf.Put16(groupId); - buf.Put(sceneId); - buf.Put16(transitionTime); - COMMAND_FOOTER(kName); + COMMAND_HEADER("RecallScene", SCENES_CLUSTER_ID); + buf.Put8(kFrameControlClusterSpecificCommand) + .Put8(kSeqNum) + .Put8(ZCL_RECALL_SCENE_COMMAND_ID) + .Put16(groupId) + .Put8(sceneId) + .Put16(transitionTime); + COMMAND_FOOTER(); } /* * Command RemoveAllScenes */ -uint16_t encodeScenesClusterRemoveAllScenesCommand(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint, - uint16_t groupId) +PacketBufferHandle encodeScenesClusterRemoveAllScenesCommand(EndpointId destinationEndpoint, uint16_t groupId) { - const char * kName = "ScenesRemoveAllScenes"; - COMMAND_HEADER(kName, SCENES_CLUSTER_ID, 0x03); - buf.Put16(groupId); - COMMAND_FOOTER(kName); + COMMAND_HEADER("RemoveAllScenes", SCENES_CLUSTER_ID); + buf.Put8(kFrameControlClusterSpecificCommand).Put8(kSeqNum).Put8(ZCL_REMOVE_ALL_SCENES_COMMAND_ID).Put16(groupId); + COMMAND_FOOTER(); } /* * Command RemoveScene */ -uint16_t encodeScenesClusterRemoveSceneCommand(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint, - uint16_t groupId, uint8_t sceneId) +PacketBufferHandle encodeScenesClusterRemoveSceneCommand(EndpointId destinationEndpoint, uint16_t groupId, uint8_t sceneId) { - const char * kName = "ScenesRemoveScene"; - COMMAND_HEADER(kName, SCENES_CLUSTER_ID, 0x02); - buf.Put16(groupId); - buf.Put(sceneId); - COMMAND_FOOTER(kName); + COMMAND_HEADER("RemoveScene", SCENES_CLUSTER_ID); + buf.Put8(kFrameControlClusterSpecificCommand).Put8(kSeqNum).Put8(ZCL_REMOVE_SCENE_COMMAND_ID).Put16(groupId).Put8(sceneId); + COMMAND_FOOTER(); } /* * Command StoreScene */ -uint16_t encodeScenesClusterStoreSceneCommand(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint, - uint16_t groupId, uint8_t sceneId) +PacketBufferHandle encodeScenesClusterStoreSceneCommand(EndpointId destinationEndpoint, uint16_t groupId, uint8_t sceneId) { - const char * kName = "ScenesStoreScene"; - COMMAND_HEADER(kName, SCENES_CLUSTER_ID, 0x04); - buf.Put16(groupId); - buf.Put(sceneId); - COMMAND_FOOTER(kName); + COMMAND_HEADER("StoreScene", SCENES_CLUSTER_ID); + buf.Put8(kFrameControlClusterSpecificCommand).Put8(kSeqNum).Put8(ZCL_STORE_SCENE_COMMAND_ID).Put16(groupId).Put8(sceneId); + COMMAND_FOOTER(); } /* * Command ViewScene */ -uint16_t encodeScenesClusterViewSceneCommand(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint, - uint16_t groupId, uint8_t sceneId) +PacketBufferHandle encodeScenesClusterViewSceneCommand(EndpointId destinationEndpoint, uint16_t groupId, uint8_t sceneId) { - const char * kName = "ScenesViewScene"; - COMMAND_HEADER(kName, SCENES_CLUSTER_ID, 0x01); - buf.Put16(groupId); - buf.Put(sceneId); - COMMAND_FOOTER(kName); + COMMAND_HEADER("ViewScene", SCENES_CLUSTER_ID); + buf.Put8(kFrameControlClusterSpecificCommand).Put8(kSeqNum).Put8(ZCL_VIEW_SCENE_COMMAND_ID).Put16(groupId).Put8(sceneId); + COMMAND_FOOTER(); } -uint16_t encodeScenesClusterDiscoverAttributes(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint) +PacketBufferHandle encodeScenesClusterDiscoverAttributes(EndpointId destinationEndpoint) { - DISCOVER_ATTRIBUTES("DiscoverScenesAttributes", SCENES_CLUSTER_ID); + COMMAND_HEADER("DiscoverScenesAttributes", SCENES_CLUSTER_ID); + buf.Put8(kFrameControlGlobalCommand).Put8(kSeqNum).Put8(ZCL_DISCOVER_ATTRIBUTES_COMMAND_ID).Put16(0x0000).Put8(0xFF); + COMMAND_FOOTER(); } /* * Attribute SceneCount */ -uint16_t encodeScenesClusterReadSceneCountAttribute(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint) +PacketBufferHandle encodeScenesClusterReadSceneCountAttribute(EndpointId destinationEndpoint) { - uint16_t attr_ids[] = { 0x0000 }; - READ_ATTRIBUTES("ReadScenesSceneCount", SCENES_CLUSTER_ID); + COMMAND_HEADER("ReadScenesSceneCount", SCENES_CLUSTER_ID); + buf.Put8(kFrameControlGlobalCommand).Put8(kSeqNum).Put8(ZCL_READ_ATTRIBUTES_COMMAND_ID).Put16(0x0000); + COMMAND_FOOTER(); } /* * Attribute CurrentScene */ -uint16_t encodeScenesClusterReadCurrentSceneAttribute(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint) +PacketBufferHandle encodeScenesClusterReadCurrentSceneAttribute(EndpointId destinationEndpoint) { - uint16_t attr_ids[] = { 0x0001 }; - READ_ATTRIBUTES("ReadScenesCurrentScene", SCENES_CLUSTER_ID); + COMMAND_HEADER("ReadScenesCurrentScene", SCENES_CLUSTER_ID); + buf.Put8(kFrameControlGlobalCommand).Put8(kSeqNum).Put8(ZCL_READ_ATTRIBUTES_COMMAND_ID).Put16(0x0001); + COMMAND_FOOTER(); } /* * Attribute CurrentGroup */ -uint16_t encodeScenesClusterReadCurrentGroupAttribute(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint) +PacketBufferHandle encodeScenesClusterReadCurrentGroupAttribute(EndpointId destinationEndpoint) { - uint16_t attr_ids[] = { 0x0002 }; - READ_ATTRIBUTES("ReadScenesCurrentGroup", SCENES_CLUSTER_ID); + COMMAND_HEADER("ReadScenesCurrentGroup", SCENES_CLUSTER_ID); + buf.Put8(kFrameControlGlobalCommand).Put8(kSeqNum).Put8(ZCL_READ_ATTRIBUTES_COMMAND_ID).Put16(0x0002); + COMMAND_FOOTER(); } /* * Attribute SceneValid */ -uint16_t encodeScenesClusterReadSceneValidAttribute(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint) +PacketBufferHandle encodeScenesClusterReadSceneValidAttribute(EndpointId destinationEndpoint) { - uint16_t attr_ids[] = { 0x0003 }; - READ_ATTRIBUTES("ReadScenesSceneValid", SCENES_CLUSTER_ID); + COMMAND_HEADER("ReadScenesSceneValid", SCENES_CLUSTER_ID); + buf.Put8(kFrameControlGlobalCommand).Put8(kSeqNum).Put8(ZCL_READ_ATTRIBUTES_COMMAND_ID).Put16(0x0003); + COMMAND_FOOTER(); } /* * Attribute NameSupport */ -uint16_t encodeScenesClusterReadNameSupportAttribute(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint) +PacketBufferHandle encodeScenesClusterReadNameSupportAttribute(EndpointId destinationEndpoint) { - uint16_t attr_ids[] = { 0x0004 }; - READ_ATTRIBUTES("ReadScenesNameSupport", SCENES_CLUSTER_ID); + COMMAND_HEADER("ReadScenesNameSupport", SCENES_CLUSTER_ID); + buf.Put8(kFrameControlGlobalCommand).Put8(kSeqNum).Put8(ZCL_READ_ATTRIBUTES_COMMAND_ID).Put16(0x0004); + COMMAND_FOOTER(); } /* * Attribute ClusterRevision */ -uint16_t encodeScenesClusterReadClusterRevisionAttribute(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint) +PacketBufferHandle encodeScenesClusterReadClusterRevisionAttribute(EndpointId destinationEndpoint) { - uint16_t attr_ids[] = { 0xFFFD }; - READ_ATTRIBUTES("ReadScenesClusterRevision", SCENES_CLUSTER_ID); + COMMAND_HEADER("ReadScenesClusterRevision", SCENES_CLUSTER_ID); + buf.Put8(kFrameControlGlobalCommand).Put8(kSeqNum).Put8(ZCL_READ_ATTRIBUTES_COMMAND_ID).Put16(0xFFFD); + COMMAND_FOOTER(); } /*----------------------------------------------------------------------------*\ @@ -2447,59 +2682,66 @@ uint16_t encodeScenesClusterReadClusterRevisionAttribute(uint8_t * buffer, uint1 | * ClusterRevision | 0xFFFD | \*----------------------------------------------------------------------------*/ -uint16_t encodeTemperatureMeasurementClusterDiscoverAttributes(uint8_t * buffer, uint16_t buf_length, - EndpointId destination_endpoint) +PacketBufferHandle encodeTemperatureMeasurementClusterDiscoverAttributes(EndpointId destinationEndpoint) { - DISCOVER_ATTRIBUTES("DiscoverTemperatureMeasurementAttributes", TEMP_MEASUREMENT_CLUSTER_ID); + COMMAND_HEADER("DiscoverTemperatureMeasurementAttributes", TEMP_MEASUREMENT_CLUSTER_ID); + buf.Put8(kFrameControlGlobalCommand).Put8(kSeqNum).Put8(ZCL_DISCOVER_ATTRIBUTES_COMMAND_ID).Put16(0x0000).Put8(0xFF); + COMMAND_FOOTER(); } /* * Attribute MeasuredValue */ -uint16_t encodeTemperatureMeasurementClusterReadMeasuredValueAttribute(uint8_t * buffer, uint16_t buf_length, - EndpointId destination_endpoint) +PacketBufferHandle encodeTemperatureMeasurementClusterReadMeasuredValueAttribute(EndpointId destinationEndpoint) { - uint16_t attr_ids[] = { 0x0000 }; - READ_ATTRIBUTES("ReadTemperatureMeasurementMeasuredValue", TEMP_MEASUREMENT_CLUSTER_ID); + COMMAND_HEADER("ReadTemperatureMeasurementMeasuredValue", TEMP_MEASUREMENT_CLUSTER_ID); + buf.Put8(kFrameControlGlobalCommand).Put8(kSeqNum).Put8(ZCL_READ_ATTRIBUTES_COMMAND_ID).Put16(0x0000); + COMMAND_FOOTER(); } -uint16_t encodeTemperatureMeasurementClusterReportMeasuredValueAttribute(uint8_t * buffer, uint16_t buf_length, - EndpointId destination_endpoint, uint16_t min_interval, - uint16_t max_interval, int16_t change) +PacketBufferHandle encodeTemperatureMeasurementClusterReportMeasuredValueAttribute(EndpointId destinationEndpoint, + uint16_t minInterval, uint16_t maxInterval, + int16_t change) { - uint16_t attr_id = 0x0000; - uint8_t attr_type = { 0x29 }; - REPORT_ATTRIBUTE("ReportTemperatureMeasurementMeasuredValue", TEMP_MEASUREMENT_CLUSTER_ID, true, change); + COMMAND_HEADER("ReportTemperatureMeasurementMeasuredValue", TEMP_MEASUREMENT_CLUSTER_ID); + buf.Put8(kFrameControlGlobalCommand) + .Put8(kSeqNum) + .Put8(ZCL_CONFIGURE_REPORTING_COMMAND_ID) + .Put8(EMBER_ZCL_REPORTING_DIRECTION_REPORTED) + .Put16(0x0000) + .Put8(0x29) + .Put16(minInterval) + .Put16(maxInterval); + buf.Put16(static_cast(change)); + COMMAND_FOOTER(); } /* * Attribute MinMeasuredValue */ -uint16_t encodeTemperatureMeasurementClusterReadMinMeasuredValueAttribute(uint8_t * buffer, uint16_t buf_length, - EndpointId destination_endpoint) +PacketBufferHandle encodeTemperatureMeasurementClusterReadMinMeasuredValueAttribute(EndpointId destinationEndpoint) { - uint16_t attr_ids[] = { 0x0001 }; - READ_ATTRIBUTES("ReadTemperatureMeasurementMinMeasuredValue", TEMP_MEASUREMENT_CLUSTER_ID); + COMMAND_HEADER("ReadTemperatureMeasurementMinMeasuredValue", TEMP_MEASUREMENT_CLUSTER_ID); + buf.Put8(kFrameControlGlobalCommand).Put8(kSeqNum).Put8(ZCL_READ_ATTRIBUTES_COMMAND_ID).Put16(0x0001); + COMMAND_FOOTER(); } /* * Attribute MaxMeasuredValue */ -uint16_t encodeTemperatureMeasurementClusterReadMaxMeasuredValueAttribute(uint8_t * buffer, uint16_t buf_length, - EndpointId destination_endpoint) +PacketBufferHandle encodeTemperatureMeasurementClusterReadMaxMeasuredValueAttribute(EndpointId destinationEndpoint) { - uint16_t attr_ids[] = { 0x0002 }; - READ_ATTRIBUTES("ReadTemperatureMeasurementMaxMeasuredValue", TEMP_MEASUREMENT_CLUSTER_ID); + COMMAND_HEADER("ReadTemperatureMeasurementMaxMeasuredValue", TEMP_MEASUREMENT_CLUSTER_ID); + buf.Put8(kFrameControlGlobalCommand).Put8(kSeqNum).Put8(ZCL_READ_ATTRIBUTES_COMMAND_ID).Put16(0x0002); + COMMAND_FOOTER(); } /* * Attribute ClusterRevision */ -uint16_t encodeTemperatureMeasurementClusterReadClusterRevisionAttribute(uint8_t * buffer, uint16_t buf_length, - EndpointId destination_endpoint) +PacketBufferHandle encodeTemperatureMeasurementClusterReadClusterRevisionAttribute(EndpointId destinationEndpoint) { - uint16_t attr_ids[] = { 0xFFFD }; - READ_ATTRIBUTES("ReadTemperatureMeasurementClusterRevision", TEMP_MEASUREMENT_CLUSTER_ID); + COMMAND_HEADER("ReadTemperatureMeasurementClusterRevision", TEMP_MEASUREMENT_CLUSTER_ID); + buf.Put8(kFrameControlGlobalCommand).Put8(kSeqNum).Put8(ZCL_READ_ATTRIBUTES_COMMAND_ID).Put16(0xFFFD); + COMMAND_FOOTER(); } - -} // extern "C" diff --git a/src/app/reporting/reporting-default-configuration.cpp b/src/app/reporting/reporting-default-configuration.cpp index c3e401c8235bd3..9fbfb4d0909134 100644 --- a/src/app/reporting/reporting-default-configuration.cpp +++ b/src/app/reporting/reporting-default-configuration.cpp @@ -58,6 +58,8 @@ void emberAfPluginReportingLoadReportingConfigDefaults(void) { #if (defined EMBER_AF_GENERATED_REPORTING_CONFIG_DEFAULTS_TABLE_SIZE && \ 0 != EMBER_AF_GENERATED_REPORTING_CONFIG_DEFAULTS_TABLE_SIZE) + static_assert(EMBER_AF_GENERATED_REPORTING_CONFIG_DEFAULTS_TABLE_SIZE <= EMBER_AF_PLUGIN_REPORTING_TABLE_SIZE, + "Not enough slots to hold EMBER_AF_GENERATED_REPORTING_CONFIG_DEFAULTS"); for (int i = 0; i < EMBER_AF_GENERATED_REPORTING_CONFIG_DEFAULTS_TABLE_SIZE; i++) { emAfPluginReportingConditionallyAddReportingEntry((EmberAfPluginReportingEntry *) &generatedReportingConfigDefaults[i]); diff --git a/src/app/reporting/reporting.cpp b/src/app/reporting/reporting.cpp index 314e1fcbd5009c..4f2e169bc95a0a 100644 --- a/src/app/reporting/reporting.cpp +++ b/src/app/reporting/reporting.cpp @@ -49,6 +49,11 @@ using namespace chip; +// TODO: Need to figure out what needs to happen wrt HAL tokens here, but for +// now define ESZP_HOST to disable it. See +// https://github.com/project-chip/connectedhomeip/issues/3275 +#define EZSP_HOST + #ifdef ATTRIBUTE_LARGEST #define READ_DATA_SIZE ATTRIBUTE_LARGEST #else @@ -125,11 +130,11 @@ static uint32_t computeStringHash(uint8_t * data, uint8_t length) static EmberAfPluginReportingEntry table[REPORT_TABLE_SIZE]; void emAfPluginReportingGetEntry(uint8_t index, EmberAfPluginReportingEntry * result) { - MEMMOVE(result, &table[index], sizeof(EmberAfPluginReportingEntry)); + memmove(result, &table[index], sizeof(EmberAfPluginReportingEntry)); } void emAfPluginReportingSetEntry(uint8_t index, EmberAfPluginReportingEntry * value) { - MEMMOVE(&table[index], value, sizeof(EmberAfPluginReportingEntry)); + memmove(&table[index], value, sizeof(EmberAfPluginReportingEntry)); } #else void emAfPluginReportingGetEntry(uint8_t index, EmberAfPluginReportingEntry * result) @@ -802,7 +807,7 @@ static void scheduleTick(void) } if (delayMs != MAX_INT32U_VALUE) { - emberAfDebugPrintln("sched report event for: 0x%4x", delayMs); + emberAfDebugPrintln("sched report event in %d ms", delayMs); emberEventControlSetDelayMS(&emberAfPluginReportingTickEventControl, delayMs); } else diff --git a/examples/common/chip-app-server/include/AppDelegate.h b/src/app/server/AppDelegate.h similarity index 100% rename from examples/common/chip-app-server/include/AppDelegate.h rename to src/app/server/AppDelegate.h diff --git a/examples/common/chip-app-server/BUILD.gn b/src/app/server/BUILD.gn similarity index 58% rename from examples/common/chip-app-server/BUILD.gn rename to src/app/server/BUILD.gn index 1f9ed65cd1f5cf..6c333b36ccb3c8 100644 --- a/examples/common/chip-app-server/BUILD.gn +++ b/src/app/server/BUILD.gn @@ -14,32 +14,22 @@ import("//build_overrides/chip.gni") -config("includes") { - include_dirs = [ - ".", - "include", - ] -} - -static_library("chip-app-server") { - output_name = "chip-app-server" +static_library("server") { + output_name = "libCHIPAppServer" - # Issue #1630 - # DataModelHandler.cpp includes files that relies on generated headers - # so we can't compile it into this static library. It needs to be compiled - # directly by someone who knows where the generated files for the app we're - # compiling live. sources = [ + "QRCodeUtil.cpp", + "QRCodeUtil.h", "RendezvousServer.cpp", + "RendezvousServer.h", "Server.cpp", + "Server.h", ] - deps = [ - "${chip_root}/src/lib", + public_deps = [ "${chip_root}/src/lib/mdns", + "${chip_root}/src/platform", + "${chip_root}/src/setup_payload", + "${chip_root}/src/transport", ] - - public_configs = [ ":includes" ] - - output_dir = root_out_dir } diff --git a/src/app/server/DataModelHandler.cpp b/src/app/server/DataModelHandler.cpp new file mode 100644 index 00000000000000..006bcbc99a68ce --- /dev/null +++ b/src/app/server/DataModelHandler.cpp @@ -0,0 +1,87 @@ +/* + * + * Copyright (c) 2020 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @file + * This file implements the handler for data model messages. + */ + +#include + +#include +#include +#include +#include +#include +#include +#include + +#ifdef EMBER_AF_GENERATED_PLUGIN_STACK_STATUS_FUNCTION_DECLARATIONS +EMBER_AF_GENERATED_PLUGIN_STACK_STATUS_FUNCTION_DECLARATIONS +#endif + +using namespace ::chip; + +/** + * Handle a message that should be processed via our data model processing + * codepath. This function will free the packet buffer. + * + * @param [in] buffer The buffer holding the message. This function guarantees + * that it will free the buffer before returning. + */ +void HandleDataModelMessage(const PacketHeader & header, System::PacketBufferHandle buffer, SecureSessionMgr * mgr) +{ + EmberApsFrame frame; + bool ok = extractApsFrame(buffer->Start(), buffer->DataLength(), &frame) > 0; + if (ok) + { + ChipLogProgress(Zcl, "APS frame processing success!"); + } + else + { + ChipLogProgress(Zcl, "APS frame processing failure!"); + return; + } + + uint8_t * message; + uint16_t messageLen = extractMessage(buffer->Start(), buffer->DataLength(), &message); + ok = emberAfProcessMessage(&frame, + 0, // type + message, messageLen, + header.GetSourceNodeId().Value(), // source identifier + NULL); + + if (ok) + { + ChipLogProgress(Zcl, "Data model processing success!"); + } + else + { + ChipLogProgress(Zcl, "Data model processing failure!"); + } +} + +void InitDataModelHandler() +{ + emberAfEndpointConfigure(); + emberAfInit(); + +#ifdef EMBER_AF_GENERATED_PLUGIN_STACK_STATUS_FUNCTION_CALLS + EmberStatus status = EMBER_NETWORK_UP; + EMBER_AF_GENERATED_PLUGIN_STACK_STATUS_FUNCTION_CALLS +#endif +} diff --git a/examples/common/chip-app-server/include/DataModelHandler.h b/src/app/server/DataModelHandler.h similarity index 100% rename from examples/common/chip-app-server/include/DataModelHandler.h rename to src/app/server/DataModelHandler.h diff --git a/examples/common/chip-app-server/QRCodeUtil.cpp b/src/app/server/QRCodeUtil.cpp similarity index 96% rename from examples/common/chip-app-server/QRCodeUtil.cpp rename to src/app/server/QRCodeUtil.cpp index 9a38a084019e4a..a57294c6c895a4 100644 --- a/examples/common/chip-app-server/QRCodeUtil.cpp +++ b/src/app/server/QRCodeUtil.cpp @@ -16,7 +16,7 @@ * limitations under the License. */ -#include "QRCodeUtil.h" +#include #include @@ -35,16 +35,16 @@ void PrintQRCode(chip::RendezvousInformationFlags rendezvousFlags) if (GetQRCode(setupPinCode, QRCode, rendezvousFlags) == CHIP_NO_ERROR) { - ChipLogProgress(AppServer, "SetupPINCode: [%" PRIu32 "]", setupPinCode); - ChipLogProgress(AppServer, "SetupQRCode: [%s]", QRCode.c_str()); - chip::Platform::ScopedMemoryBuffer qrCodeBuffer; const size_t qrCodeBufferMaxSize = 3 * QRCode.size() + 1; qrCodeBuffer.Alloc(qrCodeBufferMaxSize); + + ChipLogProgress(AppServer, "SetupPINCode: [%" PRIu32 "]", setupPinCode); + ChipLogProgress(AppServer, "SetupQRCode: [%s]", QRCode.c_str()); if (EncodeQRCodeToUrl(QRCode.c_str(), QRCode.size(), &qrCodeBuffer[0], qrCodeBufferMaxSize) == CHIP_NO_ERROR) { - ChipLogProgress(AppServer, "Copy/paste the below URL in a browser to see the QR Code:\n\t%s?data=%s", qrCodeBaseUrl, - &qrCodeBuffer[0]); + ChipLogProgress(AppServer, "Copy/paste the below URL in a browser to see the QR Code:"); + ChipLogProgress(AppServer, "%s?data=%s", qrCodeBaseUrl, &qrCodeBuffer[0]); } } else diff --git a/examples/common/chip-app-server/include/QRCodeUtil.h b/src/app/server/QRCodeUtil.h similarity index 100% rename from examples/common/chip-app-server/include/QRCodeUtil.h rename to src/app/server/QRCodeUtil.h diff --git a/examples/common/chip-app-server/RendezvousServer.cpp b/src/app/server/RendezvousServer.cpp similarity index 91% rename from examples/common/chip-app-server/RendezvousServer.cpp rename to src/app/server/RendezvousServer.cpp index ead0cf85d46088..f3ff72fc0887ef 100644 --- a/examples/common/chip-app-server/RendezvousServer.cpp +++ b/src/app/server/RendezvousServer.cpp @@ -15,9 +15,9 @@ * limitations under the License. */ -#include "RendezvousServer.h" +#include -#include "SessionManager.h" +#include #include #include #include @@ -25,7 +25,7 @@ #if CHIP_ENABLE_OPENTHREAD #include #endif -#include +#include using namespace ::chip::Inet; using namespace ::chip::Transport; @@ -97,7 +97,10 @@ void RendezvousServer::OnRendezvousStatusUpdate(Status status, CHIP_ERROR err) case RendezvousSessionDelegate::NetworkProvisioningSuccess: ChipLogProgress(AppServer, "Device was assigned network credentials"); - chip::Mdns::DiscoveryManager::GetInstance().StartPublishDevice(); + if (chip::Mdns::ServiceAdvertiser::Instance().Start(&DeviceLayer::InetLayer, chip::Mdns::kMdnsPort) != CHIP_NO_ERROR) + { + ChipLogError(AppServer, "Failed to start mDNS advertisement"); + } if (mDelegate != nullptr) { mDelegate->OnRendezvousStopped(); diff --git a/examples/common/chip-app-server/include/RendezvousServer.h b/src/app/server/RendezvousServer.h similarity index 97% rename from examples/common/chip-app-server/include/RendezvousServer.h rename to src/app/server/RendezvousServer.h index 54d097620ce928..5658baabff61da 100644 --- a/examples/common/chip-app-server/include/RendezvousServer.h +++ b/src/app/server/RendezvousServer.h @@ -17,7 +17,7 @@ #pragma once -#include "AppDelegate.h" +#include #include #include diff --git a/examples/common/chip-app-server/Server.cpp b/src/app/server/Server.cpp similarity index 65% rename from examples/common/chip-app-server/Server.cpp rename to src/app/server/Server.cpp index 0667f37c0a0dbb..e10219548a119d 100644 --- a/examples/common/chip-app-server/Server.cpp +++ b/src/app/server/Server.cpp @@ -15,21 +15,22 @@ * limitations under the License. */ -#include "Server.h" +#include -#include "DataModelHandler.h" -#include "RendezvousServer.h" -#include "SessionManager.h" +#include +#include +#include #include #include #include #include -#include +#include #include #include #include #include +#include #include #include #include @@ -60,10 +61,10 @@ bool isRendezvousBypassed() class ServerCallback : public SecureSessionMgrDelegate { public: - void OnMessageReceived(const PacketHeader & header, const PayloadHeader & payloadHeader, - const Transport::PeerConnectionState * state, System::PacketBufferHandle buffer, - SecureSessionMgr * mgr) override + void OnMessageReceived(const PacketHeader & header, const PayloadHeader & payloadHeader, SecureSessionHandle session, + System::PacketBufferHandle buffer, SecureSessionMgr * mgr) override { + auto state = mgr->GetPeerConnectionState(session); const size_t data_len = buffer->DataLength(); char src_addr[PeerAddress::kMaxToStringSize]; @@ -91,7 +92,7 @@ class ServerCallback : public SecureSessionMgrDelegate } } - void OnNewConnection(const Transport::PeerConnectionState * state, SecureSessionMgr * mgr) override + void OnNewConnection(SecureSessionHandle session, SecureSessionMgr * mgr) override { ChipLogProgress(AppServer, "Received a new connection."); } @@ -102,6 +103,69 @@ class ServerCallback : public SecureSessionMgrDelegate AppDelegate * mDelegate = nullptr; }; +#if CHIP_ENABLE_MDNS + +CHIP_ERROR InitMdns() +{ + auto & mdnsAdvertiser = Mdns::ServiceAdvertiser::Instance(); + + // TODO: advertise this only when really operational once we support both + // operational and commisioning advertising is supported. + if (ConfigurationMgr().IsFullyProvisioned()) + { + uint64_t fabricId; + + if (ConfigurationMgr().GetFabricId(fabricId) != CHIP_NO_ERROR) + { + ChipLogError(Discovery, "Fabric ID not known. Using a default"); + fabricId = 5544332211; + } + + const auto advertiseParameters = Mdns::OperationalAdvertisingParameters() + .SetFabricId(fabricId) + .SetNodeId(chip::kTestDeviceNodeId) + .SetPort(CHIP_PORT) + .EnableIpV4(true); + + ReturnErrorOnFailure(mdnsAdvertiser.Advertise(advertiseParameters)); + } + else + { + auto advertiseParameters = Mdns::CommisioningAdvertisingParameters().SetPort(CHIP_PORT).EnableIpV4(true); + + uint16_t value; + if (ConfigurationMgr().GetVendorId(value) != CHIP_NO_ERROR) + { + ChipLogProgress(Discovery, "Vendor ID not known"); + } + else + { + advertiseParameters.SetVendorId(chip::Optional::Value(value)); + } + + if (ConfigurationMgr().GetProductId(value) != CHIP_NO_ERROR) + { + ChipLogProgress(Discovery, "Product ID not known"); + } + else + { + advertiseParameters.SetProductId(chip::Optional::Value(value)); + } + + if (ConfigurationMgr().GetSetupDiscriminator(value) != CHIP_NO_ERROR) + { + ChipLogError(Discovery, "Setup discriminator not known. Using a default."); + value = 840; + } + advertiseParameters.SetShortDiscriminator(static_cast(value & 0xFF)).SetLongDiscrimininator(value); + + ReturnErrorOnFailure(mdnsAdvertiser.Advertise(advertiseParameters)); + } + + return mdnsAdvertiser.Start(&DeviceLayer::InetLayer, chip::Mdns::kMdnsPort); +} +#endif + DemoTransportMgr gTransports; SecureSessionMgr gSessions; ServerCallback gCallbacks; @@ -152,17 +216,24 @@ void InitServer(AppDelegate * delegate) uint32_t pinCode; SuccessOrExit(err = DeviceLayer::ConfigurationMgr().GetSetupPinCode(pinCode)); +#if CONFIG_NETWORK_LAYER_BLE params.SetSetupPINCode(pinCode) .SetBleLayer(DeviceLayer::ConnectivityMgr().GetBleLayer()) .SetPeerAddress(Transport::PeerAddress::BLE()); +#else + params.SetSetupPINCode(pinCode); +#endif // CONFIG_NETWORK_LAYER_BLE SuccessOrExit(err = gRendezvousServer.Init(params, &gTransports)); } - err = gSessions.NewPairing(peer, chip::kTestControllerNodeId, &gTestPairing); +#if CHIP_ENABLE_MDNS + err = InitMdns(); SuccessOrExit(err); +#endif gSessions.SetDelegate(&gCallbacks); - chip::Mdns::DiscoveryManager::GetInstance().StartPublishDevice(kIPAddressType_IPv6); + err = gSessions.NewPairing(peer, chip::kTestControllerNodeId, &gTestPairing); + SuccessOrExit(err); exit: if (err != CHIP_NO_ERROR) diff --git a/examples/common/chip-app-server/include/Server.h b/src/app/server/Server.h similarity index 97% rename from examples/common/chip-app-server/include/Server.h rename to src/app/server/Server.h index c149bb4d5eeeeb..697258a8ee4e89 100644 --- a/examples/common/chip-app-server/include/Server.h +++ b/src/app/server/Server.h @@ -17,7 +17,7 @@ #pragma once -#include "AppDelegate.h" +#include #include #include #include diff --git a/examples/common/chip-app-server/include/SessionManager.h b/src/app/server/SessionManager.h similarity index 100% rename from examples/common/chip-app-server/include/SessionManager.h rename to src/app/server/SessionManager.h diff --git a/src/app/tests/TestMessageDef.cpp b/src/app/tests/TestMessageDef.cpp index 14bf7b2992bc51..e332cb8c7efa5e 100644 --- a/src/app/tests/TestMessageDef.cpp +++ b/src/app/tests/TestMessageDef.cpp @@ -1,6 +1,6 @@ /* * - * Copyright (c) 2020 Project CHIP Authors + * Copyright (c) 2020-2021 Project CHIP Authors * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -25,7 +25,7 @@ #include #include #include -#include +#include #include @@ -44,11 +44,11 @@ void TLVPrettyPrinter(const char * aFormat, ...) va_end(args); } -CHIP_ERROR DebugPrettyPrint(chip::System::PacketBuffer * apMsgBuf) +CHIP_ERROR DebugPrettyPrint(const chip::System::PacketBufferHandle & aMsgBuf) { CHIP_ERROR err = CHIP_NO_ERROR; - chip::TLV::TLVReader reader; - reader.Init(apMsgBuf); + chip::System::PacketBufferTLVReader reader; + reader.Init(aMsgBuf.Retain()); err = reader.Next(); chip::TLV::Debug::Dump(reader, TLVPrettyPrinter); @@ -679,47 +679,41 @@ void AttributePathTest(nlTestSuite * apSuite, void * apContext) { CHIP_ERROR err = CHIP_NO_ERROR; AttributePath::Builder attributePathBuilder; - chip::TLV::TLVWriter writer; - chip::TLV::TLVReader reader; - chip::System::PacketBufferHandle bufHandle = chip::System::PacketBuffer::New(); - chip::System::PacketBuffer * buf = bufHandle.Get_ForNow(); - writer.Init(buf); + chip::System::PacketBufferTLVWriter writer; + chip::System::PacketBufferTLVReader reader; + writer.Init(chip::System::PacketBuffer::New()); attributePathBuilder.Init(&writer); BuildAttributePath(apSuite, attributePathBuilder); - err = writer.Finalize(); + chip::System::PacketBufferHandle buf; + err = writer.Finalize(&buf); NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); DebugPrettyPrint(buf); - reader.Init(buf); + reader.Init(std::move(buf)); err = reader.Next(); NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); ParseAttributePath(apSuite, reader); - - bufHandle.Adopt(nullptr); } void AttributePathListTest(nlTestSuite * apSuite, void * apContext) { CHIP_ERROR err = CHIP_NO_ERROR; - chip::TLV::TLVWriter writer; - chip::TLV::TLVReader reader; - chip::System::PacketBufferHandle bufHandle = chip::System::PacketBuffer::New(); - chip::System::PacketBuffer * buf = bufHandle.Get_ForNow(); - writer.Init(buf); + chip::System::PacketBufferTLVWriter writer; + chip::System::PacketBufferTLVReader reader; + writer.Init(chip::System::PacketBuffer::New()); BuildAttributePathList(apSuite, writer); - err = writer.Finalize(); + chip::System::PacketBufferHandle buf; + err = writer.Finalize(&buf); NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); DebugPrettyPrint(buf); - reader.Init(buf); + reader.Init(std::move(buf)); err = reader.Next(); NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); ParseAttributePathList(apSuite, reader); - - bufHandle.Adopt(nullptr); } void EventPathTest(nlTestSuite * apSuite, void * apContext) @@ -727,76 +721,67 @@ void EventPathTest(nlTestSuite * apSuite, void * apContext) CHIP_ERROR err = CHIP_NO_ERROR; EventPath::Parser eventPathParser; EventPath::Builder eventPathBuilder; - chip::TLV::TLVWriter writer; - chip::TLV::TLVReader reader; - chip::System::PacketBufferHandle bufHandle = chip::System::PacketBuffer::New(); - chip::System::PacketBuffer * buf = bufHandle.Get_ForNow(); - writer.Init(buf); + chip::System::PacketBufferTLVWriter writer; + chip::System::PacketBufferTLVReader reader; + writer.Init(chip::System::PacketBuffer::New()); eventPathBuilder.Init(&writer); BuildEventPath(apSuite, eventPathBuilder); - err = writer.Finalize(); + chip::System::PacketBufferHandle buf; + err = writer.Finalize(&buf); NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); DebugPrettyPrint(buf); - reader.Init(buf); + reader.Init(std::move(buf)); err = reader.Next(); NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); eventPathParser.Init(reader); ParseEventPath(apSuite, eventPathParser); - - bufHandle.Adopt(nullptr); } void EventPathListTest(nlTestSuite * apSuite, void * apContext) { CHIP_ERROR err = CHIP_NO_ERROR; - chip::TLV::TLVWriter writer; - chip::TLV::TLVReader reader; - chip::System::PacketBufferHandle bufHandle = chip::System::PacketBuffer::New(); - chip::System::PacketBuffer * buf = bufHandle.Get_ForNow(); - writer.Init(buf); + chip::System::PacketBufferTLVWriter writer; + chip::System::PacketBufferTLVReader reader; + writer.Init(chip::System::PacketBuffer::New()); BuildEventPathList(apSuite, writer); - err = writer.Finalize(); + chip::System::PacketBufferHandle buf; + err = writer.Finalize(&buf); NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); DebugPrettyPrint(buf); - reader.Init(buf); + reader.Init(std::move(buf)); err = reader.Next(); NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); ParseEventPathList(apSuite, reader); - - bufHandle.Adopt(nullptr); } void CommandPathTest(nlTestSuite * apSuite, void * apContext) { CHIP_ERROR err = CHIP_NO_ERROR; - chip::TLV::TLVWriter writer; - chip::TLV::TLVReader reader; + chip::System::PacketBufferTLVWriter writer; + chip::System::PacketBufferTLVReader reader; CommandPath::Builder commandPathBuilder; - chip::System::PacketBufferHandle bufHandle = chip::System::PacketBuffer::New(); - chip::System::PacketBuffer * buf = bufHandle.Get_ForNow(); - writer.Init(buf); + writer.Init(chip::System::PacketBuffer::New()); err = commandPathBuilder.Init(&writer); NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); BuildCommandPath(apSuite, commandPathBuilder); - err = writer.Finalize(); + chip::System::PacketBufferHandle buf; + err = writer.Finalize(&buf); NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); DebugPrettyPrint(buf); - reader.Init(buf); + reader.Init(std::move(buf)); err = reader.Next(); NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); ParseCommandPath(apSuite, reader); - - bufHandle.Adopt(nullptr); } void EventDataElementTest(nlTestSuite * apSuite, void * apContext) @@ -804,50 +789,44 @@ void EventDataElementTest(nlTestSuite * apSuite, void * apContext) CHIP_ERROR err = CHIP_NO_ERROR; EventDataElement::Builder eventDataElementBuilder; EventDataElement::Parser eventDataElementParser; - chip::TLV::TLVWriter writer; - chip::TLV::TLVReader reader; - chip::System::PacketBufferHandle bufHandle = chip::System::PacketBuffer::New(); - chip::System::PacketBuffer * buf = bufHandle.Get_ForNow(); - writer.Init(buf); + chip::System::PacketBufferTLVWriter writer; + chip::System::PacketBufferTLVReader reader; + writer.Init(chip::System::PacketBuffer::New()); eventDataElementBuilder.Init(&writer); BuildEventDataElement(apSuite, eventDataElementBuilder); - err = writer.Finalize(); + chip::System::PacketBufferHandle buf; + err = writer.Finalize(&buf); NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); DebugPrettyPrint(buf); - reader.Init(buf); + reader.Init(std::move(buf)); err = reader.Next(); NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); eventDataElementParser.Init(reader); ParseEventDataElement(apSuite, eventDataElementParser); - - bufHandle.Adopt(nullptr); } void EventListTest(nlTestSuite * apSuite, void * apContext) { CHIP_ERROR err = CHIP_NO_ERROR; - chip::TLV::TLVWriter writer; - chip::TLV::TLVReader reader; + chip::System::PacketBufferTLVWriter writer; + chip::System::PacketBufferTLVReader reader; EventList::Builder eventListBuilder; - chip::System::PacketBufferHandle bufHandle = chip::System::PacketBuffer::New(); - chip::System::PacketBuffer * buf = bufHandle.Get_ForNow(); - writer.Init(buf); + writer.Init(chip::System::PacketBuffer::New()); eventListBuilder.Init(&writer); BuildEventList(apSuite, eventListBuilder); - err = writer.Finalize(); + chip::System::PacketBufferHandle buf; + err = writer.Finalize(&buf); NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); DebugPrettyPrint(buf); - reader.Init(buf); + reader.Init(std::move(buf)); err = reader.Next(); NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); ParseEventList(apSuite, reader); - - bufHandle.Adopt(nullptr); } void StatusElementTest(nlTestSuite * apSuite, void * apContext) @@ -855,26 +834,23 @@ void StatusElementTest(nlTestSuite * apSuite, void * apContext) CHIP_ERROR err = CHIP_NO_ERROR; StatusElement::Builder statusElementBuilder; StatusElement::Parser statusElementParser; - chip::TLV::TLVWriter writer; - chip::TLV::TLVReader reader; - chip::System::PacketBufferHandle bufHandle = chip::System::PacketBuffer::New(); - chip::System::PacketBuffer * buf = bufHandle.Get_ForNow(); - writer.Init(buf); + chip::System::PacketBufferTLVWriter writer; + chip::System::PacketBufferTLVReader reader; + writer.Init(chip::System::PacketBuffer::New()); statusElementBuilder.Init(&writer); BuildStatusElement(apSuite, statusElementBuilder); - err = writer.Finalize(); + chip::System::PacketBufferHandle buf; + err = writer.Finalize(&buf); NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); DebugPrettyPrint(buf); - reader.Init(buf); + reader.Init(std::move(buf)); err = reader.Next(); NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); statusElementParser.Init(reader); ParseStatusElement(apSuite, statusElementParser); - - bufHandle.Adopt(nullptr); } void AttributeStatusElementTest(nlTestSuite * apSuite, void * apContext) @@ -882,51 +858,45 @@ void AttributeStatusElementTest(nlTestSuite * apSuite, void * apContext) CHIP_ERROR err = CHIP_NO_ERROR; AttributeStatusElement::Builder attributeStatusElementBuilder; AttributeStatusElement::Parser attributeStatusElementParser; - chip::TLV::TLVWriter writer; - chip::TLV::TLVReader reader; - chip::System::PacketBufferHandle bufHandle = chip::System::PacketBuffer::New(); - chip::System::PacketBuffer * buf = bufHandle.Get_ForNow(); - writer.Init(buf); + chip::System::PacketBufferTLVWriter writer; + chip::System::PacketBufferTLVReader reader; + writer.Init(chip::System::PacketBuffer::New()); attributeStatusElementBuilder.Init(&writer); BuildAttributeStatusElement(apSuite, attributeStatusElementBuilder); - err = writer.Finalize(); + chip::System::PacketBufferHandle buf; + err = writer.Finalize(&buf); NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); DebugPrettyPrint(buf); - reader.Init(buf); + reader.Init(std::move(buf)); err = reader.Next(); NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); attributeStatusElementParser.Init(reader); ParseAttributeStatusElement(apSuite, attributeStatusElementParser); - - bufHandle.Adopt(nullptr); } void AttributeStatusListTest(nlTestSuite * apSuite, void * apContext) { CHIP_ERROR err = CHIP_NO_ERROR; - chip::TLV::TLVWriter writer; - chip::TLV::TLVReader reader; - chip::System::PacketBufferHandle bufHandle = chip::System::PacketBuffer::New(); - chip::System::PacketBuffer * buf = bufHandle.Get_ForNow(); - writer.Init(buf); + chip::System::PacketBufferTLVWriter writer; + chip::System::PacketBufferTLVReader reader; + writer.Init(chip::System::PacketBuffer::New()); AttributeStatusList::Builder attributeStatusListBuilder; err = attributeStatusListBuilder.Init(&writer); NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); BuildAttributeStatusList(apSuite, attributeStatusListBuilder); - err = writer.Finalize(); + chip::System::PacketBufferHandle buf; + err = writer.Finalize(&buf); NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); DebugPrettyPrint(buf); - reader.Init(buf); + reader.Init(std::move(buf)); err = reader.Next(); NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); ParseAttributeStatusList(apSuite, reader); - - bufHandle.Adopt(nullptr); } void AttributeDataElementTest(nlTestSuite * apSuite, void * apContext) @@ -934,50 +904,44 @@ void AttributeDataElementTest(nlTestSuite * apSuite, void * apContext) CHIP_ERROR err = CHIP_NO_ERROR; AttributeDataElement::Builder attributeDataElementBuilder; AttributeDataElement::Parser attributeDataElementParser; - chip::TLV::TLVWriter writer; - chip::TLV::TLVReader reader; - chip::System::PacketBufferHandle bufHandle = chip::System::PacketBuffer::New(); - chip::System::PacketBuffer * buf = bufHandle.Get_ForNow(); - writer.Init(buf); + chip::System::PacketBufferTLVWriter writer; + chip::System::PacketBufferTLVReader reader; + writer.Init(chip::System::PacketBuffer::New()); attributeDataElementBuilder.Init(&writer); BuildAttributeDataElement(apSuite, attributeDataElementBuilder); - err = writer.Finalize(); + chip::System::PacketBufferHandle buf; + err = writer.Finalize(&buf); NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); DebugPrettyPrint(buf); - reader.Init(buf); + reader.Init(std::move(buf)); err = reader.Next(); NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); attributeDataElementParser.Init(reader); ParseAttributeDataElement(apSuite, attributeDataElementParser); - - bufHandle.Adopt(nullptr); } void AttributeDataListTest(nlTestSuite * apSuite, void * apContext) { CHIP_ERROR err = CHIP_NO_ERROR; - chip::TLV::TLVWriter writer; - chip::TLV::TLVReader reader; - chip::System::PacketBufferHandle bufHandle = chip::System::PacketBuffer::New(); - chip::System::PacketBuffer * buf = bufHandle.Get_ForNow(); - writer.Init(buf); + chip::System::PacketBufferTLVWriter writer; + chip::System::PacketBufferTLVReader reader; + writer.Init(chip::System::PacketBuffer::New()); AttributeDataList::Builder attributeDataListBuilder; attributeDataListBuilder.Init(&writer); BuildAttributeDataList(apSuite, attributeDataListBuilder); - err = writer.Finalize(); + chip::System::PacketBufferHandle buf; + err = writer.Finalize(&buf); NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); DebugPrettyPrint(buf); - reader.Init(buf); + reader.Init(std::move(buf)); err = reader.Next(); NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); ParseAttributeDataList(apSuite, reader); - - bufHandle.Adopt(nullptr); } void CommandDataElementTest(nlTestSuite * apSuite, void * apContext) @@ -985,94 +949,82 @@ void CommandDataElementTest(nlTestSuite * apSuite, void * apContext) CHIP_ERROR err = CHIP_NO_ERROR; CommandDataElement::Builder commandDataElementBuilder; CommandDataElement::Parser commandDataElementParser; - chip::TLV::TLVWriter writer; - chip::TLV::TLVReader reader; - chip::System::PacketBufferHandle bufHandle = chip::System::PacketBuffer::New(); - chip::System::PacketBuffer * buf = bufHandle.Get_ForNow(); - writer.Init(buf); + chip::System::PacketBufferTLVWriter writer; + chip::System::PacketBufferTLVReader reader; + writer.Init(chip::System::PacketBuffer::New()); commandDataElementBuilder.Init(&writer); BuildCommandDataElement(apSuite, commandDataElementBuilder); - err = writer.Finalize(); + chip::System::PacketBufferHandle buf; + err = writer.Finalize(&buf); NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); DebugPrettyPrint(buf); - reader.Init(buf); + reader.Init(std::move(buf)); err = reader.Next(); NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); commandDataElementParser.Init(reader); ParseCommandDataElement(apSuite, commandDataElementParser); - - bufHandle.Adopt(nullptr); } void CommandListTest(nlTestSuite * apSuite, void * apContext) { CHIP_ERROR err = CHIP_NO_ERROR; - chip::TLV::TLVWriter writer; - chip::TLV::TLVReader reader; + chip::System::PacketBufferTLVWriter writer; + chip::System::PacketBufferTLVReader reader; CommandList::Builder commandListBuilder; - chip::System::PacketBufferHandle bufHandle = chip::System::PacketBuffer::New(); - chip::System::PacketBuffer * buf = bufHandle.Get_ForNow(); - writer.Init(buf); + writer.Init(chip::System::PacketBuffer::New()); commandListBuilder.Init(&writer); BuildCommandList(apSuite, commandListBuilder); - err = writer.Finalize(); + chip::System::PacketBufferHandle buf; + err = writer.Finalize(&buf); NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); DebugPrettyPrint(buf); - reader.Init(buf); + reader.Init(std::move(buf)); err = reader.Next(); NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); ParseCommandList(apSuite, reader); - - bufHandle.Adopt(nullptr); } void ReportDataTest(nlTestSuite * apSuite, void * apContext) { CHIP_ERROR err = CHIP_NO_ERROR; - chip::TLV::TLVWriter writer; - chip::TLV::TLVReader reader; - chip::System::PacketBufferHandle bufHandle = chip::System::PacketBuffer::New(); - chip::System::PacketBuffer * buf = bufHandle.Get_ForNow(); - writer.Init(buf); + chip::System::PacketBufferTLVWriter writer; + chip::System::PacketBufferTLVReader reader; + writer.Init(chip::System::PacketBuffer::New()); BuildReportData(apSuite, writer); - err = writer.Finalize(); + chip::System::PacketBufferHandle buf; + err = writer.Finalize(&buf); NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); DebugPrettyPrint(buf); - reader.Init(buf); + reader.Init(std::move(buf)); err = reader.Next(); NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); ParseReportData(apSuite, reader); - - bufHandle.Adopt(nullptr); } void InvokeCommandTest(nlTestSuite * apSuite, void * apContext) { CHIP_ERROR err = CHIP_NO_ERROR; - chip::TLV::TLVWriter writer; - chip::TLV::TLVReader reader; - chip::System::PacketBufferHandle bufHandle = chip::System::PacketBuffer::New(); - chip::System::PacketBuffer * buf = bufHandle.Get_ForNow(); - writer.Init(buf); + chip::System::PacketBufferTLVWriter writer; + chip::System::PacketBufferTLVReader reader; + writer.Init(chip::System::PacketBuffer::New()); BuildInvokeCommand(apSuite, writer); - err = writer.Finalize(); + chip::System::PacketBufferHandle buf; + err = writer.Finalize(&buf); NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); DebugPrettyPrint(buf); - reader.Init(buf); + reader.Init(std::move(buf)); err = reader.Next(); NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); ParseInvokeCommand(apSuite, reader); - - bufHandle.Adopt(nullptr); } /** diff --git a/src/app/tests/integration/BUILD.gn b/src/app/tests/integration/BUILD.gn new file mode 100644 index 00000000000000..2793332554f0b9 --- /dev/null +++ b/src/app/tests/integration/BUILD.gn @@ -0,0 +1,63 @@ +# Copyright (c) 2020 Project CHIP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build_overrides/chip.gni") + +import("${chip_root}/build/chip/tools.gni") + +assert(chip_build_tools) + +executable("chip-im-initiator") { + sources = [ + "chip_im_initiator.cpp", + "common.cpp", + ] + + public_deps = [ + "${chip_root}/src/app", + "${chip_root}/src/lib/core", + "${chip_root}/src/lib/support", + "${chip_root}/src/platform", + "${chip_root}/src/protocols", + "${chip_root}/src/system", + ] + + output_dir = root_out_dir +} + +executable("chip-im-responder") { + sources = [ + "chip_im_responder.cpp", + "common.cpp", + ] + + public_deps = [ + "${chip_root}/src/app", + "${chip_root}/src/app", + "${chip_root}/src/lib/core", + "${chip_root}/src/lib/support", + "${chip_root}/src/platform", + "${chip_root}/src/protocols", + "${chip_root}/src/system", + ] + + output_dir = root_out_dir +} + +group("im") { + deps = [ + ":chip-im-initiator", + ":chip-im-responder", + ] +} diff --git a/src/app/tests/integration/Dockerfile.initiator b/src/app/tests/integration/Dockerfile.initiator new file mode 100644 index 00000000000000..eb24e834caf67d --- /dev/null +++ b/src/app/tests/integration/Dockerfile.initiator @@ -0,0 +1,6 @@ +from chip-cirque-device-base + +COPY out/chip-im-initiator /usr/bin/ +COPY entrypoint.sh / + +ENTRYPOINT ["/entrypoint.sh", "initiator"] diff --git a/src/app/tests/integration/Dockerfile.responder b/src/app/tests/integration/Dockerfile.responder new file mode 100644 index 00000000000000..89aa195bc58446 --- /dev/null +++ b/src/app/tests/integration/Dockerfile.responder @@ -0,0 +1,6 @@ +from chip-cirque-device-base + +COPY out/chip-im-responder /usr/bin/ +COPY entrypoint.sh / + +ENTRYPOINT ["/entrypoint.sh", "responder"] diff --git a/src/app/tests/integration/README.md b/src/app/tests/integration/README.md new file mode 100644 index 00000000000000..421c7b5e98a273 --- /dev/null +++ b/src/app/tests/integration/README.md @@ -0,0 +1,37 @@ +# CHIP Example IM Application Tutorial + +## Introduction + +The CHIP IM example application shows you how to implement a CHIP application +program using IM protocols. + +CHIP Protocols are, essentially, implementations of specific protocols over the +CHIP transport. Furthermore, when two CHIP nodes are exchanging messages of a +particular CHIP protocol, they do so over a construct called a CHIP Exchange +which is a description of a CHIP-based conversation over a CHIP protocol. A CHIP +Exchange is characterised by the ExchangeContext object, and every CHIP node +must create an ExchangeContext object before initiating a CHIP conversation. + +After constructing a CHIP ExchangeContext, CHIP messages are sent and received +using the ChipMessageLayer class which sends the CHIP message over a chosen +transport (TCP, UDP, or CRMP). + +## Example Applications Walk Through + +As part of this example, we have a ChipImInitiator program that acts as the +client and sends echo requests to a ChipImResponder program that receives +InvokeCommandRequests and sends back InvokeCommandResponse messages. + +### Test a device over IP + +To start the Server in echo mode, run the built executable. + + $ ./chip-im-responder + +To start the Client in echo mode, run the built executable and pass it the IP +address of the server to talk to. + + $ ./chip-im-initiator + +If valid values are supplied, it will begin to periodically send messages to the +server address provided for three times. diff --git a/src/app/tests/integration/chip_im_initiator.cpp b/src/app/tests/integration/chip_im_initiator.cpp new file mode 100644 index 00000000000000..49921939b21d4d --- /dev/null +++ b/src/app/tests/integration/chip_im_initiator.cpp @@ -0,0 +1,262 @@ +/* + * + * 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 a chip-im-initiator, for the + * CHIP Interaction Data Model Protocol. + * + * Currently it provides simple command sender with sample cluster and command + * + */ + +#include "common.h" + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#define IM_CLIENT_PORT (CHIP_PORT + 1) + +namespace { + +// Max value for the number of command request sent. +constexpr size_t kMaxCommandCount = 3; + +// The CHIP Command interval time in milliseconds. +constexpr int32_t gCommandInterval = 1000; + +// The CommandSender object. +chip::app::CommandSender * gpCommandSender = nullptr; + +chip::TransportMgr gTransportManager; + +chip::SecureSessionMgr gSessionManager; + +chip::Inet::IPAddress gDestAddr; + +// The last time a CHIP Command was attempted to be sent. +uint64_t gLastCommandTime = 0; + +// True, if the CommandSender is waiting for an CommandResponse +// after sending an CommandRequest, false otherwise. +bool gWaitingForCommandResp = false; + +// Count of the number of CommandRequests sent. +uint64_t gCommandCount = 0; + +// Count of the number of CommandResponses received. +uint64_t gCommandRespCount = 0; + +bool CommandIntervalExpired(void) +{ + uint64_t now = chip::System::Timer::GetCurrentEpoch(); + + return (now >= gLastCommandTime + gCommandInterval); +} + +CHIP_ERROR SendCommandRequest(void) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + + gLastCommandTime = chip::System::Timer::GetCurrentEpoch(); + + printf("\nSend invoke command request message to Node: %" PRIu64 "\n", chip::kTestDeviceNodeId); + + chip::app::Command::CommandParams CommandParams = { 1, // Endpoint + 0, // GroupId + 6, // ClusterId + 40, // CommandId + (chip::app::Command::kCommandPathFlag_EndpointIdValid) }; + + // Add command data here + + uint8_t effectIdentifier = 1; // Dying light + uint8_t effectVariant = 1; + + chip::TLV::TLVType dummyType = chip::TLV::kTLVType_NotSpecified; + + chip::TLV::TLVWriter writer = gpCommandSender->CreateCommandDataElementTLVWriter(); + + err = writer.StartContainer(chip::TLV::AnonymousTag, chip::TLV::kTLVType_Structure, dummyType); + SuccessOrExit(err); + + err = writer.Put(chip::TLV::ContextTag(1), effectIdentifier); + SuccessOrExit(err); + + err = writer.Put(chip::TLV::ContextTag(2), effectVariant); + SuccessOrExit(err); + + err = writer.EndContainer(dummyType); + SuccessOrExit(err); + + err = writer.Finalize(); + SuccessOrExit(err); + + err = gpCommandSender->AddCommand(CommandParams); + SuccessOrExit(err); + + err = gpCommandSender->SendCommandRequest(chip::kTestDeviceNodeId); + SuccessOrExit(err); + + if (err == CHIP_NO_ERROR) + { + gWaitingForCommandResp = true; + gCommandCount++; + } + else + { + printf("Send invoke command request failed, err: %s\n", chip::ErrorStr(err)); + } +exit: + return err; +} + +CHIP_ERROR EstablishSecureSession() +{ + CHIP_ERROR err = CHIP_NO_ERROR; + + chip::SecurePairingUsingTestSecret * testSecurePairingSecret = chip::Platform::New( + chip::Optional::Value(chip::kTestDeviceNodeId), static_cast(0), static_cast(0)); + VerifyOrExit(testSecurePairingSecret != nullptr, err = CHIP_ERROR_NO_MEMORY); + + // Attempt to connect to the peer. + err = gSessionManager.NewPairing(chip::Optional::Value( + chip::Transport::PeerAddress::UDP(gDestAddr, CHIP_PORT, INET_NULL_INTERFACEID)), + chip::kTestDeviceNodeId, testSecurePairingSecret); + +exit: + if (err != CHIP_NO_ERROR) + { + printf("Establish secure session failed, err: %s\n", chip::ErrorStr(err)); + gLastCommandTime = chip::System::Timer::GetCurrentEpoch(); + } + else + { + printf("Establish secure session succeeded\n"); + } + + return err; +} + +void HandleCommandResponseReceived(chip::TLV::TLVReader & aReader, chip::app::Command * apCommandObj) +{ + uint32_t respTime = chip::System::Timer::GetCurrentEpoch(); + uint32_t transitTime = respTime - gLastCommandTime; + + if (aReader.GetLength() != 0) + { + chip::TLV::Debug::Dump(aReader, TLVPrettyPrinter); + } + gWaitingForCommandResp = false; + gCommandRespCount++; + + printf("Command Response: %" PRIu64 "/%" PRIu64 "(%.2f%%) time=%.3fms\n", gCommandRespCount, gCommandCount, + static_cast(gCommandRespCount) * 100 / gCommandCount, static_cast(transitTime) / 1000); +} + +} // namespace + +int main(int argc, char * argv[]) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + + if (argc <= 1) + { + printf("Missing Command Server IP address\n"); + ExitNow(err = CHIP_ERROR_INVALID_ARGUMENT); + } + + if (!chip::Inet::IPAddress::FromString(argv[1], gDestAddr)) + { + printf("Invalid Command Server IP address: %s\n", argv[1]); + ExitNow(err = CHIP_ERROR_INVALID_ARGUMENT); + } + + InitializeChip(); + + err = gTransportManager.Init(chip::Transport::UdpListenParameters(&chip::DeviceLayer::InetLayer) + .SetAddressType(chip::Inet::kIPAddressType_IPv4) + .SetListenPort(IM_CLIENT_PORT)); + SuccessOrExit(err); + + err = gSessionManager.Init(chip::kTestControllerNodeId, &chip::DeviceLayer::SystemLayer, &gTransportManager); + SuccessOrExit(err); + + err = gExchangeManager.Init(&gSessionManager); + SuccessOrExit(err); + + err = chip::app::InteractionModelEngine::GetInstance()->Init(&gExchangeManager); + SuccessOrExit(err); + + chip::app::InteractionModelEngine::GetInstance()->RegisterClusterCommandHandler( + 6, 40, chip::app::Command::CommandRoleId::kCommandSenderId, HandleCommandResponseReceived); + + // Start the CHIP connection to the CHIP im responder. + err = EstablishSecureSession(); + SuccessOrExit(err); + + err = chip::app::InteractionModelEngine::GetInstance()->NewCommandSender(&gpCommandSender); + SuccessOrExit(err); + + // Connection has been established. Now send the CommandRequests. + for (unsigned int i = 0; i < kMaxCommandCount; i++) + { + if (SendCommandRequest() != CHIP_NO_ERROR) + { + printf("Send request failed: %s\n", chip::ErrorStr(err)); + break; + } + + // Wait for response until the Command interval. + while (!CommandIntervalExpired()) + { + DriveIO(); + } + + // Check if expected response was received. + if (gWaitingForCommandResp) + { + printf("No response received\n"); + gWaitingForCommandResp = false; + } + } + + chip::app::InteractionModelEngine::GetInstance()->DeregisterClusterCommandHandler( + 6, 40, chip::app::Command::CommandRoleId::kCommandSenderId); + + gpCommandSender->Shutdown(); + chip::app::InteractionModelEngine::GetInstance()->Shutdown(); + ShutdownChip(); + +exit: + if (err != CHIP_NO_ERROR) + { + printf("ChipCommandSender failed: %s\n", chip::ErrorStr(err)); + exit(EXIT_FAILURE); + } + + return EXIT_SUCCESS; +} diff --git a/src/app/tests/integration/chip_im_responder.cpp b/src/app/tests/integration/chip_im_responder.cpp new file mode 100644 index 00000000000000..9bee947677559c --- /dev/null +++ b/src/app/tests/integration/chip_im_responder.cpp @@ -0,0 +1,143 @@ +/* + * + * 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 a chip-im-responder, for the + * CHIP Interaction Data Model Protocol. + * + * Currently it provides simple command handler with sample cluster and command + * + */ + +#include "common.h" + +#include "app/InteractionModelEngine.h" +#include +#include +#include +#include + +#include "InteractionModelEngine.h" +#include +#include +#include +#include +#include + +namespace { + +// The CommandHandler object +chip::TransportMgr gTransportManager; +chip::SecureSessionMgr gSessionManager; +chip::SecurePairingUsingTestSecret gTestPairing; + +// Callback handler when a CHIP EchoRequest is received. +void HandleCommandRequestReceived(chip::TLV::TLVReader & aReader, chip::app::Command * apCommandObj) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + + if (aReader.GetLength() != 0) + { + chip::TLV::Debug::Dump(aReader, TLVPrettyPrinter); + } + + chip::app::Command::CommandParams commandParams = { 1, // Endpoint + 0, // GroupId + 6, // ClusterId + 40, // CommandId + (chip::app::Command::kCommandPathFlag_EndpointIdValid) }; + + // Add command data here + + uint8_t effectIdentifier = 1; // Dying light + uint8_t effectVariant = 1; + + chip::TLV::TLVType dummyType = chip::TLV::kTLVType_NotSpecified; + + chip::TLV::TLVWriter writer = apCommandObj->CreateCommandDataElementTLVWriter(); + + printf("responder constructing response"); + err = writer.StartContainer(chip::TLV::AnonymousTag, chip::TLV::kTLVType_Structure, dummyType); + SuccessOrExit(err); + + err = writer.Put(chip::TLV::ContextTag(1), effectIdentifier); + SuccessOrExit(err); + + err = writer.Put(chip::TLV::ContextTag(2), effectVariant); + SuccessOrExit(err); + + err = writer.EndContainer(dummyType); + SuccessOrExit(err); + + err = writer.Finalize(); + SuccessOrExit(err); + + err = apCommandObj->AddCommand(commandParams); + SuccessOrExit(err); + +exit: + return; +} + +} // namespace + +int main(int argc, char * argv[]) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + chip::Optional peer(chip::Transport::Type::kUndefined); + + InitializeChip(); + + err = gTransportManager.Init( + chip::Transport::UdpListenParameters(&chip::DeviceLayer::InetLayer).SetAddressType(chip::Inet::kIPAddressType_IPv4)); + SuccessOrExit(err); + + err = gSessionManager.Init(chip::kTestDeviceNodeId, &chip::DeviceLayer::SystemLayer, &gTransportManager); + SuccessOrExit(err); + + err = gExchangeManager.Init(&gSessionManager); + SuccessOrExit(err); + + err = chip::app::InteractionModelEngine::GetInstance()->Init(&gExchangeManager); + SuccessOrExit(err); + + err = gSessionManager.NewPairing(peer, chip::kTestControllerNodeId, &gTestPairing); + SuccessOrExit(err); + + chip::app::InteractionModelEngine::GetInstance()->RegisterClusterCommandHandler( + 6, 40, chip::app::Command::CommandRoleId::kCommandHandlerId, HandleCommandRequestReceived); + printf("Listening for IM requests...\n"); + + chip::DeviceLayer::PlatformMgr().RunEventLoop(); + +exit: + chip::app::InteractionModelEngine::GetInstance()->DeregisterClusterCommandHandler( + 6, 40, chip::app::Command::CommandRoleId::kCommandHandlerId); + + if (err != CHIP_NO_ERROR) + { + printf("CommandHandler failed, err:%s\n", chip::ErrorStr(err)); + exit(EXIT_FAILURE); + } + + chip::app::InteractionModelEngine::GetInstance()->Shutdown(); + + ShutdownChip(); + + return EXIT_SUCCESS; +} diff --git a/src/app/tests/integration/common.cpp b/src/app/tests/integration/common.cpp new file mode 100644 index 00000000000000..75d5eb5d65760c --- /dev/null +++ b/src/app/tests/integration/common.cpp @@ -0,0 +1,111 @@ +/* + * + * 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 constants, globals and interfaces common + * to and used by CHIP example applications. + * + */ + +#include + +#include "common.h" +#include +#include +#include +#include + +// The ExchangeManager global object. +chip::Messaging::ExchangeManager gExchangeManager; + +void InitializeChip(void) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + + printf("Init CHIP Stack\r\n"); + + // Initialize System memory and resources + err = chip::Platform::MemoryInit(); + SuccessOrExit(err); + + // Initialize the CHIP stack. + err = chip::DeviceLayer::PlatformMgr().InitChipStack(); + SuccessOrExit(err); + +exit: + if (err != CHIP_NO_ERROR) + { + printf("Failed to init CHIP Stack with err: %s\r\n", chip::ErrorStr(err)); + exit(EXIT_FAILURE); + } +} + +void ShutdownChip(void) +{ + gExchangeManager.Shutdown(); + chip::DeviceLayer::SystemLayer.Shutdown(); +} + +void DriveIO(void) +{ + struct timeval sleepTime; + fd_set readFDs, writeFDs, exceptFDs; + int numFDs = 0; + int selectRes; + + sleepTime.tv_sec = 0; + sleepTime.tv_usec = NETWORK_SLEEP_TIME_MSECS; + + FD_ZERO(&readFDs); + FD_ZERO(&writeFDs); + FD_ZERO(&exceptFDs); + + if (chip::DeviceLayer::SystemLayer.State() == chip::System::kLayerState_Initialized) + chip::DeviceLayer::SystemLayer.PrepareSelect(numFDs, &readFDs, &writeFDs, &exceptFDs, sleepTime); + + if (chip::DeviceLayer::InetLayer.State == chip::Inet::InetLayer::kState_Initialized) + chip::DeviceLayer::InetLayer.PrepareSelect(numFDs, &readFDs, &writeFDs, &exceptFDs, sleepTime); + + selectRes = select(numFDs, &readFDs, &writeFDs, &exceptFDs, &sleepTime); + if (selectRes < 0) + { + printf("select failed: %s\n", chip::ErrorStr(chip::System::MapErrorPOSIX(errno))); + return; + } + + if (chip::DeviceLayer::SystemLayer.State() == chip::System::kLayerState_Initialized) + { + chip::DeviceLayer::SystemLayer.HandleSelectResult(selectRes, &readFDs, &writeFDs, &exceptFDs); + } + + if (chip::DeviceLayer::InetLayer.State == chip::Inet::InetLayer::kState_Initialized) + { + chip::DeviceLayer::InetLayer.HandleSelectResult(selectRes, &readFDs, &writeFDs, &exceptFDs); + } +} + +void TLVPrettyPrinter(const char * aFormat, ...) +{ + va_list args; + + va_start(args, aFormat); + + vprintf(aFormat, args); + + va_end(args); +} diff --git a/src/darwin/Framework/CHIP/CHIPOnOff.h b/src/app/tests/integration/common.h similarity index 52% rename from src/darwin/Framework/CHIP/CHIPOnOff.h rename to src/app/tests/integration/common.h index 352a133877f97f..f925f8be5bc000 100644 --- a/src/darwin/Framework/CHIP/CHIPOnOff.h +++ b/src/app/tests/integration/common.h @@ -1,4 +1,4 @@ -/** +/* * * Copyright (c) 2020 Project CHIP Authors * @@ -15,28 +15,23 @@ * limitations under the License. */ -#ifndef CHIP_ONOFF_H -#define CHIP_ONOFF_H - -#import -#import - -@class CHIPDevice; - -NS_ASSUME_NONNULL_BEGIN - -@interface CHIPOnOff : NSObject +/** + * @file + * This file defines some of the common constants, globals and interfaces + * that are common to and used by CHIP example applications. + * + */ -- (nullable instancetype)initWithDevice:(CHIPDevice *)device endpoint:(uint8_t)endpoint queue:(dispatch_queue_t)queue; -- (BOOL)lightOn:(CHIPDeviceCallback)onCompletion; -- (BOOL)lightOff:(CHIPDeviceCallback)onCompletion; -- (BOOL)toggleLight:(CHIPDeviceCallback)onCompletion; +#pragma once -- (instancetype)init NS_UNAVAILABLE; -+ (instancetype)new NS_UNAVAILABLE; +#include -@end +#define MAX_MESSAGE_SOURCE_STR_LENGTH (100) +#define NETWORK_SLEEP_TIME_MSECS (100 * 1000) -NS_ASSUME_NONNULL_END +extern chip::Messaging::ExchangeManager gExchangeManager; -#endif /* CHIP_ONOFF_H */ +void InitializeChip(void); +void ShutdownChip(void); +void DriveIO(void); +void TLVPrettyPrinter(const char * aFormat, ...); diff --git a/src/app/tests/integration/entrypoint.sh b/src/app/tests/integration/entrypoint.sh new file mode 100755 index 00000000000000..c23ce5b0dfe8d5 --- /dev/null +++ b/src/app/tests/integration/entrypoint.sh @@ -0,0 +1,16 @@ +#!/usr/bin/env bash + +service dbus start +systemctl is-active --quiet dbus && echo dbus is running +service avahi-daemon start +/usr/sbin/otbr-agent -I wpan0 spinel+hdlc+uart:///dev/ttyUSB0 & +sleep 1 +ot-ctl panid 0x1234 +ot-ctl ifconfig up +ot-ctl thread start + +if [ "$1" = "responder" ]; then + chip-im-responder +else + sleep infinity +fi diff --git a/src/app/util/af.h b/src/app/util/af.h index ec76f9bd3af115..5c19399de2142d 100644 --- a/src/app/util/af.h +++ b/src/app/util/af.h @@ -521,6 +521,11 @@ uint8_t emberAfGetAttributeAnalogOrDiscreteType(uint8_t dataType); */ bool emberAfIsTypeSigned(EmberAfAttributeType dataType); +/** + * @brief Function that extracts a 64-bit integer from the message buffer + */ +uint64_t emberAfGetInt64u(const uint8_t * message, uint16_t currentIndex, uint16_t msgLen); + /** * @brief Function that extracts a 32-bit integer from the message buffer */ diff --git a/src/app/util/chip-message-send.cpp b/src/app/util/chip-message-send.cpp index 12aa752106021b..863a6e0393e80b 100644 --- a/src/app/util/chip-message-send.cpp +++ b/src/app/util/chip-message-send.cpp @@ -73,7 +73,8 @@ EmberStatus chipSendUnicast(NodeId destination, EmberApsFrame * apsFrame, uint16 memcpy(buffer->Start() + frameSize, message, messageLength); buffer->SetDataLength(dataLength); - CHIP_ERROR err = SessionManager().SendMessage(destination, std::move(buffer)); + // TODO: temprary create a handle from node id, will be fix in PR 3602 + CHIP_ERROR err = SessionManager().SendMessage({ destination, Transport::kAnyKeyId }, std::move(buffer)); if (err != CHIP_NO_ERROR) { // FIXME: Figure out better translations between our error types? diff --git a/src/app/util/message.cpp b/src/app/util/message.cpp index f6c6e551c64f7c..8937e220194ace 100644 --- a/src/app/util/message.cpp +++ b/src/app/util/message.cpp @@ -182,11 +182,11 @@ uint8_t * emberAfPutDateInResp(EmberAfDate * value) // buffer) // ------------------------------------ -// retrieves an uint32_t which contains between 1 and 4 bytes of relevent data +// retrieves an uint64_t which contains between 1 and 8 bytes of relevant data // depending on number of bytes requested. -uint32_t emberAfGetInt(const uint8_t * message, uint16_t currentIndex, uint16_t msgLen, uint8_t bytes) +uint64_t emberAfGetInt(const uint8_t * message, uint16_t currentIndex, uint16_t msgLen, uint8_t bytes) { - uint32_t result = 0; + uint64_t result = 0; uint8_t i = bytes; if ((currentIndex + bytes) > msgLen) { @@ -202,6 +202,11 @@ uint32_t emberAfGetInt(const uint8_t * message, uint16_t currentIndex, uint16_t return result; } +uint64_t emberAfGetInt64u(const uint8_t * message, uint16_t currentIndex, uint16_t msgLen) +{ + return emberAfGetInt(message, currentIndex, msgLen, 8); +} + uint32_t emberAfGetInt32u(const uint8_t * message, uint16_t currentIndex, uint16_t msgLen) { return emberAfGetInt(message, currentIndex, msgLen, 4); diff --git a/src/app/util/types_stub.h b/src/app/util/types_stub.h index 3ea84563523ec3..b9a3cf5924bfa2 100644 --- a/src/app/util/types_stub.h +++ b/src/app/util/types_stub.h @@ -522,7 +522,7 @@ enum * cluster ID and either the destination EUI64 (for unicast bindings) or the * 64-bit group address (for multicast bindings). */ -typedef struct +struct EmberBindingTableEntry { /** The type of binding. */ EmberBindingType type; @@ -550,7 +550,27 @@ typedef struct }; /** The index of the network the binding belongs to. */ uint8_t networkIndex; -} EmberBindingTableEntry; + + bool operator==(EmberBindingTableEntry const & other) const + { + if (type != other.type) + { + return false; + } + + if (type == EMBER_MULTICAST_BINDING && groupId != other.groupId) + { + return false; + } + + if (type == EMBER_UNICAST_BINDING && nodeId != other.nodeId) + { + return false; + } + + return local == other.local && clusterId == other.clusterId && remote == other.remote && networkIndex == other.networkIndex; + } +}; /** * @brief The decision made by the Trust Center when a node attempts to join. diff --git a/src/app/util/util.cpp b/src/app/util/util.cpp index 04fa89431227e8..c07bfcd3f2a192 100644 --- a/src/app/util/util.cpp +++ b/src/app/util/util.cpp @@ -58,11 +58,6 @@ using namespace chip; -// TODO: Need to figure out what needs to happen wrt HAL tokens here, but for -// now define ESZP_HOST to disable it. See -// https://github.com/project-chip/connectedhomeip/issues/3275 -#define EZSP_HOST - //------------------------------------------------------------------------------ // Forward Declarations diff --git a/src/app/util/util.h b/src/app/util/util.h index 664367d80a7ffc..b79683e7fde897 100644 --- a/src/app/util/util.h +++ b/src/app/util/util.h @@ -165,17 +165,17 @@ bool emberAfProcessMessageIntoZclCmd(EmberApsFrame * apsFrame, EmberIncomingMess EmberAfDifferenceType emberAfGetDifference(uint8_t * pData, EmberAfDifferenceType value, uint8_t dataSize); /** - * Retrieves an uint32_t from the given Zigbee payload. The integer retrieved + * Retrieves an uint64_t from the given Zigbee payload. The integer retrieved * may be cast into an integer of the appropriate size depending on the * number of bytes requested from the message. In Zigbee, all integers are * passed over the air in LSB form. LSB to MSB conversion is * done within this function automatically before the integer is returned. * * Obviously (due to return value) this function can only handle - * the retrieval of integers between 1 and 4 bytes in length. + * the retrieval of integers between 1 and 8 bytes in length. * */ -uint32_t emberAfGetInt(const uint8_t * message, uint16_t currentIndex, uint16_t msgLen, uint8_t bytes); +uint64_t emberAfGetInt(const uint8_t * message, uint16_t currentIndex, uint16_t msgLen, uint8_t bytes); void emberAfClearResponseData(void); uint8_t * emberAfPutInt8uInResp(uint8_t value); diff --git a/src/app/zap-templates/README.md b/src/app/zap-templates/README.md index 0b51ba643be11c..4b7450d673ff69 100644 --- a/src/app/zap-templates/README.md +++ b/src/app/zap-templates/README.md @@ -12,14 +12,15 @@ Run ZAP with UI to configure endpoints and clusters ``` cd ./third_party/zap/repo/ -node src-script/zap-start.js --logToStdout --gen ../../../src/app/zap-templates/chip-templates.json +node src-script/zap-start.js --logToStdout --gen ../../../src/app/zap-templates/app/templates.json ``` Generate files in headless mode ``` cd ./third_party/zap/repo/ -node src-script/zap-generate.js -z ./zcl-builtin/silabs/zcl.json -g ../../../src/app/zap-templates/chip-templates.json -i -o +node src-script/zap-generate.js -z ./zcl-builtin/silabs/zcl.json -g ../../../src/app/zap-templates/app-templates.json -i -o +node src-script/zap-generate.js -z ./zcl-builtin/silabs/zcl.json -g ../../../src/app/zap-templates/chip-templates.json -i -o ../../../ ``` For more information please see the documentation under `docs/` in diff --git a/src/app/zap-templates/app-templates.json b/src/app/zap-templates/app-templates.json new file mode 100644 index 00000000000000..3d67fbccdc99a3 --- /dev/null +++ b/src/app/zap-templates/app-templates.json @@ -0,0 +1,93 @@ +{ + "name": "CHIP Application templates", + "version": "chip-v1", + "helpers": ["common/StringHelper.js", "templates/app/helper.js"], + "override": "common/override.js", + "partials": [ + { + "name": "header", + "path": "partials/header.zapt" + }, + { + "name": "command_handler_cluster_commands", + "path": "partials/command_handler_cluster_commands.zapt" + } + ], + "templates": [ + { + "path": "templates/app/af-structs.zapt", + "name": "ZCL af-structs header", + "output": "af-structs.h" + }, + { + "path": "templates/app/att-storage.zapt", + "name": "ZCL att-storage header", + "output": "att-storage.h" + }, + { + "path": "templates/app/attribute-id.zapt", + "name": "ZCL attribute-id header", + "output": "attribute-id.h" + }, + { + "path": "templates/app/attribute-type.zapt", + "name": "ZCL attribute-type header", + "output": "attribute-type.h" + }, + { + "path": "templates/app/attribute-size.zapt", + "name": "ZCL attribute-size header", + "output": "attribute-size.h" + }, + { + "path": "templates/app/call-command-handler-src.zapt", + "name": "ZCL call-command-handler source", + "output": "call-command-handler.cpp" + }, + { + "path": "templates/app/call-command-handler.zapt", + "name": "ZCL call-command-handler header", + "output": "call-command-handler.h" + }, + { + "path": "templates/app/callback-stub-src.zapt", + "name": "ZCL callback-stub source", + "output": "callback-stub.cpp" + }, + { + "path": "templates/app/callback.zapt", + "name": "ZCL callback header", + "output": "callback.h" + }, + { + "path": "templates/app/client-command-macro.zapt", + "name": "ZCL client command", + "output": "client-command-macro.h" + }, + { + "path": "templates/app/cluster-id.zapt", + "name": "ZCL cluster-id header", + "output": "cluster-id.h" + }, + { + "path": "templates/app/command-id.zapt", + "name": "ZCL command-id header", + "output": "command-id.h" + }, + { + "path": "templates/app/enums.zapt", + "name": "ZCL enums header", + "output": "enums.h" + }, + { + "path": "templates/app/gen_config.zapt", + "name": "ZCL gen_config header", + "output": "gen_config.h" + }, + { + "path": "templates/app/print-cluster.zapt", + "name": "ZCL print-cluster header", + "output": "print-cluster.h" + } + ] +} diff --git a/src/app/zap-templates/chip-templates.json b/src/app/zap-templates/chip-templates.json index e889cb3d04500a..520a814e6bfe0f 100644 --- a/src/app/zap-templates/chip-templates.json +++ b/src/app/zap-templates/chip-templates.json @@ -1,9 +1,17 @@ { - "name": "CHIP templates", + "name": "CHIP Runtime templates", "version": "chip-v1", - "helpers": ["helper-chip.js"], - "override": "override.js", + "helpers": [ + "partials/helper.js", + "common/StringHelper.js", + "templates/chip/helper.js" + ], + "override": "common/override.js", "partials": [ + { + "name": "header", + "path": "partials/header.zapt" + }, { "name": "clusters_header", "path": "partials/clusters_header.zapt" @@ -15,79 +23,34 @@ ], "templates": [ { - "path": "af-structs.zapt", - "name": "ZCL af-structs header", - "output": "af-structs.h" - }, - { - "path": "att-storage.zapt", - "name": "ZCL att-storage header", - "output": "att-storage.h" - }, - { - "path": "attribute-id.zapt", - "name": "ZCL attribute-id header", - "output": "attribute-id.h" - }, - { - "path": "attribute-type.zapt", - "name": "ZCL attribute-type header", - "output": "attribute-type.h" - }, - { - "path": "attribute-size.zapt", - "name": "ZCL attribute-size header", - "output": "attribute-size.h" - }, - { - "path": "call-command-handler-src.zapt", - "name": "ZCL call-command-handler source", - "output": "call-command-handler.cpp" - }, - { - "path": "call-command-handler.zapt", - "name": "ZCL call-command-handler header", - "output": "call-command-handler.h" - }, - { - "path": "callback-stub-src.zapt", - "name": "ZCL callback-stub source", - "output": "callback-stub.cpp" - }, - { - "path": "callback.zapt", - "name": "ZCL callback header", - "output": "callback.h" - }, - { - "path": "client-command-macro.zapt", - "name": "ZCL client command", - "output": "client-command-macro.h" + "path": "templates/chip/CHIPClusters.zapt", + "name": "C++ ZCL API Header", + "output": "src/controller/CHIPClusters.h" }, { - "path": "cluster-id.zapt", - "name": "ZCL cluster-id header", - "output": "cluster-id.h" + "path": "templates/chip/CHIPClusters-src.zapt", + "name": "C++ ZCL API", + "output": "src/controller/CHIPClusters.cpp" }, { - "path": "command-id.zapt", - "name": "ZCL command-id header", - "output": "command-id.h" + "path": "templates/chip/CHIPClustersObjc.zapt", + "name": "Objc ZCL API Header", + "output": "/src/darwin/Framework/CHIP/CHIPClustersObjc.h" }, { - "path": "enums.zapt", - "name": "ZCL enums header", - "output": "enums.h" + "path": "templates/chip/CHIPClustersObjc-src.zapt", + "name": "Objc ZCL API", + "output": "/src/darwin/Framework/CHIP/CHIPClustersObjc.mm" }, { - "path": "gen_config.zapt", - "name": "ZCL gen_config header", - "output": "gen_config.h" + "path": "templates/chip/chip-zcl-zpro-codec-api.zapt", + "name": "CHIP ZCL API Header", + "output": "src/app/chip-zcl-zpro-codec-api.h" }, { - "path": "print-cluster.zapt", - "name": "ZCL print-cluster header", - "output": "print-cluster.h" + "path": "templates/chip/encoder-src.zapt", + "name": "CHIP ZCL API", + "output": "src/app/encoder.cpp" } ] } diff --git a/src/app/zap-templates/chip-zcl-zpro-codec-api.zapt b/src/app/zap-templates/chip-zcl-zpro-codec-api.zapt deleted file mode 100644 index 608c92303f205b..00000000000000 --- a/src/app/zap-templates/chip-zcl-zpro-codec-api.zapt +++ /dev/null @@ -1,59 +0,0 @@ -{{chip_header}} - -// Prevent multiple inclusion -#pragma once - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -{{> clusters_header}} - -{{#chip_server_clusters}} -{{> cluster_header}} - -{{#chip_server_cluster_commands}} -/** - * @brief - * Encode an {{asType name}} command for {{clusterName}} server into buffer including the APS frame - */ -uint16_t encode{{asCamelCased clusterName false}}Cluster{{asType name}}Command(uint8_t * buffer, uint16_t buf_length, chip::EndpointId destination_endpoint{{#chip_server_cluster_command_arguments}}, {{chipType}} {{asCamelCased label}}{{/chip_server_cluster_command_arguments}}); - -{{/chip_server_cluster_commands}} -/** - * @brief - * Encode a {{name}} server discover command into buffer including the APS frame - */ -uint16_t encode{{asCamelCased name false}}ClusterDiscoverAttributes(uint8_t * buffer, uint16_t buf_length, chip::EndpointId destination_endpoint); - -{{#chip_server_cluster_attributes}} -/** - * @brief - * Encode a {{parent.name}} server read command for the {{name}} attribute into buffer including the APS frame - */ -uint16_t encode{{asCamelCased parent.name false}}ClusterRead{{asCamelCased name false}}Attribute(uint8_t * buffer, uint16_t buf_length, chip::EndpointId destination_endpoint); - -{{#if (isWritableAttribute)}} -/** - * @brief - * Encode a {{parent.name}} server write command for the {{name}} attribute into buffer including the APS frame - */ -uint16_t encode{{asCamelCased parent.name false}}ClusterWrite{{asCamelCased name false}}Attribute(uint8_t * buffer, uint16_t buf_length, chip::EndpointId destination_endpoint, {{asUnderlyingZclType type}} {{asCamelCased name}}); - -{{/if}} -{{#if (isReportableAttribute)}} -/** - * @brief - * Encode a {{parent.name}} server report command for the {{name}} attribute into buffer including the APS frame - */ -uint16_t encode{{asCamelCased parent.name false}}ClusterReport{{asCamelCased name false}}Attribute(uint8_t * buffer, uint16_t buf_length, chip::EndpointId destination_endpoint, uint16_t min_interval, uint16_t max_interval{{#unless (isDiscreteType)}}, {{chipType}} change{{/unless}}); - -{{/if}} -{{/chip_server_cluster_attributes}} -{{/chip_server_clusters}} -#ifdef __cplusplus -} // extern "C" -#endif diff --git a/src/app/zap-templates/common/ChipTypesHelper.js b/src/app/zap-templates/common/ChipTypesHelper.js new file mode 100644 index 00000000000000..1647eca92b1df4 --- /dev/null +++ b/src/app/zap-templates/common/ChipTypesHelper.js @@ -0,0 +1,39 @@ +/* + * + * Copyright (c) 2021 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +function asBasicType(type) +{ + switch (type) { + case 'chip::CommandId': + case 'chip::EndpointId': + return 'uint8_t'; + case 'chip::AttributeId': + case 'chip::ClusterId': + case 'chip::EventId': + case 'chip::GroupId': + return 'uint16_t'; + case 'chip::NodeId': + return 'uint64_t'; + default: + return type; + } +} + +// +// Module exports +// +exports.asBasicType = asBasicType; diff --git a/src/app/zap-templates/common/StringHelper.js b/src/app/zap-templates/common/StringHelper.js new file mode 100644 index 00000000000000..c456c167bc3364 --- /dev/null +++ b/src/app/zap-templates/common/StringHelper.js @@ -0,0 +1,41 @@ +/* + * + * 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. + */ + +const stringShortTypes = [ 'CHAR_STRING', 'OCTET_STRING' ]; +const stringLongTypes = [ 'LONG_CHAR_STRING', 'LONG_OCTET_STRING' ]; + +function isShortString(type) +{ + return stringShortTypes.includes(type); +} + +function isLongString(type) +{ + return stringLongTypes.includes(type); +} + +function isString(type) +{ + return isShortString(type) || isLongString(type); +} + +// +// Module exports +// +exports.isString = isString; +exports.isShortString = isShortString; +exports.isLongString = isLongString; diff --git a/src/app/zap-templates/override.js b/src/app/zap-templates/common/override.js similarity index 86% rename from src/app/zap-templates/override.js rename to src/app/zap-templates/common/override.js index 4bdb59012461cb..f2cefdf8a2a477 100644 --- a/src/app/zap-templates/override.js +++ b/src/app/zap-templates/common/override.js @@ -18,6 +18,12 @@ function atomicType(arg) { switch (arg.name) { + case 'node_id': + return 'chip::NodeId'; + case 'endpoint_id': + return 'chip::EndpointId'; + case 'group_id': + return 'chip::GroupId'; case 'attribute_id': return 'chip::AttributeId'; case 'cluster_id': diff --git a/src/app/zap-templates/encoder-src.zapt b/src/app/zap-templates/encoder-src.zapt deleted file mode 100644 index 1f7275f39834f1..00000000000000 --- a/src/app/zap-templates/encoder-src.zapt +++ /dev/null @@ -1,309 +0,0 @@ -{{chip_header}} - -#include "chip-zcl-zpro-codec.h" - -#include -#include -#include - -#include - -using namespace chip; - -#define CHECK_FRAME_LENGTH(value, name) \ - if (value == 0) \ - { \ - ChipLogError(Zcl, "Error encoding APS Frame: %s", name); \ - return 0; \ - } - - -#define READ_ATTRIBUTES(name, cluster_id) \ - uint16_t attr_id_count = sizeof(attr_ids) / sizeof(attr_ids[0]); \ - uint16_t result = encodeReadAttributesCommand(buffer, buf_length, destination_endpoint, cluster_id, attr_ids, attr_id_count); \ - if (result == 0) \ - { \ - ChipLogError(Zcl, "Error encoding %s command", name); \ - return 0; \ - } \ - return result; - -#define WRITE_ATTRIBUTE(name, cluster_id, value) \ - BufBound buf = BufBound(buffer, buf_length); \ - if (_encodeGlobalCommand(buf, destination_endpoint, cluster_id, 0x02)) \ - { \ - buf.Put16(attr_id); \ - buf.Put(attr_type); \ - switch (attr_type) \ - { \ - {{#chip_server_writable_attributes_types}} - case {{atomicTypeId}}: \ - buf.Put{{chipTypePutLength}}(static_cast<{{chipTypePutCastType}}>(value)); \ - break; \ - {{/chip_server_writable_attributes_types}} - default: \ - ChipLogError(Zcl, "Error encoding %s command", name); \ - return 0; \ - } \ - } \ - \ - uint16_t result = buf.Fit() && CanCastTo(buf.Needed()) ? static_cast(buf.Needed()) : 0; \ - if (result == 0) \ - { \ - ChipLogError(Zcl, "Error encoding %s command", name); \ - return 0; \ - } \ - return result; - -#define REPORT_ATTRIBUTE(name, cluster_id, isAnalog, value) \ - BufBound buf = BufBound(buffer, buf_length); \ - if (_encodeGlobalCommand(buf, destination_endpoint, cluster_id, 0x06)) \ - { \ - uint8_t direction = 0x00; \ - buf.Put(direction); \ - buf.Put16(attr_id); \ - buf.Put(attr_type); \ - buf.Put16(min_interval); \ - buf.Put16(max_interval); \ - if (isAnalog) \ - { \ - switch (attr_type) \ - { \ - {{#chip_server_reportable_attributes_types}} - {{#unless (isDiscreteType)}} - case {{atomicTypeId}}: \ - buf.Put{{chipTypePutLength}}(static_cast<{{chipTypePutCastType}}>(value)); \ - break; \ - {{/unless}} - {{/chip_server_reportable_attributes_types}} - default: \ - ChipLogError(Zcl, "Type is not supported for report attribute: '0x%02x'", attr_type); \ - break; \ - } \ - } \ - } \ - \ - uint16_t result = buf.Fit() && CanCastTo(buf.Needed()) ? static_cast(buf.Needed()) : 0; \ - if (result == 0) \ - { \ - ChipLogError(Zcl, "Error encoding %s command", name); \ - return 0; \ - } \ - return result; - -#define DISCOVER_ATTRIBUTES(name, cluster_id) \ - BufBound buf = BufBound(buffer, buf_length); \ - if (_encodeGlobalCommand(buf, destination_endpoint, cluster_id, 0x0c)) \ - { \ - /* Discover all attributes */ \ - buf.Put16(0x0000); \ - buf.Put(0xFF); \ - } \ - \ - uint16_t result = buf.Fit() && CanCastTo(buf.Needed()) ? static_cast(buf.Needed()) : 0; \ - if (result == 0) \ - { \ - ChipLogError(Zcl, "Error encoding %s command", name); \ - return 0; \ - } \ - return result; - -#define COMMAND_HEADER(name, cluster_id, command_id) \ - BufBound buf = BufBound(buffer, buf_length); \ - uint16_t result = _encodeClusterSpecificCommand(buf, destination_endpoint, cluster_id, command_id); \ - if (result == 0) \ - { \ - ChipLogError(Zcl, "Error encoding %s command", name); \ - return 0; \ - } - -#define COMMAND_FOOTER(name) \ - result = buf.Fit() && CanCastTo(buf.Needed()) ? static_cast(buf.Needed()) : 0; \ - if (result == 0) \ - { \ - ChipLogError(Zcl, "Error encoding %s command", name); \ - return 0; \ - } \ - return result; - -#define COMMAND_INSERT_STRING(name, str) \ - { \ - size_t str_length = strlen(str); \ - if (!CanCastTo(str_length)) \ - { \ - ChipLogError(Zcl, "Error encoding %s command. String too long: %d", name, str_length); \ - return 0; \ - } \ - buf.Put(static_cast(str_length)); \ - buf.Put(str); \ - } \ - -#define COMMAND(name, cluster_id, command_id) \ - COMMAND_HEADER(name, cluster_id, command_id); \ - COMMAND_FOOTER(name); - -using namespace chip; -extern "C" { - -{{> clusters_header}} - -{{#chip_server_clusters}} -#define {{define}}_ID {{asHex code 4}} -{{/chip_server_clusters}} - -static uint16_t doEncodeApsFrame(BufBound & buf, ClusterId clusterId, EndpointId sourceEndpoint, - EndpointId destinationEndpoint, EmberApsOption options, GroupId groupId, uint8_t sequence, - uint8_t radius, bool isMeasuring) -{ - - uint8_t control_byte = 0; - buf.Put(control_byte) // Put in a control byte - .Put16(clusterId) - .Put(sourceEndpoint) - .Put(destinationEndpoint) - .Put(options, sizeof(EmberApsOption)) - .Put16(groupId) - .Put(sequence) - .Put(radius); - - size_t result = 0; - if (isMeasuring) - { - result = buf.Needed(); - ChipLogDetail(Zcl, "Measured APS frame size %d", result); - } - else - { - result = buf.Fit() ? buf.Needed() : 0; - CHECK_FRAME_LENGTH(result, "Buffer too small"); - ChipLogDetail(Zcl, "Successfully encoded %d bytes", result); - } - if (!CanCastTo(result)) - { - ChipLogError(Zcl, "Can't fit our measured size in uint16_t"); - result = 0; - } - - return static_cast(result); -} - -uint16_t encodeApsFrame(uint8_t * buffer, uint16_t buf_length, EmberApsFrame * apsFrame) -{ - BufBound buf = BufBound(buffer, buf_length); - return doEncodeApsFrame(buf, apsFrame->clusterId, apsFrame->sourceEndpoint, apsFrame->destinationEndpoint, - apsFrame->options, apsFrame->groupId, apsFrame->sequence, apsFrame->radius, !buffer); -} - -uint16_t _encodeCommand(BufBound & buf, EndpointId destination_endpoint, ClusterId cluster_id, CommandId command, uint8_t frame_control) -{ - CHECK_FRAME_LENGTH(buf.Size(), "Buffer is empty"); - - uint8_t seq_num = 1; // Transaction sequence number. Just pick something. - EndpointId source_endpoint = 1; // Pick source endpoint as 1 for now. - - if (doEncodeApsFrame(buf, cluster_id, source_endpoint, destination_endpoint, 0, 0, 0, 0, false)) - { - buf.Put(frame_control); - buf.Put(seq_num); - buf.Put(command); - } - - return buf.Fit() && CanCastTo(buf.Needed()) ? static_cast(buf.Needed()) : 0; -} - -uint16_t _encodeClusterSpecificCommand(BufBound & buf, EndpointId destination_endpoint, ClusterId cluster_id, CommandId command) -{ - // This is a cluster-specific command so low two bits are 0b01. The command - // is standard, so does not need a manufacturer code, and we're sending - // client to server, so all the remaining bits are 0. - uint8_t frame_control = 0x01; - - return _encodeCommand(buf, destination_endpoint, cluster_id, command, frame_control); -} - -uint16_t _encodeGlobalCommand(BufBound & buf, EndpointId destination_endpoint, ClusterId cluster_id, CommandId command) -{ - // This is a global command, so the low bits are 0b00. The command is - // standard, so does not need a manufacturer code, and we're sending client - // to server, so all the remaining bits are 0. - uint8_t frame_control = 0x00; - - return _encodeCommand(buf, destination_endpoint, cluster_id, command, frame_control); -} - -uint16_t encodeReadAttributesCommand(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint, ClusterId cluster_id, - const uint16_t * attr_ids, uint16_t attr_id_count) -{ - BufBound buf = BufBound(buffer, buf_length); - if (_encodeGlobalCommand(buf, destination_endpoint, cluster_id, 0x00)) - { - for (uint16_t i = 0; i < attr_id_count; ++i) - { - uint16_t attr_id = attr_ids[i]; - buf.Put16(attr_id); - } - } - - return buf.Fit() && CanCastTo(buf.Needed()) ? static_cast(buf.Needed()) : 0; -} - -{{#chip_server_clusters}} -{{> cluster_header}} - -{{#chip_server_cluster_commands}} -/* - * Command {{asCamelCased name false}} - */ -uint16_t encode{{asCamelCased clusterName false}}Cluster{{asType name}}Command(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint{{#chip_server_cluster_command_arguments}}, {{chipType}} {{asCamelCased label}}{{/chip_server_cluster_command_arguments}}) -{ - const char * kName = "{{asCamelCased clusterName false}}{{asType name}}"; - COMMAND_HEADER(kName, {{parent.define}}_ID, {{asHex code 2}}); - {{#chip_server_cluster_command_arguments}} - {{#if (isString type)}} - COMMAND_INSERT_STRING(kName, {{asCamelCased label}}); - {{else if (isSignedType)}} - buf.Put{{chipTypePutLength}}(static_cast<{{chipTypePutCastType}}>({{asCamelCased label}})); - {{else}} - buf.Put{{chipTypePutLength}}({{asCamelCased label}}); - {{/if}} - {{/chip_server_cluster_command_arguments}} - COMMAND_FOOTER(kName); -} - -{{/chip_server_cluster_commands}} -uint16_t encode{{asCamelCased name false}}ClusterDiscoverAttributes(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint) -{ - DISCOVER_ATTRIBUTES("Discover{{asCamelCased name false}}Attributes", {{define}}_ID); -} - -{{#chip_server_cluster_attributes}} -/* - * Attribute {{asCamelCased name false}} - */ -uint16_t encode{{asCamelCased parent.name false}}ClusterRead{{asCamelCased name false}}Attribute(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint) -{ - uint16_t attr_ids[] = { {{asHex attributeCode 4}} }; - READ_ATTRIBUTES("Read{{asCamelCased parent.name false}}{{asCamelCased name false}}", {{parent.define}}_ID); -} - -{{#if (isWritableAttribute)}} -uint16_t encode{{asCamelCased parent.name false}}ClusterWrite{{asCamelCased name false}}Attribute(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint, {{asUnderlyingZclType type}} {{asCamelCased name}}) -{ - uint16_t attr_id = {{asHex attributeCode 4}}; - uint8_t attr_type = { {{atomicTypeId}} }; - WRITE_ATTRIBUTE("Write{{asCamelCased parent.name false}}{{asCamelCased name false}}", {{parent.define}}_ID, {{asCamelCased name}}); -} - -{{/if}} -{{#if (isReportableAttribute)}} -uint16_t encode{{asCamelCased parent.name false}}ClusterReport{{asCamelCased name false}}Attribute(uint8_t * buffer, uint16_t buf_length, EndpointId destination_endpoint, uint16_t min_interval, uint16_t max_interval{{#unless (isDiscreteType)}}, {{chipType}} change{{/unless}}) -{ - uint16_t attr_id = {{asHex attributeCode 4}}; - uint8_t attr_type = { {{atomicTypeId}} }; - REPORT_ATTRIBUTE("Report{{asCamelCased parent.name false}}{{asCamelCased name false}}", {{parent.define}}_ID, {{#unless (isDiscreteType)}}true, change{{else}}false, 0{{/unless}}); -} - -{{/if}} -{{/chip_server_cluster_attributes}} -{{/chip_server_clusters}} -} // extern "C" diff --git a/src/app/zap-templates/partials/command_handler_cluster_commands.zapt b/src/app/zap-templates/partials/command_handler_cluster_commands.zapt new file mode 100644 index 00000000000000..2a1e9ec91f92e2 --- /dev/null +++ b/src/app/zap-templates/partials/command_handler_cluster_commands.zapt @@ -0,0 +1,38 @@ +{{#if (zcl_command_arguments_count this.id)}} +uint32_t payloadOffset = cmd->payloadStartIndex; +{{#zcl_command_arguments}} +{{asUnderlyingZclType type}} {{asSymbol label}}; +{{/zcl_command_arguments}} + +{{#zcl_command_arguments}} +{{#if presentIf}} +if ({{presentIf}}) +{ +{{/if}} + {{#if isArray}} + {{asSymbol label}} = cmd->buffer + payloadOffset; + {{else}} + if (cmd->bufLen < payloadOffset + {{asReadTypeLength type}}) + { + return EMBER_ZCL_STATUS_MALFORMED_COMMAND; + } + {{asSymbol label}} = emberAfGet{{asReadType type}}(cmd->buffer, payloadOffset, cmd->bufLen); + {{#unless (isLastElement index count)}} + {{#if (isString type)}} + payloadOffset += emberAf{{asReadType type}}Length({{asSymbol label}}) + {{asReadTypeLength type}}; + {{else}} + payloadOffset += {{asReadTypeLength type}}; + {{/if}} + {{/unless}} + {{/if}} +{{#if presentIf}} +} +else +{ + {{asSymbol label}} = {{asValueIfNotPresent type isArray}}; +} +{{/if}} +{{/zcl_command_arguments}} + +{{/if}} +wasHandled = emberAf{{asCamelCased parent.name false}}Cluster{{asCamelCased name false}}Callback({{#zcl_command_arguments}}{{asSymbol label}}{{#unless (isLastElement index count)}}, {{/unless}}{{/zcl_command_arguments}}); diff --git a/src/app/zap-templates/partials/header.zapt b/src/app/zap-templates/partials/header.zapt new file mode 100644 index 00000000000000..583960d1d0520a --- /dev/null +++ b/src/app/zap-templates/partials/header.zapt @@ -0,0 +1,16 @@ +/* + * + * 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. + */ diff --git a/src/app/zap-templates/partials/helper.js b/src/app/zap-templates/partials/helper.js new file mode 100644 index 00000000000000..f98c69e1e5c7c7 --- /dev/null +++ b/src/app/zap-templates/partials/helper.js @@ -0,0 +1,39 @@ +/* + * + * 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. + */ + +function pad(label, len, ch = ' ') +{ + return label.padEnd(len, ch); +} + +function concat() +{ + let str = '' + for (let arg in arguments) + { + if (typeof arguments[arg] != 'object') { + str += arguments[arg]; + } + } + return str +} + +// +// Module exports +// +exports.pad = pad; +exports.concat = concat; diff --git a/src/app/zap-templates/af-structs.zapt b/src/app/zap-templates/templates/app/af-structs.zapt similarity index 97% rename from src/app/zap-templates/af-structs.zapt rename to src/app/zap-templates/templates/app/af-structs.zapt index 59dcfb754d584c..248cb9a8546442 100644 --- a/src/app/zap-templates/af-structs.zapt +++ b/src/app/zap-templates/templates/app/af-structs.zapt @@ -1,4 +1,4 @@ -{{chip_header}} +{{> header}} // Prevent multiple inclusion #pragma once diff --git a/src/app/zap-templates/att-storage.zapt b/src/app/zap-templates/templates/app/att-storage.zapt similarity index 99% rename from src/app/zap-templates/att-storage.zapt rename to src/app/zap-templates/templates/app/att-storage.zapt index b0491aa268a312..ed664f5f20cc7f 100644 --- a/src/app/zap-templates/att-storage.zapt +++ b/src/app/zap-templates/templates/app/att-storage.zapt @@ -1,4 +1,4 @@ -{{chip_header}} +{{> header}} // Prevent multiple inclusion #pragma once diff --git a/src/app/zap-templates/attribute-id.zapt b/src/app/zap-templates/templates/app/attribute-id.zapt similarity index 62% rename from src/app/zap-templates/attribute-id.zapt rename to src/app/zap-templates/templates/app/attribute-id.zapt index 203aa4c1a22f19..ae7498e59fe8f3 100644 --- a/src/app/zap-templates/attribute-id.zapt +++ b/src/app/zap-templates/templates/app/attribute-id.zapt @@ -1,27 +1,30 @@ -{{chip_header}} +{{> header}} // Prevent multiple inclusion #pragma once +// Global cluster attribute ids +{{#zcl_attributes}} +{{#unless clusterRef}} +#define ZCL_{{asDelimitedMacro define}}_ATTRIBUTE_ID ({{asHex code 4}}) +{{/unless}} +{{/zcl_attributes}} + {{#zcl_clusters}} // Attribute ids for cluster: {{label}} -{{#zcl_attributes_client}} -{{#first}} // Client attributes -{{/first}} +{{#zcl_attributes_client}} +{{#if clusterRef}} #define ZCL_{{asDelimitedMacro define}}_ATTRIBUTE_ID ({{asHex code 4}}) -{{#last}} - -{{/last}} +{{/if}} {{/zcl_attributes_client}} -{{#zcl_attributes_server}} -{{#first}} + // Server attributes -{{/first}} +{{#zcl_attributes_server}} +{{#if clusterRef}} #define ZCL_{{asDelimitedMacro define}}_ATTRIBUTE_ID ({{asHex code 4}}) -{{#last}} - -{{/last}} +{{/if}} {{/zcl_attributes_server}} + {{/zcl_clusters}} diff --git a/src/app/zap-templates/attribute-size.zapt b/src/app/zap-templates/templates/app/attribute-size.zapt similarity index 92% rename from src/app/zap-templates/attribute-size.zapt rename to src/app/zap-templates/templates/app/attribute-size.zapt index 0c802d586e8e9b..489dca0b893f68 100644 --- a/src/app/zap-templates/attribute-size.zapt +++ b/src/app/zap-templates/templates/app/attribute-size.zapt @@ -1,4 +1,4 @@ -{{chip_header}} +{{> header}} // Prevent multiple inclusion #pragma once diff --git a/src/app/zap-templates/attribute-type.zapt b/src/app/zap-templates/templates/app/attribute-type.zapt similarity index 92% rename from src/app/zap-templates/attribute-type.zapt rename to src/app/zap-templates/templates/app/attribute-type.zapt index c41da3019762d8..bc0e3fb7d2bee2 100644 --- a/src/app/zap-templates/attribute-type.zapt +++ b/src/app/zap-templates/templates/app/attribute-type.zapt @@ -1,4 +1,4 @@ -{{chip_header}} +{{> header}} // Prevent multiple inclusion #pragma once diff --git a/src/app/zap-templates/call-command-handler-src.zapt b/src/app/zap-templates/templates/app/call-command-handler-src.zapt similarity index 68% rename from src/app/zap-templates/call-command-handler-src.zapt rename to src/app/zap-templates/templates/app/call-command-handler-src.zapt index 0f2421f55d5f28..0f7313f4858c40 100644 --- a/src/app/zap-templates/call-command-handler-src.zapt +++ b/src/app/zap-templates/templates/app/call-command-handler-src.zapt @@ -1,4 +1,4 @@ -{{chip_header}} +{{> header}} #include @@ -97,56 +97,40 @@ EmberAfStatus emberAf{{asCamelCased name false}}Cluster{{asCamelCased side false { bool wasHandled = false; + {{#if (user_cluster_has_enabled_manufacturer_command name side)}} + if (cmd->mfgSpecific) + { + {{#all_user_cluster_commands}} + {{#if mfgCode}} + {{#if (isStrEqual clusterName parent.name)}} + {{#if (isCommandAvailable parent.side incoming outgoing commandSource name)}} + if (cmd->mfgCode == {{mfgCode}} && cmd->commandId == ZCL_{{asDelimitedMacro name}}_COMMAND_ID) + { + {{> command_handler_cluster_commands}} + } + {{/if}} + {{/if}} + {{/if}} + {{/all_user_cluster_commands}} + } + else + {{else}} if (!cmd->mfgSpecific) + {{/if}} { switch (cmd->commandId) { {{#all_user_cluster_commands}} + {{#unless mfgCode}} {{#if (isStrEqual clusterName parent.name)}} {{#if (isCommandAvailable parent.side incoming outgoing commandSource name)}} case ZCL_{{asDelimitedMacro name}}_COMMAND_ID: { - {{#if (zcl_command_arguments_count this.id)}} - uint32_t payloadOffset = cmd->payloadStartIndex; - {{#zcl_command_arguments}} - {{asUnderlyingZclType type}} {{asSymbol label}}; - {{/zcl_command_arguments}} - - {{#zcl_command_arguments}} - {{#if presentIf}} - if ({{presentIf}}) - { - {{/if}} - {{#if isArray}} - {{asSymbol label}} = cmd->buffer + payloadOffset; - {{else}} - if (cmd->bufLen < payloadOffset + {{asReadTypeLength type}}) - { - return EMBER_ZCL_STATUS_MALFORMED_COMMAND; - } - {{asSymbol label}} = emberAfGet{{asReadType type}}(cmd->buffer, payloadOffset, cmd->bufLen); - {{#unless (isLastElement index count)}} - {{#if (isString type)}} - payloadOffset += emberAf{{asReadType type}}Length({{asSymbol label}}) + {{asReadTypeLength type}}; - {{else}} - payloadOffset += {{asReadTypeLength type}}; - {{/if}} - {{/unless}} - {{/if}} - {{#if presentIf}} - } - else - { - {{asSymbol label}} = {{asValueIfNotPresent type isArray}}; - } - {{/if}} - {{/zcl_command_arguments}} - - {{/if}} - wasHandled = emberAf{{asCamelCased parent.name false}}Cluster{{asCamelCased name false}}Callback({{#zcl_command_arguments}}{{asSymbol label}}{{#unless (isLastElement index count)}}, {{/unless}}{{/zcl_command_arguments}}); + {{> command_handler_cluster_commands}} break; } {{/if}} {{/if}} + {{/unless}} {{/all_user_cluster_commands}} default: { // Unrecognized command ID, error status will apply. diff --git a/src/app/zap-templates/call-command-handler.zapt b/src/app/zap-templates/templates/app/call-command-handler.zapt similarity index 80% rename from src/app/zap-templates/call-command-handler.zapt rename to src/app/zap-templates/templates/app/call-command-handler.zapt index 6ab97918f1a89c..a57e126e3feb47 100644 --- a/src/app/zap-templates/call-command-handler.zapt +++ b/src/app/zap-templates/templates/app/call-command-handler.zapt @@ -1,4 +1,4 @@ -{{chip_header}} +{{> header}} // Prevent multiple inclusion #pragma once diff --git a/src/app/zap-templates/callback-stub-src.zapt b/src/app/zap-templates/templates/app/callback-stub-src.zapt similarity index 99% rename from src/app/zap-templates/callback-stub-src.zapt rename to src/app/zap-templates/templates/app/callback-stub-src.zapt index f73a3f658fc4e3..59fd45389523d1 100644 --- a/src/app/zap-templates/callback-stub-src.zapt +++ b/src/app/zap-templates/templates/app/callback-stub-src.zapt @@ -1,4 +1,4 @@ -{{chip_header}} +{{> header}} #include "callback.h" #include "cluster-id.h" diff --git a/src/app/zap-templates/callback.zapt b/src/app/zap-templates/templates/app/callback.zapt similarity index 99% rename from src/app/zap-templates/callback.zapt rename to src/app/zap-templates/templates/app/callback.zapt index 2348c6fa870532..bd0bd8b2539c13 100644 --- a/src/app/zap-templates/callback.zapt +++ b/src/app/zap-templates/templates/app/callback.zapt @@ -1,4 +1,4 @@ -{{chip_header}} +{{> header}} // Prevent multiple inclusion #pragma once diff --git a/src/app/zap-templates/client-command-macro.zapt b/src/app/zap-templates/templates/app/client-command-macro.zapt similarity index 98% rename from src/app/zap-templates/client-command-macro.zapt rename to src/app/zap-templates/templates/app/client-command-macro.zapt index 04334521bd0120..e3f1518e20a679 100644 --- a/src/app/zap-templates/client-command-macro.zapt +++ b/src/app/zap-templates/templates/app/client-command-macro.zapt @@ -1,4 +1,4 @@ -{{chip_header}} +{{> header}} // Prevent multiple inclusion #pragma once diff --git a/src/app/zap-templates/cluster-id.zapt b/src/app/zap-templates/templates/app/cluster-id.zapt similarity index 91% rename from src/app/zap-templates/cluster-id.zapt rename to src/app/zap-templates/templates/app/cluster-id.zapt index 4331eb3b5ffe90..a89272d6bc99a5 100644 --- a/src/app/zap-templates/cluster-id.zapt +++ b/src/app/zap-templates/templates/app/cluster-id.zapt @@ -1,4 +1,4 @@ -{{chip_header}} +{{> header}} // Prevent multiple inclusion #pragma once diff --git a/src/app/zap-templates/command-id.zapt b/src/app/zap-templates/templates/app/command-id.zapt similarity index 96% rename from src/app/zap-templates/command-id.zapt rename to src/app/zap-templates/templates/app/command-id.zapt index 74a95c5a707fbe..9b6045feeac130 100644 --- a/src/app/zap-templates/command-id.zapt +++ b/src/app/zap-templates/templates/app/command-id.zapt @@ -1,4 +1,4 @@ -{{chip_header}} +{{> header}} // Prevent multiple inclusion #pragma once diff --git a/src/app/zap-templates/endpoint_config.zapt b/src/app/zap-templates/templates/app/endpoint_config.zapt similarity index 80% rename from src/app/zap-templates/endpoint_config.zapt rename to src/app/zap-templates/templates/app/endpoint_config.zapt index fba147fa7ab0d7..31f598c459370b 100644 --- a/src/app/zap-templates/endpoint_config.zapt +++ b/src/app/zap-templates/templates/app/endpoint_config.zapt @@ -1,4 +1,4 @@ -{{chip_header}} +{{> header}} // Prevent multiple inclusion #pragma once diff --git a/src/app/zap-templates/enums.zapt b/src/app/zap-templates/templates/app/enums.zapt similarity index 97% rename from src/app/zap-templates/enums.zapt rename to src/app/zap-templates/templates/app/enums.zapt index 729329ae2aa38d..2ae4602d5a1762 100644 --- a/src/app/zap-templates/enums.zapt +++ b/src/app/zap-templates/templates/app/enums.zapt @@ -1,4 +1,4 @@ -{{chip_header}} +{{> header}} // Prevent multiple inclusion #pragma once diff --git a/src/app/zap-templates/gen_config.zapt b/src/app/zap-templates/templates/app/gen_config.zapt similarity index 97% rename from src/app/zap-templates/gen_config.zapt rename to src/app/zap-templates/templates/app/gen_config.zapt index 6988c01b21de5b..e573ff8328665a 100644 --- a/src/app/zap-templates/gen_config.zapt +++ b/src/app/zap-templates/templates/app/gen_config.zapt @@ -1,4 +1,4 @@ -{{chip_header}} +{{> header}} // Prevent multiple inclusion #pragma once @@ -59,5 +59,5 @@ // Use this macro to check if Reporting plugin is included #define EMBER_AF_PLUGIN_REPORTING // User options for plugin Reporting -#define EMBER_AF_PLUGIN_REPORTING_TABLE_SIZE 5 +#define EMBER_AF_PLUGIN_REPORTING_TABLE_SIZE 20 #define EMBER_AF_PLUGIN_REPORTING_ENABLE_GROUP_BOUND_REPORTS diff --git a/src/app/zap-templates/templates/app/helper.js b/src/app/zap-templates/templates/app/helper.js new file mode 100644 index 00000000000000..aa54fe5ad2e362 --- /dev/null +++ b/src/app/zap-templates/templates/app/helper.js @@ -0,0 +1,196 @@ +/* + * + * Copyright (c) 2020 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Import helpers from zap core +const zapPath = '../../../../../third_party/zap/repo/src-electron/'; +const queryImpexp = require(zapPath + 'db/query-impexp.js') +const templateUtil = require(zapPath + 'generator/template-util.js') +const zclHelper = require(zapPath + 'generator/helper-zcl.js') +const zclQuery = require(zapPath + 'db/query-zcl.js') + +const StringHelper = require('../../common/StringHelper.js'); +const ChipTypesHelper = require('../../common/ChipTypesHelper.js'); + +/** + * Check if the cluster (name) has any enabled manufacturer commands. This works only inside + * cluster block helpers. + * + * @param {*} name : Cluster name + * @param {*} side : Cluster side + * @param {*} options + * @returns True if cluster has enabled commands otherwise false + */ +function user_cluster_has_enabled_manufacturer_command(name, side, options) +{ + return queryImpexp.exportendPointTypeIds(this.global.db, this.global.sessionId) + .then((endpointTypes) => zclQuery.exportClustersAndEndpointDetailsFromEndpointTypes(this.global.db, endpointTypes)) + .then((endpointsAndClusters) => zclQuery.exportCommandDetailsFromAllEndpointTypesAndClusters( + this.global.db, endpointsAndClusters)) + .then((endpointCommands) => { + return !!endpointCommands.find(cmd => cmd.mfgCode && zclHelper.isStrEqual(name, cmd.clusterName) + && zclHelper.isCommandAvailable(side, cmd.incoming, cmd.outgoing, cmd.commandSource, cmd.name)); + }) +} + +function asValueIfNotPresent(type, isArray) +{ + if (StringHelper.isString(type) || isArray) { + return 'NULL'; + } + + function fn(pkgId) + { + const options = { 'hash' : {} }; + return zclHelper.asUnderlyingZclType.call(this, type, options).then(zclType => { + switch (zclType) { + case 'uint8_t': + return 'UINT8_MAX'; + case 'uint16_t': + return 'UINT16_MAX'; + case 'uint32_t': + return 'UINT32_MAX'; + default: + error = 'Unhandled underlying type ' + zclType + ' for original type ' + type; + throw error; + } + }) + } + + const promise = templateUtil.ensureZclPackageId(this).then(fn.bind(this)).catch(err => console.log(err)); + return templateUtil.templatePromise(this.global, promise) +} + +// TODO Expose the readTypeLength as an additional member field of {{asUnderlyingZclType}} instead +// of having to call this method separately. +function asReadTypeLength(type) +{ + const db = this.global.db; + + if (StringHelper.isShortString(type)) { + return '1u'; + } + + if (StringHelper.isLongString(type)) { + return '2u'; + } + + function fn(pkgId) + { + const defaultResolver = zclQuery.selectAtomicType(db, pkgId, type); + + const enumResolver = zclHelper.isEnum(db, type, pkgId).then(result => { + return result == 'unknown' ? null : zclQuery.selectEnumByName(db, type, pkgId).then(rec => { + return zclQuery.selectAtomicType(db, pkgId, rec.type); + }); + }); + + const bitmapResolver = zclHelper.isBitmap(db, type, pkgId).then(result => { + return result == 'unknown' ? null : zclQuery.selectBitmapByName(db, pkgId, type).then(rec => { + return zclQuery.selectAtomicType(db, pkgId, rec.type); + }); + }); + + const typeResolver = Promise.all([ defaultResolver, enumResolver, bitmapResolver ]); + return typeResolver.then(types => (types.find(type => type)).size); + } + + const promise = templateUtil.ensureZclPackageId(this).then(fn.bind(this)).catch(err => console.log(err)); + return templateUtil.templatePromise(this.global, promise) +} + +// TODO Expose the readType as an additional member field of {{asUnderlyingZclType}} instead +// of having to call this method separately. +function asReadType(type) +{ + if (StringHelper.isShortString(type)) { + return 'String'; + } + + if (StringHelper.isLongString(type)) { + return 'LongString'; + } + + function fn(pkgId) + { + const options = { 'hash' : {} }; + return zclHelper.asUnderlyingZclType.call(this, type, options).then(zclType => { + const basicType = ChipTypesHelper.asBasicType(zclType); + switch (basicType) { + case 'int8_t': + case 'uint8_t': + return 'Int8u'; + case 'int16_t': + case 'uint16_t': + return 'Int16u'; + case 'int24_t': + case 'uint24_t': + return 'Int24u'; + case 'int32_t': + case 'uint32_t': + return 'Int32u'; + case 'int64_t': + case 'uint64_t': + return 'Int64u'; + default: + error = 'Unhandled underlying type ' + zclType + ' for original type ' + type; + throw error; + } + }) + } + + const promise = templateUtil.ensureZclPackageId(this).then(fn.bind(this)).catch(err => console.log(err)); + return templateUtil.templatePromise(this.global, promise) +} + +/** + * Returns CHIP specific type for ZCL framework + * This function is flawed since it relies on the + * type label for CHIP type conversion. CHIP specific XML should have the + * correct type directly embedded inside. + * + * @param {*} label : The xml label of the type. + * @param {*} type : The xml type to be converted + */ +function asChipUnderlyingType(label, type) +{ + + if (zclHelper.isStrEqual(label, "endpoint")) { + return 'chip::EndpointId'; + } else if (zclHelper.isStrEqual(label, "endpointId")) { + return 'chip::EndpointId'; + } else if (zclHelper.isStrEqual(type, "CLUSTER_ID")) { + return 'chip::ClusterId'; + } else if (zclHelper.isStrEqual(type, "ATTRIBUTE_ID")) { + return 'chip::AttributeId'; + } else if (zclHelper.isStrEqual(label, "groupId")) { + return 'chip::GroupId'; + } else if (zclHelper.isStrEqual(label, "commandId")) { + return 'chip::CommandId'; + } else { + const options = { 'hash' : {} }; + return zclHelper.asUnderlyingZclType.call(this, type, options); + } +} + +// +// Module exports +// +exports.asReadType = asReadType; +exports.asReadTypeLength = asReadTypeLength; +exports.asValueIfNotPresent = asValueIfNotPresent; +exports.asChipUnderlyingType = asChipUnderlyingType; +exports.user_cluster_has_enabled_manufacturer_command = user_cluster_has_enabled_manufacturer_command; diff --git a/src/app/zap-templates/print-cluster.zapt b/src/app/zap-templates/templates/app/print-cluster.zapt similarity index 98% rename from src/app/zap-templates/print-cluster.zapt rename to src/app/zap-templates/templates/app/print-cluster.zapt index 7bed5cca10f338..6b9a41db9b3f08 100644 --- a/src/app/zap-templates/print-cluster.zapt +++ b/src/app/zap-templates/templates/app/print-cluster.zapt @@ -1,4 +1,4 @@ -{{chip_header}} +{{> header}} // Prevent multiple inclusion #pragma once diff --git a/src/app/zap-templates/templates/chip/CHIPClusters-src.zapt b/src/app/zap-templates/templates/chip/CHIPClusters-src.zapt new file mode 100644 index 00000000000000..5c98f9691eaa58 --- /dev/null +++ b/src/app/zap-templates/templates/chip/CHIPClusters-src.zapt @@ -0,0 +1,53 @@ +{{> header}} +#include "CHIPClusters.h" + +#include + +namespace chip { +namespace Controller { + +{{#chip_server_clusters}} + +// {{asCamelCased name false}} Cluster Commands +{{#chip_server_cluster_commands}} +CHIP_ERROR {{asCamelCased clusterName false}}Cluster::{{asCamelCased name false}}(Callback::Callback<> * onCompletion{{#chip_server_cluster_command_arguments}}, {{chipType}} {{asCamelCased label}}{{/chip_server_cluster_command_arguments}}) +{ + System::PacketBufferHandle payload = encode{{asCamelCased clusterName false}}Cluster{{asType name}}Command(mEndpoint{{#chip_server_cluster_command_arguments}}, {{asCamelCased label}}{{/chip_server_cluster_command_arguments}}); + return SendCommand(std::move(payload), onCompletion); +} + +{{/chip_server_cluster_commands}} +// {{asCamelCased name false}} Cluster Attributes +CHIP_ERROR {{asCamelCased name false}}Cluster::DiscoverAttributes(Callback::Callback<> * onCompletion) +{ + System::PacketBufferHandle payload = encode{{asCamelCased name false}}ClusterDiscoverAttributes(mEndpoint); + return SendCommand(std::move(payload), onCompletion); +} +{{#chip_server_cluster_attributes}} +CHIP_ERROR {{asCamelCased parent.name false}}Cluster::ReadAttribute{{asCamelCased name false}}(Callback::Callback<> * onCompletion) +{ + System::PacketBufferHandle payload = encode{{asCamelCased parent.name false}}ClusterRead{{asCamelCased name false}}Attribute(mEndpoint); + return SendCommand(std::move(payload), onCompletion); +} + +{{#if (isWritableAttribute)}} +CHIP_ERROR {{asCamelCased parent.name false}}Cluster::WriteAttribute{{asCamelCased name false}}(Callback::Callback<> * onCompletion, {{asUnderlyingZclType type}} value) +{ + System::PacketBufferHandle payload = encode{{asCamelCased parent.name false}}ClusterWrite{{asCamelCased name false}}Attribute(mEndpoint, value); + return SendCommand(std::move(payload), onCompletion); +} + +{{/if}} +{{#if (isReportableAttribute)}} +CHIP_ERROR {{asCamelCased parent.name false}}Cluster::ReportAttribute{{asCamelCased name false}}(Callback::Callback<> * onCompletion, Callback::Callback<> * onChange, uint16_t minInterval, uint16_t maxInterval{{#unless (isDiscreteType)}}, {{chipType}} change{{/unless}}) +{ + System::PacketBufferHandle payload = encode{{asCamelCased parent.name false}}ClusterReport{{asCamelCased name false}}Attribute(mEndpoint, minInterval, maxInterval{{#unless (isDiscreteType)}}, change{{/unless}}); + return RequestAttributeReporting(std::move(payload), onCompletion, onChange); +} + +{{/if}} +{{/chip_server_cluster_attributes}} +{{/chip_server_clusters}} + +} // namespace Controller +} // namespace chip diff --git a/src/app/zap-templates/templates/chip/CHIPClusters.zapt b/src/app/zap-templates/templates/chip/CHIPClusters.zapt new file mode 100644 index 00000000000000..617492fed8e890 --- /dev/null +++ b/src/app/zap-templates/templates/chip/CHIPClusters.zapt @@ -0,0 +1,49 @@ +{{> header}} + +// Prevent multiple inclusion +#pragma once + +#include +#include + +namespace chip { +namespace Controller { + +{{#chip_server_clusters}} +constexpr ClusterId k{{asCamelCased name false}}ClusterId = {{asHex code 4}}; +{{/chip_server_clusters}} + +{{#chip_server_clusters}} +class DLL_EXPORT {{asCamelCased name false}}Cluster : public ClusterBase +{ +public: + {{asCamelCased name false}}Cluster() : ClusterBase(k{{asCamelCased name false}}ClusterId) {} + ~{{asCamelCased name false}}Cluster() {} + + {{#chip_server_cluster_commands}} + {{#first}} + // Cluster Commands + {{/first}} + CHIP_ERROR {{asCamelCased name false}}(Callback::Callback<> * onCompletion{{#chip_server_cluster_command_arguments}}, {{chipType}} {{asCamelCased label}}{{/chip_server_cluster_command_arguments}}); + {{/chip_server_cluster_commands}} + + // Cluster Attributes + CHIP_ERROR DiscoverAttributes(Callback::Callback<> * onCompletion); + {{#chip_server_cluster_attributes}} + CHIP_ERROR ReadAttribute{{asCamelCased name false}}(Callback::Callback<> * onCompletion); + {{/chip_server_cluster_attributes}} + {{#chip_server_cluster_attributes}} + {{#if (isWritableAttribute)}} + CHIP_ERROR WriteAttribute{{asCamelCased name false}}(Callback::Callback<> * onCompletion, {{asUnderlyingZclType type}} value); + {{/if}} + {{/chip_server_cluster_attributes}} + {{#chip_server_cluster_attributes}} + {{#if (isReportableAttribute)}} + CHIP_ERROR ReportAttribute{{asCamelCased name false}}(Callback::Callback<> * onCompletion, Callback::Callback<> * onChange, uint16_t minInterval, uint16_t maxInterval{{#unless (isDiscreteType)}}, {{chipType}} change{{/unless}}); + {{/if}} + {{/chip_server_cluster_attributes}} +}; + +{{/chip_server_clusters}} +} // namespace Controller +} // namespace chip diff --git a/src/app/zap-templates/templates/chip/CHIPClustersObjc-src.zapt b/src/app/zap-templates/templates/chip/CHIPClustersObjc-src.zapt new file mode 100644 index 00000000000000..b150786ad05e16 --- /dev/null +++ b/src/app/zap-templates/templates/chip/CHIPClustersObjc-src.zapt @@ -0,0 +1,118 @@ +{{> header}} + +#import + +#import "CHIPCallbackBridge.h" +#import "CHIPDevice.h" +#import "CHIPDevice_Internal.h" +#import "CHIPClustersObjc.h" + +#include + +{{#chip_server_clusters}} + +@interface CHIP{{asCamelCased name false}} () + +@property (readonly) chip::Controller::{{asCamelCased name false}}Cluster cppCluster; +@property (readonly, nonatomic) dispatch_queue_t callbackQueue; +@end + +@implementation CHIP{{asCamelCased name false}} + +- (instancetype)initWithDevice:(CHIPDevice *)device endpoint:(chip::EndpointId)endpoint queue:(dispatch_queue_t)queue +{ + CHIP_ERROR err = _cppCluster.Associate([device internalDevice], endpoint); + + if (err != CHIP_NO_ERROR) { + return nil; + } + + if (self = [super init]) { + _callbackQueue = queue; + } + return self; +} + +{{#chip_server_cluster_commands}} +- (BOOL){{asCamelCased name}}:(CHIPDeviceCallback)onCompletion{{#chip_server_cluster_command_arguments}} {{asCamelCased label}}:({{chipType}}){{asCamelCased label}}{{/chip_server_cluster_command_arguments}} +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.{{asCamelCased name false}}(callback{{#chip_server_cluster_command_arguments}}, {{asCamelCased label}}{{/chip_server_cluster_command_arguments}}); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} +{{/chip_server_cluster_commands}} + +{{#chip_server_cluster_attributes}} +- (BOOL)readAttribute{{asCamelCased name false}}:(CHIPDeviceCallback)onCompletion +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.ReadAttribute{{asCamelCased name false}}(callback); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} + +{{#if (isWritableAttribute)}} +- (BOOL)writeAttribute{{asCamelCased name false}}:(CHIPDeviceCallback)onCompletion value:({{asUnderlyingZclType type}})value +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.WriteAttribute{{asCamelCased name false}}(callback, value); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} + +{{/if}} +{{#if (isReportableAttribute)}} +- (BOOL) reportAttribute{{asCamelCased name false}}:(CHIPDeviceCallback)onCompletion onChange:(CHIPDeviceCallback)onChange minInterval:(uint16_t)minInterval maxInterval:(uint16_t)maxInterval{{#unless (isDiscreteType)}} change:({{chipType}})change{{/unless}} +{ + CHIPCallbackBridge * completionCallback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!completionCallback) { + return NO; + } + + CHIPCallbackBridge * changeCallback = new CHIPCallbackBridge(onChange, _callbackQueue); + if (!changeCallback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.ReportAttribute{{asCamelCased name false}}(completionCallback, changeCallback, minInterval, maxInterval{{#unless (isDiscreteType)}}, change{{/unless}}); + if (err != CHIP_NO_ERROR) { + completionCallback->Cancel(); + changeCallback->Cancel(); + delete completionCallback; + delete changeCallback; + return NO; + } + return YES; +} + +{{/if}} +{{/chip_server_cluster_attributes}} + +@end + +{{/chip_server_clusters}} diff --git a/src/app/zap-templates/templates/chip/CHIPClustersObjc.zapt b/src/app/zap-templates/templates/chip/CHIPClustersObjc.zapt new file mode 100644 index 00000000000000..51a6c7d8a93546 --- /dev/null +++ b/src/app/zap-templates/templates/chip/CHIPClustersObjc.zapt @@ -0,0 +1,40 @@ +{{> header}} + +#ifndef CHIP_CLUSTERS_H +#define CHIP_CLUSTERS_H + +#import +#import + +@class CHIPDevice; + +{{#chip_server_clusters}} + +NS_ASSUME_NONNULL_BEGIN + +@interface CHIP{{asCamelCased name false}} : NSObject + +- (nullable instancetype)initWithDevice:(CHIPDevice *)device endpoint:(uint8_t)endpoint queue:(dispatch_queue_t)queue; +{{#chip_server_cluster_commands}} +- (BOOL){{asCamelCased name}}:(CHIPDeviceCallback)onCompletion{{#chip_server_cluster_command_arguments}} {{asCamelCased label}}:({{#if (isStrEqual chipType "chip::ClusterId")}}uint16_t{{else}}{{chipType}}{{/if}}){{asCamelCased label}}{{/chip_server_cluster_command_arguments}}; +{{/chip_server_cluster_commands}} + +{{#chip_server_cluster_attributes}} +- (BOOL)readAttribute{{asCamelCased name false}}:(CHIPDeviceCallback)onCompletion; +{{#if (isWritableAttribute)}} +- (BOOL)writeAttribute{{asCamelCased name false}}:(CHIPDeviceCallback)onCompletion value:({{asUnderlyingZclType type}})value; +{{/if}} +{{#if (isReportableAttribute)}} +- (BOOL) reportAttribute{{asCamelCased name false}}:(CHIPDeviceCallback)onCompletion onChange:(CHIPDeviceCallback)onChange minInterval:(uint16_t)minInterval maxInterval:(uint16_t)maxInterval{{#unless (isDiscreteType)}} change:({{chipType}})change{{/unless}}; +{{/if}} +{{/chip_server_cluster_attributes}} + +- (instancetype)init NS_UNAVAILABLE; ++ (instancetype)new NS_UNAVAILABLE; + +@end + +NS_ASSUME_NONNULL_END +{{/chip_server_clusters}} + +#endif /* CHIP_CLUSTERS_H */ diff --git a/src/app/zap-templates/templates/chip/chip-zcl-zpro-codec-api.zapt b/src/app/zap-templates/templates/chip/chip-zcl-zpro-codec-api.zapt new file mode 100644 index 00000000000000..8f349efb714a05 --- /dev/null +++ b/src/app/zap-templates/templates/chip/chip-zcl-zpro-codec-api.zapt @@ -0,0 +1,53 @@ +{{> header}} + +// Prevent multiple inclusion +#pragma once + +#include +#include +#include + +{{> clusters_header}} + +{{#chip_server_clusters}} +{{> cluster_header}} + +{{#chip_server_cluster_commands}} +/** + * @brief + * Encode an {{asType name}} command for {{clusterName}} server into buffer including the APS frame + */ +chip::System::PacketBufferHandle encode{{asCamelCased clusterName false}}Cluster{{asType name}}Command(chip::EndpointId destinationEndpoint{{#chip_server_cluster_command_arguments}}, {{chipType}} {{asCamelCased label}}{{/chip_server_cluster_command_arguments}}); + +{{/chip_server_cluster_commands}} +/** + * @brief + * Encode a {{name}} server discover command into buffer including the APS frame + */ +chip::System::PacketBufferHandle encode{{asCamelCased name false}}ClusterDiscoverAttributes(chip::EndpointId destinationEndpoint); + +{{#chip_server_cluster_attributes}} +/** + * @brief + * Encode a {{parent.name}} server read command for the {{name}} attribute into buffer including the APS frame + */ +chip::System::PacketBufferHandle encode{{asCamelCased parent.name false}}ClusterRead{{asCamelCased name false}}Attribute(chip::EndpointId destinationEndpoint); + +{{#if (isWritableAttribute)}} +/** + * @brief + * Encode a {{parent.name}} server write command for the {{name}} attribute into buffer including the APS frame + */ +chip::System::PacketBufferHandle encode{{asCamelCased parent.name false}}ClusterWrite{{asCamelCased name false}}Attribute(chip::EndpointId destinationEndpoint, {{asUnderlyingZclType type}} {{asCamelCased name}}); + +{{/if}} +{{#if (isReportableAttribute)}} +/** + * @brief + * Encode a {{parent.name}} server report command for the {{name}} attribute into buffer including the APS frame + */ +chip::System::PacketBufferHandle encode{{asCamelCased parent.name false}}ClusterReport{{asCamelCased name false}}Attribute(chip::EndpointId destinationEndpoint, uint16_t minInterval, uint16_t maxInterval{{#unless (isDiscreteType)}}, {{chipType}} change{{/unless}}); + +{{/if}} +{{/chip_server_cluster_attributes}} +{{/chip_server_clusters}} diff --git a/src/app/zap-templates/templates/chip/encoder-src.zapt b/src/app/zap-templates/templates/chip/encoder-src.zapt new file mode 100644 index 00000000000000..a1a7de6c6662f6 --- /dev/null +++ b/src/app/zap-templates/templates/chip/encoder-src.zapt @@ -0,0 +1,225 @@ +{{> header}} + +#include "chip-zcl-zpro-codec.h" + +#include +#include +#include + +#include + +using namespace chip; +using namespace chip::System; + +static uint16_t doEncodeApsFrame(BufBound & buf, ClusterId clusterId, EndpointId sourceEndpoint, + EndpointId destinationEndpoint, EmberApsOption options, GroupId groupId, uint8_t sequence, + uint8_t radius, bool isMeasuring) +{ + + uint8_t control_byte = 0; + buf.Put(control_byte) // Put in a control byte + .Put16(clusterId) + .Put8(sourceEndpoint) + .Put8(destinationEndpoint) + .Put(options, sizeof(EmberApsOption)) + .Put16(groupId) + .Put8(sequence) + .Put8(radius); + + size_t result = buf.Needed(); + if (isMeasuring) + { + ChipLogDetail(Zcl, "Measured APS frame size %d", result); + } + else if (buf.Fit()) + { + ChipLogDetail(Zcl, "Successfully encoded %d bytes", result); + } + else + { + ChipLogError(Zcl, "Error encoding APS Frame: Buffer too small"); + result = 0; + } + + if (!CanCastTo(result)) + { + ChipLogError(Zcl, "Can't fit our measured size in uint16_t"); + result = 0; + } + + return static_cast(result); +} + +uint16_t encodeApsFrame(uint8_t * buffer, uint16_t buf_length, EmberApsFrame * apsFrame) +{ + BufBound buf = BufBound(buffer, buf_length); + return doEncodeApsFrame(buf, apsFrame->clusterId, apsFrame->sourceEndpoint, apsFrame->destinationEndpoint, + apsFrame->options, apsFrame->groupId, apsFrame->sequence, apsFrame->radius, !buffer); +} + +#define COMMAND_HEADER(name, clusterId) \ + const char * kName = name; \ + \ + PacketBufferHandle payload = PacketBuffer::NewWithAvailableSize(kMaxBufferSize); \ + if (payload.IsNull()) \ + { \ + ChipLogError(Zcl, "Could not allocate PacketBuffer while trying to encode %s command", kName); \ + return payload; \ + } \ + \ + BufBound buf = BufBound(payload->Start(), kMaxBufferSize); \ + if (doEncodeApsFrame(buf, clusterId, kSourceEndpoint, destinationEndpoint, 0, 0, 0, 0, false)) \ + { + +#define COMMAND_FOOTER() \ + } \ + uint16_t result = buf.Fit() && CanCastTo(buf.Needed()) ? static_cast(buf.Needed()) : 0; \ + if (result == 0) \ + { \ + ChipLogError(Zcl, "Command %s can't fit in the allocated buffer", kName); \ + return PacketBufferHandle(); \ + } \ + \ + payload->SetDataLength(result); \ + return payload; + +{{> clusters_header}} + +#define EMBER_ZCL_REPORTING_DIRECTION_REPORTED 0x00 + +{{#zcl_global_commands}} +#define ZCL_{{asDelimitedMacro label}}_COMMAND_ID ({{asHex code 2}}) +{{/zcl_global_commands}} + +{{#chip_server_clusters}} +#define {{define}}_ID {{asHex code 4}} +{{#chip_server_cluster_commands}} +#define ZCL_{{asDelimitedMacro name}}_COMMAND_ID ({{asHex code 2}}) +{{/chip_server_cluster_commands}} + +{{/chip_server_clusters}} + +// TODO: Find a way to calculate maximum message length for clusters +// https://github.com/project-chip/connectedhomeip/issues/965 +constexpr uint16_t kMaxBufferSize = 1024; + +// This is a cluster-specific command so low two bits are 0b01. The command +// is standard, so does not need a manufacturer code, and we're sending +// client to server, so all the remaining bits are 0. +constexpr uint8_t kFrameControlClusterSpecificCommand = 0x01; + +// This is a global command, so the low bits are 0b00. The command is +// standard, so does not need a manufacturer code, and we're sending client +// to server, so all the remaining bits are 0. +constexpr uint8_t kFrameControlGlobalCommand = 0x00; + +// Pick source endpoint as 1 for now +constexpr EndpointId kSourceEndpoint = 1; + +// Transaction sequence number. Just pick something for now. +constexpr uint8_t kSeqNum = 1; + +{{#chip_server_clusters}} +{{> cluster_header}} + +{{#chip_server_cluster_commands}} +/* + * Command {{asCamelCased name false}} + */ +PacketBufferHandle encode{{asCamelCased clusterName false}}Cluster{{asType name}}Command(EndpointId destinationEndpoint{{#chip_server_cluster_command_arguments}}, {{chipType}} {{asCamelCased label}}{{/chip_server_cluster_command_arguments}}) +{ + COMMAND_HEADER("{{asType name}}", {{parent.define}}_ID); + {{#chip_server_cluster_command_arguments}} + {{#if (isString type)}} + size_t {{asCamelCased label}}StrLen = strlen({{asCamelCased label}}); + if (!CanCastTo({{asCamelCased label}}StrLen)) + { + ChipLogError(Zcl, "Error encoding %s command. String too long: %d", kName, {{asCamelCased label}}StrLen); + return PacketBufferHandle(); + } + {{/if}} + {{/chip_server_cluster_command_arguments}} + buf + {{#if (isManufacturerSpecificCommand)}} + .Put8(kFrameControlClusterSpecificCommand | (1u << 2)) + .Put16({{asHex mfgCode 4}}) + {{else}} + .Put8(kFrameControlClusterSpecificCommand) + {{/if}} + .Put8(kSeqNum) + .Put8(ZCL_{{asDelimitedMacro name}}_COMMAND_ID) + {{#chip_server_cluster_command_arguments}} + {{#if (isString type)}} + .Put(static_cast({{asCamelCased label}}StrLen)) + .Put({{asCamelCased label}}) + {{else if (isSignedType)}} + .Put{{chipTypePutLength}}(static_cast<{{chipTypePutCastType}}>({{asCamelCased label}})) + {{else}} + .Put{{chipTypePutLength}}({{asCamelCased label}}) + {{/if}} + {{/chip_server_cluster_command_arguments}} + ; + COMMAND_FOOTER(); +} + +{{/chip_server_cluster_commands}} +PacketBufferHandle encode{{asCamelCased name false}}ClusterDiscoverAttributes(EndpointId destinationEndpoint) +{ + COMMAND_HEADER("Discover{{asCamelCased name false}}Attributes", {{define}}_ID); + buf.Put8(kFrameControlGlobalCommand) + .Put8(kSeqNum) + .Put8(ZCL_DISCOVER_ATTRIBUTES_COMMAND_ID) + .Put16(0x0000) + .Put8(0xFF); + COMMAND_FOOTER(); +} + +{{#chip_server_cluster_attributes}} +/* + * Attribute {{asCamelCased name false}} + */ +PacketBufferHandle encode{{asCamelCased parent.name false}}ClusterRead{{asCamelCased name false}}Attribute(EndpointId destinationEndpoint) +{ + COMMAND_HEADER("Read{{asCamelCased parent.name false}}{{asCamelCased name false}}", {{parent.define}}_ID); + buf.Put8(kFrameControlGlobalCommand) + .Put8(kSeqNum) + .Put8(ZCL_READ_ATTRIBUTES_COMMAND_ID) + .Put16({{asHex attributeCode 4}}); + COMMAND_FOOTER(); +} + +{{#if (isWritableAttribute)}} +PacketBufferHandle encode{{asCamelCased parent.name false}}ClusterWrite{{asCamelCased name false}}Attribute(EndpointId destinationEndpoint, {{asUnderlyingZclType type}} {{asCamelCased name}}) +{ + COMMAND_HEADER("Write{{asCamelCased parent.name false}}{{asCamelCased name false}}", {{parent.define}}_ID); + buf.Put8(kFrameControlGlobalCommand) + .Put8(kSeqNum) + .Put8(ZCL_WRITE_ATTRIBUTES_COMMAND_ID) + .Put16({{asHex attributeCode 4}}) + .Put8({{atomicTypeId}}) + .Put{{chipTypePutLength}}(static_cast<{{chipTypePutCastType}}>({{asCamelCased name}})); + COMMAND_FOOTER(); +} + +{{/if}} +{{#if (isReportableAttribute)}} +PacketBufferHandle encode{{asCamelCased parent.name false}}ClusterReport{{asCamelCased name false}}Attribute(EndpointId destinationEndpoint, uint16_t minInterval, uint16_t maxInterval{{#unless (isDiscreteType)}}, {{chipType}} change{{/unless}}) +{ + COMMAND_HEADER("Report{{asCamelCased parent.name false}}{{asCamelCased name false}}", {{parent.define}}_ID); + buf.Put8(kFrameControlGlobalCommand) + .Put8(kSeqNum) + .Put8(ZCL_CONFIGURE_REPORTING_COMMAND_ID) + .Put8(EMBER_ZCL_REPORTING_DIRECTION_REPORTED) + .Put16({{asHex attributeCode 4}}) + .Put8({{atomicTypeId}}) + .Put16(minInterval) + .Put16(maxInterval); + {{#unless (isDiscreteType)}} + buf.Put{{chipTypePutLength}}(static_cast<{{chipTypePutCastType}}>(change)); + {{/unless}} + COMMAND_FOOTER(); +} + +{{/if}} +{{/chip_server_cluster_attributes}} +{{/chip_server_clusters}} diff --git a/src/app/zap-templates/helper-chip.js b/src/app/zap-templates/templates/chip/helper.js similarity index 51% rename from src/app/zap-templates/helper-chip.js rename to src/app/zap-templates/templates/chip/helper.js index 07ec63be26f806..de668430903214 100644 --- a/src/app/zap-templates/helper-chip.js +++ b/src/app/zap-templates/templates/chip/helper.js @@ -15,240 +15,37 @@ * limitations under the License. */ -/** - * This module contains the API for templating. For more detailed instructions, read {@tutorial template-tutorial} - * - * @module Templating API: toplevel utility helpers - */ - // Import helpers from zap core -const zapPath = '../../../third_party/zap/repo/src-electron/'; -const cHelper = require(zapPath + 'generator/helper-c.js') -const zclHelper = require(zapPath + 'generator/helper-zcl.js') -const zclQuery = require(zapPath + 'db/query-zcl.js') +const zapPath = '../../../../../third_party/zap/repo/src-electron/'; const queryConfig = require(zapPath + 'db/query-config.js') const queryImpexp = require(zapPath + 'db/query-impexp.js') const templateUtil = require(zapPath + 'generator/template-util.js') +const zclHelper = require(zapPath + 'generator/helper-zcl.js') +const zclQuery = require(zapPath + 'db/query-zcl.js') -/** - * Produces the top-of-the-file header for a C file. - * - * @returns The header content - */ -function chip_header() -{ - return ` - /* - * - * 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. - */`; -} - -const stringShortTypes = [ 'CHAR_STRING', 'OCTET_STRING' ]; -const stringLongTypes = [ 'LONG_CHAR_STRING', 'LONG_OCTET_STRING' ]; - -function isShortString(type) -{ - return stringShortTypes.includes(type); -} - -function isLongString(type) -{ - return stringLongTypes.includes(type); -} - -function isString(type) -{ - return isShortString(type) || isLongString(type); -} - -function asValueIfNotPresent(type, isArray) -{ - if (isString(type) || isArray) { - return 'NULL'; - } - - function fn(pkgId) - { - const options = { 'hash' : {} }; - return zclHelper.asUnderlyingZclType.call(this, type, options).then(zclType => { - switch (zclType) { - case 'uint8_t': - return 'UINT8_MAX'; - case 'uint16_t': - return 'UINT16_MAX'; - case 'uint32_t': - return 'UINT32_MAX'; - default: - error = 'Unhandled underlying type ' + zclType + ' for original type ' + type; - throw error; - } - }) - } - - const promise = templateUtil.ensureZclPackageId(this).then(fn.bind(this)).catch(err => console.log(err)); - return templateUtil.templatePromise(this.global, promise) -} - -// TODO Expose the readTypeLength as an additional member field of {{asUnderlyingZclType}} instead -// of having to call this method separately. -function asReadTypeLength(type) -{ - const db = this.global.db; - - if (isShortString(type)) { - return '1u'; - } - - if (isLongString(type)) { - return '2u'; - } - - function fn(pkgId) - { - const defaultResolver = zclQuery.selectAtomicType(db, pkgId, type); - - const enumResolver = zclHelper.isEnum(db, type, pkgId).then(result => { - return result == 'unknown' ? null : zclQuery.selectEnumByName(db, type, pkgId).then(rec => { - return zclQuery.selectAtomicType(db, pkgId, rec.type); - }); - }); - - const bitmapResolver = zclHelper.isBitmap(db, type, pkgId).then(result => { - return result == 'unknown' ? null : zclQuery.selectBitmapByName(db, pkgId, type).then(rec => { - return zclQuery.selectAtomicType(db, pkgId, rec.type); - }); - }); - - const typeResolver = Promise.all([ defaultResolver, enumResolver, bitmapResolver ]); - return typeResolver.then(types => (types.find(type => type)).size); - } - - const promise = templateUtil.ensureZclPackageId(this).then(fn.bind(this)).catch(err => console.log(err)); - return templateUtil.templatePromise(this.global, promise) -} - -// TODO Expose the readType as an additional member field of {{asUnderlyingZclType}} instead -// of having to call this method separately. -function asReadType(type) -{ - if (isShortString(type)) { - return 'String'; - } - - if (isLongString(type)) { - return 'LongString'; - } - - function fn(pkgId) - { - const options = { 'hash' : {} }; - return zclHelper.asUnderlyingZclType.call(this, type, options).then(zclType => { - switch (zclType) { - case 'int8_t': - case 'uint8_t': - return 'Int8u'; - case 'int16_t': - case 'uint16_t': - return 'Int16u'; - case 'int24_t': - case 'uint24_t': - return 'Int24u'; - case 'int32_t': - case 'uint32_t': - return 'Int32u'; - default: - error = 'Unhandled underlying type ' + zclType + ' for original type ' + type; - throw error; - } - }) - } - - const promise = templateUtil.ensureZclPackageId(this).then(fn.bind(this)).catch(err => console.log(err)); - return templateUtil.templatePromise(this.global, promise) -} - -/** - * Returns CHIP specific type for ZCL framework - * This function is flawed since it relies on the - * type label for CHIP type conversion. CHIP specific XML should have the - * correct type directly embedded inside. - * - * @param {*} label : The xml label of the type. - * @param {*} type : The xml type to be converted - */ -function asChipUnderlyingType(label, type) -{ - - if (zclHelper.isStrEqual(label, "endpoint")) { - return 'chip::EndpointId' - } else if (zclHelper.isStrEqual(label, "endpointId")) { - return 'chip::EndpointId' - } else if (zclHelper.isStrEqual(type, "CLUSTER_ID")) { - return 'chip::ClusterId' - } else if (zclHelper.isStrEqual(type, "ATTRIBUTE_ID")) { - return 'chip::AttributeId' - } else if (zclHelper.isStrEqual(label, "groupId")) { - return 'chip::GroupId' - } else if (zclHelper.isStrEqual(label, "commandId")) { - return 'chip::CommandId' - } else { - const options = { 'hash' : {} }; - return zclHelper.asUnderlyingZclType.call(this, type, options) - } -} - -function pad(label, len, ch = ' ') -{ - return label.padEnd(len, ch) -} - -function concat() -{ - let str = '' - for (let arg in arguments) - { - if (typeof arguments[arg] != 'object') { - str += arguments[arg] - } - } - return str -} +const StringHelper = require('../../common/StringHelper.js'); +const ChipTypesHelper = require('../../common/ChipTypesHelper.js'); /** * This method converts a ZCL type to the length expected for the * BufBound.Put method. * TODO - * Not all types are supported at the moment, so if there is any unssupported type + * Not all types are supported at the moment, so if there is any unsupported type * that we are trying to convert, it will throw an error. */ function asPutLength(zclType) { - switch (zclType) { + const type = ChipTypesHelper.asBasicType(zclType); + switch (type) { case 'int8_t': - case 'uint8_t': - return ''; case 'int16_t': - case 'uint16_t': case 'int32_t': - case 'uint32_t': case 'int64_t': + case 'uint8_t': + case 'uint16_t': + case 'uint32_t': case 'uint64_t': - return zclType.replace(/[^0-9]/g, ''); - case 'chip::ClusterId': - return '16'; + return type.replace(/[^0-9]/g, ''); default: throw error = 'Unhandled type: ' + zclType; } @@ -256,19 +53,18 @@ function asPutLength(zclType) function asPutCastType(zclType) { - switch (zclType) { + const type = ChipTypesHelper.asBasicType(zclType); + switch (type) { case 'int8_t': case 'int16_t': case 'int32_t': case 'int64_t': - return 'u' + zclType; + return 'u' + type; case 'uint8_t': case 'uint16_t': case 'uint32_t': case 'uint64_t': - return zclType; - case 'chip::ClusterId': - return 'uin16_t'; + return type; default: throw error = 'Unhandled type: ' + zclType; } @@ -355,7 +151,7 @@ function chip_server_cluster_command_arguments(options) { return Promise.all(args.map(arg => collectItem.call(this, arg, pkgId))).then(items => items.flat()).then(items => { return Promise.all(items.map(item => { - if (isString(item.type)) { + if (StringHelper.isString(item.type)) { // Enhanced the command argument with 'chipType' for conveniences. item.chipType = 'char *'; return item; @@ -471,44 +267,26 @@ function chip_server_cluster_attributes(options) { return getAttributes.call(this, pkgId, options).then(atts => { atts = atts.filter(att => att.clusterCode == clusterCode && att.side == clusterSide); - return templateUtil.collectBlocks(atts, options, this); - }) - } - - const promise = templateUtil.ensureZclPackageId(this).then(fn.bind(this)).catch(err => console.log(err)); - return templateUtil.templatePromise(this.global, promise); -} - -function chip_server_attributes_types(options, cond = att => true) -{ - function fn(pkgId) - { - return getAttributes.call(this, pkgId, options).then(atts => { - atts = atts.filter(cond); - atts = atts.filter((att, index) => atts.findIndex(att2 => att.atomicTypeId == att2.atomicTypeId) == index); - // Enhanced the attribute with chipTypePutLength and chipTypePutCastType properties for convenience. atts.forEach(att => { - att.chipTypePutLength = asPutLength(att.chipType); - att.chipTypePutCastType = asPutCastType(att.chipType); + const sameAttributes = atts.filter(att2 => att.name == att2.name); + let isWritable = !!sameAttributes.find(att2 => att2.writable); + let isReportable = !!sameAttributes.find(att2 => att2.reportable.included); + if (isWritable || isReportable) { + att.chipTypePutLength = asPutLength(att.chipType); + att.chipTypePutCastType = asPutCastType(att.chipType); + att.writable = isWritable; + att.reportable.included = isReportable; + } }) + atts = atts.filter((att, index) => atts.findIndex(att2 => att.name == att2.name) == index); return templateUtil.collectBlocks(atts, options, this); - }); + }) } const promise = templateUtil.ensureZclPackageId(this).then(fn.bind(this)).catch(err => console.log(err)); return templateUtil.templatePromise(this.global, promise); } -function chip_server_writable_attributes_types(options) -{ - return chip_server_attributes_types.call(this, options, att => att.writable); -} - -function chip_server_reportable_attributes_types(options) -{ - return chip_server_attributes_types.call(this, options, att => att.reportable.included); -} - /** * Returns if a given attribute is writable. * @@ -547,27 +325,34 @@ function isReportableAttribute(options) return this.reportable.included == 1; } -// WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! -// -// Note: these exports are public API. Templates that might have been created in the past and are -// available in the wild might depend on these names. -// If you rename the functions, you need to still maintain old exports list. -exports.chip_header = chip_header; -exports.isString = isString; -exports.pad = pad -exports.concat = concat -exports.asReadType = asReadType; -exports.asReadTypeLength = asReadTypeLength; -exports.asValueIfNotPresent = asValueIfNotPresent; -exports.asChipUnderlyingType = asChipUnderlyingType; +/** + * Returns if a given command is manufacturer specific + * + * This function is meant to be used inside a {{#chip_server_cluster_commands}} block. + * It will throws otherwise. + * + * @param {*} options + */ +function isManufacturerSpecificCommand() +{ + if (this.commandSource == undefined) { + const error = 'isManufacturerSpecificCommand: Not inside a ({#chip_server_cluster_commands}} block.'; + console.log(error); + throw error; + } -exports.chip_server_clusters = chip_server_clusters; -exports.chip_server_cluster_commands = chip_server_cluster_commands; -exports.chip_server_cluster_command_arguments = chip_server_cluster_command_arguments -exports.isSignedType = isSignedType; -exports.isDiscreteType = isDiscreteType; -exports.chip_server_cluster_attributes = chip_server_cluster_attributes; -exports.isWritableAttribute = isWritableAttribute; -exports.isReportableAttribute = isReportableAttribute; -exports.chip_server_writable_attributes_types = chip_server_writable_attributes_types; -exports.chip_server_reportable_attributes_types = chip_server_reportable_attributes_types; + return !!this.mfgCode; +} + +// +// Module exports +// +exports.chip_server_clusters = chip_server_clusters; +exports.chip_server_cluster_commands = chip_server_cluster_commands; +exports.chip_server_cluster_command_arguments = chip_server_cluster_command_arguments +exports.isSignedType = isSignedType; +exports.isDiscreteType = isDiscreteType; +exports.chip_server_cluster_attributes = chip_server_cluster_attributes; +exports.isWritableAttribute = isWritableAttribute; +exports.isReportableAttribute = isReportableAttribute; +exports.isManufacturerSpecificCommand = isManufacturerSpecificCommand; diff --git a/src/app/zap-templates/zcl/binding-cluster.xml b/src/app/zap-templates/zcl/binding-cluster.xml new file mode 100644 index 00000000000000..58f30094498017 --- /dev/null +++ b/src/app/zap-templates/zcl/binding-cluster.xml @@ -0,0 +1,42 @@ + + + + + + General + Binding + 0xF000 + BINDING_CLUSTER + true + true + The Binding Cluster is meant to replace the support from the Zigbee Device Object (ZDO) for supporting the binding table. + + Add a binding + + + + + + + Remove a binding + + + + + + + diff --git a/src/app/zap-templates/zcl/chip-devices.xml b/src/app/zap-templates/zcl/chip-devices.xml new file mode 100644 index 00000000000000..0f5d7041582dfc --- /dev/null +++ b/src/app/zap-templates/zcl/chip-devices.xml @@ -0,0 +1,191 @@ + + + + + CHIP-All-Clusters-Server + CHIP + CHIP all-clusters-app server example + 0x0103 + 0x0000 + + + VERSION + POWER_SOURCE + ResetToFactoryDefaults + MfgSpecificPing + + + BarrierControlGoToPercent + BarrierControlStop + + + COLOR_CONTROL_CURRENT_HUE + COLOR_CONTROL_CURRENT_SATURATION + COLOR_CONTROL_REMAINING_TIME + COLOR_CONTROL_CURRENT_X + COLOR_CONTROL_CURRENT_Y + COLOR_CONTROL_DRIFT_COMPENSATION + COLOR_CONTROL_COMPENSATION_TEXT + COLOR_CONTROL_COLOR_TEMPERATURE + COLOR_CONTROL_COLOR_MODE + COLOR_CONTROL_OPTIONS + COLOR_CONTROL_NUMBER_OF_PRIMARIES + COLOR_CONTROL_PRIMARY_1_X + COLOR_CONTROL_PRIMARY_1_Y + COLOR_CONTROL_PRIMARY_1_INTENSITY + COLOR_CONTROL_PRIMARY_2_X + COLOR_CONTROL_PRIMARY_2_Y + COLOR_CONTROL_PRIMARY_2_INTENSITY + COLOR_CONTROL_PRIMARY_3_X + COLOR_CONTROL_PRIMARY_3_Y + COLOR_CONTROL_PRIMARY_3_INTENSITY + COLOR_CONTROL_PRIMARY_4_X + COLOR_CONTROL_PRIMARY_4_Y + COLOR_CONTROL_PRIMARY_4_INTENSITY + COLOR_CONTROL_PRIMARY_5_X + COLOR_CONTROL_PRIMARY_5_Y + COLOR_CONTROL_PRIMARY_5_INTENSITY + COLOR_CONTROL_PRIMARY_6_X + COLOR_CONTROL_PRIMARY_6_Y + COLOR_CONTROL_PRIMARY_6_INTENSITY + COLOR_CONTROL_WHITE_POINT_X + COLOR_CONTROL_WHITE_POINT_Y + COLOR_CONTROL_COLOR_POINT_R_X + COLOR_CONTROL_COLOR_POINT_R_Y + COLOR_CONTROL_COLOR_POINT_R_INTENSITY + COLOR_CONTROL_COLOR_POINT_G_X + COLOR_CONTROL_COLOR_POINT_G_Y + COLOR_CONTROL_COLOR_POINT_G_INTENSITY + COLOR_CONTROL_COLOR_POINT_B_X + COLOR_CONTROL_COLOR_POINT_B_Y + COLOR_CONTROL_COLOR_POINT_B_INTENSITY + COLOR_CONTROL_TEMPERATURE_LEVEL_MIN_MIREDS + START_UP_COLOR_TEMPERATURE_MIREDS + COLOR_CONTROL_ENHANCED_CURRENT_HUE + COLOR_CONTROL_ENHANCED_COLOR_MODE + COLOR_CONTROL_COLOR_LOOP_ACTIVE + COLOR_CONTROL_COLOR_LOOP_DIRECTION + COLOR_CONTROL_COLOR_LOOP_TIME + COLOR_CONTROL_COLOR_START_ENHANCED_HUE + COLOR_CONTROL_COLOR_STORED_ENHANCED_HUE + COLOR_CONTROL_COLOR_CAPABILITIES + COLOR_CONTROL_COLOR_TEMP_PHYSICAL_MIN + COLOR_CONTROL_COLOR_TEMP_PHYSICAL_MAX + MoveToHue + MoveHue + StepHue + MoveToSaturation + MoveSaturation + StepSaturation + MoveToHueAndSaturation + MoveToColor + MoveColor + StepColor + MoveToColorTemperature + MoveColorTemperature + StepColorTemperature + StopMoveStep + + + LockDoor + UnlockDoor + Toggle + UnlockWithTimeout + GetLogRecord + SetPin + GetPin + ClearPin + ClearAllPins + SetWeekdaySchedule + GetWeekdaySchedule + ClearWeekdaySchedule + SetYearDaySchedule + GetYearDaySchedule + ClearYearDaySchedule + SetHolidaySchedule + GetHolidaySchedule + ClearHolidaySchedule + SetUserType + GetUserType + SetRfid + GetRfid + ClearRfid + ClearAllRfids + + + GROUP_NAME_SUPPORT + AddGroup + AddGroupResponse + ViewGroup + ViewGroupResponse + GetGroupMembership + GetGroupMembershipResponse + RemoveGroup + RemoveGroupResponse + RemoveAllGroups + AddGroupIfIdentifying + + + ZoneEnrollResponse + + + IDENTIFY_TIME + Identify + IdentifyQuery + + + CURRENT_LEVEL + MoveToLevel + Move + Step + Stop + MoveToLevelWithOnOff + MoveWithOnOff + StepWithOnOff + StopWithOnOff + + + ON_OFF + Off + On + Toggle + + + SCENE_COUNT + CURRENT_SCENE + CURRENT_GROUP + SCENE_VALID + SCENE_NAME_SUPPORT + AddScene + AddSceneResponse + ViewScene + ViewSceneResponse + RemoveScene + RemoveSceneResponse + RemoveAllScenes + RemoveAllScenesResponse + StoreScene + StoreSceneResponse + RecallScene + GetSceneMembership + GetSceneMembershipResponse + + + + + + diff --git a/src/app/zap-templates/zcl/clusters-extensions.xml b/src/app/zap-templates/zcl/clusters-extensions.xml new file mode 100644 index 00000000000000..eff6e76f56fc5c --- /dev/null +++ b/src/app/zap-templates/zcl/clusters-extensions.xml @@ -0,0 +1,24 @@ + + + + + + + + + + diff --git a/src/app/zap-templates/zcl/custom-types.xml b/src/app/zap-templates/zcl/custom-types.xml new file mode 100644 index 00000000000000..489823f0eabaf2 --- /dev/null +++ b/src/app/zap-templates/zcl/custom-types.xml @@ -0,0 +1,24 @@ + + + + + + + + + + diff --git a/src/app/zap-templates/zcl/zcl.json b/src/app/zap-templates/zcl/zcl.json new file mode 100644 index 00000000000000..360f43b6f65cf0 --- /dev/null +++ b/src/app/zap-templates/zcl/zcl.json @@ -0,0 +1,49 @@ +{ + "version": "ZCL Test Data", + "xmlRoot": [".", "../../../../third_party/zap/repo/zcl-builtin/silabs/"], + "xmlFile": [ + "binding-cluster.xml", + "clusters-extensions.xml", + "custom-types.xml", + "chip-devices.xml", + "types.xml", + "general.xml", + "ha.xml", + "ha-devices.xml", + "cba.xml", + "cba-devices.xml", + "ota.xml", + "ami.xml", + "ami-devices.xml", + "zll.xml", + "zll-devices.xml", + "ta.xml", + "ta-devices.xml", + "hc.xml", + "hc-devices.xml", + "green-power.xml", + "green-power-devices.xml", + "silabs.xml", + "lo-devices.xml", + "wwah-silabs.xml", + "wwah-silabs-devices.xml", + "sample-extensions.xml" + ], + + "manufacturersXml": "../shared/manufacturers.xml", + "options": { + "text": { + "defaultResponsePolicy": ["Always", "Conditional", "Never"] + }, + "bool": ["commandDiscovery"] + }, + "defaults": { + "text": { + "manufacturerCodes": "0x1002", + "defaultResponsePolicy": "always" + }, + "bool": { + "commandDiscovery": true + } + } +} diff --git a/src/ble/BleLayer.cpp b/src/ble/BleLayer.cpp index 2a7ebf0af5cda0..f9c7f47ba6ddc6 100644 --- a/src/ble/BleLayer.cpp +++ b/src/ble/BleLayer.cpp @@ -163,6 +163,10 @@ const ChipBleUUID BleLayer::CHIP_BLE_CHAR_2_ID = { { // 18EE2EF5-263D-4559-959F- 0x18, 0xEE, 0x2E, 0xF5, 0x26, 0x3D, 0x45, 0x59, 0x95, 0x9F, 0x4F, 0x9C, 0x42, 0x9F, 0x9D, 0x12 } }; +const ChipBleUUID BleLayer::CHIP_BLE_CHAR_3_ID = { { // 64630238-8772-45F2-B87D-748A83218F04 + 0x64, 0x63, 0x02, 0x38, 0x87, 0x72, 0x45, 0xF2, 0xB8, 0x7D, 0x74, 0x8A, 0x83, + 0x21, 0x8F, 0x04 } }; + void BleLayerObject::Release() { // Decrement the ref count. When it reaches zero, NULL out the pointer to the chip::System::Layer @@ -600,7 +604,7 @@ bool BleLayer::HandleSubscribeReceived(BLE_CONNECTION_OBJECT connObj, const Chip return false; } - if (UUIDsMatch(&CHIP_BLE_CHAR_2_ID, charId)) + if (UUIDsMatch(&CHIP_BLE_CHAR_2_ID, charId) || UUIDsMatch(&CHIP_BLE_CHAR_3_ID, charId)) { // Find end point already associated with BLE connection, if any. BLEEndPoint * endPoint = sBLEEndPointPool.Find(connObj); @@ -625,7 +629,7 @@ bool BleLayer::HandleSubscribeComplete(BLE_CONNECTION_OBJECT connObj, const Chip return false; } - if (UUIDsMatch(&CHIP_BLE_CHAR_2_ID, charId)) + if (UUIDsMatch(&CHIP_BLE_CHAR_2_ID, charId) || UUIDsMatch(&CHIP_BLE_CHAR_3_ID, charId)) { BLEEndPoint * endPoint = sBLEEndPointPool.Find(connObj); @@ -649,7 +653,7 @@ bool BleLayer::HandleUnsubscribeReceived(BLE_CONNECTION_OBJECT connObj, const Ch return false; } - if (UUIDsMatch(&CHIP_BLE_CHAR_2_ID, charId)) + if (UUIDsMatch(&CHIP_BLE_CHAR_2_ID, charId) || UUIDsMatch(&CHIP_BLE_CHAR_3_ID, charId)) { // Find end point already associated with BLE connection, if any. BLEEndPoint * endPoint = sBLEEndPointPool.Find(connObj); @@ -674,7 +678,7 @@ bool BleLayer::HandleUnsubscribeComplete(BLE_CONNECTION_OBJECT connObj, const Ch return false; } - if (UUIDsMatch(&CHIP_BLE_CHAR_2_ID, charId)) + if (UUIDsMatch(&CHIP_BLE_CHAR_2_ID, charId) || UUIDsMatch(&CHIP_BLE_CHAR_3_ID, charId)) { // Find end point already associated with BLE connection, if any. BLEEndPoint * endPoint = sBLEEndPointPool.Find(connObj); diff --git a/src/ble/BleLayer.h b/src/ble/BleLayer.h index 3117bdeb310f3d..edd084aaa1ac01 100644 --- a/src/ble/BleLayer.h +++ b/src/ble/BleLayer.h @@ -334,6 +334,8 @@ class DLL_EXPORT BleLayer static const ChipBleUUID CHIP_BLE_CHAR_1_ID; // UUID of CHIP service characteristic used for peripheral indications. static const ChipBleUUID CHIP_BLE_CHAR_2_ID; + // UUID of CHIP service characteristic used for additional data + static const ChipBleUUID CHIP_BLE_CHAR_3_ID; BleConnectionDelegate * mConnectionDelegate; BlePlatformDelegate * mPlatformDelegate; diff --git a/src/ble/BtpEngine.cpp b/src/ble/BtpEngine.cpp index 1c640d85507247..78985da2beb889 100644 --- a/src/ble/BtpEngine.cpp +++ b/src/ble/BtpEngine.cpp @@ -585,7 +585,7 @@ void BtpEngine::LogState() const ChipLogError(Ble, "mRxFragmentSize: %d", mRxFragmentSize); ChipLogError(Ble, "mRxState: %d", mRxState); - ChipLogError(Ble, "mRxBuf: %p", mRxBuf.Get_ForNow()); + ChipLogError(Ble, "mRxBuf: %d", !mRxBuf.IsNull()); ChipLogError(Ble, "mRxNextSeqNum: %d", mRxNextSeqNum); ChipLogError(Ble, "mRxNewestUnackedSeqNum: %d", mRxNewestUnackedSeqNum); ChipLogError(Ble, "mRxOldestUnackedSeqNum: %d", mRxOldestUnackedSeqNum); @@ -594,7 +594,7 @@ void BtpEngine::LogState() const ChipLogError(Ble, "mTxFragmentSize: %d", mTxFragmentSize); ChipLogError(Ble, "mTxState: %d", mTxState); - ChipLogError(Ble, "mTxBuf: %p", mTxBuf.Get_ForNow()); + ChipLogError(Ble, "mTxBuf: %d", !mTxBuf.IsNull()); ChipLogError(Ble, "mTxNextSeqNum: %d", mTxNextSeqNum); ChipLogError(Ble, "mTxNewestUnackedSeqNum: %d", mTxNewestUnackedSeqNum); ChipLogError(Ble, "mTxOldestUnackedSeqNum: %d", mTxOldestUnackedSeqNum); diff --git a/src/controller/BUILD.gn b/src/controller/BUILD.gn index b62bee48fa6ab8..e453d0d4c53196 100644 --- a/src/controller/BUILD.gn +++ b/src/controller/BUILD.gn @@ -20,14 +20,14 @@ static_library("controller") { sources = [ "CHIPCluster.cpp", "CHIPCluster.h", + "CHIPClusters.cpp", + "CHIPClusters.h", "CHIPDevice.cpp", "CHIPDevice.h", "CHIPDeviceController.cpp", "CHIPDeviceController.h", "CHIPDeviceController_deprecated.cpp", "CHIPDeviceController_deprecated.h", - "OnOffCluster.cpp", - "OnOffCluster.h", ] cflags = [ "-Wconversion" ] diff --git a/src/controller/CHIPCluster.cpp b/src/controller/CHIPCluster.cpp index 17cf018b47f320..22ce8af1cfc3e0 100644 --- a/src/controller/CHIPCluster.cpp +++ b/src/controller/CHIPCluster.cpp @@ -44,26 +44,14 @@ void ClusterBase::Dissociate() mDevice = nullptr; } -CHIP_ERROR ClusterBase::SendCommand(CommandEncoder commandEncoder, uint16_t maxCmdLen, Callback::Callback<> * responseHandler) +CHIP_ERROR ClusterBase::SendCommand(chip::System::PacketBufferHandle payload, Callback::Callback<> * responseHandler) { - CHIP_ERROR err = CHIP_NO_ERROR; - uint16_t encodedLength = 0; - System::PacketBufferHandle message; + CHIP_ERROR err = CHIP_NO_ERROR; - VerifyOrExit(commandEncoder != nullptr, err = CHIP_ERROR_INVALID_ARGUMENT); VerifyOrExit(mDevice != nullptr, err = CHIP_ERROR_INCORRECT_STATE); + VerifyOrExit(!payload.IsNull(), err = CHIP_ERROR_INTERNAL); - message = System::PacketBuffer::NewWithAvailableSize(maxCmdLen); - VerifyOrExit(!message.IsNull(), err = CHIP_ERROR_NO_MEMORY); - - encodedLength = commandEncoder(message->Start(), message->AvailableDataLength(), mEndpoint); - VerifyOrExit(encodedLength != 0, err = CHIP_ERROR_INTERNAL); - VerifyOrExit(encodedLength <= maxCmdLen, err = CHIP_ERROR_INTERNAL); - - message->SetDataLength(encodedLength); - VerifyOrExit(message->DataLength() >= encodedLength, err = CHIP_ERROR_NO_MEMORY); - - err = mDevice->SendMessage(std::move(message)); + err = mDevice->SendMessage(std::move(payload)); SuccessOrExit(err); if (responseHandler != nullptr) @@ -80,40 +68,18 @@ CHIP_ERROR ClusterBase::SendCommand(CommandEncoder commandEncoder, uint16_t maxC return err; } -CHIP_ERROR ClusterBase::RequestAttributeReporting(RequestEncoder requestEncoder, uint16_t maxCmdLen, uint16_t minInterval, - uint16_t maxInterval, Callback::Callback<> * reportHandler) +CHIP_ERROR ClusterBase::RequestAttributeReporting(chip::System::PacketBufferHandle payload, Callback::Callback<> * responseHandler, + Callback::Callback<> * reportHandler) { - CHIP_ERROR err = CHIP_NO_ERROR; - uint16_t encodedLength = 0; - System::PacketBufferHandle message; - - VerifyOrExit(requestEncoder != nullptr, err = CHIP_ERROR_INVALID_ARGUMENT); - VerifyOrExit(mDevice != nullptr, err = CHIP_ERROR_INCORRECT_STATE); - - message = System::PacketBuffer::NewWithAvailableSize(maxCmdLen); - VerifyOrExit(!message.IsNull(), err = CHIP_ERROR_NO_MEMORY); - - encodedLength = requestEncoder(message->Start(), message->AvailableDataLength(), mEndpoint, minInterval, maxInterval); - VerifyOrExit(encodedLength != 0, err = CHIP_ERROR_INTERNAL); - VerifyOrExit(encodedLength <= maxCmdLen, err = CHIP_ERROR_INTERNAL); - - message->SetDataLength(encodedLength); - VerifyOrExit(message->DataLength() >= encodedLength, err = CHIP_ERROR_NO_MEMORY); + CHIP_ERROR err = CHIP_NO_ERROR; - err = mDevice->SendMessage(std::move(message)); + err = SendCommand(std::move(payload), responseHandler); SuccessOrExit(err); - if (reportHandler != nullptr) - { - mDevice->AddReportHandler(mEndpoint, mClusterId, reportHandler); - } + VerifyOrExit(reportHandler != nullptr, err = CHIP_ERROR_INVALID_ARGUMENT); + mDevice->AddReportHandler(mEndpoint, mClusterId, reportHandler); exit: - if (err != CHIP_NO_ERROR) - { - ChipLogError(Controller, "Failed in requesting attribute reporting. Err %d", err); - } - return err; } diff --git a/src/controller/CHIPCluster.h b/src/controller/CHIPCluster.h index aefa8dcadb7cc8..b3ab9f96b5cba1 100644 --- a/src/controller/CHIPCluster.h +++ b/src/controller/CHIPCluster.h @@ -45,38 +45,30 @@ class DLL_EXPORT ClusterBase protected: ClusterBase(uint16_t cluster) : mClusterId(cluster) {} - typedef uint16_t (*CommandEncoder)(uint8_t * command, uint16_t maxLen, EndpointId endpoint); - /** * @brief - * Send the command, constructed using the given encoder, to the device. Add a callback + * Send the command, contained into the associate buffer, to the device. Add a callback * handler, that'll be called when the response is received from the device. * - * @param[in] commandEncoder The function that encodes the command - * @param[in] maxCmdLen Maximum length expected for the encoded command + * @param[in] payload The payload of the encoded command * @param[in] responseHandler The handler function that's called on receiving command response */ - CHIP_ERROR SendCommand(CommandEncoder commandEncoder, uint16_t maxCmdLen, Callback::Callback<> * responseHandler); - - typedef uint16_t (*RequestEncoder)(uint8_t * request, uint16_t maxLen, EndpointId endpoint, uint16_t minInterval, - uint16_t maxInterval); + CHIP_ERROR SendCommand(chip::System::PacketBufferHandle payload, Callback::Callback<> * responseHandler); /** * @brief - * Request attribute reports from the device. The request constructed using the given encoder. Add a callback + * Request attribute reports from the device. Add a callback * handler, that'll be called when the reports are received from the device. * - * @param[in] requestEncoder The function that encodes the report request - * @param[in] maxCmdLen Maximum length expected for the encoded command - * @param[in] minInterval The minimum time interval between reports - * @param[in] maxInterval The maximum time interval between reports + * @param[in] payload The payload of the encoded command + * @param[in] responseHandler The handler function that's called on receiving command response * @param[in] reportHandler The handler function that's called on receiving attribute reports * The reporting handler continues to be called as long as the callback * is active. The user can stop the reporting by cancelling the callback. * Reference: chip::Callback::Cancel() */ - CHIP_ERROR RequestAttributeReporting(RequestEncoder requestEncoder, uint16_t maxCmdLen, uint16_t minInterval, - uint16_t maxInterval, Callback::Callback<> * reportHandler); + CHIP_ERROR RequestAttributeReporting(chip::System::PacketBufferHandle payload, Callback::Callback<> * responseHandler, + Callback::Callback<> * reportHandler); const ClusterId mClusterId; Device * mDevice; diff --git a/src/controller/CHIPClusters.cpp b/src/controller/CHIPClusters.cpp new file mode 100644 index 00000000000000..cb1296349f6ded --- /dev/null +++ b/src/controller/CHIPClusters.cpp @@ -0,0 +1,1238 @@ +/* + * + * 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 "CHIPClusters.h" + +#include + +namespace chip { +namespace Controller { + +// BarrierControl Cluster Commands +CHIP_ERROR BarrierControlCluster::BarrierControlGoToPercent(Callback::Callback<> * onCompletion, uint8_t percentOpen) +{ + System::PacketBufferHandle payload = encodeBarrierControlClusterBarrierControlGoToPercentCommand(mEndpoint, percentOpen); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR BarrierControlCluster::BarrierControlStop(Callback::Callback<> * onCompletion) +{ + System::PacketBufferHandle payload = encodeBarrierControlClusterBarrierControlStopCommand(mEndpoint); + return SendCommand(std::move(payload), onCompletion); +} + +// BarrierControl Cluster Attributes +CHIP_ERROR BarrierControlCluster::DiscoverAttributes(Callback::Callback<> * onCompletion) +{ + System::PacketBufferHandle payload = encodeBarrierControlClusterDiscoverAttributes(mEndpoint); + return SendCommand(std::move(payload), onCompletion); +} +CHIP_ERROR BarrierControlCluster::ReadAttributeBarrierMovingState(Callback::Callback<> * onCompletion) +{ + System::PacketBufferHandle payload = encodeBarrierControlClusterReadBarrierMovingStateAttribute(mEndpoint); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR BarrierControlCluster::ReadAttributeBarrierSafetyStatus(Callback::Callback<> * onCompletion) +{ + System::PacketBufferHandle payload = encodeBarrierControlClusterReadBarrierSafetyStatusAttribute(mEndpoint); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR BarrierControlCluster::ReadAttributeBarrierCapabilities(Callback::Callback<> * onCompletion) +{ + System::PacketBufferHandle payload = encodeBarrierControlClusterReadBarrierCapabilitiesAttribute(mEndpoint); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR BarrierControlCluster::ReadAttributeBarrierPosition(Callback::Callback<> * onCompletion) +{ + System::PacketBufferHandle payload = encodeBarrierControlClusterReadBarrierPositionAttribute(mEndpoint); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR BarrierControlCluster::ReadAttributeClusterRevision(Callback::Callback<> * onCompletion) +{ + System::PacketBufferHandle payload = encodeBarrierControlClusterReadClusterRevisionAttribute(mEndpoint); + return SendCommand(std::move(payload), onCompletion); +} + +// Basic Cluster Commands +CHIP_ERROR BasicCluster::MfgSpecificPing(Callback::Callback<> * onCompletion) +{ + System::PacketBufferHandle payload = encodeBasicClusterMfgSpecificPingCommand(mEndpoint); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR BasicCluster::ResetToFactoryDefaults(Callback::Callback<> * onCompletion) +{ + System::PacketBufferHandle payload = encodeBasicClusterResetToFactoryDefaultsCommand(mEndpoint); + return SendCommand(std::move(payload), onCompletion); +} + +// Basic Cluster Attributes +CHIP_ERROR BasicCluster::DiscoverAttributes(Callback::Callback<> * onCompletion) +{ + System::PacketBufferHandle payload = encodeBasicClusterDiscoverAttributes(mEndpoint); + return SendCommand(std::move(payload), onCompletion); +} +CHIP_ERROR BasicCluster::ReadAttributeZclVersion(Callback::Callback<> * onCompletion) +{ + System::PacketBufferHandle payload = encodeBasicClusterReadZclVersionAttribute(mEndpoint); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR BasicCluster::ReadAttributePowerSource(Callback::Callback<> * onCompletion) +{ + System::PacketBufferHandle payload = encodeBasicClusterReadPowerSourceAttribute(mEndpoint); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR BasicCluster::ReadAttributeClusterRevision(Callback::Callback<> * onCompletion) +{ + System::PacketBufferHandle payload = encodeBasicClusterReadClusterRevisionAttribute(mEndpoint); + return SendCommand(std::move(payload), onCompletion); +} + +// ColorControl Cluster Commands +CHIP_ERROR ColorControlCluster::MoveColor(Callback::Callback<> * onCompletion, int16_t rateX, int16_t rateY, uint8_t optionsMask, + uint8_t optionsOverride) +{ + System::PacketBufferHandle payload = + encodeColorControlClusterMoveColorCommand(mEndpoint, rateX, rateY, optionsMask, optionsOverride); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR ColorControlCluster::MoveColorTemperature(Callback::Callback<> * onCompletion, uint8_t moveMode, uint16_t rate, + uint16_t colorTemperatureMinimum, uint16_t colorTemperatureMaximum, + uint8_t optionsMask, uint8_t optionsOverride) +{ + System::PacketBufferHandle payload = encodeColorControlClusterMoveColorTemperatureCommand( + mEndpoint, moveMode, rate, colorTemperatureMinimum, colorTemperatureMaximum, optionsMask, optionsOverride); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR ColorControlCluster::MoveHue(Callback::Callback<> * onCompletion, uint8_t moveMode, uint8_t rate, uint8_t optionsMask, + uint8_t optionsOverride) +{ + System::PacketBufferHandle payload = + encodeColorControlClusterMoveHueCommand(mEndpoint, moveMode, rate, optionsMask, optionsOverride); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR ColorControlCluster::MoveSaturation(Callback::Callback<> * onCompletion, uint8_t moveMode, uint8_t rate, + uint8_t optionsMask, uint8_t optionsOverride) +{ + System::PacketBufferHandle payload = + encodeColorControlClusterMoveSaturationCommand(mEndpoint, moveMode, rate, optionsMask, optionsOverride); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR ColorControlCluster::MoveToColor(Callback::Callback<> * onCompletion, uint16_t colorX, uint16_t colorY, + uint16_t transitionTime, uint8_t optionsMask, uint8_t optionsOverride) +{ + System::PacketBufferHandle payload = + encodeColorControlClusterMoveToColorCommand(mEndpoint, colorX, colorY, transitionTime, optionsMask, optionsOverride); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR ColorControlCluster::MoveToColorTemperature(Callback::Callback<> * onCompletion, uint16_t colorTemperature, + uint16_t transitionTime, uint8_t optionsMask, uint8_t optionsOverride) +{ + System::PacketBufferHandle payload = encodeColorControlClusterMoveToColorTemperatureCommand( + mEndpoint, colorTemperature, transitionTime, optionsMask, optionsOverride); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR ColorControlCluster::MoveToHue(Callback::Callback<> * onCompletion, uint8_t hue, uint8_t direction, + uint16_t transitionTime, uint8_t optionsMask, uint8_t optionsOverride) +{ + System::PacketBufferHandle payload = + encodeColorControlClusterMoveToHueCommand(mEndpoint, hue, direction, transitionTime, optionsMask, optionsOverride); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR ColorControlCluster::MoveToHueAndSaturation(Callback::Callback<> * onCompletion, uint8_t hue, uint8_t saturation, + uint16_t transitionTime, uint8_t optionsMask, uint8_t optionsOverride) +{ + System::PacketBufferHandle payload = encodeColorControlClusterMoveToHueAndSaturationCommand( + mEndpoint, hue, saturation, transitionTime, optionsMask, optionsOverride); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR ColorControlCluster::MoveToSaturation(Callback::Callback<> * onCompletion, uint8_t saturation, uint16_t transitionTime, + uint8_t optionsMask, uint8_t optionsOverride) +{ + System::PacketBufferHandle payload = + encodeColorControlClusterMoveToSaturationCommand(mEndpoint, saturation, transitionTime, optionsMask, optionsOverride); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR ColorControlCluster::StepColor(Callback::Callback<> * onCompletion, int16_t stepX, int16_t stepY, + uint16_t transitionTime, uint8_t optionsMask, uint8_t optionsOverride) +{ + System::PacketBufferHandle payload = + encodeColorControlClusterStepColorCommand(mEndpoint, stepX, stepY, transitionTime, optionsMask, optionsOverride); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR ColorControlCluster::StepColorTemperature(Callback::Callback<> * onCompletion, uint8_t stepMode, uint16_t stepSize, + uint16_t transitionTime, uint16_t colorTemperatureMinimum, + uint16_t colorTemperatureMaximum, uint8_t optionsMask, uint8_t optionsOverride) +{ + System::PacketBufferHandle payload = + encodeColorControlClusterStepColorTemperatureCommand(mEndpoint, stepMode, stepSize, transitionTime, colorTemperatureMinimum, + colorTemperatureMaximum, optionsMask, optionsOverride); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR ColorControlCluster::StepHue(Callback::Callback<> * onCompletion, uint8_t stepMode, uint8_t stepSize, + uint8_t transitionTime, uint8_t optionsMask, uint8_t optionsOverride) +{ + System::PacketBufferHandle payload = + encodeColorControlClusterStepHueCommand(mEndpoint, stepMode, stepSize, transitionTime, optionsMask, optionsOverride); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR ColorControlCluster::StepSaturation(Callback::Callback<> * onCompletion, uint8_t stepMode, uint8_t stepSize, + uint8_t transitionTime, uint8_t optionsMask, uint8_t optionsOverride) +{ + System::PacketBufferHandle payload = + encodeColorControlClusterStepSaturationCommand(mEndpoint, stepMode, stepSize, transitionTime, optionsMask, optionsOverride); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR ColorControlCluster::StopMoveStep(Callback::Callback<> * onCompletion, uint8_t optionsMask, uint8_t optionsOverride) +{ + System::PacketBufferHandle payload = encodeColorControlClusterStopMoveStepCommand(mEndpoint, optionsMask, optionsOverride); + return SendCommand(std::move(payload), onCompletion); +} + +// ColorControl Cluster Attributes +CHIP_ERROR ColorControlCluster::DiscoverAttributes(Callback::Callback<> * onCompletion) +{ + System::PacketBufferHandle payload = encodeColorControlClusterDiscoverAttributes(mEndpoint); + return SendCommand(std::move(payload), onCompletion); +} +CHIP_ERROR ColorControlCluster::ReadAttributeCurrentHue(Callback::Callback<> * onCompletion) +{ + System::PacketBufferHandle payload = encodeColorControlClusterReadCurrentHueAttribute(mEndpoint); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR ColorControlCluster::ReportAttributeCurrentHue(Callback::Callback<> * onCompletion, Callback::Callback<> * onChange, + uint16_t minInterval, uint16_t maxInterval, uint8_t change) +{ + System::PacketBufferHandle payload = + encodeColorControlClusterReportCurrentHueAttribute(mEndpoint, minInterval, maxInterval, change); + return RequestAttributeReporting(std::move(payload), onCompletion, onChange); +} + +CHIP_ERROR ColorControlCluster::ReadAttributeCurrentSaturation(Callback::Callback<> * onCompletion) +{ + System::PacketBufferHandle payload = encodeColorControlClusterReadCurrentSaturationAttribute(mEndpoint); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR ColorControlCluster::ReportAttributeCurrentSaturation(Callback::Callback<> * onCompletion, + Callback::Callback<> * onChange, uint16_t minInterval, + uint16_t maxInterval, uint8_t change) +{ + System::PacketBufferHandle payload = + encodeColorControlClusterReportCurrentSaturationAttribute(mEndpoint, minInterval, maxInterval, change); + return RequestAttributeReporting(std::move(payload), onCompletion, onChange); +} + +CHIP_ERROR ColorControlCluster::ReadAttributeRemainingTime(Callback::Callback<> * onCompletion) +{ + System::PacketBufferHandle payload = encodeColorControlClusterReadRemainingTimeAttribute(mEndpoint); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR ColorControlCluster::ReadAttributeCurrentX(Callback::Callback<> * onCompletion) +{ + System::PacketBufferHandle payload = encodeColorControlClusterReadCurrentXAttribute(mEndpoint); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR ColorControlCluster::ReportAttributeCurrentX(Callback::Callback<> * onCompletion, Callback::Callback<> * onChange, + uint16_t minInterval, uint16_t maxInterval, uint16_t change) +{ + System::PacketBufferHandle payload = + encodeColorControlClusterReportCurrentXAttribute(mEndpoint, minInterval, maxInterval, change); + return RequestAttributeReporting(std::move(payload), onCompletion, onChange); +} + +CHIP_ERROR ColorControlCluster::ReadAttributeCurrentY(Callback::Callback<> * onCompletion) +{ + System::PacketBufferHandle payload = encodeColorControlClusterReadCurrentYAttribute(mEndpoint); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR ColorControlCluster::ReportAttributeCurrentY(Callback::Callback<> * onCompletion, Callback::Callback<> * onChange, + uint16_t minInterval, uint16_t maxInterval, uint16_t change) +{ + System::PacketBufferHandle payload = + encodeColorControlClusterReportCurrentYAttribute(mEndpoint, minInterval, maxInterval, change); + return RequestAttributeReporting(std::move(payload), onCompletion, onChange); +} + +CHIP_ERROR ColorControlCluster::ReadAttributeDriftCompensation(Callback::Callback<> * onCompletion) +{ + System::PacketBufferHandle payload = encodeColorControlClusterReadDriftCompensationAttribute(mEndpoint); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR ColorControlCluster::ReadAttributeCompensationText(Callback::Callback<> * onCompletion) +{ + System::PacketBufferHandle payload = encodeColorControlClusterReadCompensationTextAttribute(mEndpoint); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR ColorControlCluster::ReadAttributeColorTemperature(Callback::Callback<> * onCompletion) +{ + System::PacketBufferHandle payload = encodeColorControlClusterReadColorTemperatureAttribute(mEndpoint); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR ColorControlCluster::ReportAttributeColorTemperature(Callback::Callback<> * onCompletion, + Callback::Callback<> * onChange, uint16_t minInterval, + uint16_t maxInterval, uint16_t change) +{ + System::PacketBufferHandle payload = + encodeColorControlClusterReportColorTemperatureAttribute(mEndpoint, minInterval, maxInterval, change); + return RequestAttributeReporting(std::move(payload), onCompletion, onChange); +} + +CHIP_ERROR ColorControlCluster::ReadAttributeColorMode(Callback::Callback<> * onCompletion) +{ + System::PacketBufferHandle payload = encodeColorControlClusterReadColorModeAttribute(mEndpoint); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR ColorControlCluster::ReadAttributeColorControlOptions(Callback::Callback<> * onCompletion) +{ + System::PacketBufferHandle payload = encodeColorControlClusterReadColorControlOptionsAttribute(mEndpoint); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR ColorControlCluster::WriteAttributeColorControlOptions(Callback::Callback<> * onCompletion, uint8_t value) +{ + System::PacketBufferHandle payload = encodeColorControlClusterWriteColorControlOptionsAttribute(mEndpoint, value); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR ColorControlCluster::ReadAttributeNumberOfPrimaries(Callback::Callback<> * onCompletion) +{ + System::PacketBufferHandle payload = encodeColorControlClusterReadNumberOfPrimariesAttribute(mEndpoint); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR ColorControlCluster::ReadAttributePrimary1X(Callback::Callback<> * onCompletion) +{ + System::PacketBufferHandle payload = encodeColorControlClusterReadPrimary1XAttribute(mEndpoint); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR ColorControlCluster::ReadAttributePrimary1Y(Callback::Callback<> * onCompletion) +{ + System::PacketBufferHandle payload = encodeColorControlClusterReadPrimary1YAttribute(mEndpoint); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR ColorControlCluster::ReadAttributePrimary1Intensity(Callback::Callback<> * onCompletion) +{ + System::PacketBufferHandle payload = encodeColorControlClusterReadPrimary1IntensityAttribute(mEndpoint); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR ColorControlCluster::ReadAttributePrimary2X(Callback::Callback<> * onCompletion) +{ + System::PacketBufferHandle payload = encodeColorControlClusterReadPrimary2XAttribute(mEndpoint); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR ColorControlCluster::ReadAttributePrimary2Y(Callback::Callback<> * onCompletion) +{ + System::PacketBufferHandle payload = encodeColorControlClusterReadPrimary2YAttribute(mEndpoint); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR ColorControlCluster::ReadAttributePrimary2Intensity(Callback::Callback<> * onCompletion) +{ + System::PacketBufferHandle payload = encodeColorControlClusterReadPrimary2IntensityAttribute(mEndpoint); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR ColorControlCluster::ReadAttributePrimary3X(Callback::Callback<> * onCompletion) +{ + System::PacketBufferHandle payload = encodeColorControlClusterReadPrimary3XAttribute(mEndpoint); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR ColorControlCluster::ReadAttributePrimary3Y(Callback::Callback<> * onCompletion) +{ + System::PacketBufferHandle payload = encodeColorControlClusterReadPrimary3YAttribute(mEndpoint); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR ColorControlCluster::ReadAttributePrimary3Intensity(Callback::Callback<> * onCompletion) +{ + System::PacketBufferHandle payload = encodeColorControlClusterReadPrimary3IntensityAttribute(mEndpoint); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR ColorControlCluster::ReadAttributePrimary4X(Callback::Callback<> * onCompletion) +{ + System::PacketBufferHandle payload = encodeColorControlClusterReadPrimary4XAttribute(mEndpoint); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR ColorControlCluster::ReadAttributePrimary4Y(Callback::Callback<> * onCompletion) +{ + System::PacketBufferHandle payload = encodeColorControlClusterReadPrimary4YAttribute(mEndpoint); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR ColorControlCluster::ReadAttributePrimary4Intensity(Callback::Callback<> * onCompletion) +{ + System::PacketBufferHandle payload = encodeColorControlClusterReadPrimary4IntensityAttribute(mEndpoint); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR ColorControlCluster::ReadAttributePrimary5X(Callback::Callback<> * onCompletion) +{ + System::PacketBufferHandle payload = encodeColorControlClusterReadPrimary5XAttribute(mEndpoint); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR ColorControlCluster::ReadAttributePrimary5Y(Callback::Callback<> * onCompletion) +{ + System::PacketBufferHandle payload = encodeColorControlClusterReadPrimary5YAttribute(mEndpoint); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR ColorControlCluster::ReadAttributePrimary5Intensity(Callback::Callback<> * onCompletion) +{ + System::PacketBufferHandle payload = encodeColorControlClusterReadPrimary5IntensityAttribute(mEndpoint); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR ColorControlCluster::ReadAttributePrimary6X(Callback::Callback<> * onCompletion) +{ + System::PacketBufferHandle payload = encodeColorControlClusterReadPrimary6XAttribute(mEndpoint); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR ColorControlCluster::ReadAttributePrimary6Y(Callback::Callback<> * onCompletion) +{ + System::PacketBufferHandle payload = encodeColorControlClusterReadPrimary6YAttribute(mEndpoint); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR ColorControlCluster::ReadAttributePrimary6Intensity(Callback::Callback<> * onCompletion) +{ + System::PacketBufferHandle payload = encodeColorControlClusterReadPrimary6IntensityAttribute(mEndpoint); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR ColorControlCluster::ReadAttributeWhitePointX(Callback::Callback<> * onCompletion) +{ + System::PacketBufferHandle payload = encodeColorControlClusterReadWhitePointXAttribute(mEndpoint); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR ColorControlCluster::WriteAttributeWhitePointX(Callback::Callback<> * onCompletion, uint16_t value) +{ + System::PacketBufferHandle payload = encodeColorControlClusterWriteWhitePointXAttribute(mEndpoint, value); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR ColorControlCluster::ReadAttributeWhitePointY(Callback::Callback<> * onCompletion) +{ + System::PacketBufferHandle payload = encodeColorControlClusterReadWhitePointYAttribute(mEndpoint); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR ColorControlCluster::WriteAttributeWhitePointY(Callback::Callback<> * onCompletion, uint16_t value) +{ + System::PacketBufferHandle payload = encodeColorControlClusterWriteWhitePointYAttribute(mEndpoint, value); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR ColorControlCluster::ReadAttributeColorPointRX(Callback::Callback<> * onCompletion) +{ + System::PacketBufferHandle payload = encodeColorControlClusterReadColorPointRXAttribute(mEndpoint); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR ColorControlCluster::WriteAttributeColorPointRX(Callback::Callback<> * onCompletion, uint16_t value) +{ + System::PacketBufferHandle payload = encodeColorControlClusterWriteColorPointRXAttribute(mEndpoint, value); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR ColorControlCluster::ReadAttributeColorPointRY(Callback::Callback<> * onCompletion) +{ + System::PacketBufferHandle payload = encodeColorControlClusterReadColorPointRYAttribute(mEndpoint); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR ColorControlCluster::WriteAttributeColorPointRY(Callback::Callback<> * onCompletion, uint16_t value) +{ + System::PacketBufferHandle payload = encodeColorControlClusterWriteColorPointRYAttribute(mEndpoint, value); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR ColorControlCluster::ReadAttributeColorPointRIntensity(Callback::Callback<> * onCompletion) +{ + System::PacketBufferHandle payload = encodeColorControlClusterReadColorPointRIntensityAttribute(mEndpoint); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR ColorControlCluster::WriteAttributeColorPointRIntensity(Callback::Callback<> * onCompletion, uint8_t value) +{ + System::PacketBufferHandle payload = encodeColorControlClusterWriteColorPointRIntensityAttribute(mEndpoint, value); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR ColorControlCluster::ReadAttributeColorPointGX(Callback::Callback<> * onCompletion) +{ + System::PacketBufferHandle payload = encodeColorControlClusterReadColorPointGXAttribute(mEndpoint); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR ColorControlCluster::WriteAttributeColorPointGX(Callback::Callback<> * onCompletion, uint16_t value) +{ + System::PacketBufferHandle payload = encodeColorControlClusterWriteColorPointGXAttribute(mEndpoint, value); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR ColorControlCluster::ReadAttributeColorPointGY(Callback::Callback<> * onCompletion) +{ + System::PacketBufferHandle payload = encodeColorControlClusterReadColorPointGYAttribute(mEndpoint); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR ColorControlCluster::WriteAttributeColorPointGY(Callback::Callback<> * onCompletion, uint16_t value) +{ + System::PacketBufferHandle payload = encodeColorControlClusterWriteColorPointGYAttribute(mEndpoint, value); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR ColorControlCluster::ReadAttributeColorPointGIntensity(Callback::Callback<> * onCompletion) +{ + System::PacketBufferHandle payload = encodeColorControlClusterReadColorPointGIntensityAttribute(mEndpoint); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR ColorControlCluster::WriteAttributeColorPointGIntensity(Callback::Callback<> * onCompletion, uint8_t value) +{ + System::PacketBufferHandle payload = encodeColorControlClusterWriteColorPointGIntensityAttribute(mEndpoint, value); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR ColorControlCluster::ReadAttributeColorPointBX(Callback::Callback<> * onCompletion) +{ + System::PacketBufferHandle payload = encodeColorControlClusterReadColorPointBXAttribute(mEndpoint); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR ColorControlCluster::WriteAttributeColorPointBX(Callback::Callback<> * onCompletion, uint16_t value) +{ + System::PacketBufferHandle payload = encodeColorControlClusterWriteColorPointBXAttribute(mEndpoint, value); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR ColorControlCluster::ReadAttributeColorPointBY(Callback::Callback<> * onCompletion) +{ + System::PacketBufferHandle payload = encodeColorControlClusterReadColorPointBYAttribute(mEndpoint); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR ColorControlCluster::WriteAttributeColorPointBY(Callback::Callback<> * onCompletion, uint16_t value) +{ + System::PacketBufferHandle payload = encodeColorControlClusterWriteColorPointBYAttribute(mEndpoint, value); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR ColorControlCluster::ReadAttributeColorPointBIntensity(Callback::Callback<> * onCompletion) +{ + System::PacketBufferHandle payload = encodeColorControlClusterReadColorPointBIntensityAttribute(mEndpoint); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR ColorControlCluster::WriteAttributeColorPointBIntensity(Callback::Callback<> * onCompletion, uint8_t value) +{ + System::PacketBufferHandle payload = encodeColorControlClusterWriteColorPointBIntensityAttribute(mEndpoint, value); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR ColorControlCluster::ReadAttributeEnhancedCurrentHue(Callback::Callback<> * onCompletion) +{ + System::PacketBufferHandle payload = encodeColorControlClusterReadEnhancedCurrentHueAttribute(mEndpoint); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR ColorControlCluster::ReadAttributeEnhancedColorMode(Callback::Callback<> * onCompletion) +{ + System::PacketBufferHandle payload = encodeColorControlClusterReadEnhancedColorModeAttribute(mEndpoint); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR ColorControlCluster::ReadAttributeColorLoopActive(Callback::Callback<> * onCompletion) +{ + System::PacketBufferHandle payload = encodeColorControlClusterReadColorLoopActiveAttribute(mEndpoint); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR ColorControlCluster::ReadAttributeColorLoopDirection(Callback::Callback<> * onCompletion) +{ + System::PacketBufferHandle payload = encodeColorControlClusterReadColorLoopDirectionAttribute(mEndpoint); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR ColorControlCluster::ReadAttributeColorLoopTime(Callback::Callback<> * onCompletion) +{ + System::PacketBufferHandle payload = encodeColorControlClusterReadColorLoopTimeAttribute(mEndpoint); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR ColorControlCluster::ReadAttributeColorCapabilities(Callback::Callback<> * onCompletion) +{ + System::PacketBufferHandle payload = encodeColorControlClusterReadColorCapabilitiesAttribute(mEndpoint); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR ColorControlCluster::ReadAttributeColorTempPhysicalMin(Callback::Callback<> * onCompletion) +{ + System::PacketBufferHandle payload = encodeColorControlClusterReadColorTempPhysicalMinAttribute(mEndpoint); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR ColorControlCluster::ReadAttributeColorTempPhysicalMax(Callback::Callback<> * onCompletion) +{ + System::PacketBufferHandle payload = encodeColorControlClusterReadColorTempPhysicalMaxAttribute(mEndpoint); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR ColorControlCluster::ReadAttributeCoupleColorTempToLevelMinMireds(Callback::Callback<> * onCompletion) +{ + System::PacketBufferHandle payload = encodeColorControlClusterReadCoupleColorTempToLevelMinMiredsAttribute(mEndpoint); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR ColorControlCluster::ReadAttributeStartUpColorTemperatureMireds(Callback::Callback<> * onCompletion) +{ + System::PacketBufferHandle payload = encodeColorControlClusterReadStartUpColorTemperatureMiredsAttribute(mEndpoint); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR ColorControlCluster::WriteAttributeStartUpColorTemperatureMireds(Callback::Callback<> * onCompletion, uint16_t value) +{ + System::PacketBufferHandle payload = encodeColorControlClusterWriteStartUpColorTemperatureMiredsAttribute(mEndpoint, value); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR ColorControlCluster::ReadAttributeClusterRevision(Callback::Callback<> * onCompletion) +{ + System::PacketBufferHandle payload = encodeColorControlClusterReadClusterRevisionAttribute(mEndpoint); + return SendCommand(std::move(payload), onCompletion); +} + +// DoorLock Cluster Commands +CHIP_ERROR DoorLockCluster::ClearAllPins(Callback::Callback<> * onCompletion) +{ + System::PacketBufferHandle payload = encodeDoorLockClusterClearAllPinsCommand(mEndpoint); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR DoorLockCluster::ClearAllRfids(Callback::Callback<> * onCompletion) +{ + System::PacketBufferHandle payload = encodeDoorLockClusterClearAllRfidsCommand(mEndpoint); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR DoorLockCluster::ClearHolidaySchedule(Callback::Callback<> * onCompletion, uint8_t scheduleId) +{ + System::PacketBufferHandle payload = encodeDoorLockClusterClearHolidayScheduleCommand(mEndpoint, scheduleId); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR DoorLockCluster::ClearPin(Callback::Callback<> * onCompletion, uint16_t userId) +{ + System::PacketBufferHandle payload = encodeDoorLockClusterClearPinCommand(mEndpoint, userId); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR DoorLockCluster::ClearRfid(Callback::Callback<> * onCompletion, uint16_t userId) +{ + System::PacketBufferHandle payload = encodeDoorLockClusterClearRfidCommand(mEndpoint, userId); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR DoorLockCluster::ClearWeekdaySchedule(Callback::Callback<> * onCompletion, uint8_t scheduleId, uint16_t userId) +{ + System::PacketBufferHandle payload = encodeDoorLockClusterClearWeekdayScheduleCommand(mEndpoint, scheduleId, userId); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR DoorLockCluster::ClearYeardaySchedule(Callback::Callback<> * onCompletion, uint8_t scheduleId, uint16_t userId) +{ + System::PacketBufferHandle payload = encodeDoorLockClusterClearYeardayScheduleCommand(mEndpoint, scheduleId, userId); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR DoorLockCluster::GetHolidaySchedule(Callback::Callback<> * onCompletion, uint8_t scheduleId) +{ + System::PacketBufferHandle payload = encodeDoorLockClusterGetHolidayScheduleCommand(mEndpoint, scheduleId); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR DoorLockCluster::GetLogRecord(Callback::Callback<> * onCompletion, uint16_t logIndex) +{ + System::PacketBufferHandle payload = encodeDoorLockClusterGetLogRecordCommand(mEndpoint, logIndex); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR DoorLockCluster::GetPin(Callback::Callback<> * onCompletion, uint16_t userId) +{ + System::PacketBufferHandle payload = encodeDoorLockClusterGetPinCommand(mEndpoint, userId); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR DoorLockCluster::GetRfid(Callback::Callback<> * onCompletion, uint16_t userId) +{ + System::PacketBufferHandle payload = encodeDoorLockClusterGetRfidCommand(mEndpoint, userId); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR DoorLockCluster::GetUserType(Callback::Callback<> * onCompletion, uint16_t userId) +{ + System::PacketBufferHandle payload = encodeDoorLockClusterGetUserTypeCommand(mEndpoint, userId); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR DoorLockCluster::GetWeekdaySchedule(Callback::Callback<> * onCompletion, uint8_t scheduleId, uint16_t userId) +{ + System::PacketBufferHandle payload = encodeDoorLockClusterGetWeekdayScheduleCommand(mEndpoint, scheduleId, userId); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR DoorLockCluster::GetYeardaySchedule(Callback::Callback<> * onCompletion, uint8_t scheduleId, uint16_t userId) +{ + System::PacketBufferHandle payload = encodeDoorLockClusterGetYeardayScheduleCommand(mEndpoint, scheduleId, userId); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR DoorLockCluster::LockDoor(Callback::Callback<> * onCompletion, char * pin) +{ + System::PacketBufferHandle payload = encodeDoorLockClusterLockDoorCommand(mEndpoint, pin); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR DoorLockCluster::SetHolidaySchedule(Callback::Callback<> * onCompletion, uint8_t scheduleId, uint32_t localStartTime, + uint32_t localEndTime, uint8_t operatingModeDuringHoliday) +{ + System::PacketBufferHandle payload = encodeDoorLockClusterSetHolidayScheduleCommand(mEndpoint, scheduleId, localStartTime, + localEndTime, operatingModeDuringHoliday); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR DoorLockCluster::SetPin(Callback::Callback<> * onCompletion, uint16_t userId, uint8_t userStatus, uint8_t userType, + char * pin) +{ + System::PacketBufferHandle payload = encodeDoorLockClusterSetPinCommand(mEndpoint, userId, userStatus, userType, pin); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR DoorLockCluster::SetRfid(Callback::Callback<> * onCompletion, uint16_t userId, uint8_t userStatus, uint8_t userType, + char * id) +{ + System::PacketBufferHandle payload = encodeDoorLockClusterSetRfidCommand(mEndpoint, userId, userStatus, userType, id); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR DoorLockCluster::SetUserType(Callback::Callback<> * onCompletion, uint16_t userId, uint8_t userType) +{ + System::PacketBufferHandle payload = encodeDoorLockClusterSetUserTypeCommand(mEndpoint, userId, userType); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR DoorLockCluster::SetWeekdaySchedule(Callback::Callback<> * onCompletion, uint8_t scheduleId, uint16_t userId, + uint8_t daysMask, uint8_t startHour, uint8_t startMinute, uint8_t endHour, + uint8_t endMinute) +{ + System::PacketBufferHandle payload = encodeDoorLockClusterSetWeekdayScheduleCommand(mEndpoint, scheduleId, userId, daysMask, + startHour, startMinute, endHour, endMinute); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR DoorLockCluster::SetYeardaySchedule(Callback::Callback<> * onCompletion, uint8_t scheduleId, uint16_t userId, + uint32_t localStartTime, uint32_t localEndTime) +{ + System::PacketBufferHandle payload = + encodeDoorLockClusterSetYeardayScheduleCommand(mEndpoint, scheduleId, userId, localStartTime, localEndTime); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR DoorLockCluster::UnlockDoor(Callback::Callback<> * onCompletion, char * pin) +{ + System::PacketBufferHandle payload = encodeDoorLockClusterUnlockDoorCommand(mEndpoint, pin); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR DoorLockCluster::UnlockWithTimeout(Callback::Callback<> * onCompletion, uint16_t timeoutInSeconds, char * pin) +{ + System::PacketBufferHandle payload = encodeDoorLockClusterUnlockWithTimeoutCommand(mEndpoint, timeoutInSeconds, pin); + return SendCommand(std::move(payload), onCompletion); +} + +// DoorLock Cluster Attributes +CHIP_ERROR DoorLockCluster::DiscoverAttributes(Callback::Callback<> * onCompletion) +{ + System::PacketBufferHandle payload = encodeDoorLockClusterDiscoverAttributes(mEndpoint); + return SendCommand(std::move(payload), onCompletion); +} +CHIP_ERROR DoorLockCluster::ReadAttributeLockState(Callback::Callback<> * onCompletion) +{ + System::PacketBufferHandle payload = encodeDoorLockClusterReadLockStateAttribute(mEndpoint); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR DoorLockCluster::ReportAttributeLockState(Callback::Callback<> * onCompletion, Callback::Callback<> * onChange, + uint16_t minInterval, uint16_t maxInterval) +{ + System::PacketBufferHandle payload = encodeDoorLockClusterReportLockStateAttribute(mEndpoint, minInterval, maxInterval); + return RequestAttributeReporting(std::move(payload), onCompletion, onChange); +} + +CHIP_ERROR DoorLockCluster::ReadAttributeLockType(Callback::Callback<> * onCompletion) +{ + System::PacketBufferHandle payload = encodeDoorLockClusterReadLockTypeAttribute(mEndpoint); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR DoorLockCluster::ReadAttributeActuatorEnabled(Callback::Callback<> * onCompletion) +{ + System::PacketBufferHandle payload = encodeDoorLockClusterReadActuatorEnabledAttribute(mEndpoint); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR DoorLockCluster::ReadAttributeClusterRevision(Callback::Callback<> * onCompletion) +{ + System::PacketBufferHandle payload = encodeDoorLockClusterReadClusterRevisionAttribute(mEndpoint); + return SendCommand(std::move(payload), onCompletion); +} + +// Groups Cluster Commands +CHIP_ERROR GroupsCluster::AddGroup(Callback::Callback<> * onCompletion, uint16_t groupId, char * groupName) +{ + System::PacketBufferHandle payload = encodeGroupsClusterAddGroupCommand(mEndpoint, groupId, groupName); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR GroupsCluster::AddGroupIfIdentifying(Callback::Callback<> * onCompletion, uint16_t groupId, char * groupName) +{ + System::PacketBufferHandle payload = encodeGroupsClusterAddGroupIfIdentifyingCommand(mEndpoint, groupId, groupName); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR GroupsCluster::GetGroupMembership(Callback::Callback<> * onCompletion, uint8_t groupCount, uint16_t groupList) +{ + System::PacketBufferHandle payload = encodeGroupsClusterGetGroupMembershipCommand(mEndpoint, groupCount, groupList); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR GroupsCluster::RemoveAllGroups(Callback::Callback<> * onCompletion) +{ + System::PacketBufferHandle payload = encodeGroupsClusterRemoveAllGroupsCommand(mEndpoint); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR GroupsCluster::RemoveGroup(Callback::Callback<> * onCompletion, uint16_t groupId) +{ + System::PacketBufferHandle payload = encodeGroupsClusterRemoveGroupCommand(mEndpoint, groupId); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR GroupsCluster::ViewGroup(Callback::Callback<> * onCompletion, uint16_t groupId) +{ + System::PacketBufferHandle payload = encodeGroupsClusterViewGroupCommand(mEndpoint, groupId); + return SendCommand(std::move(payload), onCompletion); +} + +// Groups Cluster Attributes +CHIP_ERROR GroupsCluster::DiscoverAttributes(Callback::Callback<> * onCompletion) +{ + System::PacketBufferHandle payload = encodeGroupsClusterDiscoverAttributes(mEndpoint); + return SendCommand(std::move(payload), onCompletion); +} +CHIP_ERROR GroupsCluster::ReadAttributeNameSupport(Callback::Callback<> * onCompletion) +{ + System::PacketBufferHandle payload = encodeGroupsClusterReadNameSupportAttribute(mEndpoint); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR GroupsCluster::ReadAttributeClusterRevision(Callback::Callback<> * onCompletion) +{ + System::PacketBufferHandle payload = encodeGroupsClusterReadClusterRevisionAttribute(mEndpoint); + return SendCommand(std::move(payload), onCompletion); +} + +// IasZone Cluster Commands +// IasZone Cluster Attributes +CHIP_ERROR IasZoneCluster::DiscoverAttributes(Callback::Callback<> * onCompletion) +{ + System::PacketBufferHandle payload = encodeIasZoneClusterDiscoverAttributes(mEndpoint); + return SendCommand(std::move(payload), onCompletion); +} +CHIP_ERROR IasZoneCluster::ReadAttributeZoneState(Callback::Callback<> * onCompletion) +{ + System::PacketBufferHandle payload = encodeIasZoneClusterReadZoneStateAttribute(mEndpoint); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR IasZoneCluster::ReadAttributeZoneType(Callback::Callback<> * onCompletion) +{ + System::PacketBufferHandle payload = encodeIasZoneClusterReadZoneTypeAttribute(mEndpoint); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR IasZoneCluster::ReadAttributeZoneStatus(Callback::Callback<> * onCompletion) +{ + System::PacketBufferHandle payload = encodeIasZoneClusterReadZoneStatusAttribute(mEndpoint); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR IasZoneCluster::ReadAttributeIasCieAddress(Callback::Callback<> * onCompletion) +{ + System::PacketBufferHandle payload = encodeIasZoneClusterReadIasCieAddressAttribute(mEndpoint); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR IasZoneCluster::WriteAttributeIasCieAddress(Callback::Callback<> * onCompletion, uint64_t value) +{ + System::PacketBufferHandle payload = encodeIasZoneClusterWriteIasCieAddressAttribute(mEndpoint, value); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR IasZoneCluster::ReadAttributeZoneId(Callback::Callback<> * onCompletion) +{ + System::PacketBufferHandle payload = encodeIasZoneClusterReadZoneIdAttribute(mEndpoint); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR IasZoneCluster::ReadAttributeClusterRevision(Callback::Callback<> * onCompletion) +{ + System::PacketBufferHandle payload = encodeIasZoneClusterReadClusterRevisionAttribute(mEndpoint); + return SendCommand(std::move(payload), onCompletion); +} + +// Identify Cluster Commands +CHIP_ERROR IdentifyCluster::Identify(Callback::Callback<> * onCompletion, uint16_t identifyTime) +{ + System::PacketBufferHandle payload = encodeIdentifyClusterIdentifyCommand(mEndpoint, identifyTime); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR IdentifyCluster::IdentifyQuery(Callback::Callback<> * onCompletion) +{ + System::PacketBufferHandle payload = encodeIdentifyClusterIdentifyQueryCommand(mEndpoint); + return SendCommand(std::move(payload), onCompletion); +} + +// Identify Cluster Attributes +CHIP_ERROR IdentifyCluster::DiscoverAttributes(Callback::Callback<> * onCompletion) +{ + System::PacketBufferHandle payload = encodeIdentifyClusterDiscoverAttributes(mEndpoint); + return SendCommand(std::move(payload), onCompletion); +} +CHIP_ERROR IdentifyCluster::ReadAttributeIdentifyTime(Callback::Callback<> * onCompletion) +{ + System::PacketBufferHandle payload = encodeIdentifyClusterReadIdentifyTimeAttribute(mEndpoint); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR IdentifyCluster::WriteAttributeIdentifyTime(Callback::Callback<> * onCompletion, uint16_t value) +{ + System::PacketBufferHandle payload = encodeIdentifyClusterWriteIdentifyTimeAttribute(mEndpoint, value); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR IdentifyCluster::ReadAttributeClusterRevision(Callback::Callback<> * onCompletion) +{ + System::PacketBufferHandle payload = encodeIdentifyClusterReadClusterRevisionAttribute(mEndpoint); + return SendCommand(std::move(payload), onCompletion); +} + +// LevelControl Cluster Commands +CHIP_ERROR LevelControlCluster::Move(Callback::Callback<> * onCompletion, uint8_t moveMode, uint8_t rate, uint8_t optionMask, + uint8_t optionOverride) +{ + System::PacketBufferHandle payload = + encodeLevelControlClusterMoveCommand(mEndpoint, moveMode, rate, optionMask, optionOverride); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR LevelControlCluster::MoveToLevel(Callback::Callback<> * onCompletion, uint8_t level, uint16_t transitionTime, + uint8_t optionMask, uint8_t optionOverride) +{ + System::PacketBufferHandle payload = + encodeLevelControlClusterMoveToLevelCommand(mEndpoint, level, transitionTime, optionMask, optionOverride); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR LevelControlCluster::MoveToLevelWithOnOff(Callback::Callback<> * onCompletion, uint8_t level, uint16_t transitionTime) +{ + System::PacketBufferHandle payload = encodeLevelControlClusterMoveToLevelWithOnOffCommand(mEndpoint, level, transitionTime); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR LevelControlCluster::MoveWithOnOff(Callback::Callback<> * onCompletion, uint8_t moveMode, uint8_t rate) +{ + System::PacketBufferHandle payload = encodeLevelControlClusterMoveWithOnOffCommand(mEndpoint, moveMode, rate); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR LevelControlCluster::Step(Callback::Callback<> * onCompletion, uint8_t stepMode, uint8_t stepSize, + uint16_t transitionTime, uint8_t optionMask, uint8_t optionOverride) +{ + System::PacketBufferHandle payload = + encodeLevelControlClusterStepCommand(mEndpoint, stepMode, stepSize, transitionTime, optionMask, optionOverride); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR LevelControlCluster::StepWithOnOff(Callback::Callback<> * onCompletion, uint8_t stepMode, uint8_t stepSize, + uint16_t transitionTime) +{ + System::PacketBufferHandle payload = + encodeLevelControlClusterStepWithOnOffCommand(mEndpoint, stepMode, stepSize, transitionTime); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR LevelControlCluster::Stop(Callback::Callback<> * onCompletion, uint8_t optionMask, uint8_t optionOverride) +{ + System::PacketBufferHandle payload = encodeLevelControlClusterStopCommand(mEndpoint, optionMask, optionOverride); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR LevelControlCluster::StopWithOnOff(Callback::Callback<> * onCompletion) +{ + System::PacketBufferHandle payload = encodeLevelControlClusterStopWithOnOffCommand(mEndpoint); + return SendCommand(std::move(payload), onCompletion); +} + +// LevelControl Cluster Attributes +CHIP_ERROR LevelControlCluster::DiscoverAttributes(Callback::Callback<> * onCompletion) +{ + System::PacketBufferHandle payload = encodeLevelControlClusterDiscoverAttributes(mEndpoint); + return SendCommand(std::move(payload), onCompletion); +} +CHIP_ERROR LevelControlCluster::ReadAttributeCurrentLevel(Callback::Callback<> * onCompletion) +{ + System::PacketBufferHandle payload = encodeLevelControlClusterReadCurrentLevelAttribute(mEndpoint); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR LevelControlCluster::ReportAttributeCurrentLevel(Callback::Callback<> * onCompletion, Callback::Callback<> * onChange, + uint16_t minInterval, uint16_t maxInterval, uint8_t change) +{ + System::PacketBufferHandle payload = + encodeLevelControlClusterReportCurrentLevelAttribute(mEndpoint, minInterval, maxInterval, change); + return RequestAttributeReporting(std::move(payload), onCompletion, onChange); +} + +CHIP_ERROR LevelControlCluster::ReadAttributeClusterRevision(Callback::Callback<> * onCompletion) +{ + System::PacketBufferHandle payload = encodeLevelControlClusterReadClusterRevisionAttribute(mEndpoint); + return SendCommand(std::move(payload), onCompletion); +} + +// OnOff Cluster Commands +CHIP_ERROR OnOffCluster::Off(Callback::Callback<> * onCompletion) +{ + System::PacketBufferHandle payload = encodeOnOffClusterOffCommand(mEndpoint); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR OnOffCluster::On(Callback::Callback<> * onCompletion) +{ + System::PacketBufferHandle payload = encodeOnOffClusterOnCommand(mEndpoint); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR OnOffCluster::Toggle(Callback::Callback<> * onCompletion) +{ + System::PacketBufferHandle payload = encodeOnOffClusterToggleCommand(mEndpoint); + return SendCommand(std::move(payload), onCompletion); +} + +// OnOff Cluster Attributes +CHIP_ERROR OnOffCluster::DiscoverAttributes(Callback::Callback<> * onCompletion) +{ + System::PacketBufferHandle payload = encodeOnOffClusterDiscoverAttributes(mEndpoint); + return SendCommand(std::move(payload), onCompletion); +} +CHIP_ERROR OnOffCluster::ReadAttributeOnOff(Callback::Callback<> * onCompletion) +{ + System::PacketBufferHandle payload = encodeOnOffClusterReadOnOffAttribute(mEndpoint); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR OnOffCluster::ReportAttributeOnOff(Callback::Callback<> * onCompletion, Callback::Callback<> * onChange, + uint16_t minInterval, uint16_t maxInterval) +{ + System::PacketBufferHandle payload = encodeOnOffClusterReportOnOffAttribute(mEndpoint, minInterval, maxInterval); + return RequestAttributeReporting(std::move(payload), onCompletion, onChange); +} + +CHIP_ERROR OnOffCluster::ReadAttributeClusterRevision(Callback::Callback<> * onCompletion) +{ + System::PacketBufferHandle payload = encodeOnOffClusterReadClusterRevisionAttribute(mEndpoint); + return SendCommand(std::move(payload), onCompletion); +} + +// Scenes Cluster Commands +CHIP_ERROR ScenesCluster::AddScene(Callback::Callback<> * onCompletion, uint16_t groupId, uint8_t sceneId, uint16_t transitionTime, + char * sceneName, chip::ClusterId clusterId, uint8_t length, uint8_t value) +{ + System::PacketBufferHandle payload = + encodeScenesClusterAddSceneCommand(mEndpoint, groupId, sceneId, transitionTime, sceneName, clusterId, length, value); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR ScenesCluster::GetSceneMembership(Callback::Callback<> * onCompletion, uint16_t groupId) +{ + System::PacketBufferHandle payload = encodeScenesClusterGetSceneMembershipCommand(mEndpoint, groupId); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR ScenesCluster::RecallScene(Callback::Callback<> * onCompletion, uint16_t groupId, uint8_t sceneId, + uint16_t transitionTime) +{ + System::PacketBufferHandle payload = encodeScenesClusterRecallSceneCommand(mEndpoint, groupId, sceneId, transitionTime); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR ScenesCluster::RemoveAllScenes(Callback::Callback<> * onCompletion, uint16_t groupId) +{ + System::PacketBufferHandle payload = encodeScenesClusterRemoveAllScenesCommand(mEndpoint, groupId); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR ScenesCluster::RemoveScene(Callback::Callback<> * onCompletion, uint16_t groupId, uint8_t sceneId) +{ + System::PacketBufferHandle payload = encodeScenesClusterRemoveSceneCommand(mEndpoint, groupId, sceneId); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR ScenesCluster::StoreScene(Callback::Callback<> * onCompletion, uint16_t groupId, uint8_t sceneId) +{ + System::PacketBufferHandle payload = encodeScenesClusterStoreSceneCommand(mEndpoint, groupId, sceneId); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR ScenesCluster::ViewScene(Callback::Callback<> * onCompletion, uint16_t groupId, uint8_t sceneId) +{ + System::PacketBufferHandle payload = encodeScenesClusterViewSceneCommand(mEndpoint, groupId, sceneId); + return SendCommand(std::move(payload), onCompletion); +} + +// Scenes Cluster Attributes +CHIP_ERROR ScenesCluster::DiscoverAttributes(Callback::Callback<> * onCompletion) +{ + System::PacketBufferHandle payload = encodeScenesClusterDiscoverAttributes(mEndpoint); + return SendCommand(std::move(payload), onCompletion); +} +CHIP_ERROR ScenesCluster::ReadAttributeSceneCount(Callback::Callback<> * onCompletion) +{ + System::PacketBufferHandle payload = encodeScenesClusterReadSceneCountAttribute(mEndpoint); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR ScenesCluster::ReadAttributeCurrentScene(Callback::Callback<> * onCompletion) +{ + System::PacketBufferHandle payload = encodeScenesClusterReadCurrentSceneAttribute(mEndpoint); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR ScenesCluster::ReadAttributeCurrentGroup(Callback::Callback<> * onCompletion) +{ + System::PacketBufferHandle payload = encodeScenesClusterReadCurrentGroupAttribute(mEndpoint); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR ScenesCluster::ReadAttributeSceneValid(Callback::Callback<> * onCompletion) +{ + System::PacketBufferHandle payload = encodeScenesClusterReadSceneValidAttribute(mEndpoint); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR ScenesCluster::ReadAttributeNameSupport(Callback::Callback<> * onCompletion) +{ + System::PacketBufferHandle payload = encodeScenesClusterReadNameSupportAttribute(mEndpoint); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR ScenesCluster::ReadAttributeClusterRevision(Callback::Callback<> * onCompletion) +{ + System::PacketBufferHandle payload = encodeScenesClusterReadClusterRevisionAttribute(mEndpoint); + return SendCommand(std::move(payload), onCompletion); +} + +// TemperatureMeasurement Cluster Commands +// TemperatureMeasurement Cluster Attributes +CHIP_ERROR TemperatureMeasurementCluster::DiscoverAttributes(Callback::Callback<> * onCompletion) +{ + System::PacketBufferHandle payload = encodeTemperatureMeasurementClusterDiscoverAttributes(mEndpoint); + return SendCommand(std::move(payload), onCompletion); +} +CHIP_ERROR TemperatureMeasurementCluster::ReadAttributeMeasuredValue(Callback::Callback<> * onCompletion) +{ + System::PacketBufferHandle payload = encodeTemperatureMeasurementClusterReadMeasuredValueAttribute(mEndpoint); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR TemperatureMeasurementCluster::ReportAttributeMeasuredValue(Callback::Callback<> * onCompletion, + Callback::Callback<> * onChange, uint16_t minInterval, + uint16_t maxInterval, int16_t change) +{ + System::PacketBufferHandle payload = + encodeTemperatureMeasurementClusterReportMeasuredValueAttribute(mEndpoint, minInterval, maxInterval, change); + return RequestAttributeReporting(std::move(payload), onCompletion, onChange); +} + +CHIP_ERROR TemperatureMeasurementCluster::ReadAttributeMinMeasuredValue(Callback::Callback<> * onCompletion) +{ + System::PacketBufferHandle payload = encodeTemperatureMeasurementClusterReadMinMeasuredValueAttribute(mEndpoint); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR TemperatureMeasurementCluster::ReadAttributeMaxMeasuredValue(Callback::Callback<> * onCompletion) +{ + System::PacketBufferHandle payload = encodeTemperatureMeasurementClusterReadMaxMeasuredValueAttribute(mEndpoint); + return SendCommand(std::move(payload), onCompletion); +} + +CHIP_ERROR TemperatureMeasurementCluster::ReadAttributeClusterRevision(Callback::Callback<> * onCompletion) +{ + System::PacketBufferHandle payload = encodeTemperatureMeasurementClusterReadClusterRevisionAttribute(mEndpoint); + return SendCommand(std::move(payload), onCompletion); +} + +} // namespace Controller +} // namespace chip diff --git a/src/controller/CHIPClusters.h b/src/controller/CHIPClusters.h new file mode 100644 index 00000000000000..7fc363280d2f04 --- /dev/null +++ b/src/controller/CHIPClusters.h @@ -0,0 +1,377 @@ +/* + * + * 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. + */ + +// Prevent multiple inclusion +#pragma once + +#include +#include + +namespace chip { +namespace Controller { + +constexpr ClusterId kBarrierControlClusterId = 0x0103; +constexpr ClusterId kBasicClusterId = 0x0000; +constexpr ClusterId kColorControlClusterId = 0x0300; +constexpr ClusterId kDoorLockClusterId = 0x0101; +constexpr ClusterId kGroupsClusterId = 0x0004; +constexpr ClusterId kIasZoneClusterId = 0x0500; +constexpr ClusterId kIdentifyClusterId = 0x0003; +constexpr ClusterId kLevelControlClusterId = 0x0008; +constexpr ClusterId kOnOffClusterId = 0x0006; +constexpr ClusterId kScenesClusterId = 0x0005; +constexpr ClusterId kTemperatureMeasurementClusterId = 0x0402; + +class DLL_EXPORT BarrierControlCluster : public ClusterBase +{ +public: + BarrierControlCluster() : ClusterBase(kBarrierControlClusterId) {} + ~BarrierControlCluster() {} + + // Cluster Commands + CHIP_ERROR BarrierControlGoToPercent(Callback::Callback<> * onCompletion, uint8_t percentOpen); + CHIP_ERROR BarrierControlStop(Callback::Callback<> * onCompletion); + + // Cluster Attributes + CHIP_ERROR DiscoverAttributes(Callback::Callback<> * onCompletion); + CHIP_ERROR ReadAttributeBarrierMovingState(Callback::Callback<> * onCompletion); + CHIP_ERROR ReadAttributeBarrierSafetyStatus(Callback::Callback<> * onCompletion); + CHIP_ERROR ReadAttributeBarrierCapabilities(Callback::Callback<> * onCompletion); + CHIP_ERROR ReadAttributeBarrierPosition(Callback::Callback<> * onCompletion); + CHIP_ERROR ReadAttributeClusterRevision(Callback::Callback<> * onCompletion); +}; + +class DLL_EXPORT BasicCluster : public ClusterBase +{ +public: + BasicCluster() : ClusterBase(kBasicClusterId) {} + ~BasicCluster() {} + + // Cluster Commands + CHIP_ERROR MfgSpecificPing(Callback::Callback<> * onCompletion); + CHIP_ERROR ResetToFactoryDefaults(Callback::Callback<> * onCompletion); + + // Cluster Attributes + CHIP_ERROR DiscoverAttributes(Callback::Callback<> * onCompletion); + CHIP_ERROR ReadAttributeZclVersion(Callback::Callback<> * onCompletion); + CHIP_ERROR ReadAttributePowerSource(Callback::Callback<> * onCompletion); + CHIP_ERROR ReadAttributeClusterRevision(Callback::Callback<> * onCompletion); +}; + +class DLL_EXPORT ColorControlCluster : public ClusterBase +{ +public: + ColorControlCluster() : ClusterBase(kColorControlClusterId) {} + ~ColorControlCluster() {} + + // Cluster Commands + CHIP_ERROR MoveColor(Callback::Callback<> * onCompletion, int16_t rateX, int16_t rateY, uint8_t optionsMask, + uint8_t optionsOverride); + CHIP_ERROR MoveColorTemperature(Callback::Callback<> * onCompletion, uint8_t moveMode, uint16_t rate, + uint16_t colorTemperatureMinimum, uint16_t colorTemperatureMaximum, uint8_t optionsMask, + uint8_t optionsOverride); + CHIP_ERROR MoveHue(Callback::Callback<> * onCompletion, uint8_t moveMode, uint8_t rate, uint8_t optionsMask, + uint8_t optionsOverride); + CHIP_ERROR MoveSaturation(Callback::Callback<> * onCompletion, uint8_t moveMode, uint8_t rate, uint8_t optionsMask, + uint8_t optionsOverride); + CHIP_ERROR MoveToColor(Callback::Callback<> * onCompletion, uint16_t colorX, uint16_t colorY, uint16_t transitionTime, + uint8_t optionsMask, uint8_t optionsOverride); + CHIP_ERROR MoveToColorTemperature(Callback::Callback<> * onCompletion, uint16_t colorTemperature, uint16_t transitionTime, + uint8_t optionsMask, uint8_t optionsOverride); + CHIP_ERROR MoveToHue(Callback::Callback<> * onCompletion, uint8_t hue, uint8_t direction, uint16_t transitionTime, + uint8_t optionsMask, uint8_t optionsOverride); + CHIP_ERROR MoveToHueAndSaturation(Callback::Callback<> * onCompletion, uint8_t hue, uint8_t saturation, uint16_t transitionTime, + uint8_t optionsMask, uint8_t optionsOverride); + CHIP_ERROR MoveToSaturation(Callback::Callback<> * onCompletion, uint8_t saturation, uint16_t transitionTime, + uint8_t optionsMask, uint8_t optionsOverride); + CHIP_ERROR StepColor(Callback::Callback<> * onCompletion, int16_t stepX, int16_t stepY, uint16_t transitionTime, + uint8_t optionsMask, uint8_t optionsOverride); + CHIP_ERROR StepColorTemperature(Callback::Callback<> * onCompletion, uint8_t stepMode, uint16_t stepSize, + uint16_t transitionTime, uint16_t colorTemperatureMinimum, uint16_t colorTemperatureMaximum, + uint8_t optionsMask, uint8_t optionsOverride); + CHIP_ERROR StepHue(Callback::Callback<> * onCompletion, uint8_t stepMode, uint8_t stepSize, uint8_t transitionTime, + uint8_t optionsMask, uint8_t optionsOverride); + CHIP_ERROR StepSaturation(Callback::Callback<> * onCompletion, uint8_t stepMode, uint8_t stepSize, uint8_t transitionTime, + uint8_t optionsMask, uint8_t optionsOverride); + CHIP_ERROR StopMoveStep(Callback::Callback<> * onCompletion, uint8_t optionsMask, uint8_t optionsOverride); + + // Cluster Attributes + CHIP_ERROR DiscoverAttributes(Callback::Callback<> * onCompletion); + CHIP_ERROR ReadAttributeCurrentHue(Callback::Callback<> * onCompletion); + CHIP_ERROR ReadAttributeCurrentSaturation(Callback::Callback<> * onCompletion); + CHIP_ERROR ReadAttributeRemainingTime(Callback::Callback<> * onCompletion); + CHIP_ERROR ReadAttributeCurrentX(Callback::Callback<> * onCompletion); + CHIP_ERROR ReadAttributeCurrentY(Callback::Callback<> * onCompletion); + CHIP_ERROR ReadAttributeDriftCompensation(Callback::Callback<> * onCompletion); + CHIP_ERROR ReadAttributeCompensationText(Callback::Callback<> * onCompletion); + CHIP_ERROR ReadAttributeColorTemperature(Callback::Callback<> * onCompletion); + CHIP_ERROR ReadAttributeColorMode(Callback::Callback<> * onCompletion); + CHIP_ERROR ReadAttributeColorControlOptions(Callback::Callback<> * onCompletion); + CHIP_ERROR ReadAttributeNumberOfPrimaries(Callback::Callback<> * onCompletion); + CHIP_ERROR ReadAttributePrimary1X(Callback::Callback<> * onCompletion); + CHIP_ERROR ReadAttributePrimary1Y(Callback::Callback<> * onCompletion); + CHIP_ERROR ReadAttributePrimary1Intensity(Callback::Callback<> * onCompletion); + CHIP_ERROR ReadAttributePrimary2X(Callback::Callback<> * onCompletion); + CHIP_ERROR ReadAttributePrimary2Y(Callback::Callback<> * onCompletion); + CHIP_ERROR ReadAttributePrimary2Intensity(Callback::Callback<> * onCompletion); + CHIP_ERROR ReadAttributePrimary3X(Callback::Callback<> * onCompletion); + CHIP_ERROR ReadAttributePrimary3Y(Callback::Callback<> * onCompletion); + CHIP_ERROR ReadAttributePrimary3Intensity(Callback::Callback<> * onCompletion); + CHIP_ERROR ReadAttributePrimary4X(Callback::Callback<> * onCompletion); + CHIP_ERROR ReadAttributePrimary4Y(Callback::Callback<> * onCompletion); + CHIP_ERROR ReadAttributePrimary4Intensity(Callback::Callback<> * onCompletion); + CHIP_ERROR ReadAttributePrimary5X(Callback::Callback<> * onCompletion); + CHIP_ERROR ReadAttributePrimary5Y(Callback::Callback<> * onCompletion); + CHIP_ERROR ReadAttributePrimary5Intensity(Callback::Callback<> * onCompletion); + CHIP_ERROR ReadAttributePrimary6X(Callback::Callback<> * onCompletion); + CHIP_ERROR ReadAttributePrimary6Y(Callback::Callback<> * onCompletion); + CHIP_ERROR ReadAttributePrimary6Intensity(Callback::Callback<> * onCompletion); + CHIP_ERROR ReadAttributeWhitePointX(Callback::Callback<> * onCompletion); + CHIP_ERROR ReadAttributeWhitePointY(Callback::Callback<> * onCompletion); + CHIP_ERROR ReadAttributeColorPointRX(Callback::Callback<> * onCompletion); + CHIP_ERROR ReadAttributeColorPointRY(Callback::Callback<> * onCompletion); + CHIP_ERROR ReadAttributeColorPointRIntensity(Callback::Callback<> * onCompletion); + CHIP_ERROR ReadAttributeColorPointGX(Callback::Callback<> * onCompletion); + CHIP_ERROR ReadAttributeColorPointGY(Callback::Callback<> * onCompletion); + CHIP_ERROR ReadAttributeColorPointGIntensity(Callback::Callback<> * onCompletion); + CHIP_ERROR ReadAttributeColorPointBX(Callback::Callback<> * onCompletion); + CHIP_ERROR ReadAttributeColorPointBY(Callback::Callback<> * onCompletion); + CHIP_ERROR ReadAttributeColorPointBIntensity(Callback::Callback<> * onCompletion); + CHIP_ERROR ReadAttributeEnhancedCurrentHue(Callback::Callback<> * onCompletion); + CHIP_ERROR ReadAttributeEnhancedColorMode(Callback::Callback<> * onCompletion); + CHIP_ERROR ReadAttributeColorLoopActive(Callback::Callback<> * onCompletion); + CHIP_ERROR ReadAttributeColorLoopDirection(Callback::Callback<> * onCompletion); + CHIP_ERROR ReadAttributeColorLoopTime(Callback::Callback<> * onCompletion); + CHIP_ERROR ReadAttributeColorCapabilities(Callback::Callback<> * onCompletion); + CHIP_ERROR ReadAttributeColorTempPhysicalMin(Callback::Callback<> * onCompletion); + CHIP_ERROR ReadAttributeColorTempPhysicalMax(Callback::Callback<> * onCompletion); + CHIP_ERROR ReadAttributeCoupleColorTempToLevelMinMireds(Callback::Callback<> * onCompletion); + CHIP_ERROR ReadAttributeStartUpColorTemperatureMireds(Callback::Callback<> * onCompletion); + CHIP_ERROR ReadAttributeClusterRevision(Callback::Callback<> * onCompletion); + CHIP_ERROR WriteAttributeColorControlOptions(Callback::Callback<> * onCompletion, uint8_t value); + CHIP_ERROR WriteAttributeWhitePointX(Callback::Callback<> * onCompletion, uint16_t value); + CHIP_ERROR WriteAttributeWhitePointY(Callback::Callback<> * onCompletion, uint16_t value); + CHIP_ERROR WriteAttributeColorPointRX(Callback::Callback<> * onCompletion, uint16_t value); + CHIP_ERROR WriteAttributeColorPointRY(Callback::Callback<> * onCompletion, uint16_t value); + CHIP_ERROR WriteAttributeColorPointRIntensity(Callback::Callback<> * onCompletion, uint8_t value); + CHIP_ERROR WriteAttributeColorPointGX(Callback::Callback<> * onCompletion, uint16_t value); + CHIP_ERROR WriteAttributeColorPointGY(Callback::Callback<> * onCompletion, uint16_t value); + CHIP_ERROR WriteAttributeColorPointGIntensity(Callback::Callback<> * onCompletion, uint8_t value); + CHIP_ERROR WriteAttributeColorPointBX(Callback::Callback<> * onCompletion, uint16_t value); + CHIP_ERROR WriteAttributeColorPointBY(Callback::Callback<> * onCompletion, uint16_t value); + CHIP_ERROR WriteAttributeColorPointBIntensity(Callback::Callback<> * onCompletion, uint8_t value); + CHIP_ERROR WriteAttributeStartUpColorTemperatureMireds(Callback::Callback<> * onCompletion, uint16_t value); + CHIP_ERROR ReportAttributeCurrentHue(Callback::Callback<> * onCompletion, Callback::Callback<> * onChange, uint16_t minInterval, + uint16_t maxInterval, uint8_t change); + CHIP_ERROR ReportAttributeCurrentSaturation(Callback::Callback<> * onCompletion, Callback::Callback<> * onChange, + uint16_t minInterval, uint16_t maxInterval, uint8_t change); + CHIP_ERROR ReportAttributeCurrentX(Callback::Callback<> * onCompletion, Callback::Callback<> * onChange, uint16_t minInterval, + uint16_t maxInterval, uint16_t change); + CHIP_ERROR ReportAttributeCurrentY(Callback::Callback<> * onCompletion, Callback::Callback<> * onChange, uint16_t minInterval, + uint16_t maxInterval, uint16_t change); + CHIP_ERROR ReportAttributeColorTemperature(Callback::Callback<> * onCompletion, Callback::Callback<> * onChange, + uint16_t minInterval, uint16_t maxInterval, uint16_t change); +}; + +class DLL_EXPORT DoorLockCluster : public ClusterBase +{ +public: + DoorLockCluster() : ClusterBase(kDoorLockClusterId) {} + ~DoorLockCluster() {} + + // Cluster Commands + CHIP_ERROR ClearAllPins(Callback::Callback<> * onCompletion); + CHIP_ERROR ClearAllRfids(Callback::Callback<> * onCompletion); + CHIP_ERROR ClearHolidaySchedule(Callback::Callback<> * onCompletion, uint8_t scheduleId); + CHIP_ERROR ClearPin(Callback::Callback<> * onCompletion, uint16_t userId); + CHIP_ERROR ClearRfid(Callback::Callback<> * onCompletion, uint16_t userId); + CHIP_ERROR ClearWeekdaySchedule(Callback::Callback<> * onCompletion, uint8_t scheduleId, uint16_t userId); + CHIP_ERROR ClearYeardaySchedule(Callback::Callback<> * onCompletion, uint8_t scheduleId, uint16_t userId); + CHIP_ERROR GetHolidaySchedule(Callback::Callback<> * onCompletion, uint8_t scheduleId); + CHIP_ERROR GetLogRecord(Callback::Callback<> * onCompletion, uint16_t logIndex); + CHIP_ERROR GetPin(Callback::Callback<> * onCompletion, uint16_t userId); + CHIP_ERROR GetRfid(Callback::Callback<> * onCompletion, uint16_t userId); + CHIP_ERROR GetUserType(Callback::Callback<> * onCompletion, uint16_t userId); + CHIP_ERROR GetWeekdaySchedule(Callback::Callback<> * onCompletion, uint8_t scheduleId, uint16_t userId); + CHIP_ERROR GetYeardaySchedule(Callback::Callback<> * onCompletion, uint8_t scheduleId, uint16_t userId); + CHIP_ERROR LockDoor(Callback::Callback<> * onCompletion, char * pin); + CHIP_ERROR SetHolidaySchedule(Callback::Callback<> * onCompletion, uint8_t scheduleId, uint32_t localStartTime, + uint32_t localEndTime, uint8_t operatingModeDuringHoliday); + CHIP_ERROR SetPin(Callback::Callback<> * onCompletion, uint16_t userId, uint8_t userStatus, uint8_t userType, char * pin); + CHIP_ERROR SetRfid(Callback::Callback<> * onCompletion, uint16_t userId, uint8_t userStatus, uint8_t userType, char * id); + CHIP_ERROR SetUserType(Callback::Callback<> * onCompletion, uint16_t userId, uint8_t userType); + CHIP_ERROR SetWeekdaySchedule(Callback::Callback<> * onCompletion, uint8_t scheduleId, uint16_t userId, uint8_t daysMask, + uint8_t startHour, uint8_t startMinute, uint8_t endHour, uint8_t endMinute); + CHIP_ERROR SetYeardaySchedule(Callback::Callback<> * onCompletion, uint8_t scheduleId, uint16_t userId, uint32_t localStartTime, + uint32_t localEndTime); + CHIP_ERROR UnlockDoor(Callback::Callback<> * onCompletion, char * pin); + CHIP_ERROR UnlockWithTimeout(Callback::Callback<> * onCompletion, uint16_t timeoutInSeconds, char * pin); + + // Cluster Attributes + CHIP_ERROR DiscoverAttributes(Callback::Callback<> * onCompletion); + CHIP_ERROR ReadAttributeLockState(Callback::Callback<> * onCompletion); + CHIP_ERROR ReadAttributeLockType(Callback::Callback<> * onCompletion); + CHIP_ERROR ReadAttributeActuatorEnabled(Callback::Callback<> * onCompletion); + CHIP_ERROR ReadAttributeClusterRevision(Callback::Callback<> * onCompletion); + CHIP_ERROR ReportAttributeLockState(Callback::Callback<> * onCompletion, Callback::Callback<> * onChange, uint16_t minInterval, + uint16_t maxInterval); +}; + +class DLL_EXPORT GroupsCluster : public ClusterBase +{ +public: + GroupsCluster() : ClusterBase(kGroupsClusterId) {} + ~GroupsCluster() {} + + // Cluster Commands + CHIP_ERROR AddGroup(Callback::Callback<> * onCompletion, uint16_t groupId, char * groupName); + CHIP_ERROR AddGroupIfIdentifying(Callback::Callback<> * onCompletion, uint16_t groupId, char * groupName); + CHIP_ERROR GetGroupMembership(Callback::Callback<> * onCompletion, uint8_t groupCount, uint16_t groupList); + CHIP_ERROR RemoveAllGroups(Callback::Callback<> * onCompletion); + CHIP_ERROR RemoveGroup(Callback::Callback<> * onCompletion, uint16_t groupId); + CHIP_ERROR ViewGroup(Callback::Callback<> * onCompletion, uint16_t groupId); + + // Cluster Attributes + CHIP_ERROR DiscoverAttributes(Callback::Callback<> * onCompletion); + CHIP_ERROR ReadAttributeNameSupport(Callback::Callback<> * onCompletion); + CHIP_ERROR ReadAttributeClusterRevision(Callback::Callback<> * onCompletion); +}; + +class DLL_EXPORT IasZoneCluster : public ClusterBase +{ +public: + IasZoneCluster() : ClusterBase(kIasZoneClusterId) {} + ~IasZoneCluster() {} + + // Cluster Attributes + CHIP_ERROR DiscoverAttributes(Callback::Callback<> * onCompletion); + CHIP_ERROR ReadAttributeZoneState(Callback::Callback<> * onCompletion); + CHIP_ERROR ReadAttributeZoneType(Callback::Callback<> * onCompletion); + CHIP_ERROR ReadAttributeZoneStatus(Callback::Callback<> * onCompletion); + CHIP_ERROR ReadAttributeIasCieAddress(Callback::Callback<> * onCompletion); + CHIP_ERROR ReadAttributeZoneId(Callback::Callback<> * onCompletion); + CHIP_ERROR ReadAttributeClusterRevision(Callback::Callback<> * onCompletion); + CHIP_ERROR WriteAttributeIasCieAddress(Callback::Callback<> * onCompletion, uint64_t value); +}; + +class DLL_EXPORT IdentifyCluster : public ClusterBase +{ +public: + IdentifyCluster() : ClusterBase(kIdentifyClusterId) {} + ~IdentifyCluster() {} + + // Cluster Commands + CHIP_ERROR Identify(Callback::Callback<> * onCompletion, uint16_t identifyTime); + CHIP_ERROR IdentifyQuery(Callback::Callback<> * onCompletion); + + // Cluster Attributes + CHIP_ERROR DiscoverAttributes(Callback::Callback<> * onCompletion); + CHIP_ERROR ReadAttributeIdentifyTime(Callback::Callback<> * onCompletion); + CHIP_ERROR ReadAttributeClusterRevision(Callback::Callback<> * onCompletion); + CHIP_ERROR WriteAttributeIdentifyTime(Callback::Callback<> * onCompletion, uint16_t value); +}; + +class DLL_EXPORT LevelControlCluster : public ClusterBase +{ +public: + LevelControlCluster() : ClusterBase(kLevelControlClusterId) {} + ~LevelControlCluster() {} + + // Cluster Commands + CHIP_ERROR Move(Callback::Callback<> * onCompletion, uint8_t moveMode, uint8_t rate, uint8_t optionMask, + uint8_t optionOverride); + CHIP_ERROR MoveToLevel(Callback::Callback<> * onCompletion, uint8_t level, uint16_t transitionTime, uint8_t optionMask, + uint8_t optionOverride); + CHIP_ERROR MoveToLevelWithOnOff(Callback::Callback<> * onCompletion, uint8_t level, uint16_t transitionTime); + CHIP_ERROR MoveWithOnOff(Callback::Callback<> * onCompletion, uint8_t moveMode, uint8_t rate); + CHIP_ERROR Step(Callback::Callback<> * onCompletion, uint8_t stepMode, uint8_t stepSize, uint16_t transitionTime, + uint8_t optionMask, uint8_t optionOverride); + CHIP_ERROR StepWithOnOff(Callback::Callback<> * onCompletion, uint8_t stepMode, uint8_t stepSize, uint16_t transitionTime); + CHIP_ERROR Stop(Callback::Callback<> * onCompletion, uint8_t optionMask, uint8_t optionOverride); + CHIP_ERROR StopWithOnOff(Callback::Callback<> * onCompletion); + + // Cluster Attributes + CHIP_ERROR DiscoverAttributes(Callback::Callback<> * onCompletion); + CHIP_ERROR ReadAttributeCurrentLevel(Callback::Callback<> * onCompletion); + CHIP_ERROR ReadAttributeClusterRevision(Callback::Callback<> * onCompletion); + CHIP_ERROR ReportAttributeCurrentLevel(Callback::Callback<> * onCompletion, Callback::Callback<> * onChange, + uint16_t minInterval, uint16_t maxInterval, uint8_t change); +}; + +class DLL_EXPORT OnOffCluster : public ClusterBase +{ +public: + OnOffCluster() : ClusterBase(kOnOffClusterId) {} + ~OnOffCluster() {} + + // Cluster Commands + CHIP_ERROR Off(Callback::Callback<> * onCompletion); + CHIP_ERROR On(Callback::Callback<> * onCompletion); + CHIP_ERROR Toggle(Callback::Callback<> * onCompletion); + + // Cluster Attributes + CHIP_ERROR DiscoverAttributes(Callback::Callback<> * onCompletion); + CHIP_ERROR ReadAttributeOnOff(Callback::Callback<> * onCompletion); + CHIP_ERROR ReadAttributeClusterRevision(Callback::Callback<> * onCompletion); + CHIP_ERROR ReportAttributeOnOff(Callback::Callback<> * onCompletion, Callback::Callback<> * onChange, uint16_t minInterval, + uint16_t maxInterval); +}; + +class DLL_EXPORT ScenesCluster : public ClusterBase +{ +public: + ScenesCluster() : ClusterBase(kScenesClusterId) {} + ~ScenesCluster() {} + + // Cluster Commands + CHIP_ERROR AddScene(Callback::Callback<> * onCompletion, uint16_t groupId, uint8_t sceneId, uint16_t transitionTime, + char * sceneName, chip::ClusterId clusterId, uint8_t length, uint8_t value); + CHIP_ERROR GetSceneMembership(Callback::Callback<> * onCompletion, uint16_t groupId); + CHIP_ERROR RecallScene(Callback::Callback<> * onCompletion, uint16_t groupId, uint8_t sceneId, uint16_t transitionTime); + CHIP_ERROR RemoveAllScenes(Callback::Callback<> * onCompletion, uint16_t groupId); + CHIP_ERROR RemoveScene(Callback::Callback<> * onCompletion, uint16_t groupId, uint8_t sceneId); + CHIP_ERROR StoreScene(Callback::Callback<> * onCompletion, uint16_t groupId, uint8_t sceneId); + CHIP_ERROR ViewScene(Callback::Callback<> * onCompletion, uint16_t groupId, uint8_t sceneId); + + // Cluster Attributes + CHIP_ERROR DiscoverAttributes(Callback::Callback<> * onCompletion); + CHIP_ERROR ReadAttributeSceneCount(Callback::Callback<> * onCompletion); + CHIP_ERROR ReadAttributeCurrentScene(Callback::Callback<> * onCompletion); + CHIP_ERROR ReadAttributeCurrentGroup(Callback::Callback<> * onCompletion); + CHIP_ERROR ReadAttributeSceneValid(Callback::Callback<> * onCompletion); + CHIP_ERROR ReadAttributeNameSupport(Callback::Callback<> * onCompletion); + CHIP_ERROR ReadAttributeClusterRevision(Callback::Callback<> * onCompletion); +}; + +class DLL_EXPORT TemperatureMeasurementCluster : public ClusterBase +{ +public: + TemperatureMeasurementCluster() : ClusterBase(kTemperatureMeasurementClusterId) {} + ~TemperatureMeasurementCluster() {} + + // Cluster Attributes + CHIP_ERROR DiscoverAttributes(Callback::Callback<> * onCompletion); + CHIP_ERROR ReadAttributeMeasuredValue(Callback::Callback<> * onCompletion); + CHIP_ERROR ReadAttributeMinMeasuredValue(Callback::Callback<> * onCompletion); + CHIP_ERROR ReadAttributeMaxMeasuredValue(Callback::Callback<> * onCompletion); + CHIP_ERROR ReadAttributeClusterRevision(Callback::Callback<> * onCompletion); + CHIP_ERROR ReportAttributeMeasuredValue(Callback::Callback<> * onCompletion, Callback::Callback<> * onChange, + uint16_t minInterval, uint16_t maxInterval, int16_t change); +}; + +} // namespace Controller +} // namespace chip diff --git a/src/controller/CHIPDevice.cpp b/src/controller/CHIPDevice.cpp index c9d4af8b9038e5..2743855a65ba53 100644 --- a/src/controller/CHIPDevice.cpp +++ b/src/controller/CHIPDevice.cpp @@ -74,7 +74,7 @@ CHIP_ERROR Device::SendMessage(System::PacketBufferHandle buffer) resend = buffer.Retain(); } - err = mSessionManager->SendMessage(mDeviceId, std::move(buffer)); + err = mSessionManager->SendMessage(mSecureSession, std::move(buffer)); buffer = nullptr; ChipLogDetail(Controller, "SendMessage returned %d", err); @@ -87,7 +87,7 @@ CHIP_ERROR Device::SendMessage(System::PacketBufferHandle buffer) err = LoadSecureSessionParameters(ResetTransport::kYes); SuccessOrExit(err); - err = mSessionManager->SendMessage(mDeviceId, std::move(resend)); + err = mSessionManager->SendMessage(mSecureSession, std::move(resend)); ChipLogDetail(Controller, "Re-SendMessage returned %d", err); SuccessOrExit(err); } @@ -175,9 +175,20 @@ CHIP_ERROR Device::Deserialize(const SerializedDevice & input) return error; } -void Device::OnMessageReceived(const PacketHeader & header, const PayloadHeader & payloadHeader, - const Transport::PeerConnectionState * state, System::PacketBufferHandle msgBuf, - SecureSessionMgr * mgr) +void Device::OnNewConnection(SecureSessionHandle session, SecureSessionMgr * mgr) +{ + mState = ConnectionState::SecureConnected; + mSecureSession = session; +} + +void Device::OnConnectionExpired(SecureSessionHandle session, SecureSessionMgr * mgr) +{ + mState = ConnectionState::NotConnected; + mSecureSession = SecureSessionHandle{}; +} + +void Device::OnMessageReceived(const PacketHeader & header, const PayloadHeader & payloadHeader, SecureSessionHandle session, + System::PacketBufferHandle msgBuf, SecureSessionMgr * mgr) { if (mState == ConnectionState::SecureConnected) { @@ -255,8 +266,6 @@ CHIP_ERROR Device::LoadSecureSessionParameters(ResetTransport resetNeeded) &pairingSession); SuccessOrExit(err); - mState = ConnectionState::SecureConnected; - exit: if (err != CHIP_NO_ERROR) @@ -268,9 +277,10 @@ CHIP_ERROR Device::LoadSecureSessionParameters(ResetTransport resetNeeded) bool Device::GetIpAddress(Inet::IPAddress & addr) const { - if (mState == ConnectionState::SecureConnected) - addr = mDeviceAddr; - return mState == ConnectionState::SecureConnected; + if (mState == ConnectionState::NotConnected) + return false; + addr = mDeviceAddr; + return true; } void Device::AddResponseHandler(EndpointId endpoint, ClusterId cluster, Callback::Callback<> * onResponse) diff --git a/src/controller/CHIPDevice.h b/src/controller/CHIPDevice.h index 7484608624e5d6..23b8f53cc9de25 100644 --- a/src/controller/CHIPDevice.h +++ b/src/controller/CHIPDevice.h @@ -156,6 +156,26 @@ class DLL_EXPORT Device **/ CHIP_ERROR Deserialize(const SerializedDevice & input); + /** + * @brief + * Called when a new pairing is being established + * + * @param session A handle to the secure session + * @param mgr A pointer to the SecureSessionMgr + */ + void OnNewConnection(SecureSessionHandle session, SecureSessionMgr * mgr); + + /** + * @brief + * Called when a connection is closing. + * + * The receiver should release all resources associated with the connection. + * + * @param session A handle to the secure session + * @param mgr A pointer to the SecureSessionMgr + */ + void OnConnectionExpired(SecureSessionHandle session, SecureSessionMgr * mgr); + /** * @brief * This function is called when a message is received from the corresponding CHIP @@ -164,12 +184,12 @@ class DLL_EXPORT Device * * @param[in] header Reference to common packet header of the received message * @param[in] payloadHeader Reference to payload header in the message - * @param[in] state Pointer to the peer connection state on which message is received + * @param[in] session A handle to the secure session * @param[in] msgBuf The message buffer * @param[in] mgr Pointer to secure session manager which received the message */ - void OnMessageReceived(const PacketHeader & header, const PayloadHeader & payloadHeader, - const Transport::PeerConnectionState * state, System::PacketBufferHandle msgBuf, SecureSessionMgr * mgr); + void OnMessageReceived(const PacketHeader & header, const PayloadHeader & payloadHeader, SecureSessionHandle session, + System::PacketBufferHandle msgBuf, SecureSessionMgr * mgr); /** * @brief @@ -180,6 +200,8 @@ class DLL_EXPORT Device void SetActive(bool active) { mActive = active; } + bool IsSecureConnected() const { return IsActive() && mState == ConnectionState::SecureConnected; } + void Reset() { SetActive(false); @@ -191,6 +213,8 @@ class DLL_EXPORT Device NodeId GetDeviceId() const { return mDeviceId; } + bool MatchesSession(SecureSessionHandle session) const { return mSecureSession == session; } + void SetAddress(const Inet::IPAddress & deviceAddr) { mDeviceAddr = deviceAddr; } SecurePairingSessionSerializable & GetPairing() { return mPairing; } @@ -242,6 +266,8 @@ class DLL_EXPORT Device DeviceTransportMgr * mTransportMgr; + SecureSessionHandle mSecureSession = {}; + /* Track all outstanding response callbacks for this device. The callbacks are registered when a command is sent to the device, to get notified with the results. */ Callback::CallbackDeque mResponses; diff --git a/src/controller/CHIPDeviceController.cpp b/src/controller/CHIPDeviceController.cpp index a0f61db664f3d1..03542e57128530 100644 --- a/src/controller/CHIPDeviceController.cpp +++ b/src/controller/CHIPDeviceController.cpp @@ -106,6 +106,12 @@ CHIP_ERROR DeviceController::Init(NodeId localDeviceId, PersistentStorageDelegat else { #if CONFIG_DEVICE_LAYER +#if CHIP_DEVICE_LAYER_TARGET_LINUX && CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE + // By default, Linux device is configured as a BLE peripheral while the controller needs a BLE central. + err = DeviceLayer::Internal::BLEMgrImpl().ConfigureBle(/* BLE adapter ID */ 0, /* BLE central */ true); + SuccessOrExit(err); +#endif // CHIP_DEVICE_LAYER_TARGET_LINUX && CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE + err = DeviceLayer::PlatformMgr().InitChipStack(); SuccessOrExit(err); @@ -334,24 +340,57 @@ CHIP_ERROR DeviceController::ServiceEventSignal() return err; } -void DeviceController::OnNewConnection(const Transport::PeerConnectionState * peerConnection, SecureSessionMgr * mgr) {} +void DeviceController::OnNewConnection(SecureSessionHandle session, SecureSessionMgr * mgr) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + uint16_t index = 0; + + VerifyOrExit(mState == State::Initialized, err = CHIP_ERROR_INCORRECT_STATE); + + index = FindDeviceIndex(mgr->GetPeerConnectionState(session)->GetPeerNodeId()); + VerifyOrExit(index < kNumMaxActiveDevices, err = CHIP_ERROR_INVALID_DEVICE_DESCRIPTOR); + + mActiveDevices[index].OnNewConnection(session, mgr); + +exit: + if (err != CHIP_NO_ERROR) + { + ChipLogError(Controller, "Failed to process received message: err %d", err); + } +} + +void DeviceController::OnConnectionExpired(SecureSessionHandle session, SecureSessionMgr * mgr) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + uint16_t index = 0; + + VerifyOrExit(mState == State::Initialized, err = CHIP_ERROR_INCORRECT_STATE); + + index = FindDeviceIndex(session); + VerifyOrExit(index < kNumMaxActiveDevices, err = CHIP_ERROR_INVALID_DEVICE_DESCRIPTOR); + + mActiveDevices[index].OnConnectionExpired(session, mgr); + +exit: + if (err != CHIP_NO_ERROR) + { + ChipLogError(Controller, "Failed to process received message: err %d", err); + } +} void DeviceController::OnMessageReceived(const PacketHeader & header, const PayloadHeader & payloadHeader, - const Transport::PeerConnectionState * state, System::PacketBufferHandle msgBuf, - SecureSessionMgr * mgr) + SecureSessionHandle session, System::PacketBufferHandle msgBuf, SecureSessionMgr * mgr) { CHIP_ERROR err = CHIP_NO_ERROR; uint16_t index = 0; - NodeId peer; VerifyOrExit(mState == State::Initialized, err = CHIP_ERROR_INCORRECT_STATE); VerifyOrExit(header.GetSourceNodeId().HasValue(), err = CHIP_ERROR_INVALID_ARGUMENT); - peer = header.GetSourceNodeId().Value(); - index = FindDeviceIndex(peer); + index = FindDeviceIndex(session); VerifyOrExit(index < kNumMaxActiveDevices, err = CHIP_ERROR_INVALID_DEVICE_DESCRIPTOR); - mActiveDevices[index].OnMessageReceived(header, payloadHeader, state, std::move(msgBuf), mgr); + mActiveDevices[index].OnMessageReceived(header, payloadHeader, session, std::move(msgBuf), mgr); exit: if (err != CHIP_NO_ERROR) @@ -395,6 +434,20 @@ void DeviceController::ReleaseAllDevices() } } +uint16_t DeviceController::FindDeviceIndex(SecureSessionHandle session) +{ + uint16_t i = 0; + while (i < kNumMaxActiveDevices) + { + if (mActiveDevices[i].IsActive() && mActiveDevices[i].IsSecureConnected() && mActiveDevices[i].MatchesSession(session)) + { + return i; + } + i++; + } + return i; +} + uint16_t DeviceController::FindDeviceIndex(NodeId id) { uint16_t i = 0; @@ -522,7 +575,8 @@ CHIP_ERROR DeviceCommissioner::PairDevice(NodeId remoteDeviceId, RendezvousParam exit: if (err != CHIP_NO_ERROR) { - if (mRendezvousSession != nullptr) + // Delete the current rendezvous session only if a device is not currently being paired. + if (mDeviceBeingPaired == kNumMaxActiveDevices && mRendezvousSession != nullptr) { chip::Platform::Delete(mRendezvousSession); mRendezvousSession = nullptr; @@ -636,7 +690,8 @@ void DeviceCommissioner::RendezvousCleanup(CHIP_ERROR status) mPairingDelegate->OnPairingComplete(status); } - if (mDeviceBeingPaired != kNumMaxActiveDevices) + // TODO: make mStorageDelegate mandatory once all controller applications implement the interface. + if (mDeviceBeingPaired != kNumMaxActiveDevices && mStorageDelegate != nullptr) { // Let's release the device that's being paired. // If pairing was successful, its information is diff --git a/src/controller/CHIPDeviceController.h b/src/controller/CHIPDeviceController.h index c12c2881117496..550264c6ccd462 100644 --- a/src/controller/CHIPDeviceController.h +++ b/src/controller/CHIPDeviceController.h @@ -192,17 +192,18 @@ class DLL_EXPORT DeviceController : public SecureSessionMgrDelegate, public Pers uint16_t mListenPort; uint16_t GetInactiveDeviceIndex(); + uint16_t FindDeviceIndex(SecureSessionHandle session); uint16_t FindDeviceIndex(NodeId id); void ReleaseDevice(uint16_t index); CHIP_ERROR SetPairedDeviceList(const char * pairedDeviceSerializedSet); private: //////////// SecureSessionMgrDelegate Implementation /////////////// - void OnMessageReceived(const PacketHeader & header, const PayloadHeader & payloadHeader, - const Transport::PeerConnectionState * state, System::PacketBufferHandle msgBuf, - SecureSessionMgr * mgr) override; + void OnMessageReceived(const PacketHeader & header, const PayloadHeader & payloadHeader, SecureSessionHandle session, + System::PacketBufferHandle msgBuf, SecureSessionMgr * mgr) override; - void OnNewConnection(const Transport::PeerConnectionState * state, SecureSessionMgr * mgr) override; + void OnNewConnection(SecureSessionHandle session, SecureSessionMgr * mgr) override; + void OnConnectionExpired(SecureSessionHandle session, SecureSessionMgr * mgr) override; //////////// PersistentStorageResultDelegate Implementation /////////////// void OnValue(const char * key, const char * value) override; diff --git a/src/controller/CHIPDeviceController_deprecated.cpp b/src/controller/CHIPDeviceController_deprecated.cpp index 6793799dc655a5..b05aaafcae56f2 100644 --- a/src/controller/CHIPDeviceController_deprecated.cpp +++ b/src/controller/CHIPDeviceController_deprecated.cpp @@ -171,12 +171,15 @@ bool ChipDeviceController::IsConnected() const return mState == kState_Initialized; } -bool ChipDeviceController::GetIpAddress(Inet::IPAddress & addr) const +bool ChipDeviceController::GetIpAddress(Inet::IPAddress & addr) { - if (IsConnected() && mDevice != nullptr) - return mDevice->GetIpAddress(addr); + if (!IsConnected()) + return false; - return false; + if (mDevice == nullptr) + InitDevice(); + + return mDevice != nullptr && mDevice->GetIpAddress(addr); } CHIP_ERROR ChipDeviceController::DisconnectDevice() @@ -205,15 +208,7 @@ CHIP_ERROR ChipDeviceController::SendMessage(void * appReqState, PacketBufferHan if (mDevice == nullptr) { - if (mPairingWithoutSecurity) - { - err = mCommissioner.GetDevice(mRemoteDeviceId, mSerializedTestDevice, &mDevice); - } - else - { - err = mCommissioner.GetDevice(mRemoteDeviceId, &mDevice); - } - SuccessOrExit(err); + SuccessOrExit(InitDevice()); } VerifyOrExit(mDevice != nullptr, err = CHIP_ERROR_INVALID_ARGUMENT); @@ -240,5 +235,11 @@ void ChipDeviceController::OnMessage(System::PacketBufferHandle msgBuf) } } +CHIP_ERROR ChipDeviceController::InitDevice() +{ + return mPairingWithoutSecurity ? mCommissioner.GetDevice(mRemoteDeviceId, mSerializedTestDevice, &mDevice) + : mCommissioner.GetDevice(mRemoteDeviceId, &mDevice); +} + } // namespace DeviceController } // namespace chip diff --git a/src/controller/CHIPDeviceController_deprecated.h b/src/controller/CHIPDeviceController_deprecated.h index d851700fac028b..52b98d1c4536d9 100644 --- a/src/controller/CHIPDeviceController_deprecated.h +++ b/src/controller/CHIPDeviceController_deprecated.h @@ -143,7 +143,7 @@ class DLL_EXPORT ChipDeviceController : public Controller::DeviceStatusDelegate * * @return bool If IP Address was returned */ - bool GetIpAddress(Inet::IPAddress & addr) const; + bool GetIpAddress(Inet::IPAddress & addr); // ----- Messaging ----- /** @@ -185,6 +185,8 @@ class DLL_EXPORT ChipDeviceController : public Controller::DeviceStatusDelegate void OnMessage(System::PacketBufferHandle msg) override; private: + CHIP_ERROR InitDevice(); + enum { kState_NotInitialized = 0, diff --git a/src/controller/OnOffCluster.cpp b/src/controller/OnOffCluster.cpp deleted file mode 100644 index c377517375bc04..00000000000000 --- a/src/controller/OnOffCluster.cpp +++ /dev/null @@ -1,61 +0,0 @@ -/* - * - * Copyright (c) 2020 Project CHIP Authors - * All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include - -namespace chip { -namespace Controller { - -// TODO: Find a way to calculate maximum message length for clusters -// https://github.com/project-chip/connectedhomeip/issues/965 -constexpr uint16_t kMaxOnOffMessageLength = 64; - -CHIP_ERROR OnOffCluster::On(Callback::Callback<> * onCompletion) -{ - return SendCommand(encodeOnOffClusterOnCommand, kMaxOnOffMessageLength, onCompletion); -} - -CHIP_ERROR OnOffCluster::Off(Callback::Callback<> * onCompletion) -{ - return SendCommand(encodeOnOffClusterOffCommand, kMaxOnOffMessageLength, onCompletion); -} - -CHIP_ERROR OnOffCluster::Toggle(Callback::Callback<> * onCompletion) -{ - return SendCommand(encodeOnOffClusterToggleCommand, kMaxOnOffMessageLength, onCompletion); -} - -CHIP_ERROR OnOffCluster::ReadAttributeOnOff(Callback::Callback<> * onCompletion) -{ - return SendCommand(encodeOnOffClusterReadOnOffAttribute, kMaxOnOffMessageLength, onCompletion); -} - -CHIP_ERROR OnOffCluster::ReportAttributeOnOff(Callback::Callback<> * onChange, uint16_t minInterval, uint16_t maxInterval) -{ - return RequestAttributeReporting(encodeOnOffClusterReportOnOffAttribute, kMaxOnOffMessageLength, minInterval, maxInterval, - onChange); -} - -CHIP_ERROR OnOffCluster::ReadAttributeClusterRevision(Callback::Callback<> * onCompletion) -{ - return CHIP_NO_ERROR; -} - -} // namespace Controller -} // namespace chip diff --git a/src/controller/OnOffCluster.h b/src/controller/OnOffCluster.h deleted file mode 100644 index 91a775d7e9007b..00000000000000 --- a/src/controller/OnOffCluster.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * - * Copyright (c) 2020 Project CHIP Authors - * All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#pragma once - -#include -#include - -namespace chip { -namespace Controller { - -constexpr ClusterId kOnOffClusterId = 0x0006; - -class DLL_EXPORT OnOffCluster : public ClusterBase -{ -public: - OnOffCluster() : ClusterBase(kOnOffClusterId) {} - ~OnOffCluster() {} - - CHIP_ERROR On(Callback::Callback<> * onCompletion); - CHIP_ERROR Off(Callback::Callback<> * onCompletion); - CHIP_ERROR Toggle(Callback::Callback<> * onCompletion); - - CHIP_ERROR ReadAttributeOnOff(Callback::Callback<> * onCompletion); - CHIP_ERROR ReportAttributeOnOff(Callback::Callback<> * onChange, uint16_t minInterval, uint16_t maxInterval); - - CHIP_ERROR ReadAttributeClusterRevision(Callback::Callback<> * onCompletion); -}; - -} // namespace Controller -} // namespace chip diff --git a/src/controller/java/CHIPDeviceController-JNI.cpp b/src/controller/java/CHIPDeviceController-JNI.cpp index 6c4b81044fc5c1..f2e2463ae7e89d 100644 --- a/src/controller/java/CHIPDeviceController-JNI.cpp +++ b/src/controller/java/CHIPDeviceController-JNI.cpp @@ -27,6 +27,7 @@ #include "AndroidBlePlatformDelegate.h" #include "AndroidDeviceControllerWrapper.h" +#include #include #include #include @@ -38,10 +39,6 @@ #include #include -extern "C" { -#include -} // extern "C" - // Choose an approximation of PTHREAD_NULL if pthread.h doesn't define one. #ifndef PTHREAD_NULL #define PTHREAD_NULL 0 @@ -429,10 +426,29 @@ JNI_METHOD(void, beginSendCommand)(JNIEnv * env, jobject self, jlong handle, job { ScopedPthreadLock lock(&sStackLock); + System::PacketBufferHandle buffer; - // Make sure our buffer is big enough, but this will need a better setup! - static const size_t bufferSize = 1024; - System::PacketBufferHandle buffer = System::PacketBuffer::NewWithAvailableSize(bufferSize); + // Hardcode endpoint to 1 for now + uint8_t endpoint = 1; + + switch (commandID) + { + case 0: + buffer = encodeOnOffClusterOffCommand(endpoint); + break; + case 1: + buffer = encodeOnOffClusterOnCommand(endpoint); + break; + case 2: + buffer = encodeOnOffClusterToggleCommand(endpoint); + break; + case 3: + buffer = encodeLevelControlClusterMoveToLevelCommand(endpoint, (uint8_t)(aValue & 0xff), 0xFFFF, 0, 0); + break; + default: + ChipLogError(Controller, "Unknown command: %d", commandID); + return; + } if (buffer.IsNull()) { @@ -440,32 +456,6 @@ JNI_METHOD(void, beginSendCommand)(JNIEnv * env, jobject self, jlong handle, job } else { - // Hardcode endpoint to 1 for now - uint8_t endpoint = 1; - - uint16_t dataLength = 0; - switch (commandID) - { - case 0: - dataLength = encodeOnOffClusterOffCommand(buffer->Start(), bufferSize, endpoint); - break; - case 1: - dataLength = encodeOnOffClusterOnCommand(buffer->Start(), bufferSize, endpoint); - break; - case 2: - dataLength = encodeOnOffClusterToggleCommand(buffer->Start(), bufferSize, endpoint); - break; - case 3: - dataLength = encodeLevelControlClusterMoveToLevelCommand(buffer->Start(), bufferSize, endpoint, - (uint8_t)(aValue & 0xff), 0xFFFF, 0, 0); - break; - default: - ChipLogError(Controller, "Unknown command: %d", commandID); - return; - } - - buffer->SetDataLength(dataLength); - // Hardcode endpoint to 1 for now err = wrapper->Controller()->SendMessage((void *) "SendMessage", std::move(buffer)); } diff --git a/src/controller/python/README.md b/src/controller/python/README.md new file mode 100644 index 00000000000000..b92e84e4d733c8 --- /dev/null +++ b/src/controller/python/README.md @@ -0,0 +1,162 @@ +# CHIP Device Controller - Python Binding & Command line interface + +## Overview + +Chip Device Controller is a general library to control devices and manage +commissioner functionality, it has Python, Java (for Android) and ObjC (for iOS) +bindings for building tests and CHIP mobile applications. This document will +focus on its python binding interface on Linux and mac os. + +## Checkout / Build / Install + +> Note: The CHIP can be built on Linux (amd64 / aarch64) and macOS + +1. Clone Project CHIP repo. + +``` +git clone https://github.com/project-chip/connectedhomeip.git +``` + +2. Build CHIP + +Follow [BUILDING.md](/docs/BUILDING.md) to build CHIP on your platform. + +3. Install Chip Device Controller + +**For Linux** + +``` +cd out/debug/controller/python +sudo pip3 install chip-0.0-cp38-cp38-linux_aarch64.whl +``` + +> Note: for linux, sudo is necessary since it need to interact with bluetoothd +> via dbus with sudo permission + +**For macOS** + +``` +cd out/debug/mac_x64_clang/controller/python +pip3 install chip-0.0-cp38-cp38-mac_aarch64.whl +``` + +## BLE Virtualization on Linux (Optional) + +If we would like to setup virtual BLE central and peripheral in the same +machine, then Bluez setup + +``` +cd third_party/bluez/repo +./bootstrap +third_party/bluez/repo/configure --prefix=/usr --mandir=/usr/share/man --sysconfdir=/etc --localstatedir=/var --enable-experimental --with-systemdsystemunitdir=/lib/systemd/system --with-systemduserunitdir=/usr/lib/systemd --enable-deprecated --enable-testing --enable-tools +make +``` + +Note: You also need to install several packages on RPi if you want to build +bluez + +``` +sudo apt-get install libtool m4 automake autotools-dev libudev-dev libical-dev libreadline-dev +``` + +Run bluetoothd: + +``` +sudo third_party/bluez/repo/src/bluetoothd --experimental --debug & +``` + +Bring up two virtual ble interface: + +``` +sudo third_party/bluez/repo/emulator/btvirt -L -l2 +``` + +## Usage + +1. Run CHIP Device Controller + +``` +sudo chip-device-ctrl +``` + +2. [Required when there are multiple BLE adapters] Select BLE adapter (Linux + only) + +``` +chip-device-ctrl > ble-adapter-print +2020-11-23 17:41:53,116 ChipBLEMgr INFO adapter 0 = DE:AD:BE:EF:00:00 +2020-11-23 17:41:53,116 ChipBLEMgr INFO adapter 1 = DE:AD:BE:EF:01:01 +2020-11-23 17:41:53,116 ChipBLEMgr INFO adapter 2 = DE:AD:BE:EF:02:02 + +chip-device-ctrl > ble-adapter-select DE:AD:BE:EF:00:00 +``` + +3. Scan BLE devices + +``` +chip-device-ctrl > ble-scan +2020-11-23 17:36:18,012 ChipBLEMgr INFO use default adapter +2020-11-23 17:36:18,102 ChipBLEMgr INFO scanning started +2020-11-23 17:36:18,837 ChipBLEMgr INFO Name = CHIP-0000 +2020-11-23 17:36:18,837 ChipBLEMgr INFO ID = f8cc7d32-c110-398b-984b-e43732c9afa1 +2020-11-23 17:36:18,839 ChipBLEMgr INFO RSSI = -56 +2020-11-23 17:36:18,840 ChipBLEMgr INFO address = C3:A7:6C:A5:E3:ED +2020-11-23 17:36:18,843 ChipBLEMgr INFO ADV data: 0000feaf-0000-1000-8000-00805f9b34fb +Connect to BLE device +``` + +**Using device name** + +``` +chip-device-ctrl > ble-connect CHIP-0000 +2020-11-23 17:36:41,894 ChipBLEMgr INFO trying to connect to CHIP-0000 +2020-11-23 17:36:44,571 ChipBLEMgr INFO BLE connecting +2020-11-23 17:36:44,572 ChipBLEMgr INFO Discovering services +2020-11-23 17:36:45,939 ChipBLEMgr INFO Service discovering success +2020-11-23 17:36:45,971 ChipBLEMgr INFO connect success +``` + +**Using device address (on Linux)** + +``` +chip-device-ctrl > ble-connect C3:A7:6C:A5:E3:ED +2020-11-23 17:36:41,894 ChipBLEMgr INFO trying to connect to C3:A7:6C:A5:E3:ED +2020-11-23 17:36:44,571 ChipBLEMgr INFO BLE connecting +2020-11-23 17:36:44,572 ChipBLEMgr INFO Discovering services +2020-11-23 17:36:45,939 ChipBLEMgr INFO Service discovering success +2020-11-23 17:36:45,971 ChipBLEMgr INFO connect success +``` + +**Using uuid (on macOS)** + +``` +chip-device-ctrl > ble-connect f8cc7d32-c110-398b-984b-e43732c9afa1 +2020-11-23 17:36:41,894 ChipBLEMgr INFO trying to connect to f8cc7d32-c110-398b-984b-e43732c9afa1 +2020-11-23 17:36:44,571 ChipBLEMgr INFO BLE connecting +2020-11-23 17:36:44,572 ChipBLEMgr INFO Discovering services +2020-11-23 17:36:45,939 ChipBLEMgr INFO Service discovering success +2020-11-23 17:36:45,971 ChipBLEMgr INFO connect success +``` + +> Note, they will be replaced by using discriminator. + +5. Set wifi credential + +> Note: This command will be deprerated after the network provisioning cluster +> is ready. + +``` +chip-device-ctrl > set-pairing-wifi-credential TestAP TestPassword +``` + +6. Connect to device using setup pin code + +``` +chip-device-ctrl > connect 12345678 +``` + +## Commands + +// TODO: For now, the CHIP device controller does not have any interaction model +(cluster) or service provisioning commands, they will be added to the device +controller as soon as they are implemented. diff --git a/src/controller/python/chip-device-ctrl.py b/src/controller/python/chip-device-ctrl.py index 6921cc0a45f21f..d6850461a8bf5e 100755 --- a/src/controller/python/chip-device-ctrl.py +++ b/src/controller/python/chip-device-ctrl.py @@ -311,7 +311,10 @@ def do_blescan(self, line): def do_bleconnect(self, line): """ - ble-connect + ble-connect + ble-connect + ble-connect + ble-connect Connect to a BLE peripheral identified by line. """ @@ -324,7 +327,10 @@ def do_bleconnect(self, line): def do_blescanconnect(self, line): """ - ble-scan-connect + ble-scan-connect + ble-scan-connect + ble-scan-connect + ble-scan-connect Scan and connect to a BLE peripheral identified by line. """ diff --git a/src/controller/python/chip/ChipBleUtility.py b/src/controller/python/chip/ChipBleUtility.py index c809326cf76d89..7ac34cab1acc85 100644 --- a/src/controller/python/chip/ChipBleUtility.py +++ b/src/controller/python/chip/ChipBleUtility.py @@ -345,3 +345,20 @@ def fromBleSubscribeEvent(cls, bleSubscribeEvent): bleSubscribeEventStruct.Operation = bleSubscribeEvent.Operation bleSubscribeEventStruct.Status = bleSubscribeEvent.Status return bleSubscribeEventStruct + +class BleDeviceIdentificationInfo: + def __init__(self, pairingState, discriminator, vendorId, productId): + self.pairingState = pairingState + self.discriminator = discriminator + self.vendorId = vendorId + self.productId = productId + +def ParseServiceData(data): + if len(data) != 7: + return None + return BleDeviceIdentificationInfo( + int(data[0]), + int.from_bytes(data[1:3], byteorder='little'), + int.from_bytes(data[3:5], byteorder='little'), + int.from_bytes(data[5:7], byteorder='little'), + ) diff --git a/src/controller/python/chip/ChipBluezMgr.py b/src/controller/python/chip/ChipBluezMgr.py index 57af58cff90c70..b6632aabcbf2b6 100644 --- a/src/controller/python/chip/ChipBluezMgr.py +++ b/src/controller/python/chip/ChipBluezMgr.py @@ -63,6 +63,8 @@ BleDisconnectEventStruct, BleRxEventStruct, BleSubscribeEventStruct, + BleDeviceIdentificationInfo, + ParseServiceData, ) from .ChipBleBase import ChipBleBase @@ -282,6 +284,12 @@ def find_devices(self, uuids): if i in uuids: found.append(device) break + # Some devices do not advertise their uuid lists, thus we should also check service data. + if device.ServiceData: + for i in device.ServiceData: + if uuid.UUID(str(i)) in uuids: + found.append(device) + break return found def clear_adapter(self): @@ -789,6 +797,7 @@ def __init__(self, devMgr, logger=None): ) self.scan_quiet = False self.peripheral_list = [] + self.device_uuid_list = [] self.chip_queue = six.moves.queue.Queue() self.Gmainloop = None self.daemon_thread = None @@ -944,15 +953,24 @@ def scan_connect(self, line): return False def dump_scan_result(self, device): - self.logger.info("{0:<10}{1}".format("Name =", device.Name)) - self.logger.info("{0:<10}{1}".format("ID =", device.device_id)) - self.logger.info("{0:<10}{1}".format("RSSI =", device.RSSI)) - self.logger.info("{0:<10}{1}".format("address =", device.Address)) - self.logger.info( - "ADV data: " + ("".join([str(i) for i in dict(device.ServiceData).keys()])) - if device.ServiceData - else "" - ) + self.logger.info("{0:<16}= {1}".format("Name", device.Name)) + self.logger.info("{0:<16}= {1}".format("ID", device.device_id)) + self.logger.info("{0:<16}= {1}".format("RSSI", device.RSSI)) + self.logger.info("{0:<16}= {1}".format("Address", device.Address)) + + devIdInfo = self.get_peripheral_devIdInfo(device) + if devIdInfo != None: + self.logger.info("{0:<16}= {1}".format("Pairing State", devIdInfo.pairingState)) + self.logger.info("{0:<16}= {1}".format("Discriminator", devIdInfo.discriminator)) + self.logger.info("{0:<16}= {1}".format("Vendor Id", devIdInfo.vendorId)) + self.logger.info("{0:<16}= {1}".format("Product Id", devIdInfo.productId)) + + if device.ServiceData: + for advuuid in device.ServiceData: + self.logger.info("{0:<16}= {1}".format("Adv UUID", str(advuuid))) + self.logger.info("{0:<16}= {1}".format("Adv Data", bytes(device.ServiceData[advuuid]).hex())) + else: + self.logger.info("") self.logger.info("") def scan_bg_implementation(self, **kwargs): @@ -963,9 +981,11 @@ def scan_bg_implementation(self, **kwargs): found = False identifier = kwargs["identifier"] timeout = kwargs["timeout"] + time.time() + self.device_uuid_list = [] + self.peripheral_list = [] while time.time() < timeout: - self.peripheral_list = self.adapter.find_devices( + scanned_peripheral_list = self.adapter.find_devices( [ chip_service, chip_service_short, @@ -973,22 +993,28 @@ def scan_bg_implementation(self, **kwargs): chromecast_setup_service_short, ] ) - for device in self.peripheral_list: + for device in scanned_peripheral_list: try: - if not self.scan_quiet: + if not self.scan_quiet and device.Address not in self.device_uuid_list: # display all scanned results + self.device_uuid_list.append(device.Address) + self.peripheral_list.append(device) self.dump_scan_result(device) - if device.Name == identifier or str(device.Address).upper() == str( + devIdInfo = self.get_peripheral_devIdInfo(device) + if not devIdInfo: + # Not a chip device + continue + if identifier and (device.Name == identifier or str(device.Address).upper() == str( identifier.upper() - ): + ) or str(devIdInfo.discriminator) == identifier): if self.scan_quiet: # only display the scanned target's info when quiet self.dump_scan_result(device) self.target = device found = True break - except Exception as ex: - pass + except Exception: + traceback.print_exc() if found: break @@ -1060,20 +1086,36 @@ def disconnect_bg_implementation(self, **kwargs): self.service.destroy() self.service = None + def get_peripheral_devIdInfo(self, peripheral): + if not peripheral.ServiceData: + return None + for advuuid in peripheral.ServiceData: + if str(advuuid).lower() == str(chip_service).lower(): + return ParseServiceData(bytes(peripheral.ServiceData[advuuid])) + return None + def connect(self, identifier): found = False self.logger.info("trying to connect to " + identifier) for p in self.peripheral_list: + p_discriminator = None + devIdInfo = self.get_peripheral_devIdInfo(p) + if not devIdInfo: + # Not a chip device + continue + p_discriminator = devIdInfo.discriminator p_id = str(p.device_id) p_name = str(p.Name) p_address = str(p.Address) self.logger.debug(p_id + " vs " + str(identifier)) self.logger.debug(p_name + " vs " + str(identifier)) self.logger.debug(p_address + " vs " + str(identifier)) + self.logger.debug(str(p_discriminator) + " vs " + str(identifier)) if ( p_id == str(identifier) or p_name == str(identifier) or p_address.upper() == str(identifier).upper() + or str(p_discriminator) == str(identifier) ): self.target = p found = True diff --git a/src/controller/python/chip/ChipCoreBluetoothMgr.py b/src/controller/python/chip/ChipCoreBluetoothMgr.py index 53dcf1d2c6e9a4..15c828631a91fa 100644 --- a/src/controller/python/chip/ChipCoreBluetoothMgr.py +++ b/src/controller/python/chip/ChipCoreBluetoothMgr.py @@ -44,6 +44,8 @@ BleDisconnectEventStruct, BleRxEventStruct, BleSubscribeEventStruct, + BleDeviceIdentificationInfo, + ParseServiceData, ) from .ChipUtility import ChipUtility @@ -104,6 +106,35 @@ def _VoidPtrToCBUUID(ptr, len): return ptr +class LoopCondition: + def __init__(self, op, timelimit, arg = None): + self.op = op + self.due = time.time() + timelimit + self.arg = arg + + def TimeLimitExceeded(self): + return time.time() > self.due + +class BlePeripheral: + def __init__(self, peripheral, advData): + self.peripheral = peripheral + self.advData = dict(advData) + + def __eq__(self, another): + return self.peripheral == another.peripheral + + def getPeripheralDevIdInfo(self): + # CHIP_SERVICE_SHORT + if not self.advData: + return None + servDataDict = self.advData.get("kCBAdvDataServiceData", None) + if not servDataDict: + return None + servDataDict = dict(servDataDict) + for i in servDataDict.keys(): + if str(i).lower() == str(CHIP_SERVICE_SHORT).lower(): + return ParseServiceData(bytes(servDataDict[i])) + return None class CoreBluetoothManager(ChipBleBase): def __init__(self, devCtrl, logger=None): @@ -121,6 +152,7 @@ def __init__(self, devCtrl, logger=None): self.scan_quiet = False self.characteristics = {} self.peripheral_list = [] + self.peripheral_adv_list = [] self.bg_peripheral_name = None self.chip_queue = six.moves.queue.Queue() @@ -135,7 +167,7 @@ def __init__(self, devCtrl, logger=None): self.send_condition = False self.subscribe_condition = False - self.runLoopUntil(("ready", time.time(), 10.0)) + self.runLoopUntil(LoopCondition("ready", 10.0)) self.orig_input_hook = None self.hookFuncPtr = None @@ -171,7 +203,7 @@ def HandleBleCloseCB(connObj): self.logger.info("disconnecting old connection.") self.loop_condition = False self.manager.cancelPeripheralConnection_(periph) - self.runLoopUntil(("disconnect", time.time(), 5.0)) + self.runLoopUntil(LoopCondition("disconnect", 5.0)) self.connect_state = False self.loop_condition = False @@ -207,49 +239,41 @@ def setInputHook(self, hookFunc): # set the new hook. readLine will call this periodically as it polls for input. pyos_inputhook_ptr.value = cast(self.hookFuncPtr, c_void_p).value - def shouldLoop(self, should_tuple): - """ Used by runLoopUntil to determine whether it should exit the runloop.""" - result = False - - time_expired = time.time() >= should_tuple[1] + should_tuple[2] - - if should_tuple[0] == "ready": - if not self.ready_condition and not time_expired: - result = True - elif should_tuple[0] == "scan": - if not time_expired: - result = True + def shouldLoop(self, cond:LoopCondition): + """ Used by runLoopUntil to determine whether it should exit the runloop. """ - for peripheral in self.peripheral_list: - if should_tuple[3] and str(peripheral._.name) == should_tuple[3]: - result = False - break + if cond.TimeLimitExceeded(): + return False - elif should_tuple[0] == "connect": - if not self.loop_condition and not time_expired: - result = True - elif should_tuple[0] == "disconnect": - if not self.loop_condition and not time_expired: - result = True - elif should_tuple[0] == "send": - if not self.send_condition and not time_expired: - result = True - elif should_tuple[0] == "subscribe": - if not self.subscribe_condition and not time_expired: - result = True - elif should_tuple[0] == "unsubscribe": - if self.subscribe_condition and not time_expired: - result = True + if cond.op == "ready": + return not self.ready_condition + elif cond.op == "scan": + for peripheral in self.peripheral_adv_list: + if cond.arg and str(peripheral.peripheral._.name) == cond.arg: + return False + devIdInfo = peripheral.getPeripheralDevIdInfo() + if devIdInfo and cond.arg and str(devIdInfo.discriminator) == cond.arg: + return False + elif cond.op == "connect": + return (not self.loop_condition) + elif cond.op == "disconnect": + return (not self.loop_condition) + elif cond.op == "send": + return (not self.send_condition) + elif cond.op == "subscribe": + return (not self.subscribe_condition) + elif cond.op == "unsubscribe": + return self.subscribe_condition - return result + return True - def runLoopUntil(self, should_tuple): + def runLoopUntil(self, cond:LoopCondition): """Helper function to drive OSX runloop until an expected event is received or the timeout expires.""" runLoop = NSRunLoop.currentRunLoop() nextfire = 1 - while nextfire and self.shouldLoop(should_tuple): + while nextfire and self.shouldLoop(cond): nextfire = runLoop.limitDateForMode_(NSDefaultRunLoopMode) def centralManagerDidUpdateState_(self, manager): @@ -271,23 +295,31 @@ def centralManager_didDiscoverPeripheral_advertisementData_RSSI_( self.logger.info("adding to scan list:") self.logger.info("") self.logger.info( - "{0:<10}{1:<80}".format("Name =", str(peripheral._.name)) + "{0:<16}= {1:<80}".format("Name", str(peripheral._.name)) ) self.logger.info( - "{0:<10}{1:<80}".format( - "ID =", str(peripheral._.identifier.UUIDString()) + "{0:<16}= {1:<80}".format( + "ID", str(peripheral._.identifier.UUIDString()) ) ) - self.logger.info("{0:<10}{1:<80}".format("RSSI =", rssi)) + self.logger.info("{0:<16}= {1:<80}".format("RSSI", rssi)) + devIdInfo = BlePeripheral(peripheral, data).getPeripheralDevIdInfo() + if devIdInfo: + self.logger.info("{0:<16}= {1}".format("Pairing State", devIdInfo.pairingState)) + self.logger.info("{0:<16}= {1}".format("Discriminator", devIdInfo.discriminator)) + self.logger.info("{0:<16}= {1}".format("Vendor Id", devIdInfo.vendorId)) + self.logger.info("{0:<16}= {1}".format("Product Id", devIdInfo.productId)) self.logger.info("ADV data: " + repr(data)) self.logger.info("") self.peripheral_list.append(peripheral) + self.peripheral_adv_list.append(BlePeripheral(peripheral, data)) else: - if peripheral._.name == self.bg_peripheral_name: + if (peripheral._.name == self.bg_peripheral_name) or (str(devIdInfo.discriminator) == self.bg_peripheral_name): if len(self.peripheral_list) == 0: self.logger.info("found background peripheral") self.peripheral_list = [peripheral] + self.peripheral_adv_list = [BlePeripheral(peripheral, data)] def centralManager_didConnectPeripheral_(self, manager, peripheral): """Called by CoreBluetooth via runloop when a connection succeeds.""" @@ -462,7 +494,9 @@ def scan(self, line): self.scan_quiet = args[1] self.bg_peripheral_name = None del self.peripheral_list[:] + del self.peripheral_adv_list[:] self.peripheral_list = [] + self.peripheral_adv_list = [] # Filter on the service UUID Array or None to accept all scan results. self.manager.scanForPeripheralsWithServices_options_( [ @@ -475,7 +509,7 @@ def scan(self, line): ) # self.manager.scanForPeripheralsWithServices_options_(None, None) - self.runLoopUntil(("scan", time.time(), args[0], args[2])) + self.runLoopUntil(LoopCondition("scan", args[0], args[2])) self.manager.stopScan() self.logger.info("scanning stopped") @@ -510,19 +544,24 @@ def connect(self, identifier): if self.connect_state: self.logger.error("ERROR: Connection to a BLE device already exists!") else: - for p in self.peripheral_list: + for peripheral in self.peripheral_adv_list: + p = peripheral.peripheral + devIdInfo = peripheral.getPeripheralDevIdInfo() + if not devIdInfo: + # Not a chip device + continue p_id = str(p.identifier().UUIDString()) p_name = str(p.name()) self.logger.debug(p_id + " vs " + str(identifier)) self.logger.debug(p_name + " vs " + str(identifier)) - if p_id == str(identifier) or p_name == str(identifier): + if p_id == str(identifier) or p_name == str(identifier) or str(devIdInfo.discriminator) == str(identifier): self.loop_condition = False self.peripheral = p self.manager.connectPeripheral_options_(p, None) - self.runLoopUntil(("connect", time.time(), 15.0)) + self.runLoopUntil(LoopCondition("connect", 15.0)) # Cleanup when the connect fails due to timeout, # otherwise CoreBluetooth will continue to try to connect after this # API exits. @@ -550,7 +589,7 @@ def disconnect(self): self.loop_condition = False self.manager.cancelPeripheralConnection_(self.peripheral) - self.runLoopUntil(("disconnect", time.time(), 10.0)) + self.runLoopUntil(LoopCondition("disconnect", 10.0)) resString = "disconnect " + ( "success" if self.loop_condition and not self.connect_state else "fail" diff --git a/src/credentials/BUILD.gn b/src/credentials/BUILD.gn new file mode 100755 index 00000000000000..bcb4feb0d1119b --- /dev/null +++ b/src/credentials/BUILD.gn @@ -0,0 +1,37 @@ +# Copyright (c) 2020-2021 Project CHIP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build_overrides/chip.gni") +import("//build_overrides/nlassert.gni") + +static_library("credentials") { + output_name = "libCredentials" + + sources = [ + "CHIPCert.cpp", + "CHIPCert.h", + "CHIPCertFromX509.cpp", + "CHIPCertToX509.cpp", + ] + + cflags = [ "-Wconversion" ] + + public_deps = [ + "${chip_root}/src/crypto", + "${chip_root}/src/lib/asn1", + "${chip_root}/src/lib/core", + "${chip_root}/src/lib/support", + "${nlassert_root}:nlassert", + ] +} diff --git a/src/credentials/CHIPCert.cpp b/src/credentials/CHIPCert.cpp new file mode 100755 index 00000000000000..c5b5bcd23ca081 --- /dev/null +++ b/src/credentials/CHIPCert.cpp @@ -0,0 +1,843 @@ +/* + * + * Copyright (c) 2020-2021 Project CHIP Authors + * Copyright (c) 2019 Google LLC. + * Copyright (c) 2013-2017 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 + * This file implements objects for modeling and working with + * CHIP certificates. + * + */ + +#ifndef __STDC_LIMIT_MACROS +#define __STDC_LIMIT_MACROS +#endif + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace chip { +namespace Credentials { + +using namespace chip::ASN1; +using namespace chip::TLV; +using namespace chip::Protocols; +using namespace chip::Crypto; + +extern CHIP_ERROR DecodeConvertTBSCert(TLVReader & reader, ASN1Writer & writer, ChipCertificateData & certData); +extern CHIP_ERROR DecodeECDSASignature(TLVReader & reader, ChipCertificateData & certData); + +ChipCertificateSet::ChipCertificateSet() +{ + mCerts = nullptr; + mCertCount = 0; + mMaxCerts = 0; + mDecodeBuf = nullptr; + mDecodeBufSize = 0; + mMemoryAllocInternal = false; +} + +ChipCertificateSet::~ChipCertificateSet() +{ + Release(); +} + +CHIP_ERROR ChipCertificateSet::Init(uint8_t maxCertsArraySize, uint16_t decodeBufSize) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + + VerifyOrExit(maxCertsArraySize > 0, err = CHIP_ERROR_INVALID_ARGUMENT); + mCerts = reinterpret_cast(chip::Platform::MemoryAlloc(sizeof(ChipCertificateData) * maxCertsArraySize)); + VerifyOrExit(mCerts != nullptr, err = CHIP_ERROR_NO_MEMORY); + + VerifyOrExit(decodeBufSize > 0, err = CHIP_ERROR_INVALID_ARGUMENT); + mDecodeBuf = reinterpret_cast(chip::Platform::MemoryAlloc(decodeBufSize)); + VerifyOrExit(mDecodeBuf != nullptr, err = CHIP_ERROR_NO_MEMORY); + + mCertCount = 0; + mMaxCerts = maxCertsArraySize; + mDecodeBufSize = decodeBufSize; + mMemoryAllocInternal = true; + +exit: + if (err != CHIP_NO_ERROR) + { + Release(); + } + + return err; +} + +CHIP_ERROR ChipCertificateSet::Init(ChipCertificateData * certsArray, uint8_t certsArraySize, uint8_t * decodeBuf, + uint16_t decodeBufSize) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + + VerifyOrExit(certsArray != nullptr, err = CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrExit(certsArraySize > 0, err = CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrExit(decodeBuf != nullptr, err = CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrExit(decodeBufSize > 0, err = CHIP_ERROR_INVALID_ARGUMENT); + + mCertCount = 0; + mCerts = certsArray; + mMaxCerts = certsArraySize; + mDecodeBuf = decodeBuf; + mDecodeBufSize = decodeBufSize; + mMemoryAllocInternal = false; + +exit: + return err; +} + +void ChipCertificateSet::Release() +{ + if (mMemoryAllocInternal) + { + if (mCerts != nullptr) + { + chip::Platform::MemoryFree(mCerts); + mCerts = nullptr; + } + if (mDecodeBuf != nullptr) + { + chip::Platform::MemoryFree(mDecodeBuf); + mDecodeBuf = nullptr; + } + } +} + +void ChipCertificateSet::Clear() +{ + for (int i = 0; i < mCertCount; i++) + { + mCerts[i].Clear(); + } + + mCertCount = 0; +} + +CHIP_ERROR ChipCertificateSet::LoadCert(const uint8_t * chipCert, uint32_t chipCertLen, + BitFlags decodeFlags) +{ + CHIP_ERROR err; + TLVReader reader; + + reader.Init(chipCert, chipCertLen); + reader.ImplicitProfileId = kProtocol_OpCredentials; + + err = reader.Next(kTLVType_Structure, ProfileTag(kProtocol_OpCredentials, kTag_ChipCertificate)); + SuccessOrExit(err); + + err = LoadCert(reader, decodeFlags); + +exit: + return err; +} + +CHIP_ERROR ChipCertificateSet::LoadCert(TLVReader & reader, BitFlags decodeFlags) +{ + CHIP_ERROR err; + ASN1Writer writer; // ASN1Writer is used to encode TBS portion of the certificate for the purpose of signature + // validation, which should be performed on the TBS data encoded in ASN.1 DER form. + ChipCertificateData * cert = nullptr; + + // Must be positioned on the structure element representing the certificate. + VerifyOrExit(reader.GetType() == kTLVType_Structure, err = CHIP_ERROR_INVALID_ARGUMENT); + + // Verify we have room for the new certificate. + VerifyOrExit(mCertCount < mMaxCerts, err = CHIP_ERROR_NO_MEMORY); + + cert = new (&mCerts[mCertCount]) ChipCertificateData(); + + { + TLVType containerType; + + // Enter the certificate structure... + err = reader.EnterContainer(containerType); + SuccessOrExit(err); + + // Initialize an ASN1Writer and convert the TBS (to-be-signed) portion of the certificate to ASN.1 DER + // encoding. At the same time, parse various components within the certificate and set the corresponding + // fields in the CertificateData object. + writer.Init(mDecodeBuf, mDecodeBufSize); + err = DecodeConvertTBSCert(reader, writer, *cert); + SuccessOrExit(err); + + // Verify the cert has both the Subject Key Id and Authority Key Id extensions present. + // Only certs with both these extensions are supported for the purposes of certificate validation. + VerifyOrExit(cert->mCertFlags.Has(CertFlags::kExtPresent_SubjectKeyId) && + cert->mCertFlags.Has(CertFlags::kExtPresent_AuthKeyId), + err = CHIP_ERROR_UNSUPPORTED_CERT_FORMAT); + + // Verify the cert was signed with ECDSA-SHA256. This is the only signature algorithm currently supported. + VerifyOrExit(cert->mSigAlgoOID == kOID_SigAlgo_ECDSAWithSHA256, err = CHIP_ERROR_UNSUPPORTED_SIGNATURE_TYPE); + + // If requested, generate the hash of the TBS portion of the certificate... + if (decodeFlags.Has(CertDecodeFlags::kGenerateTBSHash)) + { + // Finish writing the ASN.1 DER encoding of the TBS certificate. + err = writer.Finalize(); + SuccessOrExit(err); + + // Generate a SHA hash of the encoded TBS certificate. + chip::Crypto::Hash_SHA256(mDecodeBuf, writer.GetLengthWritten(), cert->mTBSHash); + + cert->mCertFlags.Set(CertFlags::kTBSHashPresent); + } + + // Decode the certificate's signature... + err = DecodeECDSASignature(reader, *cert); + SuccessOrExit(err); + + // Verify no more elements in the certificate. + err = reader.VerifyEndOfContainer(); + SuccessOrExit(err); + + err = reader.ExitContainer(containerType); + SuccessOrExit(err); + } + + // If requested by the caller, mark the certificate as trusted. + if (decodeFlags.Has(CertDecodeFlags::kIsTrustAnchor)) + { + cert->mCertFlags.Set(CertFlags::kIsTrustAnchor); + } + + // Assign a default type for the certificate based on its subject and attributes. + err = DetermineCertType(*cert); + SuccessOrExit(err); + + mCertCount++; + +exit: + if (err != CHIP_NO_ERROR) + { + if (cert != nullptr) + { + cert->Clear(); + } + } + + return err; +} + +CHIP_ERROR ChipCertificateSet::LoadCerts(const uint8_t * chipCerts, uint32_t chipCertsLen, + BitFlags decodeFlags) +{ + CHIP_ERROR err; + TLVReader reader; + TLVType type; + uint64_t tag; + + reader.Init(chipCerts, chipCertsLen); + reader.ImplicitProfileId = kProtocol_OpCredentials; + + err = reader.Next(); + SuccessOrExit(err); + + type = reader.GetType(); + tag = reader.GetTag(); + + VerifyOrExit((type == kTLVType_Structure && tag == ProfileTag(kProtocol_OpCredentials, kTag_ChipCertificate)) || + (type == kTLVType_Array && tag == ProfileTag(kProtocol_OpCredentials, kTag_ChipCertificateArray)), + err = CHIP_ERROR_UNEXPECTED_TLV_ELEMENT); + + err = LoadCerts(reader, decodeFlags); + +exit: + return err; +} + +CHIP_ERROR ChipCertificateSet::LoadCerts(TLVReader & reader, BitFlags decodeFlags) +{ + CHIP_ERROR err; + uint8_t initialCertCount = mCertCount; + + // If positioned on a structure, we assume that structure is a single certificate. + if (reader.GetType() == kTLVType_Structure) + { + err = LoadCert(reader, decodeFlags); + SuccessOrExit(err); + } + + // Other we expect to be positioned on an Array that contains a sequence of + // zero or more certificates... + else + { + TLVType containerType; + + err = reader.EnterContainer(containerType); + SuccessOrExit(err); + + while ((err = reader.Next()) == CHIP_NO_ERROR) + { + VerifyOrExit(reader.GetTag() == AnonymousTag, err = CHIP_ERROR_UNEXPECTED_TLV_ELEMENT); + + err = LoadCert(reader, decodeFlags); + SuccessOrExit(err); + } + if (err != CHIP_END_OF_TLV) + { + ExitNow(); + } + + err = reader.ExitContainer(containerType); + SuccessOrExit(err); + } + +exit: + if (err != CHIP_NO_ERROR) + { + for (uint8_t i = initialCertCount; i < mCertCount; i++) + { + mCerts[i].Clear(); + } + mCertCount = initialCertCount; + } + + return err; +} + +CHIP_ERROR ChipCertificateSet::AddTrustedKey(uint64_t caId, OID curveOID, const uint8_t * pubKey, uint8_t pubKeyLen, + const uint8_t * pubKeyId, uint8_t pubKeyIdLen) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + ChipCertificateData * cert; + + // Verify we have room for the new certificate. + VerifyOrExit(mCertCount < mMaxCerts, err = CHIP_ERROR_NO_MEMORY); + + cert = new (&mCerts[mCertCount]) ChipCertificateData(); + + cert->mSubjectDN.mAttrOID = kOID_AttributeType_ChipCAId; + cert->mSubjectDN.mAttrValue.mChipId = caId; + cert->mIssuerDN = cert->mSubjectDN; + cert->mPubKeyCurveOID = curveOID; + cert->mPublicKey = pubKey; + cert->mPublicKeyLen = pubKeyLen; + cert->mSubjectKeyId.mId = pubKeyId; + cert->mSubjectKeyId.mLen = pubKeyIdLen; + cert->mAuthKeyId = cert->mSubjectKeyId; + cert->mCertType = kCertType_CA; + + cert->mCertFlags.Set(CertFlags::kExtPresent_BasicConstraints); + cert->mCertFlags.Set(CertFlags::kExtPresent_KeyUsage); + cert->mCertFlags.Set(CertFlags::kExtPresent_SubjectKeyId); + cert->mCertFlags.Set(CertFlags::kExtPresent_AuthKeyId); + cert->mCertFlags.Set(CertFlags::kIsCA); + cert->mCertFlags.Set(CertFlags::kIsTrustAnchor); + + cert->mKeyUsageFlags.Set(KeyUsageFlags::kKeyCertSign); + + mCertCount++; + +exit: + return err; +} + +const ChipCertificateData * ChipCertificateSet::FindCert(const CertificateKeyId & subjectKeyId) const +{ + for (uint8_t i = 0; i < mCertCount; i++) + { + ChipCertificateData & cert = mCerts[i]; + if (cert.mSubjectKeyId.IsEqual(subjectKeyId)) + { + return &cert; + } + } + + return nullptr; +} + +bool ChipCertificateSet::IsCertInTheSet(const ChipCertificateData * cert) const +{ + for (uint8_t i = 0; i < mCertCount; i++) + { + if (cert == &mCerts[i]) + { + return true; + } + } + + return false; +} + +CHIP_ERROR ChipCertificateSet::ValidateCert(const ChipCertificateData * cert, ValidationContext & context) +{ + CHIP_ERROR err; + + VerifyOrExit(IsCertInTheSet(cert), err = CHIP_ERROR_INVALID_ARGUMENT); + + context.mTrustAnchor = nullptr; + + err = ValidateCert(cert, context, context.mValidateFlags, 0); + +exit: + return err; +} + +CHIP_ERROR ChipCertificateSet::FindValidCert(const ChipDN & subjectDN, const CertificateKeyId & subjectKeyId, + ValidationContext & context, ChipCertificateData *& cert) +{ + CHIP_ERROR err; + + context.mTrustAnchor = nullptr; + + err = FindValidCert(subjectDN, subjectKeyId, context, context.mValidateFlags, 0, cert); + SuccessOrExit(err); + +exit: + return err; +} + +CHIP_ERROR ChipCertificateSet::VerifySignature(const ChipCertificateData * cert, const ChipCertificateData * caCert) +{ + static constexpr size_t kMaxBytesForDeferredLenList = sizeof(uint8_t *) + // size of a single pointer in the deferred list + 4 + // extra memory allocated for the deferred length field (kLengthFieldReserveSize - 1) + 3; // the deferred length list is alligned to 32bit boundary + + CHIP_ERROR err; + P256PublicKey caPublicKey; + P256ECDSASignature signature; + uint8_t tmpBuf[signature.Capacity() + kMaxBytesForDeferredLenList]; + ASN1Writer writer; + + writer.Init(tmpBuf, static_cast(sizeof(tmpBuf))); + + // Ecdsa-Sig-Value ::= SEQUENCE + ASN1_START_SEQUENCE + { + // r INTEGER + err = writer.PutValue(kASN1TagClass_Universal, kASN1UniversalTag_Integer, false, cert->mSignature.R, cert->mSignature.RLen); + SuccessOrExit(err); + + // s INTEGER + err = writer.PutValue(kASN1TagClass_Universal, kASN1UniversalTag_Integer, false, cert->mSignature.S, cert->mSignature.SLen); + SuccessOrExit(err); + } + ASN1_END_SEQUENCE; + + err = writer.Finalize(); + SuccessOrExit(err); + + VerifyOrExit(writer.GetLengthWritten() <= signature.Capacity(), err = CHIP_ERROR_BUFFER_TOO_SMALL); + + memcpy(signature, tmpBuf, writer.GetLengthWritten()); + err = signature.SetLength(writer.GetLengthWritten()); + SuccessOrExit(err); + + memcpy(caPublicKey, caCert->mPublicKey, caCert->mPublicKeyLen); + + err = caPublicKey.ECDSA_validate_hash_signature(cert->mTBSHash, chip::Crypto::kSHA256_Hash_Length, signature); + SuccessOrExit(err); + +exit: + return err; +} + +CHIP_ERROR ChipCertificateSet::ValidateCert(const ChipCertificateData * cert, ValidationContext & context, + BitFlags validateFlags, uint8_t depth) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + ChipCertificateData * caCert = nullptr; + static constexpr int kLastSecondOfDay = kSecondsPerDay - 1; + + // If the depth is greater than 0 then the certificate is required to be a CA certificate... + if (depth > 0) + { + // Verify the isCA flag is present. + VerifyOrExit(cert->mCertFlags.Has(CertFlags::kIsCA), err = CHIP_ERROR_CERT_USAGE_NOT_ALLOWED); + + // Verify the key usage extension is present and contains the 'keyCertSign' flag. + VerifyOrExit(cert->mCertFlags.Has(CertFlags::kExtPresent_KeyUsage) && cert->mKeyUsageFlags.Has(KeyUsageFlags::kKeyCertSign), + err = CHIP_ERROR_CERT_USAGE_NOT_ALLOWED); + + // Verify that the certificate type is set to "CA". + VerifyOrExit(cert->mCertType == kCertType_CA, err = CHIP_ERROR_WRONG_CERT_TYPE); + + // If a path length constraint was included, verify the cert depth vs. the specified constraint. + // + // From the RFC, the path length constraint "gives the maximum number of non-self-issued + // intermediate certificates that may follow this certificate in a valid certification path. + // (Note: The last certificate in the certification path is not an intermediate certificate, + // and is not included in this limit...)" + // + if (cert->mCertFlags.Has(CertFlags::kPathLenConstraintPresent)) + { + VerifyOrExit((depth - 1) <= cert->mPathLenConstraint, err = CHIP_ERROR_CERT_PATH_LEN_CONSTRAINT_EXCEEDED); + } + } + + // Otherwise verify the desired certificate usages/purposes/type given in the validation context... + else + { + // If a set of desired key usages has been specified, verify that the key usage extension exists + // in the certificate and that the corresponding usages are supported. + if (context.mRequiredKeyUsages.Raw() != 0) + { + VerifyOrExit(cert->mCertFlags.Has(CertFlags::kExtPresent_KeyUsage) && + cert->mKeyUsageFlags.Has(context.mRequiredKeyUsages.Raw()), + err = CHIP_ERROR_CERT_USAGE_NOT_ALLOWED); + } + + // If a set of desired key purposes has been specified, verify that the extended key usage extension + // exists in the certificate and that the corresponding purposes are supported. + if (context.mRequiredKeyPurposes.Raw() != 0) + { + VerifyOrExit(cert->mCertFlags.Has(CertFlags::kExtPresent_ExtendedKeyUsage) && + cert->mKeyPurposeFlags.Has(context.mRequiredKeyPurposes.Raw()), + err = CHIP_ERROR_CERT_USAGE_NOT_ALLOWED); + } + + // If a required certificate type has been specified, verify it against the current certificate's type. + if (context.mRequiredCertType != kCertType_NotSpecified) + { + VerifyOrExit(cert->mCertType == context.mRequiredCertType, err = CHIP_ERROR_WRONG_CERT_TYPE); + } + } + + // Verify the validity time of the certificate, if requested. + if (cert->mNotBeforeDate != 0 && !validateFlags.Has(CertValidateFlags::kIgnoreNotBefore)) + { + VerifyOrExit(context.mEffectiveTime >= PackedCertDateToTime(cert->mNotBeforeDate), err = CHIP_ERROR_CERT_NOT_VALID_YET); + } + if (cert->mNotAfterDate != 0 && !validateFlags.Has(CertValidateFlags::kIgnoreNotAfter)) + { + VerifyOrExit(context.mEffectiveTime <= PackedCertDateToTime(cert->mNotAfterDate) + kLastSecondOfDay, + err = CHIP_ERROR_CERT_EXPIRED); + } + + // If the certificate itself is trusted, then it is implicitly valid. Record this certificate as the trust + // anchor and return success. + if (cert->mCertFlags.Has(CertFlags::kIsTrustAnchor)) + { + context.mTrustAnchor = cert; + ExitNow(err = CHIP_NO_ERROR); + } + + // Otherwise we must validate the certificate by looking for a chain of valid certificates up to a trusted + // certificate known as the 'trust anchor'. + + // Fail validation if the certificate is self-signed. Since we don't trust this certificate (see the check above) and + // it has no path we can follow to a trust anchor, it can't be considered valid. + if (cert->mIssuerDN.IsEqual(cert->mSubjectDN) && cert->mAuthKeyId.IsEqual(cert->mSubjectKeyId)) + { + ExitNow(err = CHIP_ERROR_CERT_NOT_TRUSTED); + } + + // Verify that the certificate depth is less than the total number of certificates. It is technically possible to create + // a circular chain of certificates. Limiting the maximum depth of the certificate path prevents infinite + // recursion in such a case. + VerifyOrExit(depth < mCertCount, err = CHIP_ERROR_CERT_PATH_TOO_LONG); + + // Verify that a hash of the 'to-be-signed' portion of the certificate has been computed. We will need this to + // verify the cert's signature below. + VerifyOrExit(cert->mCertFlags.Has(CertFlags::kTBSHashPresent), err = CHIP_ERROR_INVALID_ARGUMENT); + + // Search for a valid CA certificate that matches the Issuer DN and Authority Key Id of the current certificate. + // Fail if no acceptable certificate is found. + err = FindValidCert(cert->mIssuerDN, cert->mAuthKeyId, context, validateFlags, static_cast(depth + 1), caCert); + if (err != CHIP_NO_ERROR) + { + ExitNow(err = CHIP_ERROR_CA_CERT_NOT_FOUND); + } + + // Verify signature of the current certificate against public key of the CA certificate. If signature verification + // succeeds, the current certificate is valid. + err = VerifySignature(cert, caCert); + SuccessOrExit(err); + +exit: + return err; +} + +CHIP_ERROR ChipCertificateSet::FindValidCert(const ChipDN & subjectDN, const CertificateKeyId & subjectKeyId, + ValidationContext & context, BitFlags validateFlags, + uint8_t depth, ChipCertificateData *& cert) +{ + CHIP_ERROR err; + + // Default error if we don't find any matching cert. + err = (depth > 0) ? CHIP_ERROR_CA_CERT_NOT_FOUND : CHIP_ERROR_CERT_NOT_FOUND; + + // Fail immediately if neither of the input criteria are specified. + if (subjectDN.IsEmpty() && subjectKeyId.IsEmpty()) + { + ExitNow(); + } + + // For each cert in the set... + for (uint8_t i = 0; i < mCertCount; i++) + { + ChipCertificateData * candidateCert = &mCerts[i]; + + // Skip the certificate if its subject DN and key id do not match the input criteria. + if (!subjectDN.IsEmpty() && !candidateCert->mSubjectDN.IsEqual(subjectDN)) + { + continue; + } + if (!subjectKeyId.IsEmpty() && !candidateCert->mSubjectKeyId.IsEqual(subjectKeyId)) + { + continue; + } + + // Attempt to validate the cert. If the cert is valid, return it to the caller. Otherwise, + // save the returned error and continue searching. If there are no other matching certs this + // will be the error returned to the caller. + err = ValidateCert(candidateCert, context, validateFlags, depth); + if (err == CHIP_NO_ERROR) + { + cert = candidateCert; + ExitNow(); + } + } + + cert = nullptr; + +exit: + return err; +} + +ChipCertificateData::ChipCertificateData() +{ + Clear(); +} + +ChipCertificateData::~ChipCertificateData() {} + +void ChipCertificateData::Clear() +{ + mSubjectDN.Clear(); + mIssuerDN.Clear(); + mSubjectKeyId.Clear(); + mAuthKeyId.Clear(); + mNotBeforeDate = 0; + mNotAfterDate = 0; + mPublicKey = nullptr; + mPublicKeyLen = 0; + mPubKeyCurveOID = 0; + mPubKeyAlgoOID = 0; + mSigAlgoOID = 0; + mCertFlags.SetRaw(0); + mKeyUsageFlags.SetRaw(0); + mKeyPurposeFlags.SetRaw(0); + mPathLenConstraint = 0; + mCertType = kCertType_NotSpecified; + mSignature.R = nullptr; + mSignature.RLen = 0; + mSignature.S = nullptr; + mSignature.SLen = 0; + memset(mTBSHash, 0, sizeof(mTBSHash)); +} + +void ValidationContext::Reset() +{ + mEffectiveTime = 0; + mTrustAnchor = nullptr; + mSigningCert = nullptr; + mRequiredKeyUsages.SetRaw(0); + mRequiredKeyPurposes.SetRaw(0); + mValidateFlags.SetRaw(0); + mRequiredCertType = kCertType_NotSpecified; +} + +CHIP_ERROR DetermineCertType(ChipCertificateData & cert) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + + // If the certificate subject contains a ChipCAId attribute... + if (cert.mSubjectDN.mAttrOID == kOID_AttributeType_ChipCAId) + { + // Verify the BasicConstraints isCA flag is true. + VerifyOrExit(cert.mCertFlags.Has(CertFlags::kIsCA), err = CHIP_ERROR_CERT_USAGE_NOT_ALLOWED); + + // Verify the key usage extension is present and contains the 'keyCertSign' flag. + VerifyOrExit(cert.mCertFlags.Has(CertFlags::kExtPresent_KeyUsage) && cert.mKeyUsageFlags.Has(KeyUsageFlags::kKeyCertSign), + err = CHIP_ERROR_CERT_USAGE_NOT_ALLOWED); + + // Set the certificate type to CA. + cert.mCertType = kCertType_CA; + } + + // If the certificate subject contains a ChipNodeId attribute set the certificate type to Node. + else if (cert.mSubjectDN.mAttrOID == kOID_AttributeType_ChipNodeId) + { + cert.mCertType = kCertType_Node; + } + + // If the certificate subject contains a ChipSoftwarePublisherId attribute set the certificate type to FirmwareSigning. + else if (cert.mSubjectDN.mAttrOID == kOID_AttributeType_ChipSoftwarePublisherId) + { + cert.mCertType = kCertType_FirmwareSigning; + } + + else + { + err = CHIP_ERROR_WRONG_CERT_TYPE; + } + +exit: + return err; +} + +bool ChipDN::IsEqual(const ChipDN & other) const +{ + if (mAttrOID == kOID_Unknown || mAttrOID == kOID_NotSpecified || mAttrOID != other.mAttrOID) + { + return false; + } + + if (IsChipIdX509Attr(mAttrOID)) + { + return mAttrValue.mChipId == other.mAttrValue.mChipId; + } + else + { + return (mAttrValue.mString.mLen == other.mAttrValue.mString.mLen && + memcmp(mAttrValue.mString.mValue, other.mAttrValue.mString.mValue, mAttrValue.mString.mLen) == 0); + } +} + +bool CertificateKeyId::IsEqual(const CertificateKeyId & other) const +{ + return mId != nullptr && other.mId != nullptr && mLen == other.mLen && memcmp(mId, other.mId, mLen) == 0; +} + +DLL_EXPORT CHIP_ERROR PackCertTime(const ASN1UniversalTime & time, uint32_t & packedTime) +{ + enum + { + kCertTimeBaseYear = 2020, + kCertTimeMaxYear = kCertTimeBaseYear + + UINT32_MAX / (kMonthsPerYear * kMaxDaysPerMonth * kHoursPerDay * kMinutesPerHour * kSecondsPerMinute), + kX509NoWellDefinedExpirationDateYear = 9999 + }; + + // The packed time in a CHIP certificate cannot represent dates prior to 2020/01/01. + if (time.Year < kCertTimeBaseYear) + { + return ASN1_ERROR_UNSUPPORTED_ENCODING; + } + + // X.509/RFC5280 defines the special time 99991231235959Z to mean 'no well-defined expiration date'. + // We represent that as a packed time value of 0, which for simplicity's sake is assigned to any + // date in the associated year. + if (time.Year == kX509NoWellDefinedExpirationDateYear) + { + packedTime = kNullCertTime; + return CHIP_NO_ERROR; + } + + // Technically packed certificate time values could grow beyond 32bits. However we restrict it here + // to dates that fit within 32bits to reduce code size and eliminate the need for 64bit math. + if (time.Year > kCertTimeMaxYear) + { + return ASN1_ERROR_UNSUPPORTED_ENCODING; + } + + packedTime = time.Year - kCertTimeBaseYear; + packedTime = packedTime * kMonthsPerYear + time.Month - 1; + packedTime = packedTime * kMaxDaysPerMonth + time.Day - 1; + packedTime = packedTime * kHoursPerDay + time.Hour; + packedTime = packedTime * kMinutesPerHour + time.Minute; + packedTime = packedTime * kSecondsPerMinute + time.Second; + + return CHIP_NO_ERROR; +} + +DLL_EXPORT CHIP_ERROR UnpackCertTime(uint32_t packedTime, ASN1UniversalTime & time) +{ + enum + { + kCertTimeBaseYear = 2020, + kX509NoWellDefinedExpirationDateYear = 9999, + }; + + // X.509/RFC5280 defines the special time 99991231235959Z to mean 'no well-defined expiration date'. + // We represent that as a packed time value of 0. + if (packedTime == kNullCertTime) + { + time.Year = kX509NoWellDefinedExpirationDateYear; + time.Month = kMonthsPerYear; + time.Day = kMaxDaysPerMonth; + time.Hour = kHoursPerDay - 1; + time.Minute = kMinutesPerHour - 1; + time.Second = kSecondsPerMinute - 1; + } + + else + { + time.Second = static_cast(packedTime % kSecondsPerMinute); + packedTime /= kSecondsPerMinute; + + time.Minute = static_cast(packedTime % kMinutesPerHour); + packedTime /= kMinutesPerHour; + + time.Hour = static_cast(packedTime % kHoursPerDay); + packedTime /= kHoursPerDay; + + time.Day = static_cast((packedTime % kMaxDaysPerMonth) + 1); + packedTime /= kMaxDaysPerMonth; + + time.Month = static_cast((packedTime % kMonthsPerYear) + 1); + packedTime /= kMonthsPerYear; + + time.Year = static_cast(packedTime + kCertTimeBaseYear); + } + + return CHIP_NO_ERROR; +} + +DLL_EXPORT uint16_t PackedCertTimeToDate(uint32_t packedTime) +{ + return static_cast(packedTime / kSecondsPerDay); +} + +DLL_EXPORT uint32_t PackedCertDateToTime(uint16_t packedDate) +{ + return static_cast(packedDate * kSecondsPerDay); +} + +DLL_EXPORT uint32_t SecondsSinceEpochToPackedCertTime(uint32_t secondsSinceEpoch) +{ + chip::ASN1::ASN1UniversalTime asn1Time; + uint32_t packedTime; + + // Convert seconds-since-epoch to calendar date and time and store in an ASN1UniversalTime structure. + SecondsSinceEpochToCalendarTime(secondsSinceEpoch, asn1Time.Year, asn1Time.Month, asn1Time.Day, asn1Time.Hour, asn1Time.Minute, + asn1Time.Second); + + // Convert the calendar date/time to a packed certificate date/time. + PackCertTime(asn1Time, packedTime); + + return packedTime; +} + +} // namespace Credentials +} // namespace chip diff --git a/src/credentials/CHIPCert.h b/src/credentials/CHIPCert.h new file mode 100755 index 00000000000000..d08c9c61790368 --- /dev/null +++ b/src/credentials/CHIPCert.h @@ -0,0 +1,718 @@ +/* + * + * Copyright (c) 2020-2021 Project CHIP Authors + * Copyright (c) 2019 Google LLC. + * Copyright (c) 2013-2017 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 + * This file defines data types and objects for modeling and + * working with CHIP certificates. + * + */ + +#pragma once + +#include + +#include +#include +#include +#include +#include +#include + +namespace chip { +namespace Credentials { + +/** Data Element Tags for the CHIP Certificate + */ +enum +{ + // ---- Top-level Protocol-Specific Tags ---- + kTag_ChipCertificate = 1, /**< [ structure ] A CHIP certificate. */ + kTag_ChipCertificateArray = 2, /**< [ array ] An array of CHIP certificates. */ + + // ---- Context-specific Tags for ChipCertificate Structure ---- + kTag_SerialNumber = 1, /**< [ byte string ] Certificate serial number, in BER integer encoding. */ + kTag_SignatureAlgorithm = 2, /**< [ unsigned int ] Enumerated value identifying the certificate signature algorithm. */ + kTag_Issuer = 3, /**< [ list ] The issuer distinguished name of the certificate. */ + kTag_NotBefore = 4, /**< [ unsigned int ] Certificate validity period start (certificate date format). */ + kTag_NotAfter = 5, /**< [ unsigned int ] Certificate validity period end (certificate date format). */ + kTag_Subject = 6, /**< [ list ] The subject distinguished name of the certificate. */ + kTag_PublicKeyAlgorithm = 7, /**< [ unsigned int ] Identifies the algorithm with which the public key can be used. */ + kTag_EllipticCurveIdentifier = 8, /**< [ unsigned int ] For EC certs, identifies the elliptic curve used. */ + kTag_EllipticCurvePublicKey = 9, /**< [ byte string ] The elliptic curve public key, in X9.62 encoded format. */ + kTag_ECDSASignature = 10, /**< [ structure ] The ECDSA signature for the certificate. */ + // ---- Tags identifying certificate extensions (tag numbers 128 - 255) ---- + kCertificateExtensionTagsStart = 128, + kTag_BasicConstraints = 128, /**< [ structure ] Identifies whether the subject of the certificate is a CA. */ + kTag_KeyUsage = 129, /**< [ structure ] Purpose of the key contained in the certificate. */ + kTag_ExtendedKeyUsage = 130, /**< [ structure ] Purposes for which the certified public key may be used. */ + kTag_SubjectKeyIdentifier = 131, /**< [ structure ] Information about the certificate's public key. */ + kTag_AuthorityKeyIdentifier = 132, /**< [ structure ] Information about the public key used to sign the certificate. */ + kCertificateExtensionTagsEnd = 255, + + // ---- Context-specific Tags for ECDSASignature Structure ---- + kTag_ECDSASignature_r = 1, /**< [ byte string ] ECDSA r value, in ASN.1 integer encoding. */ + kTag_ECDSASignature_s = 2, /**< [ byte string ] ECDSA s value, in ASN.1 integer encoding. */ + + // ---- Context-specific Tags for AuthorityKeyIdentifier Structure ---- + kTag_AuthorityKeyIdentifier_Critical = 1, /**< [ boolean ] True if the AuthorityKeyIdentifier extension is critical. + Otherwise absent. */ + kTag_AuthorityKeyIdentifier_KeyIdentifier = 2, /**< [ byte string ] Unique identifier of the issuer's public key, + per RFC5280. */ + + // ---- Context-specific Tags for SubjectKeyIdentifier Structure ---- + kTag_SubjectKeyIdentifier_Critical = 1, /**< [ boolean ] True if the SubjectKeyIdentifier extension is critical. + Otherwise absent. */ + kTag_SubjectKeyIdentifier_KeyIdentifier = 2, /**< [ byte string ] Unique identifier for certificate's public key, + per RFC5280. */ + + // ---- Context-specific Tags for KeyUsage Structure ---- + kTag_KeyUsage_Critical = 1, /**< [ boolean ] True if the KeyUsage extension is critical. Otherwise absent. */ + kTag_KeyUsage_KeyUsage = 2, /**< [ unsigned int ] Integer containing key usage bits, per to RFC5280. */ + + // ---- Context-specific Tags for BasicConstraints Structure ---- + kTag_BasicConstraints_Critical = 1, /**< [ boolean ] True if the BasicConstraints extension is critical. + Otherwise absent. */ + kTag_BasicConstraints_IsCA = 2, /**< [ boolean ] True if the certificate can be used to verify certificate + signatures. */ + kTag_BasicConstraints_PathLenConstraint = 3, /**< [ unsigned int ] Maximum number of subordinate intermediate certificates. */ + + // ---- Context-specific Tags for ExtendedKeyUsage Structure ---- + kTag_ExtendedKeyUsage_Critical = 1, /**< [ boolean ] True if the ExtendedKeyUsage extension is critical. Otherwise absent. */ + kTag_ExtendedKeyUsage_KeyPurposes = 2, /**< [ array ] Array of enumerated values giving the purposes for which the public key + can be used. */ +}; + +/** Identifies the purpose or application of certificate + * + * A certificate type is a label that describes a certificate's purpose or application. + * Certificate types are not carried as attributes of the corresponding certificates, but + * rather are derived from the certificate's structure and/or the context in which it is used. + * The certificate type enumeration includes a set of pre-defined values describing commonly + * used certificate applications. Developers can also extend the certificate type value + * range with application-specific types that described custom certificates or certificates + * with unique security properties. + * + * Certificate types are primarily used in the implementation of access control policies, + * where access to application features is influenced by the type of certificate presented + * by a requester. + * + * @note Cert type is an API data type only; it should never be sent over-the-wire. + */ +enum +{ + kCertType_NotSpecified = 0x00, /**< The certificate's type has not been specified. */ + kCertType_CA = 0x01, /**< A CHIP CA certificate. */ + kCertType_Node = 0x02, /**< A CHIP node certificate. */ + kCertType_FirmwareSigning = 0x03, /**< A CHIP firmware signing certificate. */ + kCertType_AppDefinedBase = 0x7F, /**< Application-specific certificate types should have values >= this value. */ +}; + +/** X.509 Certificate Key Purpose Flags + * + * The flags order must match the enumeration order of corresponding kOID_KeyPurpose values. + */ +enum class KeyPurposeFlags : uint8_t +{ + kServerAuth = 0x01, /**< Extended key usage is server authentication. */ + kClientAuth = 0x02, /**< Extended key usage is client authentication. */ + kCodeSigning = 0x04, /**< Extended key usage is code signing. */ + kEmailProtection = 0x08, /**< Extended key usage is email protection. */ + kTimeStamping = 0x10, /**< Extended key usage is time stamping. */ + kOCSPSigning = 0x20, /**< Extended key usage is OCSP signing. */ +}; + +/** X.509 Certificate Key Usage Flags + */ +enum class KeyUsageFlags : uint16_t +{ + kDigitalSignature = 0x0001, /**< Key usage is digital signature. */ + kNonRepudiation = 0x0002, /**< Key usage is non-repudiation. */ + kKeyEncipherment = 0x0004, /**< Key usage is key encipherment. */ + kDataEncipherment = 0x0008, /**< Key usage is data encipherment. */ + kKeyAgreement = 0x0010, /**< Key usage is key agreement. */ + kKeyCertSign = 0x0020, /**< Key usage is key cert signing. */ + kCRLSign = 0x0040, /**< Key usage is CRL signing. */ + kEncipherOnly = 0x0080, /**< Key usage is encipher only. */ + kDecipherOnly = 0x0100, /**< Key usage is decipher only. */ +}; + +/** CHIP Certificate Flags + * + * Contains information about a certificate that has been loaded into a ChipCertificateData object. + */ +enum class CertFlags : uint16_t +{ + kExtPresent_BasicConstraints = 0x0001, /**< Basic constraints extension is present in the certificate. */ + kExtPresent_KeyUsage = 0x0002, /**< Key usage extention is present in the certificate. */ + kExtPresent_ExtendedKeyUsage = 0x0004, /**< Extended key usage extention is present in the certificate. */ + kExtPresent_SubjectKeyId = 0x0008, /**< Subject key identifier extention is present in the certificate. */ + kExtPresent_AuthKeyId = 0x0010, /**< Authority key identifier extention is present in the certificate. */ + kPathLenConstraintPresent = 0x0020, /**< Path length constraint is present in the certificate. */ + kIsCA = 0x0040, /**< Indicates that certificate is a CA certificate. */ + kIsTrustAnchor = 0x0080, /**< Indicates that certificate is a trust anchor. */ + kTBSHashPresent = 0x0100, /**< Indicates that TBS hash of the certificate was generated and stored. */ +}; + +/** CHIP Certificate Decode Flags + * + * Contains information specifying how a certificate should be decoded. + */ +enum class CertDecodeFlags : uint8_t +{ + kGenerateTBSHash = 0x01, /**< Indicates that to-be-signed (TBS) hash of the certificate should be calculated when certificate is + loaded. The TBS hash is then used to validate certificate signature. Normally, all certificates + (except trust anchor) in the certificate validation chain require TBS hash. */ + kIsTrustAnchor = 0x02, /**< Indicates that the corresponding certificate is trust anchor. */ +}; + +/** CHIP Certificate Validate Flags + * + * Contains information specifying how a certificate should be validated. + */ +enum class CertValidateFlags : uint8_t +{ + kIgnoreNotBefore = 0x01, /**< Indicate that a Not Before field should be ignored when doing certificate validation. This + flag applies to all certificates in the validation chain. */ + kIgnoreNotAfter = 0x02, /**< Indicate that a Not After field should be ignored when doing certificate validation. This + flag applies to all certificates in the validation chain. */ +}; + +enum +{ + kNullCertTime = 0 +}; + +/** + * @struct ChipDN + * + * @brief + * A data structure representing a Distinguished Name (DN) in a CHIP certificate. + */ +struct ChipDN +{ + union + { + uint64_t mChipId; /**< CHIP specific DN attribute value. */ + struct + { + const uint8_t * mValue; /**< Pointer to the DN attribute value. */ + uint32_t mLen; /**< DN attribute length. */ + } mString; /**< DN attribute structure when encoded as a string. */ + } mAttrValue; /**< DN attribute value union: string or unsigned integer. */ + chip::ASN1::OID mAttrOID; /**< DN attribute CHIP OID. */ + + bool IsEqual(const ChipDN & other) const; + bool IsEmpty() const { return mAttrOID == chip::ASN1::kOID_NotSpecified; } + void Clear() { mAttrOID = chip::ASN1::kOID_NotSpecified; } +}; + +/** + * @struct CertificateKeyId + * + * @brief + * A data structure representing a certificate key identifier. + */ +struct CertificateKeyId +{ + const uint8_t * mId; /**< Pointer to the key identifier. Encoded as Octet String and represented as the ASN.1 DER Integer (X.690 + standard). */ + uint8_t mLen; /**< Key identifier length. */ + + bool IsEqual(const CertificateKeyId & other) const; + bool IsEmpty() const { return mId == nullptr; } + void Clear() { mId = nullptr; } +}; + +/** + * @struct ChipCertificateData + * + * @brief + * In-memory representation of data extracted from a CHIP certificate. + * + * Some of the fields in this structure are pointers to the fields in the original + * CHIP certificate. That CHIP certificate is stored in a separate buffer and it is + * required that data in that buffer remains valid while the corresponding + * ChipCertificateData structure is used. + */ +struct ChipCertificateData +{ + ChipCertificateData(); + ~ChipCertificateData(); + + void Clear(); + + ChipDN mSubjectDN; /**< Certificate Subject DN. */ + ChipDN mIssuerDN; /**< Certificate Issuer DN. */ + CertificateKeyId mSubjectKeyId; /**< Certificate Subject public key identifier. */ + CertificateKeyId mAuthKeyId; /**< Certificate Authority public key identifier. */ + uint16_t mNotBeforeDate; /**< Certificate validity: Not Before field. */ + uint16_t mNotAfterDate; /**< Certificate validity: Not After field. */ + const uint8_t * mPublicKey; /**< Pointer to the certificate public key. */ + uint8_t mPublicKeyLen; /**< Certificate public key length. */ + uint16_t mPubKeyCurveOID; /**< Public key Elliptic Curve CHIP OID. */ + uint16_t mPubKeyAlgoOID; /**< Public key algorithm CHIP OID. */ + uint16_t mSigAlgoOID; /**< Certificate signature algorithm CHIP OID. */ + BitFlags mCertFlags; /**< Certificate data flags. */ + BitFlags mKeyUsageFlags; /**< Certificate key usage extensions flags. */ + BitFlags mKeyPurposeFlags; /**< Certificate extended key usage extensions flags. */ + uint8_t mPathLenConstraint; /**< Basic constraint: path length. */ + uint8_t mCertType; /**< Certificate type. */ + struct + { + const uint8_t * R; /**< Pointer to the R element of the signature, encoded as ASN.1 DER Integer. */ + uint8_t RLen; /**< Length of R. */ + const uint8_t * S; /**< Pointer to the S element of the signature, encoded as ASN.1 DER Integer. */ + uint8_t SLen; /**< Length of R. */ + } mSignature; /**< Certificate signature structure. */ + uint8_t mTBSHash[chip::Crypto::kSHA256_Hash_Length]; /**< Certificate TBS hash. */ +}; + +/** + * @struct ValidationContext + * + * @brief + * Context information used during certification validation. + */ +struct ValidationContext +{ + uint32_t mEffectiveTime; /**< Current time in the CHIP Packed Certificate Time format. */ + const ChipCertificateData * mTrustAnchor; /**< Pointer to the Trust Anchor Certificate data structure. */ + const ChipCertificateData * mSigningCert; /**< Pointer to the Signing Certificate data structure. */ + BitFlags mRequiredKeyUsages; /**< Key usage extensions that should be present in the + validated certificate. */ + BitFlags mRequiredKeyPurposes; /**< Extended Key usage extensions that should be present + in the validated certificate. */ + BitFlags mValidateFlags; /**< Certificate validation flags, specifying how a certificate + should be validated. */ + uint8_t mRequiredCertType; /**< Required certificate type. */ + + void Reset(); +}; + +/** + * @class ChipCertificateSet + * + * @brief + * Collection of CHIP certificate data providing methods for + * certificate validation and signature verification. + */ +class DLL_EXPORT ChipCertificateSet +{ +public: + ChipCertificateSet(); + ~ChipCertificateSet(); + + /** + * @brief Initialize ChipCertificateSet. + * This initialization method is used when all memory structures needed for operation are + * allocated internally using chip::Platform::MemoryAlloc() and freed with chip::Platform::MemoryFree(). + * + * @param maxCertsArraySize Maximum number of CHIP certificates to be loaded to the set. + * @param decodeBufSize Size of the buffer that should be allocated to perform CHIP certificate decoding. + * + * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise + **/ + CHIP_ERROR Init(uint8_t maxCertsArraySize, uint16_t decodeBufSize); + + /** + * @brief Initialize ChipCertificateSet. + * This initialization method is used when all memory structures needed for operation are + * allocated externally and methods in this class don't need to deal with memory allocations. + * + * @param certsArray A pointer to the array of the ChipCertificateData structures. + * @param certsArraySize Number of ChipCertificateData entries in the array. + * @param decodeBuf Buffer to use for temporary storage of intermediate processing results. + * @param decodeBufSize Size of decoding buffer. + * + * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise + **/ + CHIP_ERROR Init(ChipCertificateData * certsArray, uint8_t certsArraySize, uint8_t * decodeBuf, uint16_t decodeBufSize); + + /** + * @brief Release resources allocated by this class. + **/ + void Release(); + + /** + * @brief Clear certificate data loaded into this set. + **/ + void Clear(); + + /** + * @brief Load CHIP certificate into set. + * It is required that the CHIP certificate in the chipCert buffer stays valid while + * the certificate data in the set is used. + * In case of an error the certificate set is left in the same state as prior to this call. + * + * @param chipCert Buffer containing certificate encoded in CHIP format. + * @param chipCertLen The length of the certificate buffer. + * @param decodeFlags Certificate decoding option flags. + * + * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise + **/ + CHIP_ERROR LoadCert(const uint8_t * chipCert, uint32_t chipCertLen, BitFlags decodeFlags); + + /** + * @brief Load CHIP certificate into set. + * It is required that the CHIP certificate in the reader's underlying buffer stays valid while + * the certificate data in the set is used. + * In case of an error the certificate set is left in the same state as prior to this call. + * + * @param reader A TLVReader positioned at the CHIP certificate TLV structure. + * @param decodeFlags Certificate decoding option flags. + * + * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise + **/ + CHIP_ERROR LoadCert(chip::TLV::TLVReader & reader, BitFlags decodeFlags); + + /** + * @brief Load CHIP certificates into set. + * It is required that the CHIP certificates in the chipCerts buffer stays valid while + * the certificates data in the set is used. + * In case of an error the certificate set is left in the same state as prior to this call. + * + * @param chipCerts Buffer containing array of certificates or a single certificate encoded in CHIP TLV form. + * @param chipCertsLen The length of the certificates buffer. + * @param decodeFlags Certificate decoding option flags. + * + * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise + **/ + CHIP_ERROR LoadCerts(const uint8_t * chipCerts, uint32_t chipCertsLen, BitFlags decodeFlags); + + /** + * @brief Load CHIP certificates into set. + * It is required that the CHIP certificates in the reader's underlying buffer stays valid while + * the certificates data in the set is used. + * In case of an error the certificate set is left in the same state as prior to this call. + * + * @param reader A TLVReader positioned at the CHIP certificates TLV array + * or TLV structure for a single certificate. + * @param decodeFlags Certificate decoding option flags. + * + * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise + **/ + CHIP_ERROR LoadCerts(chip::TLV::TLVReader & reader, BitFlags decodeFlags); + + /** + * @brief Add trusted anchor key to the certificate set. + * It is required that the public key and public key Id in the pubKey and pubKeyId buffers + * stay valid while the certificate set is used. + * In case of an error the certificate set is left in the same state as prior to this call. + * + * @param caId CA certificate CHIP identifier. + * @param curveOID Elliptic curve CHIP OID. + * @param pubKey Trusted public key. + * @param pubKeyLen The length of the trusted public key. + * @param pubKeyId Trusted public key identifier. + * @param pubKeyIdLen The length of the trusted public key identifier. + * + * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise + **/ + CHIP_ERROR AddTrustedKey(uint64_t caId, chip::ASN1::OID curveOID, const uint8_t * pubKey, uint8_t pubKeyLen, + const uint8_t * pubKeyId, uint8_t pubKeyIdLen); + + /** + * @brief Find certificate in the set. + * + * @param subjectKeyId Subject key identifier of the certificate to be found in the set. + * + * @return A pointer to the certificate data On success. Otherwise, NULL if no certificate found. + **/ + const ChipCertificateData * FindCert(const CertificateKeyId & subjectKeyId) const; + + /** + * @return A pointer to the set of certificate data entries. + **/ + const ChipCertificateData * GetCertSet() const { return mCerts; } + + /** + * @return A pointer to the last certificate data in the set. Returns NULL if certificate set is empty. + **/ + const ChipCertificateData * GetLastCert() const { return (mCertCount > 0) ? &mCerts[mCertCount - 1] : nullptr; } + + /** + * @return Number of certificates loaded into the set. + **/ + uint8_t GetCertCount() const { return mCertCount; } + + /** + * @brief Check whether certificate is in the set. + * + * @param cert Pointer to the ChipCertificateData structures. + * + * @return True if certificate is in the set, false otherwise. + **/ + bool IsCertInTheSet(const ChipCertificateData * cert) const; + + /** + * @brief Validate CHIP certificate. + * + * @param cert Pointer to the CHIP certificiate to be validated. The certificate is + * required to be in this set, otherwise this function returns error. + * @param context Certificate validation context. + * + * @return Returns a CHIP_ERROR on validation or other error, CHIP_NO_ERROR otherwise + **/ + CHIP_ERROR ValidateCert(const ChipCertificateData * cert, ValidationContext & context); + + /** + * @brief Find and validate CHIP certificate. + * + * @param subjectDN Subject distinguished name to use as certificate search parameter. + * @param subjectKeyId Subject key identifier to use as certificate search parameter. + * @param context Certificate validation context. + * @param cert A pointer to the valid CHIP certificate that matches search criteria. + * + * @return Returns a CHIP_ERROR on validation or other error, CHIP_NO_ERROR otherwise + **/ + CHIP_ERROR FindValidCert(const ChipDN & subjectDN, const CertificateKeyId & subjectKeyId, ValidationContext & context, + ChipCertificateData *& cert); + + /** + * @brief Verify CHIP certificate signature. + * + * @param cert Pointer to the CHIP certificiate which signature should be validated. + * @param caCert Pointer to the CA certificate of the verified certificate. + * + * @return Returns a CHIP_ERROR on validation or other error, CHIP_NO_ERROR otherwise + **/ + static CHIP_ERROR VerifySignature(const ChipCertificateData * cert, const ChipCertificateData * caCert); + +private: + ChipCertificateData * mCerts; /**< Pointer to an array of certificate data. */ + uint8_t mCertCount; /**< Number of certificates in mCerts array. */ + uint8_t mMaxCerts; /**< Length of mCerts array. */ + uint8_t * mDecodeBuf; /**< Certificate decode buffer. */ + uint16_t mDecodeBufSize; /**< Certificate decode buffer size. */ + bool mMemoryAllocInternal; /**< Indicates whether temporary memory buffers are allocated internally. */ + + /** + * @brief Find and validate CHIP certificate. + * + * @param subjectDN Subject distinguished name to use as certificate search parameter. + * @param subjectKeyId Subject key identifier to use as certificate search parameter. + * @param context Certificate validation context. + * @param validateFlags Certificate validation flags. + * @param depth Depth of the current certificate in the certificate validation chain. + * @param cert A pointer to the valid CHIP certificate that matches search criteria. + * + * @return Returns a CHIP_ERROR on validation or other error, CHIP_NO_ERROR otherwise + **/ + CHIP_ERROR FindValidCert(const ChipDN & subjectDN, const CertificateKeyId & subjectKeyId, ValidationContext & context, + BitFlags validateFlags, uint8_t depth, ChipCertificateData *& cert); + + /** + * @brief Validate CHIP certificate. + * + * @param cert Pointer to the CHIP certificiate to be validated. + * @param context Certificate validation context. + * @param validateFlags Certificate validation flags. + * @param depth Depth of the current certificate in the certificate validation chain. + * + * @return Returns a CHIP_ERROR on validation or other error, CHIP_NO_ERROR otherwise + **/ + CHIP_ERROR ValidateCert(const ChipCertificateData * cert, ValidationContext & context, + BitFlags validateFlags, uint8_t depth); +}; + +/** + * @brief Decode CHIP certificate. + * It is required that the CHIP certificate in the chipCert buffer stays valid while + * the certData is used. + * + * @param chipCert Buffer containing CHIP certificate. + * @param chipCertLen The length of the CHIP certificate. + * @param certData Structure containing data extracted from the CHIP certificate. + * + * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise + **/ +CHIP_ERROR DecodeChipCert(const uint8_t * chipCert, uint32_t chipCertLen, ChipCertificateData & certData); + +/** + * @brief Decode CHIP certificate. + * It is required that the CHIP certificate in the reader's underlying buffer stays valid while + * the certData is used. + * + * @param reader A TLVReader positioned at the CHIP certificate TLV structure. + * @param certData Structure containing data extracted from the CHIP certificate. + * + * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise + **/ +CHIP_ERROR DecodeChipCert(chip::TLV::TLVReader & reader, ChipCertificateData & certData); + +/** + * @brief Decode CHIP Distinguished Name (DN). + * It is required that the CHIP DN in the reader's underlying buffer stays valid while + * the dn structure is used. + * + * @param reader A TLVReader positioned at the CHIP DN TLV structure. + * @param dn Distinguished Name structure. + * + * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise + **/ +CHIP_ERROR DecodeChipDN(chip::TLV::TLVReader & reader, ChipDN & dn); + +/** + * @brief Convert standard X.509 certificate to CHIP certificate. + * + * @param x509Cert Buffer containing X.509 DER encoded certificate. + * @param x509CertLen The length of the X.509 DER encoded certificate. + * @param chipCertBuf Buffer to store converted certificate in CHIP format. + * @param chipCertBufSize The size of the buffer to store converted certificate. + * @param chipCertLen The length of the converted certificate. + * + * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise + **/ +CHIP_ERROR ConvertX509CertToChipCert(const uint8_t * x509Cert, uint32_t x509CertLen, uint8_t * chipCertBuf, + uint32_t chipCertBufSize, uint32_t & chipCertLen); + +/** + * @brief Convert CHIP certificate to the standard X.509 DER encoded certificate. + * + * @param chipCert Buffer containing CHIP certificate. + * @param chipCertLen The length of the CHIP certificate. + * @param x509CertBuf Buffer to store converted certificate in X.509 DER format. + * @param x509CertBufSize The size of the buffer to store converted certificate. + * @param x509CertLen The length of the converted certificate. + * + * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise + **/ +CHIP_ERROR ConvertChipCertToX509Cert(const uint8_t * chipCert, uint32_t chipCertLen, uint8_t * x509CertBuf, + uint32_t x509CertBufSize, uint32_t & x509CertLen); + +/** + * Determine type of a CHIP certificate. + * + * This function performs an assessment of a certificate's type and sets cert.mCertType value + * based on the structure of its subject DN and the extensions present. Applications are free + * to override this assessment by setting cert.mCertType to another value, including an + * application-defined one. + * + * In general, applications will only trust a peer's certificate if it chains to a trusted + * root certificate. However, the type assigned to a certificate can influence the *nature* + * of this trust, e.g. to allow or disallow access to certain features. Because of this, + * changes to this algorithm can have VERY SIGNIFICANT and POTENTIALLY CATASTROPHIC effects + * on overall system security, and should not be made without a thorough understanding of + * the implications. + **/ +CHIP_ERROR DetermineCertType(ChipCertificateData & cert); + +/** + * @brief + * Convert a certificate date/time (in the form of an ASN.1 universal time structure) into a packed + * certificate date/time. + * + * @details + * Packed certificate date/times provide a compact representation for the time values within a certificate + * (notBefore and notAfter) that does not require full calendar math to interpret. + * + * A packed certificate date/time contains the fields of a calendar date/time--i.e. year, month, day, hour, + * minute, second--packed into an unsigned integer. The bit representation is organized such that + * ordinal comparisons of packed date/time values correspond to the natural ordering of the corresponding + * times. To reduce their size, packed certificate date/times are limited to representing times that are on + * or after 2020/01/01 00:00:00. When housed within a 32-bit unsigned integer, packed certificate + * date/times can represent times up to the year 2153. + * + * @note + * This function makes no attempt to verify the correct range of the input time other than year. + * Therefore callers must make sure the supplied values are valid prior to invocation. + * + * @param time The calendar date/time to be converted. + * @param packedTime A reference to an integer that will receive packed date/time. + * + * @retval #CHIP_NO_ERROR If the input time was successfully converted. + * @retval #ASN1_ERROR_UNSUPPORTED_ENCODING If the input time contained a year value that could not + * be represented in a packed certificate time value. + **/ +CHIP_ERROR PackCertTime(const chip::ASN1::ASN1UniversalTime & time, uint32_t & packedTime); + +/** + * @brief + * Unpack a packed certificate date/time into an ASN.1 universal time structure. + * + * @param packedTime A packed certificate time to be unpacked. + * @param time A reference to an ASN1UniversalTime structure to receive the unpacked date/time. + * + * @retval #CHIP_NO_ERROR If the input time was successfully unpacked. + */ +CHIP_ERROR UnpackCertTime(uint32_t packedTime, chip::ASN1::ASN1UniversalTime & time); + +/** + * @brief + * Convert a packed certificate date/time to a packed certificate date. + * + * @details + * A packed certificate date contains the fields of a calendar date--year, month, day--packed into an + * unsigned integer. The bits are organized such that ordinal comparisons of packed date values + * correspond to the natural ordering of the corresponding dates. To reduce their size, packed + * certificate dates are limited to representing dates on or after 2020/01/01. When housed within + * a 16-bit unsigned integer, packed certificate dates can represent dates up to the year 2196. + * + * @param packedTime The packed certificate date/time to be converted. + * + * @return A corresponding packed certificate date. + **/ +uint16_t PackedCertTimeToDate(uint32_t packedTime); + +/** + * @brief + * Convert a packed certificate date to a corresponding packed certificate date/time, where + * the time portion of the value is set to 00:00:00. + * + * @param packedDate The packed certificate date to be converted. + * + * @return A corresponding packed certificate date/time. + **/ +uint32_t PackedCertDateToTime(uint16_t packedDate); + +/** + * @brief + * Convert the number of seconds since 1970-01-01 00:00:00 UTC to a packed certificate date/time. + * + * @param secondsSinceEpoch Number of seconds since 1970-01-01 00:00:00 UTC. + * Note: this value is compatible with *positive* values + * of the POSIX time_t value, up to the year 2105. + * + * @return A corresponding packed certificate date/time. + **/ +uint32_t SecondsSinceEpochToPackedCertTime(uint32_t secondsSinceEpoch); + +/** + * @return True if the OID represents a CHIP-defined X.509 distinguished named attribute. + **/ +inline bool IsChipX509Attr(chip::ASN1::OID oid) +{ + return (oid == chip::ASN1::kOID_AttributeType_ChipNodeId || oid == chip::ASN1::kOID_AttributeType_ChipCAId || + oid == chip::ASN1::kOID_AttributeType_ChipSoftwarePublisherId || oid == chip::ASN1::kOID_AttributeType_ChipFabricId); +} + +/** + * @return True if the OID represents a CHIP-defined X.509 distinguished named attribute + * that contains a 64-bit CHIP id. + **/ +inline bool IsChipIdX509Attr(chip::ASN1::OID oid) +{ + return (oid == chip::ASN1::kOID_AttributeType_ChipNodeId || oid == chip::ASN1::kOID_AttributeType_ChipCAId || + oid == chip::ASN1::kOID_AttributeType_ChipSoftwarePublisherId); +} + +} // namespace Credentials +} // namespace chip diff --git a/src/credentials/CHIPCertFromX509.cpp b/src/credentials/CHIPCertFromX509.cpp new file mode 100755 index 00000000000000..30fd558818d16f --- /dev/null +++ b/src/credentials/CHIPCertFromX509.cpp @@ -0,0 +1,720 @@ +/* + * + * Copyright (c) 2020-2021 Project CHIP Authors + * Copyright (c) 2013-2017 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 + * This file implements methods for converting a standard X.509 + * certificate to a CHIP TLV-encoded certificate. + * + */ + +#ifndef __STDC_LIMIT_MACROS +#define __STDC_LIMIT_MACROS +#endif + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace chip { +namespace Credentials { + +using namespace chip::ASN1; +using namespace chip::TLV; +using namespace chip::Protocols; + +static ASN1_ERROR ParseChipIdAttribute(ASN1Reader & reader, uint64_t & chipIdOut) +{ + ASN1_ERROR err = ASN1_NO_ERROR; + const uint8_t * value = nullptr; + + static constexpr uint32_t kChipIdUTF8Length = 16; + + VerifyOrExit(reader.GetValueLen() == kChipIdUTF8Length, err = ASN1_ERROR_INVALID_ENCODING); + + value = reader.GetValue(); + VerifyOrExit(value != nullptr, err = ASN1_ERROR_INVALID_ENCODING); + + chipIdOut = 0; + + for (uint32_t i = 0; i < kChipIdUTF8Length; i++) + { + chipIdOut <<= 4; + uint8_t ch = value[i]; + if (ch >= '0' && ch <= '9') + { + chipIdOut |= (ch - '0'); + } + // CHIP Id attribute encodings only support uppercase chars. + else if (ch >= 'A' && ch <= 'F') + { + chipIdOut |= (ch - 'A' + 10); + } + else + { + ExitNow(err = ASN1_ERROR_INVALID_ENCODING); + } + } + +exit: + return err; +} + +static CHIP_ERROR ConvertDistinguishedName(ASN1Reader & reader, TLVWriter & writer, uint64_t tag) +{ + CHIP_ERROR err; + TLVType outerContainer; + OID attrOID; + + err = writer.StartContainer(tag, kTLVType_Path, outerContainer); + SuccessOrExit(err); + + // RDNSequence ::= SEQUENCE OF RelativeDistinguishedName + ASN1_PARSE_ENTER_SEQUENCE + { + while ((err = reader.Next()) == ASN1_NO_ERROR) + { + // RelativeDistinguishedName ::= SET SIZE (1..MAX) OF AttributeTypeAndValue + ASN1_ENTER_SET + { + // AttributeTypeAndValue ::= SEQUENCE + ASN1_PARSE_ENTER_SEQUENCE + { + // type AttributeType + // AttributeType ::= OBJECT IDENTIFIER + ASN1_PARSE_OBJECT_ID(attrOID); + VerifyOrExit(GetOIDCategory(attrOID) == kOIDCategory_AttributeType, err = ASN1_ERROR_INVALID_ENCODING); + + // AttributeValue ::= ANY -- DEFINED BY AttributeType + ASN1_PARSE_ANY; + + // Can only support UTF8String, PrintableString and IA5String. + VerifyOrExit(reader.GetClass() == kASN1TagClass_Universal && + (reader.GetTag() == kASN1UniversalTag_PrintableString || + reader.GetTag() == kASN1UniversalTag_UTF8String || + reader.GetTag() == kASN1UniversalTag_IA5String), + err = ASN1_ERROR_UNSUPPORTED_ENCODING); + + // CHIP id attributes must be UTF8Strings. + if (IsChipIdX509Attr(attrOID)) + { + VerifyOrExit(reader.GetTag() == kASN1UniversalTag_UTF8String, err = ASN1_ERROR_INVALID_ENCODING); + } + + // Derive the TLV tag number from the enum value assigned to the attribute type OID. For attributes that can be + // either UTF8String or PrintableString, use the high bit in the tag number to distinguish the two. + uint8_t tlvTagNum = GetOIDEnum(attrOID); + if (reader.GetTag() == kASN1UniversalTag_PrintableString) + { + tlvTagNum |= 0x80; + } + + // If the attribute is a CHIP-defined attribute that contains a 64-bit CHIP id... + if (IsChipIdX509Attr(attrOID)) + { + // Parse the attribute string into a 64-bit CHIP id. + uint64_t chipId; + err = ParseChipIdAttribute(reader, chipId); + SuccessOrExit(err); + + // Write the CHIP id into the TLV. + err = writer.Put(ContextTag(tlvTagNum), chipId); + SuccessOrExit(err); + } + + // + else + { + err = + writer.PutString(ContextTag(tlvTagNum), Uint8::to_const_char(reader.GetValue()), reader.GetValueLen()); + SuccessOrExit(err); + } + } + ASN1_EXIT_SEQUENCE; + + // Only one AttributeTypeAndValue allowed per RDN. + err = reader.Next(); + if (err == ASN1_NO_ERROR) + { + ExitNow(err = ASN1_ERROR_UNSUPPORTED_ENCODING); + } + if (err != ASN1_END) + { + ExitNow(); + } + } + ASN1_EXIT_SET; + } + } + ASN1_EXIT_SEQUENCE; + + err = writer.EndContainer(outerContainer); + SuccessOrExit(err); + +exit: + return err; +} + +static CHIP_ERROR ConvertValidity(ASN1Reader & reader, TLVWriter & writer) +{ + CHIP_ERROR err; + ASN1UniversalTime notBeforeTime, notAfterTime; + uint32_t packedNotBeforeTime, packedNotAfterTime; + + ASN1_PARSE_ENTER_SEQUENCE + { + ASN1_PARSE_TIME(notBeforeTime); + err = PackCertTime(notBeforeTime, packedNotBeforeTime); + SuccessOrExit(err); + err = writer.Put(ContextTag(kTag_NotBefore), packedNotBeforeTime); + SuccessOrExit(err); + + ASN1_PARSE_TIME(notAfterTime); + err = PackCertTime(notAfterTime, packedNotAfterTime); + SuccessOrExit(err); + err = writer.Put(ContextTag(kTag_NotAfter), packedNotAfterTime); + SuccessOrExit(err); + } + ASN1_EXIT_SEQUENCE; + +exit: + return err; +} + +static CHIP_ERROR ConvertAuthorityKeyIdentifierExtension(ASN1Reader & reader, TLVWriter & writer) +{ + CHIP_ERROR err; + + // AuthorityKeyIdentifier ::= SEQUENCE + ASN1_PARSE_ENTER_SEQUENCE + { + err = reader.Next(); + + // keyIdentifier [0] IMPLICIT KeyIdentifier OPTIONAL, + // KeyIdentifier ::= OCTET STRING + if (err == ASN1_NO_ERROR && reader.GetClass() == kASN1TagClass_ContextSpecific && reader.GetTag() == 0) + { + VerifyOrExit(reader.IsConstructed() == false, err = ASN1_ERROR_INVALID_ENCODING); + + err = writer.PutBytes(ContextTag(kTag_AuthorityKeyIdentifier_KeyIdentifier), reader.GetValue(), reader.GetValueLen()); + SuccessOrExit(err); + + err = reader.Next(); + } + + if (err != ASN1_END) + { + SuccessOrExit(err); + } + } + ASN1_EXIT_SEQUENCE; + +exit: + return err; +} + +static CHIP_ERROR ConvertSubjectPublicKeyInfo(ASN1Reader & reader, TLVWriter & writer) +{ + CHIP_ERROR err; + OID pubKeyAlgoOID, pubKeyCurveOID; + + // subjectPublicKeyInfo SubjectPublicKeyInfo, + ASN1_PARSE_ENTER_SEQUENCE + { + // algorithm AlgorithmIdentifier, + // AlgorithmIdentifier ::= SEQUENCE + ASN1_PARSE_ENTER_SEQUENCE + { + // algorithm OBJECT IDENTIFIER, + ASN1_PARSE_OBJECT_ID(pubKeyAlgoOID); + + // Verify that the algorithm type is supported. + VerifyOrExit(pubKeyAlgoOID == kOID_PubKeyAlgo_ECPublicKey, err = ASN1_ERROR_UNSUPPORTED_ENCODING); + + err = writer.Put(ContextTag(kTag_PublicKeyAlgorithm), GetOIDEnum(pubKeyAlgoOID)); + SuccessOrExit(err); + + // EcpkParameters ::= CHOICE { + // ecParameters ECParameters, + // namedCurve OBJECT IDENTIFIER, + // implicitlyCA NULL } + ASN1_PARSE_ANY; + + // ecParameters and implicitlyCA not supported. + if (reader.GetClass() == kASN1TagClass_Universal && reader.GetTag() == kASN1UniversalTag_Sequence) + { + ExitNow(err = ASN1_ERROR_UNSUPPORTED_ENCODING); + } + if (reader.GetClass() == kASN1TagClass_Universal && reader.GetTag() == kASN1UniversalTag_Null) + { + ExitNow(err = ASN1_ERROR_UNSUPPORTED_ENCODING); + } + + ASN1_VERIFY_TAG(kASN1TagClass_Universal, kASN1UniversalTag_ObjectId); + + ASN1_GET_OBJECT_ID(pubKeyCurveOID); + + // Verify the curve name is recognized. + VerifyOrExit(GetOIDCategory(pubKeyCurveOID) == kOIDCategory_EllipticCurve, err = ASN1_ERROR_UNSUPPORTED_ENCODING); + + err = writer.Put(ContextTag(kTag_EllipticCurveIdentifier), GetOIDEnum(pubKeyCurveOID)); + SuccessOrExit(err); + } + ASN1_EXIT_SEQUENCE; + + // subjectPublicKey BIT STRING + ASN1_PARSE_ELEMENT(kASN1TagClass_Universal, kASN1UniversalTag_BitString); + + // Verify public key length. + VerifyOrExit(reader.GetValueLen() > 0, err = ASN1_ERROR_INVALID_ENCODING); + + // The first byte is Unused Bit Count value, which should be zero. + VerifyOrExit(reader.GetValue()[0] == 0, err = ASN1_ERROR_INVALID_ENCODING); + + // Copy the X9.62 encoded EC point into the CHIP certificate as a byte string. + // Skip the first Unused Bit Count byte. + err = writer.PutBytes(ContextTag(kTag_EllipticCurvePublicKey), reader.GetValue() + 1, reader.GetValueLen() - 1); + SuccessOrExit(err); + } + ASN1_EXIT_SEQUENCE; + +exit: + return err; +} + +static CHIP_ERROR ConvertExtension(ASN1Reader & reader, TLVWriter & writer) +{ + CHIP_ERROR err; + TLVType outerContainer, outerContainer2; + OID extensionOID; + bool critical = false; + + // Extension ::= SEQUENCE + ASN1_ENTER_SEQUENCE + { + // extnID OBJECT IDENTIFIER, + ASN1_PARSE_OBJECT_ID(extensionOID); + + if (extensionOID == kOID_Unknown) + { + ExitNow(err = ASN1_ERROR_UNSUPPORTED_ENCODING); + } + if (GetOIDCategory(extensionOID) != kOIDCategory_Extension) + { + ExitNow(err = ASN1_ERROR_INVALID_ENCODING); + } + + // critical BOOLEAN DEFAULT FALSE, + ASN1_PARSE_ANY; + if (reader.GetClass() == kASN1TagClass_Universal && reader.GetTag() == kASN1UniversalTag_Boolean) + { + ASN1_GET_BOOLEAN(critical); + + if (!critical) + { + ExitNow(err = ASN1_ERROR_INVALID_ENCODING); + } + + ASN1_PARSE_ANY; + } + + // extnValue OCTET STRING + // -- contains the DER encoding of an ASN.1 value + // -- corresponding to the extension type identified + // -- by extnID + ASN1_ENTER_ENCAPSULATED(kASN1TagClass_Universal, kASN1UniversalTag_OctetString) + { + if (extensionOID == kOID_Extension_AuthorityKeyIdentifier) + { + err = writer.StartContainer(ContextTag(kTag_AuthorityKeyIdentifier), kTLVType_Structure, outerContainer); + SuccessOrExit(err); + + if (critical) + { + err = writer.PutBoolean(ContextTag(kTag_AuthorityKeyIdentifier_Critical), critical); + SuccessOrExit(err); + } + + err = ConvertAuthorityKeyIdentifierExtension(reader, writer); + SuccessOrExit(err); + } + else if (extensionOID == kOID_Extension_SubjectKeyIdentifier) + { + // SubjectKeyIdentifier ::= KeyIdentifier + ASN1_PARSE_ELEMENT(kASN1TagClass_Universal, kASN1UniversalTag_OctetString); + + err = writer.StartContainer(ContextTag(kTag_SubjectKeyIdentifier), kTLVType_Structure, outerContainer); + SuccessOrExit(err); + + if (critical) + { + err = writer.PutBoolean(ContextTag(kTag_SubjectKeyIdentifier_Critical), critical); + SuccessOrExit(err); + } + + err = writer.PutBytes(ContextTag(kTag_SubjectKeyIdentifier_KeyIdentifier), reader.GetValue(), reader.GetValueLen()); + SuccessOrExit(err); + } + else if (extensionOID == kOID_Extension_KeyUsage) + { + // KeyUsage ::= BIT STRING + ASN1_PARSE_ELEMENT(kASN1TagClass_Universal, kASN1UniversalTag_BitString); + + err = writer.StartContainer(ContextTag(kTag_KeyUsage), kTLVType_Structure, outerContainer); + SuccessOrExit(err); + + if (critical) + { + err = writer.PutBoolean(ContextTag(kTag_KeyUsage_Critical), critical); + SuccessOrExit(err); + } + + uint32_t keyUsageBits; + err = reader.GetBitString(keyUsageBits); + SuccessOrExit(err); + VerifyOrExit(keyUsageBits <= UINT16_MAX, err = ASN1_ERROR_INVALID_ENCODING); + + // Check that only supported flags are set. + BitFlags keyUsageFlags; + keyUsageFlags.SetRaw(static_cast(keyUsageBits)); + VerifyOrExit(keyUsageFlags.HasOnly( + KeyUsageFlags::kDigitalSignature, KeyUsageFlags::kNonRepudiation, KeyUsageFlags::kKeyEncipherment, + KeyUsageFlags::kDataEncipherment, KeyUsageFlags::kKeyAgreement, KeyUsageFlags::kKeyCertSign, + KeyUsageFlags::kCRLSign, KeyUsageFlags::kEncipherOnly, KeyUsageFlags::kEncipherOnly), + err = ASN1_ERROR_INVALID_ENCODING); + + err = writer.Put(ContextTag(kTag_KeyUsage_KeyUsage), keyUsageBits); + SuccessOrExit(err); + } + else if (extensionOID == kOID_Extension_BasicConstraints) + { + // BasicConstraints ::= SEQUENCE + ASN1_PARSE_ENTER_SEQUENCE + { + bool isCA = false; + int64_t pathLenConstraint = -1; + + // cA BOOLEAN DEFAULT FALSE + err = reader.Next(); + if (err == ASN1_NO_ERROR && reader.GetClass() == kASN1TagClass_Universal && + reader.GetTag() == kASN1UniversalTag_Boolean) + { + ASN1_GET_BOOLEAN(isCA); + + VerifyOrExit(isCA == true, err = ASN1_ERROR_INVALID_ENCODING); + + err = reader.Next(); + } + + // pathLenConstraint INTEGER (0..MAX) OPTIONAL + if (err == ASN1_NO_ERROR && reader.GetClass() == kASN1TagClass_Universal && + reader.GetTag() == kASN1UniversalTag_Integer) + { + ASN1_GET_INTEGER(pathLenConstraint); + + VerifyOrExit(pathLenConstraint <= UINT8_MAX, err = ASN1_ERROR_INVALID_ENCODING); + VerifyOrExit(pathLenConstraint >= 0, err = ASN1_ERROR_INVALID_ENCODING); + } + + err = writer.StartContainer(ContextTag(kTag_BasicConstraints), kTLVType_Structure, outerContainer); + SuccessOrExit(err); + + if (critical) + { + err = writer.PutBoolean(ContextTag(kTag_BasicConstraints_Critical), critical); + SuccessOrExit(err); + } + + if (isCA) + { + err = writer.PutBoolean(ContextTag(kTag_BasicConstraints_IsCA), isCA); + SuccessOrExit(err); + } + + if (pathLenConstraint != -1) + { + err = writer.Put(ContextTag(kTag_BasicConstraints_PathLenConstraint), + static_cast(pathLenConstraint)); + SuccessOrExit(err); + } + } + ASN1_EXIT_SEQUENCE; + } + else if (extensionOID == kOID_Extension_ExtendedKeyUsage) + { + err = writer.StartContainer(ContextTag(kTag_ExtendedKeyUsage), kTLVType_Structure, outerContainer); + SuccessOrExit(err); + + if (critical) + { + err = writer.PutBoolean(ContextTag(kTag_ExtendedKeyUsage_Critical), critical); + SuccessOrExit(err); + } + + err = writer.StartContainer(ContextTag(kTag_ExtendedKeyUsage_KeyPurposes), kTLVType_Array, outerContainer2); + SuccessOrExit(err); + + // ExtKeyUsageSyntax ::= SEQUENCE SIZE (1..MAX) OF KeyPurposeId + ASN1_PARSE_ENTER_SEQUENCE + { + while ((err = reader.Next()) == ASN1_NO_ERROR) + { + // KeyPurposeId ::= OBJECT IDENTIFIER + OID keyPurposeOID; + ASN1_GET_OBJECT_ID(keyPurposeOID); + + VerifyOrExit(keyPurposeOID != kOID_Unknown, err = ASN1_ERROR_UNSUPPORTED_ENCODING); + VerifyOrExit(GetOIDCategory(keyPurposeOID) == kOIDCategory_KeyPurpose, err = ASN1_ERROR_INVALID_ENCODING); + + err = writer.Put(AnonymousTag, GetOIDEnum(keyPurposeOID)); + SuccessOrExit(err); + } + if (err != ASN1_END) + { + SuccessOrExit(err); + } + } + ASN1_EXIT_SEQUENCE; + + err = writer.EndContainer(outerContainer2); + SuccessOrExit(err); + } + else + ExitNow(err = ASN1_ERROR_UNSUPPORTED_ENCODING); + + err = writer.EndContainer(outerContainer); + SuccessOrExit(err); + } + ASN1_EXIT_ENCAPSULATED; + } + ASN1_EXIT_SEQUENCE; + +exit: + return err; +} + +static CHIP_ERROR ConvertExtensions(ASN1Reader & reader, TLVWriter & writer) +{ + CHIP_ERROR err; + + // Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension + ASN1_PARSE_ENTER_SEQUENCE + { + while ((err = reader.Next()) == ASN1_NO_ERROR) + { + err = ConvertExtension(reader, writer); + SuccessOrExit(err); + } + + if (err != ASN1_END) + { + SuccessOrExit(err); + } + } + ASN1_EXIT_SEQUENCE; + +exit: + return err; +} + +static CHIP_ERROR ConvertCertificate(ASN1Reader & reader, TLVWriter & writer) +{ + CHIP_ERROR err; + int64_t version; + OID sigAlgoOID; + TLVType containerType; + + err = writer.StartContainer(ProfileTag(kProtocol_OpCredentials, kTag_ChipCertificate), kTLVType_Structure, containerType); + SuccessOrExit(err); + + // Certificate ::= SEQUENCE + ASN1_PARSE_ENTER_SEQUENCE + { + // tbsCertificate TBSCertificate, + // TBSCertificate ::= SEQUENCE + ASN1_PARSE_ENTER_SEQUENCE + { + // version [0] EXPLICIT Version DEFAULT v1 + ASN1_PARSE_ENTER_CONSTRUCTED(kASN1TagClass_ContextSpecific, 0) + { + // Version ::= INTEGER { v1(0), v2(1), v3(2) } + ASN1_PARSE_INTEGER(version); + + // Verify that the X.509 certificate version is v3 + VerifyOrExit(version == 2, err = ASN1_ERROR_UNSUPPORTED_ENCODING); + } + ASN1_EXIT_CONSTRUCTED; + + // serialNumber CertificateSerialNumber + // CertificateSerialNumber ::= INTEGER + ASN1_PARSE_ELEMENT(kASN1TagClass_Universal, kASN1UniversalTag_Integer); + err = writer.PutBytes(ContextTag(kTag_SerialNumber), reader.GetValue(), reader.GetValueLen()); + SuccessOrExit(err); + + // signature AlgorithmIdentifier + // AlgorithmIdentifier ::= SEQUENCE + ASN1_PARSE_ENTER_SEQUENCE + { + // algorithm OBJECT IDENTIFIER, + ASN1_PARSE_OBJECT_ID(sigAlgoOID); + + VerifyOrExit(sigAlgoOID == kOID_SigAlgo_ECDSAWithSHA256, err = ASN1_ERROR_UNSUPPORTED_ENCODING); + + err = writer.Put(ContextTag(kTag_SignatureAlgorithm), GetOIDEnum(sigAlgoOID)); + SuccessOrExit(err); + } + ASN1_EXIT_SEQUENCE; + + // issuer Name + err = ConvertDistinguishedName(reader, writer, ContextTag(kTag_Issuer)); + SuccessOrExit(err); + + // validity Validity, + err = ConvertValidity(reader, writer); + SuccessOrExit(err); + + // subject Name, + err = ConvertDistinguishedName(reader, writer, ContextTag(kTag_Subject)); + SuccessOrExit(err); + + err = ConvertSubjectPublicKeyInfo(reader, writer); + SuccessOrExit(err); + + err = reader.Next(); + + // issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL, + // Not supported. + if (err == ASN1_NO_ERROR && reader.GetClass() == kASN1TagClass_ContextSpecific && reader.GetTag() == 1) + { + ExitNow(err = ASN1_ERROR_UNSUPPORTED_ENCODING); + } + + // subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL, + // Not supported. + if (err == ASN1_NO_ERROR && reader.GetClass() == kASN1TagClass_ContextSpecific && reader.GetTag() == 2) + { + ExitNow(err = ASN1_ERROR_UNSUPPORTED_ENCODING); + } + + // extensions [3] EXPLICIT Extensions OPTIONAL + if (err == ASN1_NO_ERROR && reader.GetClass() == kASN1TagClass_ContextSpecific && reader.GetTag() == 3) + { + ASN1_ENTER_CONSTRUCTED(kASN1TagClass_ContextSpecific, 3) + { + err = ConvertExtensions(reader, writer); + SuccessOrExit(err); + } + ASN1_EXIT_CONSTRUCTED; + + err = reader.Next(); + } + + if (err != ASN1_END) + { + ExitNow(); + } + } + ASN1_EXIT_SEQUENCE; + + // signatureAlgorithm AlgorithmIdentifier + // AlgorithmIdentifier ::= SEQUENCE + ASN1_PARSE_ENTER_SEQUENCE + { + OID localSigAlgoOID; + + // algorithm OBJECT IDENTIFIER, + ASN1_PARSE_OBJECT_ID(localSigAlgoOID); + + // Verify that the signatureAlgorithm is the same as the "signature" field in TBSCertificate. + VerifyOrExit(localSigAlgoOID == sigAlgoOID, err = ASN1_ERROR_UNSUPPORTED_ENCODING); + } + ASN1_EXIT_SEQUENCE; + + // signatureValue BIT STRING + ASN1_PARSE_ELEMENT(kASN1TagClass_Universal, kASN1UniversalTag_BitString); + + // Per RFC3279, the ECDSA signature value is encoded in DER encapsulated in the signatureValue BIT STRING. + ASN1_ENTER_ENCAPSULATED(kASN1TagClass_Universal, kASN1UniversalTag_BitString) + { + TLVType outerContainer; + + err = writer.StartContainer(ContextTag(kTag_ECDSASignature), kTLVType_Structure, outerContainer); + SuccessOrExit(err); + + // Ecdsa-Sig-Value ::= SEQUENCE + ASN1_PARSE_ENTER_SEQUENCE + { + // r INTEGER + ASN1_PARSE_ELEMENT(kASN1TagClass_Universal, kASN1UniversalTag_Integer); + err = writer.PutBytes(ContextTag(kTag_ECDSASignature_r), reader.GetValue(), reader.GetValueLen()); + SuccessOrExit(err); + + // s INTEGER + ASN1_PARSE_ELEMENT(kASN1TagClass_Universal, kASN1UniversalTag_Integer); + err = writer.PutBytes(ContextTag(kTag_ECDSASignature_s), reader.GetValue(), reader.GetValueLen()); + SuccessOrExit(err); + } + ASN1_EXIT_SEQUENCE; + + err = writer.EndContainer(outerContainer); + SuccessOrExit(err); + } + ASN1_EXIT_ENCAPSULATED; + } + ASN1_EXIT_SEQUENCE; + + err = writer.EndContainer(containerType); + SuccessOrExit(err); + +exit: + return err; +} + +DLL_EXPORT CHIP_ERROR ConvertX509CertToChipCert(const uint8_t * x509Cert, uint32_t x509CertLen, uint8_t * chipCertBuf, + uint32_t chipCertBufSize, uint32_t & chipCertLen) +{ + CHIP_ERROR err; + ASN1Reader reader; + TLVWriter writer; + + reader.Init(x509Cert, x509CertLen); + + writer.Init(chipCertBuf, chipCertBufSize); + + err = ConvertCertificate(reader, writer); + SuccessOrExit(err); + + err = writer.Finalize(); + SuccessOrExit(err); + + chipCertLen = writer.GetLengthWritten(); + +exit: + return err; +} + +} // namespace Credentials +} // namespace chip diff --git a/src/credentials/CHIPCertToX509.cpp b/src/credentials/CHIPCertToX509.cpp new file mode 100644 index 00000000000000..b820b1919c9a26 --- /dev/null +++ b/src/credentials/CHIPCertToX509.cpp @@ -0,0 +1,920 @@ +/* + * + * Copyright (c) 2020-2021 Project CHIP Authors + * Copyright (c) 2013-2017 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 + * This file implements methods for converting a CHIP + * TLV-encoded certificate to a standard X.509 certificate. + * + */ + +#ifndef __STDC_LIMIT_MACROS +#define __STDC_LIMIT_MACROS +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace chip { +namespace Credentials { + +using namespace chip::ASN1; +using namespace chip::TLV; +using namespace chip::Protocols; + +inline bool IsCertificateExtensionTag(uint64_t tag) +{ + if (IsContextTag(tag)) + { + uint32_t tagNum = TagNumFromTag(tag); + return (tagNum >= kCertificateExtensionTagsStart && tagNum <= kCertificateExtensionTagsEnd); + } + + return false; +} + +static CHIP_ERROR DecodeConvertDN(TLVReader & reader, ASN1Writer & writer, ChipDN & dn) +{ + CHIP_ERROR err; + TLVType outerContainer; + TLVType elemType; + uint64_t tlvTag; + uint32_t tlvTagNum; + OID attrOID; + uint32_t asn1Tag; + const uint8_t * asn1AttrVal; + uint32_t asn1AttrValLen; + uint8_t chipIdStr[17]; + + // Enter the List TLV element that represents the DN in TLV format. + err = reader.EnterContainer(outerContainer); + SuccessOrExit(err); + + // Read the first TLV element in the List. This represents the first RDN in the original ASN.1 DN. + // + // NOTE: Although CHIP certificate encoding allows for DNs containing multiple RDNs, and/or multiple + // attributes per RDN, this implementation only supports DNs with a single RDN that contains exactly + // one attribute. + // + err = reader.Next(); + SuccessOrExit(err); + + // Get the TLV tag, make sure it is a context tag and extract the context tag number. + tlvTag = reader.GetTag(); + VerifyOrExit(IsContextTag(tlvTag), err = CHIP_ERROR_INVALID_TLV_TAG); + tlvTagNum = TagNumFromTag(tlvTag); + + // Get the element type. + elemType = reader.GetType(); + + // Derive the OID of the corresponding ASN.1 attribute from the TLV tag number. + // The numeric value of the OID is encoded in the bottom 7 bits of the TLV tag number. + // This eliminates the need for a translation table/switch statement but has the + // effect of tying the two encodings together. + // + // NOTE: In the event that the computed OID value is not one that we recognize + // (specifically, is not in the table of OIDs defined in ASN1OID.h) then the + // macro call below that encodes the attribute's object id (ASN1_ENCODE_OBJECT_ID) + // will fail for lack of the OID's encoded representation. Given this there's no + // need to test the validity of the OID here. + // + attrOID = GetOID(kOIDCategory_AttributeType, static_cast(tlvTagNum & 0x7f)); + + // Save the attribute OID in the caller's DN structure. + dn.mAttrOID = attrOID; + + // If the attribute is one of the CHIP-defined X.509 attributes that contains a CHIP id... + if (IsChipIdX509Attr(attrOID)) + { + // Verify that the underlying TLV data type is unsigned integer. + VerifyOrExit(elemType == kTLVType_UnsignedInteger, err = CHIP_ERROR_WRONG_TLV_TYPE); + + // Read the value of the CHIP id. + uint64_t chipId; + err = reader.Get(chipId); + SuccessOrExit(err); + + // Generate the string representation of the id that will appear in the ASN.1 attribute. + // For CHIP ids the string representation is *always* 16 uppercase hex characters. + snprintf(reinterpret_cast(chipIdStr), sizeof(chipIdStr), "%016" PRIX64, chipId); + asn1AttrVal = chipIdStr; + asn1AttrValLen = 16; + + // The ASN.1 tag for CHIP id attributes is always UTF8String. + asn1Tag = kASN1UniversalTag_UTF8String; + + // Save the CHIP id value in the caller's DN structure. + dn.mAttrValue.mChipId = chipId; + } + + // Otherwise the attribute is either one of the supported X.509 attributes or a CHIP-defined + // attribute that is *not* a CHIP id... + else + { + // Verify that the underlying data type is UTF8 string. + VerifyOrExit(elemType == kTLVType_UTF8String, err = CHIP_ERROR_WRONG_TLV_TYPE); + + // Get a pointer the underlying string data, plus its length. + err = reader.GetDataPtr(asn1AttrVal); + SuccessOrExit(err); + asn1AttrValLen = reader.GetLength(); + + // Determine the appropriate ASN.1 tag for the DN attribute. + // - CHIP-defined attributes are always UTF8Strings. + // - DomainComponent is always an IA5String. + // - For all other ASN.1 defined attributes, bit 0x80 in the TLV tag value conveys whether the attribute + // is a UTF8String or a PrintableString (in some cases the certificate generator has a choice). + if (IsChipX509Attr(attrOID)) + { + asn1Tag = kASN1UniversalTag_UTF8String; + } + else if (attrOID == kOID_AttributeType_DomainComponent) + { + asn1Tag = kASN1UniversalTag_IA5String; + } + else + { + asn1Tag = (tlvTagNum & 0x80) ? kASN1UniversalTag_PrintableString : kASN1UniversalTag_UTF8String; + } + + // Save the string value in the caller's DN structure. + dn.mAttrValue.mString.mValue = asn1AttrVal; + dn.mAttrValue.mString.mLen = asn1AttrValLen; + } + + // Verify that there are no further elements in the DN. + err = reader.VerifyEndOfContainer(); + SuccessOrExit(err); + + err = reader.ExitContainer(outerContainer); + SuccessOrExit(err); + + // Write the ASN.1 representation of the DN... + + // RDNSequence ::= SEQUENCE OF RelativeDistinguishedName + ASN1_START_SEQUENCE + { + // RelativeDistinguishedName ::= SET SIZE (1..MAX) OF AttributeTypeAndValue + ASN1_START_SET + { + // AttributeTypeAndValue ::= SEQUENCE + ASN1_START_SEQUENCE + { + // type AttributeType + // AttributeType ::= OBJECT IDENTIFIER + ASN1_ENCODE_OBJECT_ID(attrOID); + + // value AttributeValue + // AttributeValue ::= ANY -- DEFINED BY AttributeType + err = writer.PutString(asn1Tag, Uint8::to_const_char(asn1AttrVal), static_cast(asn1AttrValLen)); + SuccessOrExit(err); + } + ASN1_END_SEQUENCE; + } + ASN1_END_SET; + } + ASN1_END_SEQUENCE; + +exit: + return err; +} + +static CHIP_ERROR DecodeConvertValidity(TLVReader & reader, ASN1Writer & writer, ChipCertificateData & certData) +{ + CHIP_ERROR err; + ASN1UniversalTime asn1Time; + uint64_t packedTime; + + ASN1_START_SEQUENCE + { + err = reader.Next(kTLVType_UnsignedInteger, ContextTag(kTag_NotBefore)); + SuccessOrExit(err); + err = reader.Get(packedTime); + SuccessOrExit(err); + VerifyOrExit(packedTime <= UINT32_MAX, err = CHIP_ERROR_UNSUPPORTED_CERT_FORMAT); + certData.mNotBeforeDate = PackedCertTimeToDate(static_cast(packedTime)); + err = UnpackCertTime(static_cast(packedTime), asn1Time); + SuccessOrExit(err); + + ASN1_ENCODE_TIME(asn1Time); + + err = reader.Next(kTLVType_UnsignedInteger, ContextTag(kTag_NotAfter)); + SuccessOrExit(err); + err = reader.Get(packedTime); + SuccessOrExit(err); + VerifyOrExit(packedTime <= UINT32_MAX, err = CHIP_ERROR_UNSUPPORTED_CERT_FORMAT); + certData.mNotAfterDate = PackedCertTimeToDate(static_cast(packedTime)); + err = UnpackCertTime(static_cast(packedTime), asn1Time); + SuccessOrExit(err); + + ASN1_ENCODE_TIME(asn1Time); + } + ASN1_END_SEQUENCE; + +exit: + return err; +} + +static CHIP_ERROR DecodeConvertSubjectPublicKeyInfo(TLVReader & reader, ASN1Writer & writer, ChipCertificateData & certData) +{ + CHIP_ERROR err; + uint64_t pubKeyAlgoId, pubKeyCurveId; + OID pubKeyAlgoOID; + + err = reader.Next(kTLVType_UnsignedInteger, ContextTag(kTag_PublicKeyAlgorithm)); + SuccessOrExit(err); + err = reader.Get(pubKeyAlgoId); + SuccessOrExit(err); + VerifyOrExit(pubKeyAlgoId <= UINT8_MAX, err = CHIP_ERROR_UNSUPPORTED_CERT_FORMAT); + + pubKeyAlgoOID = GetOID(kOIDCategory_PubKeyAlgo, static_cast(pubKeyAlgoId)); + certData.mPubKeyAlgoOID = pubKeyAlgoOID; + + VerifyOrExit(pubKeyAlgoOID == kOID_PubKeyAlgo_ECPublicKey, err = CHIP_ERROR_UNSUPPORTED_CERT_FORMAT); + + err = reader.Next(kTLVType_UnsignedInteger, ContextTag(kTag_EllipticCurveIdentifier)); + SuccessOrExit(err); + err = reader.Get(pubKeyCurveId); + SuccessOrExit(err); + VerifyOrExit(pubKeyCurveId <= UINT8_MAX, err = CHIP_ERROR_UNSUPPORTED_CERT_FORMAT); + + certData.mPubKeyCurveOID = GetOID(kOIDCategory_EllipticCurve, static_cast(pubKeyCurveId)); + + // subjectPublicKeyInfo SubjectPublicKeyInfo, + ASN1_START_SEQUENCE + { + // algorithm AlgorithmIdentifier, + // AlgorithmIdentifier ::= SEQUENCE + ASN1_START_SEQUENCE + { + // algorithm OBJECT IDENTIFIER, + ASN1_ENCODE_OBJECT_ID(pubKeyAlgoOID); + + // EcpkParameters ::= CHOICE { + // ecParameters ECParameters, + // namedCurve OBJECT IDENTIFIER, + // implicitlyCA NULL } + // + // (Only namedCurve supported). + // + ASN1_ENCODE_OBJECT_ID(certData.mPubKeyCurveOID); + } + ASN1_END_SEQUENCE; + + err = reader.Next(kTLVType_ByteString, ContextTag(kTag_EllipticCurvePublicKey)); + SuccessOrExit(err); + + err = reader.GetDataPtr(certData.mPublicKey); + SuccessOrExit(err); + + uint32_t len = reader.GetLength(); + VerifyOrExit(len == chip::Crypto::kP256_PublicKey_Length, err = CHIP_ERROR_UNSUPPORTED_CERT_FORMAT); + certData.mPublicKeyLen = static_cast(len); + + // For EC certs, the subjectPublicKey BIT STRING contains the X9.62 encoded EC point. + err = writer.PutBitString(0, certData.mPublicKey, certData.mPublicKeyLen); + SuccessOrExit(err); + } + ASN1_END_SEQUENCE; + +exit: + return err; +} + +static CHIP_ERROR DecodeConvertAuthorityKeyIdentifierExtension(TLVReader & reader, ASN1Writer & writer, + ChipCertificateData & certData) +{ + CHIP_ERROR err, nextRes; + uint32_t len; + + certData.mCertFlags.Set(CertFlags::kExtPresent_AuthKeyId); + + // AuthorityKeyIdentifier ::= SEQUENCE + ASN1_START_SEQUENCE + { + // keyIdentifier [0] IMPLICIT KeyIdentifier OPTIONAL, + // KeyIdentifier ::= OCTET STRING + if (reader.GetTag() == ContextTag(kTag_AuthorityKeyIdentifier_KeyIdentifier)) + { + VerifyOrExit(reader.GetType() == kTLVType_ByteString, err = CHIP_ERROR_WRONG_TLV_TYPE); + + err = reader.GetDataPtr(certData.mAuthKeyId.mId); + SuccessOrExit(err); + + len = reader.GetLength(); + VerifyOrExit(len <= UINT8_MAX, err = CHIP_ERROR_UNSUPPORTED_CERT_FORMAT); + + certData.mAuthKeyId.mLen = static_cast(len); + + err = writer.PutOctetString(kASN1TagClass_ContextSpecific, 0, certData.mAuthKeyId.mId, certData.mAuthKeyId.mLen); + SuccessOrExit(err); + + nextRes = reader.Next(); + VerifyOrExit(nextRes == CHIP_NO_ERROR || nextRes == CHIP_END_OF_TLV, err = nextRes); + } + } + ASN1_END_SEQUENCE; + +exit: + return err; +} + +static CHIP_ERROR DecodeConvertSubjectKeyIdentifierExtension(TLVReader & reader, ASN1Writer & writer, + ChipCertificateData & certData) +{ + CHIP_ERROR err; + uint32_t len; + + certData.mCertFlags.Set(CertFlags::kExtPresent_SubjectKeyId); + + // SubjectKeyIdentifier ::= KeyIdentifier + // KeyIdentifier ::= OCTET STRING + VerifyOrExit(reader.GetType() == kTLVType_ByteString, err = CHIP_ERROR_WRONG_TLV_TYPE); + VerifyOrExit(reader.GetTag() == ContextTag(kTag_SubjectKeyIdentifier_KeyIdentifier), err = CHIP_ERROR_UNEXPECTED_TLV_ELEMENT); + + len = reader.GetLength(); + VerifyOrExit(len <= UINT8_MAX, err = CHIP_ERROR_UNSUPPORTED_CERT_FORMAT); + + certData.mSubjectKeyId.mLen = static_cast(len); + + err = reader.GetDataPtr(certData.mSubjectKeyId.mId); + SuccessOrExit(err); + + err = writer.PutOctetString(certData.mSubjectKeyId.mId, certData.mSubjectKeyId.mLen); + SuccessOrExit(err); + +exit: + return err; +} + +static CHIP_ERROR DecodeConvertKeyUsageExtension(TLVReader & reader, ASN1Writer & writer, ChipCertificateData & certData) +{ + CHIP_ERROR err; + uint64_t keyUsageBits; + BitFlags keyUsageFlags; + + certData.mCertFlags.Set(CertFlags::kExtPresent_KeyUsage); + + // KeyUsage ::= BIT STRING + VerifyOrExit(reader.GetTag() == ContextTag(kTag_KeyUsage_KeyUsage), err = CHIP_ERROR_UNEXPECTED_TLV_ELEMENT); + err = reader.Get(keyUsageBits); + SuccessOrExit(err); + VerifyOrExit(keyUsageBits <= UINT16_MAX, err = CHIP_ERROR_UNSUPPORTED_CERT_FORMAT); + + keyUsageFlags.SetRaw(static_cast(keyUsageBits)); + VerifyOrExit(keyUsageFlags.HasOnly(KeyUsageFlags::kDigitalSignature, KeyUsageFlags::kNonRepudiation, + KeyUsageFlags::kKeyEncipherment, KeyUsageFlags::kDataEncipherment, + KeyUsageFlags::kKeyAgreement, KeyUsageFlags::kKeyCertSign, KeyUsageFlags::kCRLSign, + KeyUsageFlags::kEncipherOnly, KeyUsageFlags::kEncipherOnly), + err = CHIP_ERROR_UNSUPPORTED_CERT_FORMAT); + + ASN1_ENCODE_BIT_STRING(static_cast(keyUsageBits)); + + certData.mKeyUsageFlags = keyUsageFlags; + +exit: + return err; +} + +static CHIP_ERROR DecodeConvertBasicConstraintsExtension(TLVReader & reader, ASN1Writer & writer, ChipCertificateData & certData) +{ + CHIP_ERROR err, nextRes; + + certData.mCertFlags.Set(CertFlags::kExtPresent_BasicConstraints); + + // BasicConstraints ::= SEQUENCE + ASN1_START_SEQUENCE + { + // cA BOOLEAN DEFAULT FALSE + if (reader.GetTag() == ContextTag(kTag_BasicConstraints_IsCA)) + { + bool isCA; + + err = reader.Get(isCA); + SuccessOrExit(err); + + if (isCA) + { + ASN1_ENCODE_BOOLEAN(true); + certData.mCertFlags.Set(CertFlags::kIsCA); + } + + nextRes = reader.Next(); + VerifyOrExit(nextRes == CHIP_NO_ERROR || nextRes == CHIP_END_OF_TLV, err = nextRes); + } + + // pathLenConstraint INTEGER (0..MAX) OPTIONAL + if (reader.GetTag() == ContextTag(kTag_BasicConstraints_PathLenConstraint)) + { + uint64_t pathLenConstraint; + + err = reader.Get(pathLenConstraint); + SuccessOrExit(err); + + VerifyOrExit(pathLenConstraint <= UINT8_MAX, err = CHIP_ERROR_UNSUPPORTED_CERT_FORMAT); + + ASN1_ENCODE_INTEGER(static_cast(pathLenConstraint)); + + certData.mPathLenConstraint = static_cast(pathLenConstraint); + + certData.mCertFlags.Set(CertFlags::kPathLenConstraintPresent); + } + } + ASN1_END_SEQUENCE; + +exit: + return err; +} + +static CHIP_ERROR DecodeConvertExtendedKeyUsageExtension(TLVReader & reader, ASN1Writer & writer, ChipCertificateData & certData) +{ + CHIP_ERROR err, nextRes; + TLVType outerContainer; + + certData.mCertFlags.Set(CertFlags::kExtPresent_ExtendedKeyUsage); + + // ExtKeyUsageSyntax ::= SEQUENCE SIZE (1..MAX) OF KeyPurposeId + ASN1_START_SEQUENCE + { + VerifyOrExit(reader.GetTag() == ContextTag(kTag_ExtendedKeyUsage_KeyPurposes), err = CHIP_ERROR_WRONG_TLV_TYPE); + VerifyOrExit(reader.GetType() == kTLVType_Array, err = CHIP_ERROR_WRONG_TLV_TYPE); + + err = reader.EnterContainer(outerContainer); + SuccessOrExit(err); + + while ((nextRes = reader.Next(kTLVType_UnsignedInteger, AnonymousTag)) == CHIP_NO_ERROR) + { + uint64_t keyPurposeId; + OID keyPurposeOID; + + err = reader.Get(keyPurposeId); + SuccessOrExit(err); + + VerifyOrExit(keyPurposeId <= UINT8_MAX, err = CHIP_ERROR_UNSUPPORTED_CERT_FORMAT); + + keyPurposeOID = GetOID(kOIDCategory_KeyPurpose, static_cast(keyPurposeId)); + + // KeyPurposeId ::= OBJECT IDENTIFIER + ASN1_ENCODE_OBJECT_ID(keyPurposeOID); + + certData.mKeyPurposeFlags.Set(static_cast(0x01 << (keyPurposeId - 1))); + } + + VerifyOrExit(nextRes == CHIP_END_OF_TLV, err = nextRes); + + err = reader.ExitContainer(outerContainer); + SuccessOrExit(err); + } + ASN1_END_SEQUENCE; + +exit: + return err; +} + +static CHIP_ERROR DecodeConvertExtension(TLVReader & reader, ASN1Writer & writer, ChipCertificateData & certData) +{ + CHIP_ERROR err, nextRes; + TLVType outerContainer; + uint64_t extensionTagNum = TagNumFromTag(reader.GetTag()); + OID extensionOID; + + if (extensionTagNum == kTag_AuthorityKeyIdentifier) + { + extensionOID = kOID_Extension_AuthorityKeyIdentifier; + } + else if (extensionTagNum == kTag_SubjectKeyIdentifier) + { + extensionOID = kOID_Extension_SubjectKeyIdentifier; + } + else if (extensionTagNum == kTag_KeyUsage) + { + extensionOID = kOID_Extension_KeyUsage; + } + else if (extensionTagNum == kTag_BasicConstraints) + { + extensionOID = kOID_Extension_BasicConstraints; + } + else if (extensionTagNum == kTag_ExtendedKeyUsage) + { + extensionOID = kOID_Extension_ExtendedKeyUsage; + } + else + { + ExitNow(err = CHIP_ERROR_UNEXPECTED_TLV_ELEMENT); + } + + err = reader.EnterContainer(outerContainer); + SuccessOrExit(err); + + // Extension ::= SEQUENCE + ASN1_START_SEQUENCE + { + // extnID OBJECT IDENTIFIER, + ASN1_ENCODE_OBJECT_ID(extensionOID); + + // critical BOOLEAN DEFAULT FALSE, + nextRes = reader.Next(); + VerifyOrExit(nextRes == CHIP_NO_ERROR || nextRes == CHIP_END_OF_TLV, err = nextRes); + if (reader.GetTag() == ContextTag(kTag_BasicConstraints_Critical)) + { + bool critical; + err = reader.Get(critical); + SuccessOrExit(err); + if (critical) + { + ASN1_ENCODE_BOOLEAN(true); + } + + nextRes = reader.Next(); + VerifyOrExit(nextRes == CHIP_NO_ERROR || nextRes == CHIP_END_OF_TLV, err = nextRes); + } + + // extnValue OCTET STRING + // -- contains the DER encoding of an ASN.1 value + // -- corresponding to the extension type identified + // -- by extnID + ASN1_START_OCTET_STRING_ENCAPSULATED + { + if (extensionTagNum == kTag_AuthorityKeyIdentifier) + { + err = DecodeConvertAuthorityKeyIdentifierExtension(reader, writer, certData); + } + else if (extensionTagNum == kTag_SubjectKeyIdentifier) + { + err = DecodeConvertSubjectKeyIdentifierExtension(reader, writer, certData); + } + else if (extensionTagNum == kTag_KeyUsage) + { + err = DecodeConvertKeyUsageExtension(reader, writer, certData); + } + else if (extensionTagNum == kTag_BasicConstraints) + { + err = DecodeConvertBasicConstraintsExtension(reader, writer, certData); + } + else if (extensionTagNum == kTag_ExtendedKeyUsage) + { + err = DecodeConvertExtendedKeyUsageExtension(reader, writer, certData); + } + else + { + err = CHIP_ERROR_UNSUPPORTED_CERT_FORMAT; + } + SuccessOrExit(err); + } + ASN1_END_ENCAPSULATED; + } + ASN1_END_SEQUENCE; + + // Verify that all elements in the extension structure were consumed. + err = reader.VerifyEndOfContainer(); + SuccessOrExit(err); + + err = reader.ExitContainer(outerContainer); + SuccessOrExit(err); + +exit: + return err; +} + +static CHIP_ERROR DecodeConvertExtensions(TLVReader & reader, ASN1Writer & writer, ChipCertificateData & certData) +{ + CHIP_ERROR err; + uint64_t tag; + + // extensions [3] EXPLICIT Extensions OPTIONAL + ASN1_START_CONSTRUCTED(kASN1TagClass_ContextSpecific, 3) + { + // Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension + ASN1_START_SEQUENCE + { + while (true) + { + err = DecodeConvertExtension(reader, writer, certData); + SuccessOrExit(err); + + // Break the loop if the next certificate element is NOT an extension. + err = reader.Next(); + SuccessOrExit(err); + tag = reader.GetTag(); + if (!IsCertificateExtensionTag(tag)) + { + break; + } + } + } + ASN1_END_SEQUENCE; + } + ASN1_END_CONSTRUCTED; + +exit: + return err; +} + +CHIP_ERROR DecodeECDSASignature(TLVReader & reader, ChipCertificateData & certData) +{ + CHIP_ERROR err; + TLVType containerType; + uint32_t len; + + // Verify the tag and type + VerifyOrExit(reader.GetType() == kTLVType_Structure, err = CHIP_ERROR_WRONG_TLV_TYPE); + VerifyOrExit(reader.GetTag() == ContextTag(kTag_ECDSASignature), err = CHIP_ERROR_UNEXPECTED_TLV_ELEMENT); + + err = reader.EnterContainer(containerType); + SuccessOrExit(err); + + // r INTEGER + err = reader.Next(kTLVType_ByteString, ContextTag(kTag_ECDSASignature_r)); + SuccessOrExit(err); + + err = reader.GetDataPtr(certData.mSignature.R); + SuccessOrExit(err); + + len = reader.GetLength(); + VerifyOrExit(len <= UINT8_MAX, err = CHIP_ERROR_UNSUPPORTED_CERT_FORMAT); + + certData.mSignature.RLen = static_cast(len); + + // s INTEGER + err = reader.Next(kTLVType_ByteString, ContextTag(kTag_ECDSASignature_s)); + SuccessOrExit(err); + + err = reader.GetDataPtr(certData.mSignature.S); + SuccessOrExit(err); + + len = reader.GetLength(); + VerifyOrExit(len < UINT8_MAX, err = CHIP_ERROR_UNSUPPORTED_CERT_FORMAT); + + certData.mSignature.SLen = static_cast(len); + + // Verify no more elements in the signature. + reader.Next(); + err = reader.VerifyEndOfContainer(); + SuccessOrExit(err); + + err = reader.ExitContainer(containerType); + SuccessOrExit(err); + +exit: + return err; +} + +static CHIP_ERROR DecodeConvertECDSASignature(TLVReader & reader, ASN1Writer & writer, ChipCertificateData & certData) +{ + CHIP_ERROR err; + + err = DecodeECDSASignature(reader, certData); + SuccessOrExit(err); + + // signatureValue BIT STRING + // Per RFC3279, the ECDSA signature value is encoded in DER encapsulated in the signatureValue BIT STRING. + ASN1_START_BIT_STRING_ENCAPSULATED + { + // Ecdsa-Sig-Value ::= SEQUENCE + ASN1_START_SEQUENCE + { + // r INTEGER + err = writer.PutValue(kASN1TagClass_Universal, kASN1UniversalTag_Integer, false, certData.mSignature.R, + certData.mSignature.RLen); + SuccessOrExit(err); + + // s INTEGER + err = writer.PutValue(kASN1TagClass_Universal, kASN1UniversalTag_Integer, false, certData.mSignature.S, + certData.mSignature.SLen); + SuccessOrExit(err); + } + ASN1_END_SEQUENCE; + } + ASN1_END_ENCAPSULATED; + +exit: + return err; +} + +/** + * @brief Decode and convert the To-Be-Signed (TBS) portion of the CHIP certificate + * into X.509 DER encoded form. + * + * @param reader A TLVReader positioned at the beginning of the TBS portion + * (certificate serial number) of the CHIP certificates. + * @param writer A reference to the ASN1Writer to store DER encoded TBS portion of + * the CHIP certificate. + * @param certData Structure containing data extracted from the TBS portion of the + * CHIP certificate. + * + * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise + **/ +CHIP_ERROR DecodeConvertTBSCert(TLVReader & reader, ASN1Writer & writer, ChipCertificateData & certData) +{ + CHIP_ERROR err; + uint64_t tag; + + // tbsCertificate TBSCertificate, + // TBSCertificate ::= SEQUENCE + ASN1_START_SEQUENCE + { + // version [0] EXPLICIT Version DEFAULT v1 + ASN1_START_CONSTRUCTED(kASN1TagClass_ContextSpecific, 0) + { + // Version ::= INTEGER { v1(0), v2(1), v3(2) } + ASN1_ENCODE_INTEGER(2); + } + ASN1_END_CONSTRUCTED; + + err = reader.Next(kTLVType_ByteString, ContextTag(kTag_SerialNumber)); + SuccessOrExit(err); + + // serialNumber CertificateSerialNumber + // CertificateSerialNumber ::= INTEGER + err = writer.PutValue(kASN1TagClass_Universal, kASN1UniversalTag_Integer, false, reader); + SuccessOrExit(err); + + // signature AlgorithmIdentifier + // AlgorithmIdentifier ::= SEQUENCE + ASN1_START_SEQUENCE + { + uint64_t sigAlgoId; + OID sigAlgoOID; + + err = reader.Next(kTLVType_UnsignedInteger, ContextTag(kTag_SignatureAlgorithm)); + SuccessOrExit(err); + + err = reader.Get(sigAlgoId); + SuccessOrExit(err); + + VerifyOrExit(sigAlgoId <= UINT8_MAX, err = CHIP_ERROR_UNSUPPORTED_CERT_FORMAT); + + sigAlgoOID = GetOID(kOIDCategory_SigAlgo, static_cast(sigAlgoId)); + ASN1_ENCODE_OBJECT_ID(sigAlgoOID); + + certData.mSigAlgoOID = sigAlgoOID; + } + ASN1_END_SEQUENCE; + + // issuer Name + err = reader.Next(kTLVType_Path, ContextTag(kTag_Issuer)); + SuccessOrExit(err); + err = DecodeConvertDN(reader, writer, certData.mIssuerDN); + SuccessOrExit(err); + + // validity Validity, + err = DecodeConvertValidity(reader, writer, certData); + SuccessOrExit(err); + + // subject Name + err = reader.Next(kTLVType_Path, ContextTag(kTag_Subject)); + SuccessOrExit(err); + err = DecodeConvertDN(reader, writer, certData.mSubjectDN); + SuccessOrExit(err); + + // subjectPublicKeyInfo SubjectPublicKeyInfo, + err = DecodeConvertSubjectPublicKeyInfo(reader, writer, certData); + SuccessOrExit(err); + + // If the next element is a certificate extension... + err = reader.Next(); + SuccessOrExit(err); + tag = reader.GetTag(); + if (IsCertificateExtensionTag(tag)) + { + err = DecodeConvertExtensions(reader, writer, certData); + SuccessOrExit(err); + } + } + ASN1_END_SEQUENCE; + +exit: + return err; +} + +static CHIP_ERROR DecodeConvertCert(TLVReader & reader, ASN1Writer & writer, ChipCertificateData & certData) +{ + CHIP_ERROR err; + uint64_t tag; + TLVType containerType; + + if (reader.GetType() == kTLVType_NotSpecified) + { + err = reader.Next(); + SuccessOrExit(err); + } + VerifyOrExit(reader.GetType() == kTLVType_Structure, err = CHIP_ERROR_WRONG_TLV_TYPE); + tag = reader.GetTag(); + VerifyOrExit(tag == ProfileTag(kProtocol_OpCredentials, kTag_ChipCertificate) || tag == AnonymousTag, + err = CHIP_ERROR_UNEXPECTED_TLV_ELEMENT); + + err = reader.EnterContainer(containerType); + SuccessOrExit(err); + + // Certificate ::= SEQUENCE + ASN1_START_SEQUENCE + { + // tbsCertificate TBSCertificate, + err = DecodeConvertTBSCert(reader, writer, certData); + SuccessOrExit(err); + + // signatureAlgorithm AlgorithmIdentifier + // AlgorithmIdentifier ::= SEQUENCE + ASN1_START_SEQUENCE { ASN1_ENCODE_OBJECT_ID(static_cast(certData.mSigAlgoOID)); } + ASN1_END_SEQUENCE; + + // signatureValue BIT STRING + err = DecodeConvertECDSASignature(reader, writer, certData); + SuccessOrExit(err); + } + ASN1_END_SEQUENCE; + + // Verify no more elements in certificate. + err = reader.VerifyEndOfContainer(); + SuccessOrExit(err); + + err = reader.ExitContainer(containerType); + SuccessOrExit(err); + +exit: + return err; +} + +DLL_EXPORT CHIP_ERROR ConvertChipCertToX509Cert(const uint8_t * chipCert, uint32_t chipCertLen, uint8_t * x509CertBuf, + uint32_t x509CertBufSize, uint32_t & x509CertLen) +{ + CHIP_ERROR err; + TLVReader reader; + ASN1Writer writer; + ChipCertificateData certData; + + reader.Init(chipCert, chipCertLen); + + writer.Init(x509CertBuf, x509CertBufSize); + + err = DecodeConvertCert(reader, writer, certData); + SuccessOrExit(err); + + err = writer.Finalize(); + SuccessOrExit(err); + + x509CertLen = writer.GetLengthWritten(); + +exit: + return err; +} + +CHIP_ERROR DecodeChipCert(const uint8_t * chipCert, uint32_t chipCertLen, ChipCertificateData & certData) +{ + TLVReader reader; + + reader.Init(chipCert, chipCertLen); + + return DecodeChipCert(reader, certData); +} + +CHIP_ERROR DecodeChipCert(TLVReader & reader, ChipCertificateData & certData) +{ + ASN1Writer writer; + + writer.InitNullWriter(); + + certData.Clear(); + + return DecodeConvertCert(reader, writer, certData); +} + +CHIP_ERROR DecodeChipDN(TLVReader & reader, ChipDN & dn) +{ + ASN1Writer writer; + + writer.InitNullWriter(); + + dn.Clear(); + + return DecodeConvertDN(reader, writer, dn); +} + +} // namespace Credentials +} // namespace chip diff --git a/src/credentials/tests/BUILD.gn b/src/credentials/tests/BUILD.gn new file mode 100644 index 00000000000000..35306cbcaf2c44 --- /dev/null +++ b/src/credentials/tests/BUILD.gn @@ -0,0 +1,37 @@ +# Copyright (c) 2020-2021 Project CHIP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build_overrides/chip.gni") +import("//build_overrides/nlunit_test.gni") + +import("${chip_root}/build/chip/chip_test_suite.gni") + +chip_test_suite("tests") { + output_name = "libChipCredentials" + + sources = [ + "CHIPCert_test_vectors.cpp", + "CHIPCert_test_vectors.h", + ] + + test_sources = [ "TestChipCert.cpp" ] + + cflags = [ "-Wconversion" ] + + public_deps = [ + "${chip_root}/src/credentials", + "${chip_root}/src/lib/core", + "${nlunit_test_root}:nlunit-test", + ] +} diff --git a/src/credentials/tests/CHIPCert_test_vectors.cpp b/src/credentials/tests/CHIPCert_test_vectors.cpp new file mode 100644 index 00000000000000..cd9844a0b3574a --- /dev/null +++ b/src/credentials/tests/CHIPCert_test_vectors.cpp @@ -0,0 +1,784 @@ +/* + * + * Copyright (c) 2020-2021 Project CHIP Authors + * Copyright (c) 2019 Google LLC. + * Copyright (c) 2016-2017 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 + * This file contains definitions of test certificates used by various unit tests. + * + */ + +#include + +#include "CHIPCert_test_vectors.h" + +namespace chip { +namespace TestCerts { + +using namespace chip::Credentials; +using namespace chip::ASN1; + +// clang-format off +extern const uint8_t gTestCerts[] = { + TestCertTypes::kRoot, + TestCertTypes::kNodeCA, + TestCertTypes::kNode01, + TestCertTypes::kFirmwareSigningCA, + TestCertTypes::kFirmwareSigning, +}; +// clang-format on + +extern const size_t gNumTestCerts = sizeof(gTestCerts) / sizeof(gTestCerts[0]); + +CHIP_ERROR GetTestCert(uint8_t certType, BitFlags certLoadFlags, const uint8_t *& certData, + uint32_t & certDataLen) +{ + CHIP_ERROR err; + bool derForm = certLoadFlags.Has(TestCertLoadFlags::kDERForm); + +#define SELECT_CERT(NAME) \ + do \ + { \ + if (certType == TestCertTypes::k##NAME) \ + { \ + if (derForm) \ + { \ + certData = sTestCert_##NAME##_DER; \ + certDataLen = sTestCert_##NAME##_DER_Len; \ + } \ + else \ + { \ + certData = sTestCert_##NAME##_Chip; \ + certDataLen = sTestCert_##NAME##_Chip_Len; \ + } \ + ExitNow(err = CHIP_NO_ERROR); \ + } \ + } while (0) + + SELECT_CERT(Root); + SELECT_CERT(NodeCA); + SELECT_CERT(Node01); + SELECT_CERT(FirmwareSigningCA); + SELECT_CERT(FirmwareSigning); + + err = CHIP_ERROR_CA_CERT_NOT_FOUND; + +exit: + return err; +} + +const char * GetTestCertName(uint8_t certType) +{ +#define NAME_CERT(NAME) \ + do \ + { \ + if (certType == TestCertTypes::k##NAME) \ + { \ + return #NAME; \ + } \ + } while (0) + + NAME_CERT(Root); + NAME_CERT(NodeCA); + NAME_CERT(Node01); + NAME_CERT(FirmwareSigningCA); + NAME_CERT(FirmwareSigning); + + return nullptr; +} + +CHIP_ERROR LoadTestCert(ChipCertificateSet & certSet, uint8_t certType, BitFlags certLoadFlags, + BitFlags decodeFlags) +{ + CHIP_ERROR err; + ChipCertificateData * cert; + const uint8_t * certData; + uint32_t certDataLen; + + // Special case for loading the root public key only. + if (certType == TestCertTypes::kRootKey) + { + // Add the trusted root key to the certificate set. + err = certSet.AddTrustedKey(sTestCert_Root_Id, kOID_EllipticCurve_prime256v1, sTestCert_Root_PublicKey, + sTestCert_Root_PublicKey_Len, sTestCert_Root_SubjectKeyId, sTestCert_Root_SubjectKeyId_Len); + ExitNow(); + } + + // Get the requested certificate data. + err = GetTestCert(certType, certLoadFlags, certData, certDataLen); + SuccessOrExit(err); + + // Load it into the certificate set. + err = certSet.LoadCert(certData, certDataLen, decodeFlags); + SuccessOrExit(err); + + // Get loaded certificate data. + cert = const_cast(certSet.GetLastCert()); + VerifyOrExit(cert != nullptr, err = CHIP_ERROR_INVALID_ARGUMENT); + + // Apply load flags. + if (certLoadFlags.Has(TestCertLoadFlags::kSuppressIsCA)) + { + cert->mCertFlags.Clear(CertFlags::kIsCA); + } + if (certLoadFlags.Has(TestCertLoadFlags::kSuppressKeyUsage)) + { + cert->mCertFlags.Clear(CertFlags::kExtPresent_KeyUsage); + } + if (certLoadFlags.Has(TestCertLoadFlags::kSuppressKeyCertSign)) + { + cert->mKeyUsageFlags.Clear(KeyUsageFlags::kKeyCertSign); + } + if (certLoadFlags.Has(TestCertLoadFlags::kSetPathLenConstZero)) + { + cert->mCertFlags.Set(CertFlags::kPathLenConstraintPresent); + cert->mPathLenConstraint = 0; + } + if (certLoadFlags.Has(TestCertLoadFlags::kSetAppDefinedCertType)) + { + cert->mCertType = kCertType_AppDefinedBase; + } + +exit: + return err; +} + +// ------------------------------ TEST CERTIFICATES ---------------------------------------- + +/************** Test Root Certificate ************** +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 5763064141628170117 (0x4ffa844d8389df85) + Signature Algorithm: ecdsa-with-SHA256 + Issuer: 1.3.6.1.4.1.37244.1.2 = CACACACA00000001 + Validity + Not Before: Oct 15 14:23:43 2020 GMT + Not After : Oct 15 14:23:42 2040 GMT + Subject: 1.3.6.1.4.1.37244.1.2 = CACACACA00000001 + Subject Public Key Info: + Public Key Algorithm: id-ecPublicKey + Public-Key: (256 bit) + pub: + 04:9d:30:fe:21:2d:09:ea:f2:ec:c7:9c:56:24:df: + 3c:22:6d:5b:9c:fa:3d:7f:74:ff:38:7c:20:c8:04: + 27:cb:9b:03:ad:76:e9:30:c5:2e:b5:80:be:b9:fa: + e5:24:7c:03:5b:38:fe:9c:b8:49:91:70:fc:fc:1e: + c6:67:23:d8:df + ASN1 OID: prime256v1 + NIST CURVE: P-256 + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 Subject Key Identifier: + 4F:5A:CC:78:01:43:03:52 + X509v3 Authority Key Identifier: + keyid:4F:5A:CC:78:01:43:03:52 + + Signature Algorithm: ecdsa-with-SHA256 + 30:44:02:20:0d:4c:2a:85:cd:91:ae:25:9b:09:bd:58:20:dc: + c6:2c:62:38:b7:11:27:08:62:dc:f2:a5:08:c1:c0:aa:b9:2c: + 02:20:24:1e:39:d0:2d:5b:9a:b5:f2:23:8b:25:9b:f0:98:10: + fe:29:e7:f2:89:1f:77:11:7f:d7:f0:9c:e5:f4:0b:31 + +-----BEGIN CERTIFICATE----- +MIIBhDCCASugAwIBAgIIT/qETYOJ34UwCgYIKoZIzj0EAwIwIjEgMB4GCisGAQQB +gqJ8AQIMEENBQ0FDQUNBMDAwMDAwMDEwHhcNMjAxMDE1MTQyMzQzWhcNNDAxMDE1 +MTQyMzQyWjAiMSAwHgYKKwYBBAGConwBAgwQQ0FDQUNBQ0EwMDAwMDAwMTBZMBMG +ByqGSM49AgEGCCqGSM49AwEHA0IABJ0w/iEtCery7MecViTfPCJtW5z6PX90/zh8 +IMgEJ8ubA6126TDFLrWAvrn65SR8A1s4/py4SZFw/Pwexmcj2N+jSzBJMA8GA1Ud +EwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMBEGA1UdDgQKBAhPWsx4AUMDUjAT +BgNVHSMEDDAKgAhPWsx4AUMDUjAKBggqhkjOPQQDAgNHADBEAiANTCqFzZGuJZsJ +vVgg3MYsYji3EScIYtzypQjBwKq5LAIgJB450C1bmrXyI4slm/CYEP4p5/KJH3cR +f9fwnOX0CzE= +-----END CERTIFICATE----- + +-----BEGIN EC PRIVATE KEY----- +MHcCAQEEIE6Daw+GnPVjVCdtXWDRlU7MgIUvySg6V82n/1tIpIDGoAoGCCqGSM49 +AwEHoUQDQgAEnTD+IS0J6vLsx5xWJN88Im1bnPo9f3T/OHwgyAQny5sDrXbpMMUu +tYC+ufrlJHwDWzj+nLhJkXD8/B7GZyPY3w== +-----END EC PRIVATE KEY----- +*/ + +extern const uint8_t sTestCert_Root_Chip[] = { + 0xd5, 0x00, 0x00, 0x08, 0x00, 0x01, 0x00, 0x30, 0x01, 0x08, 0x4f, 0xfa, 0x84, 0x4d, 0x83, 0x89, 0xdf, 0x85, 0x24, 0x02, 0x01, + 0x37, 0x03, 0x27, 0x12, 0x01, 0x00, 0x00, 0x00, 0xca, 0xca, 0xca, 0xca, 0x18, 0x26, 0x04, 0xef, 0x11, 0x83, 0x01, 0x26, 0x05, + 0xee, 0xa9, 0xd3, 0x27, 0x37, 0x06, 0x27, 0x12, 0x01, 0x00, 0x00, 0x00, 0xca, 0xca, 0xca, 0xca, 0x18, 0x24, 0x07, 0x01, 0x24, + 0x08, 0x01, 0x30, 0x09, 0x41, 0x04, 0x9d, 0x30, 0xfe, 0x21, 0x2d, 0x09, 0xea, 0xf2, 0xec, 0xc7, 0x9c, 0x56, 0x24, 0xdf, 0x3c, + 0x22, 0x6d, 0x5b, 0x9c, 0xfa, 0x3d, 0x7f, 0x74, 0xff, 0x38, 0x7c, 0x20, 0xc8, 0x04, 0x27, 0xcb, 0x9b, 0x03, 0xad, 0x76, 0xe9, + 0x30, 0xc5, 0x2e, 0xb5, 0x80, 0xbe, 0xb9, 0xfa, 0xe5, 0x24, 0x7c, 0x03, 0x5b, 0x38, 0xfe, 0x9c, 0xb8, 0x49, 0x91, 0x70, 0xfc, + 0xfc, 0x1e, 0xc6, 0x67, 0x23, 0xd8, 0xdf, 0x35, 0x80, 0x29, 0x01, 0x29, 0x02, 0x18, 0x35, 0x81, 0x29, 0x01, 0x24, 0x02, 0x60, + 0x18, 0x35, 0x83, 0x30, 0x02, 0x08, 0x4f, 0x5a, 0xcc, 0x78, 0x01, 0x43, 0x03, 0x52, 0x18, 0x35, 0x84, 0x30, 0x02, 0x08, 0x4f, + 0x5a, 0xcc, 0x78, 0x01, 0x43, 0x03, 0x52, 0x18, 0x35, 0x0a, 0x30, 0x01, 0x20, 0x0d, 0x4c, 0x2a, 0x85, 0xcd, 0x91, 0xae, 0x25, + 0x9b, 0x09, 0xbd, 0x58, 0x20, 0xdc, 0xc6, 0x2c, 0x62, 0x38, 0xb7, 0x11, 0x27, 0x08, 0x62, 0xdc, 0xf2, 0xa5, 0x08, 0xc1, 0xc0, + 0xaa, 0xb9, 0x2c, 0x30, 0x02, 0x20, 0x24, 0x1e, 0x39, 0xd0, 0x2d, 0x5b, 0x9a, 0xb5, 0xf2, 0x23, 0x8b, 0x25, 0x9b, 0xf0, 0x98, + 0x10, 0xfe, 0x29, 0xe7, 0xf2, 0x89, 0x1f, 0x77, 0x11, 0x7f, 0xd7, 0xf0, 0x9c, 0xe5, 0xf4, 0x0b, 0x31, 0x18, 0x18, +}; + +extern const uint32_t sTestCert_Root_Chip_Len = sizeof(sTestCert_Root_Chip); + +extern const uint8_t sTestCert_Root_DER[] = { + 0x30, 0x82, 0x01, 0x84, 0x30, 0x82, 0x01, 0x2b, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x08, 0x4f, 0xfa, 0x84, 0x4d, 0x83, 0x89, + 0xdf, 0x85, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x30, 0x22, 0x31, 0x20, 0x30, 0x1e, 0x06, + 0x0a, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0xa2, 0x7c, 0x01, 0x02, 0x0c, 0x10, 0x43, 0x41, 0x43, 0x41, 0x43, 0x41, 0x43, 0x41, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x30, 0x1e, 0x17, 0x0d, 0x32, 0x30, 0x31, 0x30, 0x31, 0x35, 0x31, 0x34, 0x32, + 0x33, 0x34, 0x33, 0x5a, 0x17, 0x0d, 0x34, 0x30, 0x31, 0x30, 0x31, 0x35, 0x31, 0x34, 0x32, 0x33, 0x34, 0x32, 0x5a, 0x30, 0x22, + 0x31, 0x20, 0x30, 0x1e, 0x06, 0x0a, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0xa2, 0x7c, 0x01, 0x02, 0x0c, 0x10, 0x43, 0x41, 0x43, + 0x41, 0x43, 0x41, 0x43, 0x41, 0x30, 0x30, 0x30, 0x30, 0x30, 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, 0x9d, 0x30, + 0xfe, 0x21, 0x2d, 0x09, 0xea, 0xf2, 0xec, 0xc7, 0x9c, 0x56, 0x24, 0xdf, 0x3c, 0x22, 0x6d, 0x5b, 0x9c, 0xfa, 0x3d, 0x7f, 0x74, + 0xff, 0x38, 0x7c, 0x20, 0xc8, 0x04, 0x27, 0xcb, 0x9b, 0x03, 0xad, 0x76, 0xe9, 0x30, 0xc5, 0x2e, 0xb5, 0x80, 0xbe, 0xb9, 0xfa, + 0xe5, 0x24, 0x7c, 0x03, 0x5b, 0x38, 0xfe, 0x9c, 0xb8, 0x49, 0x91, 0x70, 0xfc, 0xfc, 0x1e, 0xc6, 0x67, 0x23, 0xd8, 0xdf, 0xa3, + 0x4b, 0x30, 0x49, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, + 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, 0x11, 0x06, 0x03, 0x55, 0x1d, + 0x0e, 0x04, 0x0a, 0x04, 0x08, 0x4f, 0x5a, 0xcc, 0x78, 0x01, 0x43, 0x03, 0x52, 0x30, 0x13, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, + 0x0c, 0x30, 0x0a, 0x80, 0x08, 0x4f, 0x5a, 0xcc, 0x78, 0x01, 0x43, 0x03, 0x52, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, + 0x3d, 0x04, 0x03, 0x02, 0x03, 0x47, 0x00, 0x30, 0x44, 0x02, 0x20, 0x0d, 0x4c, 0x2a, 0x85, 0xcd, 0x91, 0xae, 0x25, 0x9b, 0x09, + 0xbd, 0x58, 0x20, 0xdc, 0xc6, 0x2c, 0x62, 0x38, 0xb7, 0x11, 0x27, 0x08, 0x62, 0xdc, 0xf2, 0xa5, 0x08, 0xc1, 0xc0, 0xaa, 0xb9, + 0x2c, 0x02, 0x20, 0x24, 0x1e, 0x39, 0xd0, 0x2d, 0x5b, 0x9a, 0xb5, 0xf2, 0x23, 0x8b, 0x25, 0x9b, 0xf0, 0x98, 0x10, 0xfe, 0x29, + 0xe7, 0xf2, 0x89, 0x1f, 0x77, 0x11, 0x7f, 0xd7, 0xf0, 0x9c, 0xe5, 0xf4, 0x0b, 0x31, +}; + +extern const uint32_t sTestCert_Root_DER_Len = sizeof(sTestCert_Root_DER); + +extern const uint8_t sTestCert_Root_PublicKey[] = { + 0x04, 0x9d, 0x30, 0xfe, 0x21, 0x2d, 0x09, 0xea, 0xf2, 0xec, 0xc7, 0x9c, 0x56, 0x24, 0xdf, 0x3c, 0x22, + 0x6d, 0x5b, 0x9c, 0xfa, 0x3d, 0x7f, 0x74, 0xff, 0x38, 0x7c, 0x20, 0xc8, 0x04, 0x27, 0xcb, 0x9b, 0x03, + 0xad, 0x76, 0xe9, 0x30, 0xc5, 0x2e, 0xb5, 0x80, 0xbe, 0xb9, 0xfa, 0xe5, 0x24, 0x7c, 0x03, 0x5b, 0x38, + 0xfe, 0x9c, 0xb8, 0x49, 0x91, 0x70, 0xfc, 0xfc, 0x1e, 0xc6, 0x67, 0x23, 0xd8, 0xdf, +}; + +extern const uint8_t sTestCert_Root_PublicKey_Len = sizeof(sTestCert_Root_PublicKey); + +extern const uint8_t sTestCert_Root_PrivateKey[] = { + 0x4e, 0x83, 0x6b, 0x0f, 0x86, 0x9c, 0xf5, 0x63, 0x54, 0x27, 0x6d, 0x5d, 0x60, 0xd1, 0x95, 0x4e, + 0xcc, 0x80, 0x85, 0x2f, 0xc9, 0x28, 0x3a, 0x57, 0xcd, 0xa7, 0xff, 0x5b, 0x48, 0xa4, 0x80, 0xc6, +}; + +extern const uint8_t sTestCert_Root_PrivateKey_Len = sizeof(sTestCert_Root_PrivateKey); + +extern const uint8_t sTestCert_Root_SubjectKeyId[] = { + 0x4F, 0x5A, 0xCC, 0x78, 0x01, 0x43, 0x03, 0x52, +}; + +extern const uint8_t sTestCert_Root_SubjectKeyId_Len = sizeof(sTestCert_Root_SubjectKeyId); + +extern const uint64_t sTestCert_Root_Id = 0xCACACACA00000001ULL; + +/************** Test NodeCA Certificate ************** +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 3348080933522780927 (0x2e76c5dec1e232ff) + Signature Algorithm: ecdsa-with-SHA256 + Issuer: 1.3.6.1.4.1.37244.1.2 = CACACACA00000001 + Validity + Not Before: Oct 15 14:23:43 2020 GMT + Not After : Oct 15 14:23:42 2040 GMT + Subject: 1.3.6.1.4.1.37244.1.2 = CACACACA00000002 + Subject Public Key Info: + Public Key Algorithm: id-ecPublicKey + Public-Key: (256 bit) + pub: + 04:8a:34:94:8d:8c:9f:c4:2b:64:e7:df:9e:3c:7f: + a8:80:1a:93:56:e0:07:32:de:9a:89:27:59:d7:76: + 79:91:98:21:1a:d6:bd:4f:f2:d2:27:31:59:81:a1: + 35:05:f2:77:f3:e9:00:92:72:0d:92:fc:40:1d:a1: + ad:a5:5b:5b:6c + ASN1 OID: prime256v1 + NIST CURVE: P-256 + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 Subject Key Identifier: + 45:24:B6:E8:4A:64:EB:12 + X509v3 Authority Key Identifier: + keyid:4F:5A:CC:78:01:43:03:52 + + Signature Algorithm: ecdsa-with-SHA256 + 30:45:02:20:1a:a0:23:d2:5c:0a:72:8c:10:41:d5:4e:f8:86: + 7d:b1:53:3b:f2:c5:97:3f:cf:1c:ff:96:45:26:b3:0e:57:9c: + 02:21:00:9c:c9:37:0e:a4:de:77:2a:f1:67:f9:2a:f3:a3:b4: + 16:f9:3a:9f:4d:5a:b8:f0:41:c4:97:b5:4a:c4:6f:76:c0 + +-----BEGIN CERTIFICATE----- +MIIBhTCCASugAwIBAgIILnbF3sHiMv8wCgYIKoZIzj0EAwIwIjEgMB4GCisGAQQB +gqJ8AQIMEENBQ0FDQUNBMDAwMDAwMDEwHhcNMjAxMDE1MTQyMzQzWhcNNDAxMDE1 +MTQyMzQyWjAiMSAwHgYKKwYBBAGConwBAgwQQ0FDQUNBQ0EwMDAwMDAwMjBZMBMG +ByqGSM49AgEGCCqGSM49AwEHA0IABIo0lI2Mn8QrZOffnjx/qIAak1bgBzLemokn +Wdd2eZGYIRrWvU/y0icxWYGhNQXyd/PpAJJyDZL8QB2hraVbW2yjSzBJMA8GA1Ud +EwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMBEGA1UdDgQKBAhFJLboSmTrEjAT +BgNVHSMEDDAKgAhPWsx4AUMDUjAKBggqhkjOPQQDAgNIADBFAiAaoCPSXApyjBBB +1U74hn2xUzvyxZc/zxz/lkUmsw5XnAIhAJzJNw6k3ncq8Wf5KvOjtBb5Op9NWrjw +QcSXtUrEb3bA +-----END CERTIFICATE----- + +-----BEGIN EC PRIVATE KEY----- +MHcCAQEEIO61TIc64TOKEDAIZaMXYqu/E7Rq61cDiEkXRW6bFI7ToAoGCCqGSM49 +AwEHoUQDQgAEijSUjYyfxCtk59+ePH+ogBqTVuAHMt6aiSdZ13Z5kZghGta9T/LS +JzFZgaE1BfJ38+kAknINkvxAHaGtpVtbbA== +-----END EC PRIVATE KEY----- +*/ + +extern const uint8_t sTestCert_NodeCA_Chip[] = { + 0xd5, 0x00, 0x00, 0x08, 0x00, 0x01, 0x00, 0x30, 0x01, 0x08, 0x2e, 0x76, 0xc5, 0xde, 0xc1, 0xe2, 0x32, 0xff, 0x24, 0x02, 0x01, + 0x37, 0x03, 0x27, 0x12, 0x01, 0x00, 0x00, 0x00, 0xca, 0xca, 0xca, 0xca, 0x18, 0x26, 0x04, 0xef, 0x11, 0x83, 0x01, 0x26, 0x05, + 0xee, 0xa9, 0xd3, 0x27, 0x37, 0x06, 0x27, 0x12, 0x02, 0x00, 0x00, 0x00, 0xca, 0xca, 0xca, 0xca, 0x18, 0x24, 0x07, 0x01, 0x24, + 0x08, 0x01, 0x30, 0x09, 0x41, 0x04, 0x8a, 0x34, 0x94, 0x8d, 0x8c, 0x9f, 0xc4, 0x2b, 0x64, 0xe7, 0xdf, 0x9e, 0x3c, 0x7f, 0xa8, + 0x80, 0x1a, 0x93, 0x56, 0xe0, 0x07, 0x32, 0xde, 0x9a, 0x89, 0x27, 0x59, 0xd7, 0x76, 0x79, 0x91, 0x98, 0x21, 0x1a, 0xd6, 0xbd, + 0x4f, 0xf2, 0xd2, 0x27, 0x31, 0x59, 0x81, 0xa1, 0x35, 0x05, 0xf2, 0x77, 0xf3, 0xe9, 0x00, 0x92, 0x72, 0x0d, 0x92, 0xfc, 0x40, + 0x1d, 0xa1, 0xad, 0xa5, 0x5b, 0x5b, 0x6c, 0x35, 0x80, 0x29, 0x01, 0x29, 0x02, 0x18, 0x35, 0x81, 0x29, 0x01, 0x24, 0x02, 0x60, + 0x18, 0x35, 0x83, 0x30, 0x02, 0x08, 0x45, 0x24, 0xb6, 0xe8, 0x4a, 0x64, 0xeb, 0x12, 0x18, 0x35, 0x84, 0x30, 0x02, 0x08, 0x4f, + 0x5a, 0xcc, 0x78, 0x01, 0x43, 0x03, 0x52, 0x18, 0x35, 0x0a, 0x30, 0x01, 0x20, 0x1a, 0xa0, 0x23, 0xd2, 0x5c, 0x0a, 0x72, 0x8c, + 0x10, 0x41, 0xd5, 0x4e, 0xf8, 0x86, 0x7d, 0xb1, 0x53, 0x3b, 0xf2, 0xc5, 0x97, 0x3f, 0xcf, 0x1c, 0xff, 0x96, 0x45, 0x26, 0xb3, + 0x0e, 0x57, 0x9c, 0x30, 0x02, 0x21, 0x00, 0x9c, 0xc9, 0x37, 0x0e, 0xa4, 0xde, 0x77, 0x2a, 0xf1, 0x67, 0xf9, 0x2a, 0xf3, 0xa3, + 0xb4, 0x16, 0xf9, 0x3a, 0x9f, 0x4d, 0x5a, 0xb8, 0xf0, 0x41, 0xc4, 0x97, 0xb5, 0x4a, 0xc4, 0x6f, 0x76, 0xc0, 0x18, 0x18, +}; + +extern const uint32_t sTestCert_NodeCA_Chip_Len = sizeof(sTestCert_NodeCA_Chip); + +extern const uint8_t sTestCert_NodeCA_DER[] = { + 0x30, 0x82, 0x01, 0x85, 0x30, 0x82, 0x01, 0x2b, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x08, 0x2e, 0x76, 0xc5, 0xde, 0xc1, 0xe2, + 0x32, 0xff, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x30, 0x22, 0x31, 0x20, 0x30, 0x1e, 0x06, + 0x0a, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0xa2, 0x7c, 0x01, 0x02, 0x0c, 0x10, 0x43, 0x41, 0x43, 0x41, 0x43, 0x41, 0x43, 0x41, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x30, 0x1e, 0x17, 0x0d, 0x32, 0x30, 0x31, 0x30, 0x31, 0x35, 0x31, 0x34, 0x32, + 0x33, 0x34, 0x33, 0x5a, 0x17, 0x0d, 0x34, 0x30, 0x31, 0x30, 0x31, 0x35, 0x31, 0x34, 0x32, 0x33, 0x34, 0x32, 0x5a, 0x30, 0x22, + 0x31, 0x20, 0x30, 0x1e, 0x06, 0x0a, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0xa2, 0x7c, 0x01, 0x02, 0x0c, 0x10, 0x43, 0x41, 0x43, + 0x41, 0x43, 0x41, 0x43, 0x41, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x32, 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, 0x8a, 0x34, + 0x94, 0x8d, 0x8c, 0x9f, 0xc4, 0x2b, 0x64, 0xe7, 0xdf, 0x9e, 0x3c, 0x7f, 0xa8, 0x80, 0x1a, 0x93, 0x56, 0xe0, 0x07, 0x32, 0xde, + 0x9a, 0x89, 0x27, 0x59, 0xd7, 0x76, 0x79, 0x91, 0x98, 0x21, 0x1a, 0xd6, 0xbd, 0x4f, 0xf2, 0xd2, 0x27, 0x31, 0x59, 0x81, 0xa1, + 0x35, 0x05, 0xf2, 0x77, 0xf3, 0xe9, 0x00, 0x92, 0x72, 0x0d, 0x92, 0xfc, 0x40, 0x1d, 0xa1, 0xad, 0xa5, 0x5b, 0x5b, 0x6c, 0xa3, + 0x4b, 0x30, 0x49, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, + 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, 0x11, 0x06, 0x03, 0x55, 0x1d, + 0x0e, 0x04, 0x0a, 0x04, 0x08, 0x45, 0x24, 0xb6, 0xe8, 0x4a, 0x64, 0xeb, 0x12, 0x30, 0x13, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, + 0x0c, 0x30, 0x0a, 0x80, 0x08, 0x4f, 0x5a, 0xcc, 0x78, 0x01, 0x43, 0x03, 0x52, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, + 0x3d, 0x04, 0x03, 0x02, 0x03, 0x48, 0x00, 0x30, 0x45, 0x02, 0x20, 0x1a, 0xa0, 0x23, 0xd2, 0x5c, 0x0a, 0x72, 0x8c, 0x10, 0x41, + 0xd5, 0x4e, 0xf8, 0x86, 0x7d, 0xb1, 0x53, 0x3b, 0xf2, 0xc5, 0x97, 0x3f, 0xcf, 0x1c, 0xff, 0x96, 0x45, 0x26, 0xb3, 0x0e, 0x57, + 0x9c, 0x02, 0x21, 0x00, 0x9c, 0xc9, 0x37, 0x0e, 0xa4, 0xde, 0x77, 0x2a, 0xf1, 0x67, 0xf9, 0x2a, 0xf3, 0xa3, 0xb4, 0x16, 0xf9, + 0x3a, 0x9f, 0x4d, 0x5a, 0xb8, 0xf0, 0x41, 0xc4, 0x97, 0xb5, 0x4a, 0xc4, 0x6f, 0x76, 0xc0, +}; + +extern const uint32_t sTestCert_NodeCA_DER_Len = sizeof(sTestCert_NodeCA_DER); + +extern const uint8_t sTestCert_NodeCA_PublicKey[] = { + 0x04, 0x8a, 0x34, 0x94, 0x8d, 0x8c, 0x9f, 0xc4, 0x2b, 0x64, 0xe7, 0xdf, 0x9e, 0x3c, 0x7f, 0xa8, 0x80, + 0x1a, 0x93, 0x56, 0xe0, 0x07, 0x32, 0xde, 0x9a, 0x89, 0x27, 0x59, 0xd7, 0x76, 0x79, 0x91, 0x98, 0x21, + 0x1a, 0xd6, 0xbd, 0x4f, 0xf2, 0xd2, 0x27, 0x31, 0x59, 0x81, 0xa1, 0x35, 0x05, 0xf2, 0x77, 0xf3, 0xe9, + 0x00, 0x92, 0x72, 0x0d, 0x92, 0xfc, 0x40, 0x1d, 0xa1, 0xad, 0xa5, 0x5b, 0x5b, 0x6c, +}; + +extern const uint8_t sTestCert_NodeCA_PublicKey_Len = sizeof(sTestCert_NodeCA_PublicKey); + +extern const uint8_t sTestCert_NodeCA_PrivateKey[] = { + 0xee, 0xb5, 0x4c, 0x87, 0x3a, 0xe1, 0x33, 0x8a, 0x10, 0x30, 0x08, 0x65, 0xa3, 0x17, 0x62, 0xab, + 0xbf, 0x13, 0xb4, 0x6a, 0xeb, 0x57, 0x03, 0x88, 0x49, 0x17, 0x45, 0x6e, 0x9b, 0x14, 0x8e, 0xd3, +}; + +extern const uint8_t sTestCert_NodeCA_PrivateKey_Len = sizeof(sTestCert_NodeCA_PrivateKey); + +extern const uint8_t sTestCert_NodeCA_SubjectKeyId[] = { + 0x45, 0x24, 0xB6, 0xE8, 0x4A, 0x64, 0xEB, 0x12, +}; + +extern const uint8_t sTestCert_NodeCA_SubjectKeyId_Len = sizeof(sTestCert_NodeCA_SubjectKeyId); + +extern const uint64_t sTestCert_NodeCA_Id = 0xCACACACA00000002ULL; + +/************** Test Node01 Certificate ************** +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 3589844900143231134 (0x31d1b0eab7c8f09e) + Signature Algorithm: ecdsa-with-SHA256 + Issuer: 1.3.6.1.4.1.37244.1.2 = CACACACA00000002 + Validity + Not Before: Oct 15 14:23:43 2020 GMT + Not After : Oct 15 14:23:42 2040 GMT + Subject: 1.3.6.1.4.1.37244.1.1 = DEDEDEDE00000001 + Subject Public Key Info: + Public Key Algorithm: id-ecPublicKey + Public-Key: (256 bit) + pub: + 04:80:52:1c:92:47:f8:e5:e3:08:a7:ac:57:5b:7a: + d3:c1:5f:ea:be:48:62:1c:4a:d6:95:f1:14:23:4c: + 76:99:52:38:09:73:28:ba:1b:91:10:12:22:fb:35: + 91:dc:f1:87:34:06:c1:4c:e2:dd:2e:3f:b0:9d:6e: + 04:10:09:f4:70 + ASN1 OID: prime256v1 + NIST CURVE: P-256 + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:FALSE + X509v3 Key Usage: critical + Digital Signature, Key Encipherment + X509v3 Extended Key Usage: critical + TLS Web Client Authentication, TLS Web Server Authentication + X509v3 Subject Key Identifier: + 4F:81:F0:44:C8:5F:C3:D9 + X509v3 Authority Key Identifier: + keyid:45:24:B6:E8:4A:64:EB:12 + + Signature Algorithm: ecdsa-with-SHA256 + 30:45:02:21:00:c8:5b:66:7d:9e:3a:2d:21:2f:df:6a:c6:6e: + 11:1e:83:03:0c:0a:34:93:48:88:30:eb:51:28:4b:ca:9a:3d: + 22:02:20:24:42:5c:3b:f6:05:8e:e8:8c:01:ca:35:8e:b7:d5: + c8:c1:69:46:cf:bb:c6:76:c3:ea:2f:ed:8d:75:c4:fc:f5 + +-----BEGIN CERTIFICATE----- +MIIBpDCCAUqgAwIBAgIIMdGw6rfI8J4wCgYIKoZIzj0EAwIwIjEgMB4GCisGAQQB +gqJ8AQIMEENBQ0FDQUNBMDAwMDAwMDIwHhcNMjAxMDE1MTQyMzQzWhcNNDAxMDE1 +MTQyMzQyWjAiMSAwHgYKKwYBBAGConwBAQwQREVERURFREUwMDAwMDAwMTBZMBMG +ByqGSM49AgEGCCqGSM49AwEHA0IABIBSHJJH+OXjCKesV1t608Ff6r5IYhxK1pXx +FCNMdplSOAlzKLobkRASIvs1kdzxhzQGwUzi3S4/sJ1uBBAJ9HCjajBoMAwGA1Ud +EwEB/wQCMAAwDgYDVR0PAQH/BAQDAgWgMCAGA1UdJQEB/wQWMBQGCCsGAQUFBwMC +BggrBgEFBQcDATARBgNVHQ4ECgQIT4HwRMhfw9kwEwYDVR0jBAwwCoAIRSS26Epk +6xIwCgYIKoZIzj0EAwIDSAAwRQIhAMhbZn2eOi0hL99qxm4RHoMDDAo0k0iIMOtR +KEvKmj0iAiAkQlw79gWO6IwByjWOt9XIwWlGz7vGdsPqL+2NdcT89Q== +-----END CERTIFICATE----- + +-----BEGIN EC PRIVATE KEY----- +MHcCAQEEIIn4fUhgu/czgPVN1vpYGPmZ5nZLDaeJyVCibIlZua8QoAoGCCqGSM49 +AwEHoUQDQgAEgFIckkf45eMIp6xXW3rTwV/qvkhiHErWlfEUI0x2mVI4CXMouhuR +EBIi+zWR3PGHNAbBTOLdLj+wnW4EEAn0cA== +-----END EC PRIVATE KEY----- +*/ + +extern const uint8_t sTestCert_Node01_Chip[] = { + 0xd5, 0x00, 0x00, 0x08, 0x00, 0x01, 0x00, 0x30, 0x01, 0x08, 0x31, 0xd1, 0xb0, 0xea, 0xb7, 0xc8, 0xf0, 0x9e, 0x24, 0x02, 0x01, + 0x37, 0x03, 0x27, 0x12, 0x02, 0x00, 0x00, 0x00, 0xca, 0xca, 0xca, 0xca, 0x18, 0x26, 0x04, 0xef, 0x11, 0x83, 0x01, 0x26, 0x05, + 0xee, 0xa9, 0xd3, 0x27, 0x37, 0x06, 0x27, 0x11, 0x01, 0x00, 0x00, 0x00, 0xde, 0xde, 0xde, 0xde, 0x18, 0x24, 0x07, 0x01, 0x24, + 0x08, 0x01, 0x30, 0x09, 0x41, 0x04, 0x80, 0x52, 0x1c, 0x92, 0x47, 0xf8, 0xe5, 0xe3, 0x08, 0xa7, 0xac, 0x57, 0x5b, 0x7a, 0xd3, + 0xc1, 0x5f, 0xea, 0xbe, 0x48, 0x62, 0x1c, 0x4a, 0xd6, 0x95, 0xf1, 0x14, 0x23, 0x4c, 0x76, 0x99, 0x52, 0x38, 0x09, 0x73, 0x28, + 0xba, 0x1b, 0x91, 0x10, 0x12, 0x22, 0xfb, 0x35, 0x91, 0xdc, 0xf1, 0x87, 0x34, 0x06, 0xc1, 0x4c, 0xe2, 0xdd, 0x2e, 0x3f, 0xb0, + 0x9d, 0x6e, 0x04, 0x10, 0x09, 0xf4, 0x70, 0x35, 0x80, 0x29, 0x01, 0x18, 0x35, 0x81, 0x29, 0x01, 0x24, 0x02, 0x05, 0x18, 0x35, + 0x82, 0x29, 0x01, 0x36, 0x02, 0x04, 0x02, 0x04, 0x01, 0x18, 0x18, 0x35, 0x83, 0x30, 0x02, 0x08, 0x4f, 0x81, 0xf0, 0x44, 0xc8, + 0x5f, 0xc3, 0xd9, 0x18, 0x35, 0x84, 0x30, 0x02, 0x08, 0x45, 0x24, 0xb6, 0xe8, 0x4a, 0x64, 0xeb, 0x12, 0x18, 0x35, 0x0a, 0x30, + 0x01, 0x21, 0x00, 0xc8, 0x5b, 0x66, 0x7d, 0x9e, 0x3a, 0x2d, 0x21, 0x2f, 0xdf, 0x6a, 0xc6, 0x6e, 0x11, 0x1e, 0x83, 0x03, 0x0c, + 0x0a, 0x34, 0x93, 0x48, 0x88, 0x30, 0xeb, 0x51, 0x28, 0x4b, 0xca, 0x9a, 0x3d, 0x22, 0x30, 0x02, 0x20, 0x24, 0x42, 0x5c, 0x3b, + 0xf6, 0x05, 0x8e, 0xe8, 0x8c, 0x01, 0xca, 0x35, 0x8e, 0xb7, 0xd5, 0xc8, 0xc1, 0x69, 0x46, 0xcf, 0xbb, 0xc6, 0x76, 0xc3, 0xea, + 0x2f, 0xed, 0x8d, 0x75, 0xc4, 0xfc, 0xf5, 0x18, 0x18, +}; + +extern const uint32_t sTestCert_Node01_Chip_Len = sizeof(sTestCert_Node01_Chip); + +extern const uint8_t sTestCert_Node01_DER[] = { + 0x30, 0x82, 0x01, 0xa4, 0x30, 0x82, 0x01, 0x4a, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x08, 0x31, 0xd1, 0xb0, 0xea, 0xb7, 0xc8, + 0xf0, 0x9e, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x30, 0x22, 0x31, 0x20, 0x30, 0x1e, 0x06, + 0x0a, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0xa2, 0x7c, 0x01, 0x02, 0x0c, 0x10, 0x43, 0x41, 0x43, 0x41, 0x43, 0x41, 0x43, 0x41, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x32, 0x30, 0x1e, 0x17, 0x0d, 0x32, 0x30, 0x31, 0x30, 0x31, 0x35, 0x31, 0x34, 0x32, + 0x33, 0x34, 0x33, 0x5a, 0x17, 0x0d, 0x34, 0x30, 0x31, 0x30, 0x31, 0x35, 0x31, 0x34, 0x32, 0x33, 0x34, 0x32, 0x5a, 0x30, 0x22, + 0x31, 0x20, 0x30, 0x1e, 0x06, 0x0a, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0xa2, 0x7c, 0x01, 0x01, 0x0c, 0x10, 0x44, 0x45, 0x44, + 0x45, 0x44, 0x45, 0x44, 0x45, 0x30, 0x30, 0x30, 0x30, 0x30, 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, 0x80, 0x52, + 0x1c, 0x92, 0x47, 0xf8, 0xe5, 0xe3, 0x08, 0xa7, 0xac, 0x57, 0x5b, 0x7a, 0xd3, 0xc1, 0x5f, 0xea, 0xbe, 0x48, 0x62, 0x1c, 0x4a, + 0xd6, 0x95, 0xf1, 0x14, 0x23, 0x4c, 0x76, 0x99, 0x52, 0x38, 0x09, 0x73, 0x28, 0xba, 0x1b, 0x91, 0x10, 0x12, 0x22, 0xfb, 0x35, + 0x91, 0xdc, 0xf1, 0x87, 0x34, 0x06, 0xc1, 0x4c, 0xe2, 0xdd, 0x2e, 0x3f, 0xb0, 0x9d, 0x6e, 0x04, 0x10, 0x09, 0xf4, 0x70, 0xa3, + 0x6a, 0x30, 0x68, 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, 0x05, 0xa0, 0x30, 0x20, 0x06, 0x03, 0x55, 0x1d, 0x25, 0x01, 0x01, + 0xff, 0x04, 0x16, 0x30, 0x14, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x02, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, + 0x05, 0x07, 0x03, 0x01, 0x30, 0x11, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x0a, 0x04, 0x08, 0x4f, 0x81, 0xf0, 0x44, 0xc8, 0x5f, + 0xc3, 0xd9, 0x30, 0x13, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x0c, 0x30, 0x0a, 0x80, 0x08, 0x45, 0x24, 0xb6, 0xe8, 0x4a, 0x64, + 0xeb, 0x12, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x03, 0x48, 0x00, 0x30, 0x45, 0x02, 0x21, + 0x00, 0xc8, 0x5b, 0x66, 0x7d, 0x9e, 0x3a, 0x2d, 0x21, 0x2f, 0xdf, 0x6a, 0xc6, 0x6e, 0x11, 0x1e, 0x83, 0x03, 0x0c, 0x0a, 0x34, + 0x93, 0x48, 0x88, 0x30, 0xeb, 0x51, 0x28, 0x4b, 0xca, 0x9a, 0x3d, 0x22, 0x02, 0x20, 0x24, 0x42, 0x5c, 0x3b, 0xf6, 0x05, 0x8e, + 0xe8, 0x8c, 0x01, 0xca, 0x35, 0x8e, 0xb7, 0xd5, 0xc8, 0xc1, 0x69, 0x46, 0xcf, 0xbb, 0xc6, 0x76, 0xc3, 0xea, 0x2f, 0xed, 0x8d, + 0x75, 0xc4, 0xfc, 0xf5, +}; + +extern const uint32_t sTestCert_Node01_DER_Len = sizeof(sTestCert_Node01_DER); + +extern const uint8_t sTestCert_Node01_PublicKey[] = { + 0x04, 0x80, 0x52, 0x1c, 0x92, 0x47, 0xf8, 0xe5, 0xe3, 0x08, 0xa7, 0xac, 0x57, 0x5b, 0x7a, 0xd3, 0xc1, + 0x5f, 0xea, 0xbe, 0x48, 0x62, 0x1c, 0x4a, 0xd6, 0x95, 0xf1, 0x14, 0x23, 0x4c, 0x76, 0x99, 0x52, 0x38, + 0x09, 0x73, 0x28, 0xba, 0x1b, 0x91, 0x10, 0x12, 0x22, 0xfb, 0x35, 0x91, 0xdc, 0xf1, 0x87, 0x34, 0x06, + 0xc1, 0x4c, 0xe2, 0xdd, 0x2e, 0x3f, 0xb0, 0x9d, 0x6e, 0x04, 0x10, 0x09, 0xf4, 0x70, +}; + +extern const uint8_t sTestCert_Node01_PublicKey_Len = sizeof(sTestCert_Node01_PublicKey); + +extern const uint8_t sTestCert_Node01_PrivateKey[] = { + 0x89, 0xf8, 0x7d, 0x48, 0x60, 0xbb, 0xf7, 0x33, 0x80, 0xf5, 0x4d, 0xd6, 0xfa, 0x58, 0x18, 0xf9, + 0x99, 0xe6, 0x76, 0x4b, 0x0d, 0xa7, 0x89, 0xc9, 0x50, 0xa2, 0x6c, 0x89, 0x59, 0xb9, 0xaf, 0x10, +}; + +extern const uint8_t sTestCert_Node01_PrivateKey_Len = sizeof(sTestCert_Node01_PrivateKey); + +extern const uint8_t sTestCert_Node01_SubjectKeyId[] = { + 0x4F, 0x81, 0xF0, 0x44, 0xC8, 0x5F, 0xC3, 0xD9, +}; + +extern const uint8_t sTestCert_Node01_SubjectKeyId_Len = sizeof(sTestCert_Node01_SubjectKeyId); + +extern const uint64_t sTestCert_Node01_Id = 0xDEDEDEDE00000001ULL; + +/************** Test FirmwareSigningCA Certificate ************** +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4858935668214195254 (0x436e683f1a61e436) + Signature Algorithm: ecdsa-with-SHA256 + Issuer: 1.3.6.1.4.1.37244.1.2 = CACACACA00000001 + Validity + Not Before: Oct 15 14:23:43 2020 GMT + Not After : Oct 15 14:23:42 2040 GMT + Subject: 1.3.6.1.4.1.37244.1.2 = CACACACA00000004 + Subject Public Key Info: + Public Key Algorithm: id-ecPublicKey + Public-Key: (256 bit) + pub: + 04:67:47:90:a4:cb:5a:98:8c:50:01:1d:c0:3b:11: + f5:d0:91:b2:25:90:c1:e7:e8:01:ca:b1:8d:79:9d: + 4a:27:af:a4:e5:e2:9d:65:cb:97:98:d0:5e:6e:1b: + 72:ab:41:57:cb:f0:cf:47:fe:a2:61:76:82:fc:6d: + e3:6e:43:34:d1 + ASN1 OID: prime256v1 + NIST CURVE: P-256 + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 Subject Key Identifier: + 4D:CB:CD:82:9E:BF:5C:EB + X509v3 Authority Key Identifier: + keyid:4F:5A:CC:78:01:43:03:52 + + Signature Algorithm: ecdsa-with-SHA256 + 30:45:02:21:00:d5:cb:c1:61:61:34:6d:c7:07:7e:89:07:78: + cd:1f:e0:79:c8:8f:24:bd:01:11:34:a9:3d:af:73:d7:02:f9: + 3b:02:20:5b:64:52:76:29:16:5e:73:a0:cc:f1:ff:f2:56:40: + 84:48:a4:3c:23:d1:32:ba:f0:02:21:55:9d:cb:2c:e8:0c + +-----BEGIN CERTIFICATE----- +MIIBhTCCASugAwIBAgIIQ25oPxph5DYwCgYIKoZIzj0EAwIwIjEgMB4GCisGAQQB +gqJ8AQIMEENBQ0FDQUNBMDAwMDAwMDEwHhcNMjAxMDE1MTQyMzQzWhcNNDAxMDE1 +MTQyMzQyWjAiMSAwHgYKKwYBBAGConwBAgwQQ0FDQUNBQ0EwMDAwMDAwNDBZMBMG +ByqGSM49AgEGCCqGSM49AwEHA0IABGdHkKTLWpiMUAEdwDsR9dCRsiWQwefoAcqx +jXmdSievpOXinWXLl5jQXm4bcqtBV8vwz0f+omF2gvxt425DNNGjSzBJMA8GA1Ud +EwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMBEGA1UdDgQKBAhNy82Cnr9c6zAT +BgNVHSMEDDAKgAhPWsx4AUMDUjAKBggqhkjOPQQDAgNIADBFAiEA1cvBYWE0bccH +fokHeM0f4HnIjyS9ARE0qT2vc9cC+TsCIFtkUnYpFl5zoMzx//JWQIRIpDwj0TK6 +8AIhVZ3LLOgM +-----END CERTIFICATE----- + +-----BEGIN EC PRIVATE KEY----- +MHcCAQEEILbvCa3t51vMpV/OCeDhzQ/ZhTOfj1O75pktTZh7d9kmoAoGCCqGSM49 +AwEHoUQDQgAEZ0eQpMtamIxQAR3AOxH10JGyJZDB5+gByrGNeZ1KJ6+k5eKdZcuX +mNBebhtyq0FXy/DPR/6iYXaC/G3jbkM00Q== +-----END EC PRIVATE KEY----- +*/ + +extern const uint8_t sTestCert_FirmwareSigningCA_Chip[] = { + 0xd5, 0x00, 0x00, 0x08, 0x00, 0x01, 0x00, 0x30, 0x01, 0x08, 0x43, 0x6e, 0x68, 0x3f, 0x1a, 0x61, 0xe4, 0x36, 0x24, 0x02, 0x01, + 0x37, 0x03, 0x27, 0x12, 0x01, 0x00, 0x00, 0x00, 0xca, 0xca, 0xca, 0xca, 0x18, 0x26, 0x04, 0xef, 0x11, 0x83, 0x01, 0x26, 0x05, + 0xee, 0xa9, 0xd3, 0x27, 0x37, 0x06, 0x27, 0x12, 0x04, 0x00, 0x00, 0x00, 0xca, 0xca, 0xca, 0xca, 0x18, 0x24, 0x07, 0x01, 0x24, + 0x08, 0x01, 0x30, 0x09, 0x41, 0x04, 0x67, 0x47, 0x90, 0xa4, 0xcb, 0x5a, 0x98, 0x8c, 0x50, 0x01, 0x1d, 0xc0, 0x3b, 0x11, 0xf5, + 0xd0, 0x91, 0xb2, 0x25, 0x90, 0xc1, 0xe7, 0xe8, 0x01, 0xca, 0xb1, 0x8d, 0x79, 0x9d, 0x4a, 0x27, 0xaf, 0xa4, 0xe5, 0xe2, 0x9d, + 0x65, 0xcb, 0x97, 0x98, 0xd0, 0x5e, 0x6e, 0x1b, 0x72, 0xab, 0x41, 0x57, 0xcb, 0xf0, 0xcf, 0x47, 0xfe, 0xa2, 0x61, 0x76, 0x82, + 0xfc, 0x6d, 0xe3, 0x6e, 0x43, 0x34, 0xd1, 0x35, 0x80, 0x29, 0x01, 0x29, 0x02, 0x18, 0x35, 0x81, 0x29, 0x01, 0x24, 0x02, 0x60, + 0x18, 0x35, 0x83, 0x30, 0x02, 0x08, 0x4d, 0xcb, 0xcd, 0x82, 0x9e, 0xbf, 0x5c, 0xeb, 0x18, 0x35, 0x84, 0x30, 0x02, 0x08, 0x4f, + 0x5a, 0xcc, 0x78, 0x01, 0x43, 0x03, 0x52, 0x18, 0x35, 0x0a, 0x30, 0x01, 0x21, 0x00, 0xd5, 0xcb, 0xc1, 0x61, 0x61, 0x34, 0x6d, + 0xc7, 0x07, 0x7e, 0x89, 0x07, 0x78, 0xcd, 0x1f, 0xe0, 0x79, 0xc8, 0x8f, 0x24, 0xbd, 0x01, 0x11, 0x34, 0xa9, 0x3d, 0xaf, 0x73, + 0xd7, 0x02, 0xf9, 0x3b, 0x30, 0x02, 0x20, 0x5b, 0x64, 0x52, 0x76, 0x29, 0x16, 0x5e, 0x73, 0xa0, 0xcc, 0xf1, 0xff, 0xf2, 0x56, + 0x40, 0x84, 0x48, 0xa4, 0x3c, 0x23, 0xd1, 0x32, 0xba, 0xf0, 0x02, 0x21, 0x55, 0x9d, 0xcb, 0x2c, 0xe8, 0x0c, 0x18, 0x18, +}; + +extern const uint32_t sTestCert_FirmwareSigningCA_Chip_Len = sizeof(sTestCert_FirmwareSigningCA_Chip); + +extern const uint8_t sTestCert_FirmwareSigningCA_DER[] = { + 0x30, 0x82, 0x01, 0x85, 0x30, 0x82, 0x01, 0x2b, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x08, 0x43, 0x6e, 0x68, 0x3f, 0x1a, 0x61, + 0xe4, 0x36, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x30, 0x22, 0x31, 0x20, 0x30, 0x1e, 0x06, + 0x0a, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0xa2, 0x7c, 0x01, 0x02, 0x0c, 0x10, 0x43, 0x41, 0x43, 0x41, 0x43, 0x41, 0x43, 0x41, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x30, 0x1e, 0x17, 0x0d, 0x32, 0x30, 0x31, 0x30, 0x31, 0x35, 0x31, 0x34, 0x32, + 0x33, 0x34, 0x33, 0x5a, 0x17, 0x0d, 0x34, 0x30, 0x31, 0x30, 0x31, 0x35, 0x31, 0x34, 0x32, 0x33, 0x34, 0x32, 0x5a, 0x30, 0x22, + 0x31, 0x20, 0x30, 0x1e, 0x06, 0x0a, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0xa2, 0x7c, 0x01, 0x02, 0x0c, 0x10, 0x43, 0x41, 0x43, + 0x41, 0x43, 0x41, 0x43, 0x41, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x34, 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, 0x67, 0x47, + 0x90, 0xa4, 0xcb, 0x5a, 0x98, 0x8c, 0x50, 0x01, 0x1d, 0xc0, 0x3b, 0x11, 0xf5, 0xd0, 0x91, 0xb2, 0x25, 0x90, 0xc1, 0xe7, 0xe8, + 0x01, 0xca, 0xb1, 0x8d, 0x79, 0x9d, 0x4a, 0x27, 0xaf, 0xa4, 0xe5, 0xe2, 0x9d, 0x65, 0xcb, 0x97, 0x98, 0xd0, 0x5e, 0x6e, 0x1b, + 0x72, 0xab, 0x41, 0x57, 0xcb, 0xf0, 0xcf, 0x47, 0xfe, 0xa2, 0x61, 0x76, 0x82, 0xfc, 0x6d, 0xe3, 0x6e, 0x43, 0x34, 0xd1, 0xa3, + 0x4b, 0x30, 0x49, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, + 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, 0x11, 0x06, 0x03, 0x55, 0x1d, + 0x0e, 0x04, 0x0a, 0x04, 0x08, 0x4d, 0xcb, 0xcd, 0x82, 0x9e, 0xbf, 0x5c, 0xeb, 0x30, 0x13, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, + 0x0c, 0x30, 0x0a, 0x80, 0x08, 0x4f, 0x5a, 0xcc, 0x78, 0x01, 0x43, 0x03, 0x52, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, + 0x3d, 0x04, 0x03, 0x02, 0x03, 0x48, 0x00, 0x30, 0x45, 0x02, 0x21, 0x00, 0xd5, 0xcb, 0xc1, 0x61, 0x61, 0x34, 0x6d, 0xc7, 0x07, + 0x7e, 0x89, 0x07, 0x78, 0xcd, 0x1f, 0xe0, 0x79, 0xc8, 0x8f, 0x24, 0xbd, 0x01, 0x11, 0x34, 0xa9, 0x3d, 0xaf, 0x73, 0xd7, 0x02, + 0xf9, 0x3b, 0x02, 0x20, 0x5b, 0x64, 0x52, 0x76, 0x29, 0x16, 0x5e, 0x73, 0xa0, 0xcc, 0xf1, 0xff, 0xf2, 0x56, 0x40, 0x84, 0x48, + 0xa4, 0x3c, 0x23, 0xd1, 0x32, 0xba, 0xf0, 0x02, 0x21, 0x55, 0x9d, 0xcb, 0x2c, 0xe8, 0x0c, +}; + +extern const uint32_t sTestCert_FirmwareSigningCA_DER_Len = sizeof(sTestCert_FirmwareSigningCA_DER); + +extern const uint8_t sTestCert_FirmwareSigningCA_PublicKey[] = { + 0x04, 0x67, 0x47, 0x90, 0xa4, 0xcb, 0x5a, 0x98, 0x8c, 0x50, 0x01, 0x1d, 0xc0, 0x3b, 0x11, 0xf5, 0xd0, + 0x91, 0xb2, 0x25, 0x90, 0xc1, 0xe7, 0xe8, 0x01, 0xca, 0xb1, 0x8d, 0x79, 0x9d, 0x4a, 0x27, 0xaf, 0xa4, + 0xe5, 0xe2, 0x9d, 0x65, 0xcb, 0x97, 0x98, 0xd0, 0x5e, 0x6e, 0x1b, 0x72, 0xab, 0x41, 0x57, 0xcb, 0xf0, + 0xcf, 0x47, 0xfe, 0xa2, 0x61, 0x76, 0x82, 0xfc, 0x6d, 0xe3, 0x6e, 0x43, 0x34, 0xd1, +}; + +extern const uint8_t sTestCert_FirmwareSigningCA_PublicKey_Len = sizeof(sTestCert_FirmwareSigningCA_PublicKey); + +extern const uint8_t sTestCert_FirmwareSigningCA_PrivateKey[] = { + 0xb6, 0xef, 0x09, 0xad, 0xed, 0xe7, 0x5b, 0xcc, 0xa5, 0x5f, 0xce, 0x09, 0xe0, 0xe1, 0xcd, 0x0f, + 0xd9, 0x85, 0x33, 0x9f, 0x8f, 0x53, 0xbb, 0xe6, 0x99, 0x2d, 0x4d, 0x98, 0x7b, 0x77, 0xd9, 0x26, +}; + +extern const uint8_t sTestCert_FirmwareSigningCA_PrivateKey_Len = sizeof(sTestCert_FirmwareSigningCA_PrivateKey); + +extern const uint8_t sTestCert_FirmwareSigningCA_SubjectKeyId[] = { + 0x4D, 0xCB, 0xCD, 0x82, 0x9E, 0xBF, 0x5C, 0xEB, +}; + +extern const uint8_t sTestCert_FirmwareSigningCA_SubjectKeyId_Len = sizeof(sTestCert_FirmwareSigningCA_SubjectKeyId); + +extern const uint64_t sTestCert_FirmwareSigningCA_Id = 0xCACACACA00000004ULL; + +/************** Test FirmwareSigning Certificate ************** +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 1126576049446033558 (0xfa266f2b7b19896) + Signature Algorithm: ecdsa-with-SHA256 + Issuer: 1.3.6.1.4.1.37244.1.2 = CACACACA00000004 + Validity + Not Before: Oct 15 14:23:43 2020 GMT + Not After : Oct 15 14:23:42 2040 GMT + Subject: 1.3.6.1.4.1.37244.1.3 = FFFFFFFF00000001 + Subject Public Key Info: + Public Key Algorithm: id-ecPublicKey + Public-Key: (256 bit) + pub: + 04:df:fd:b3:fe:de:d3:1f:39:f4:04:9a:fd:90:58: + dd:6d:88:5a:26:52:83:a4:fe:b1:26:9a:66:dc:c1: + 11:7d:0d:cc:ea:b7:33:ce:c3:84:bf:0d:7e:26:2c: + 30:7a:83:50:02:94:ad:78:57:02:93:1c:31:fe:41: + a3:d8:ae:e4:ef + ASN1 OID: prime256v1 + NIST CURVE: P-256 + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:FALSE + X509v3 Key Usage: critical + Digital Signature + X509v3 Extended Key Usage: critical + Code Signing + X509v3 Subject Key Identifier: + 42:8E:80:02:A4:BF:23:1D + X509v3 Authority Key Identifier: + keyid:4D:CB:CD:82:9E:BF:5C:EB + + Signature Algorithm: ecdsa-with-SHA256 + 30:45:02:21:00:9c:97:f5:9b:3a:fb:43:95:c1:7d:3e:4f:50: + 55:aa:29:b6:de:4d:53:41:00:32:c6:8f:54:ca:4b:46:76:46: + d4:02:20:5d:b5:b3:b6:72:18:cb:b6:64:bd:02:fe:ab:63:e7: + 48:67:d6:7a:04:1b:1e:1d:2e:b7:4c:bd:71:d4:23:83:3e + +-----BEGIN CERTIFICATE----- +MIIBmjCCAUCgAwIBAgIID6Jm8rexmJYwCgYIKoZIzj0EAwIwIjEgMB4GCisGAQQB +gqJ8AQIMEENBQ0FDQUNBMDAwMDAwMDQwHhcNMjAxMDE1MTQyMzQzWhcNNDAxMDE1 +MTQyMzQyWjAiMSAwHgYKKwYBBAGConwBAwwQRkZGRkZGRkYwMDAwMDAwMTBZMBMG +ByqGSM49AgEGCCqGSM49AwEHA0IABN/9s/7e0x859ASa/ZBY3W2IWiZSg6T+sSaa +ZtzBEX0NzOq3M87DhL8NfiYsMHqDUAKUrXhXApMcMf5Bo9iu5O+jYDBeMAwGA1Ud +EwEB/wQCMAAwDgYDVR0PAQH/BAQDAgeAMBYGA1UdJQEB/wQMMAoGCCsGAQUFBwMD +MBEGA1UdDgQKBAhCjoACpL8jHTATBgNVHSMEDDAKgAhNy82Cnr9c6zAKBggqhkjO +PQQDAgNIADBFAiEAnJf1mzr7Q5XBfT5PUFWqKbbeTVNBADLGj1TKS0Z2RtQCIF21 +s7ZyGMu2ZL0C/qtj50hn1noEGx4dLrdMvXHUI4M+ +-----END CERTIFICATE----- + +-----BEGIN EC PRIVATE KEY----- +MHcCAQEEIOyBqPX2jlDA3uiS+G+t0ENrPZ+3iJdPTpafK6yxjKr4oAoGCCqGSM49 +AwEHoUQDQgAE3/2z/t7THzn0BJr9kFjdbYhaJlKDpP6xJppm3MERfQ3M6rczzsOE +vw1+JiwweoNQApSteFcCkxwx/kGj2K7k7w== +-----END EC PRIVATE KEY----- +*/ + +extern const uint8_t sTestCert_FirmwareSigning_Chip[] = { + 0xd5, 0x00, 0x00, 0x08, 0x00, 0x01, 0x00, 0x30, 0x01, 0x08, 0x0f, 0xa2, 0x66, 0xf2, 0xb7, 0xb1, 0x98, 0x96, 0x24, 0x02, + 0x01, 0x37, 0x03, 0x27, 0x12, 0x04, 0x00, 0x00, 0x00, 0xca, 0xca, 0xca, 0xca, 0x18, 0x26, 0x04, 0xef, 0x11, 0x83, 0x01, + 0x26, 0x05, 0xee, 0xa9, 0xd3, 0x27, 0x37, 0x06, 0x27, 0x13, 0x01, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x18, 0x24, + 0x07, 0x01, 0x24, 0x08, 0x01, 0x30, 0x09, 0x41, 0x04, 0xdf, 0xfd, 0xb3, 0xfe, 0xde, 0xd3, 0x1f, 0x39, 0xf4, 0x04, 0x9a, + 0xfd, 0x90, 0x58, 0xdd, 0x6d, 0x88, 0x5a, 0x26, 0x52, 0x83, 0xa4, 0xfe, 0xb1, 0x26, 0x9a, 0x66, 0xdc, 0xc1, 0x11, 0x7d, + 0x0d, 0xcc, 0xea, 0xb7, 0x33, 0xce, 0xc3, 0x84, 0xbf, 0x0d, 0x7e, 0x26, 0x2c, 0x30, 0x7a, 0x83, 0x50, 0x02, 0x94, 0xad, + 0x78, 0x57, 0x02, 0x93, 0x1c, 0x31, 0xfe, 0x41, 0xa3, 0xd8, 0xae, 0xe4, 0xef, 0x35, 0x80, 0x29, 0x01, 0x18, 0x35, 0x81, + 0x29, 0x01, 0x24, 0x02, 0x01, 0x18, 0x35, 0x82, 0x29, 0x01, 0x36, 0x02, 0x04, 0x03, 0x18, 0x18, 0x35, 0x83, 0x30, 0x02, + 0x08, 0x42, 0x8e, 0x80, 0x02, 0xa4, 0xbf, 0x23, 0x1d, 0x18, 0x35, 0x84, 0x30, 0x02, 0x08, 0x4d, 0xcb, 0xcd, 0x82, 0x9e, + 0xbf, 0x5c, 0xeb, 0x18, 0x35, 0x0a, 0x30, 0x01, 0x21, 0x00, 0x9c, 0x97, 0xf5, 0x9b, 0x3a, 0xfb, 0x43, 0x95, 0xc1, 0x7d, + 0x3e, 0x4f, 0x50, 0x55, 0xaa, 0x29, 0xb6, 0xde, 0x4d, 0x53, 0x41, 0x00, 0x32, 0xc6, 0x8f, 0x54, 0xca, 0x4b, 0x46, 0x76, + 0x46, 0xd4, 0x30, 0x02, 0x20, 0x5d, 0xb5, 0xb3, 0xb6, 0x72, 0x18, 0xcb, 0xb6, 0x64, 0xbd, 0x02, 0xfe, 0xab, 0x63, 0xe7, + 0x48, 0x67, 0xd6, 0x7a, 0x04, 0x1b, 0x1e, 0x1d, 0x2e, 0xb7, 0x4c, 0xbd, 0x71, 0xd4, 0x23, 0x83, 0x3e, 0x18, 0x18, +}; + +extern const uint32_t sTestCert_FirmwareSigning_Chip_Len = sizeof(sTestCert_FirmwareSigning_Chip); + +extern const uint8_t sTestCert_FirmwareSigning_DER[] = { + 0x30, 0x82, 0x01, 0x9a, 0x30, 0x82, 0x01, 0x40, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x08, 0x0f, 0xa2, 0x66, 0xf2, 0xb7, 0xb1, + 0x98, 0x96, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x30, 0x22, 0x31, 0x20, 0x30, 0x1e, 0x06, + 0x0a, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0xa2, 0x7c, 0x01, 0x02, 0x0c, 0x10, 0x43, 0x41, 0x43, 0x41, 0x43, 0x41, 0x43, 0x41, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x34, 0x30, 0x1e, 0x17, 0x0d, 0x32, 0x30, 0x31, 0x30, 0x31, 0x35, 0x31, 0x34, 0x32, + 0x33, 0x34, 0x33, 0x5a, 0x17, 0x0d, 0x34, 0x30, 0x31, 0x30, 0x31, 0x35, 0x31, 0x34, 0x32, 0x33, 0x34, 0x32, 0x5a, 0x30, 0x22, + 0x31, 0x20, 0x30, 0x1e, 0x06, 0x0a, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0xa2, 0x7c, 0x01, 0x03, 0x0c, 0x10, 0x46, 0x46, 0x46, + 0x46, 0x46, 0x46, 0x46, 0x46, 0x30, 0x30, 0x30, 0x30, 0x30, 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, 0xdf, 0xfd, + 0xb3, 0xfe, 0xde, 0xd3, 0x1f, 0x39, 0xf4, 0x04, 0x9a, 0xfd, 0x90, 0x58, 0xdd, 0x6d, 0x88, 0x5a, 0x26, 0x52, 0x83, 0xa4, 0xfe, + 0xb1, 0x26, 0x9a, 0x66, 0xdc, 0xc1, 0x11, 0x7d, 0x0d, 0xcc, 0xea, 0xb7, 0x33, 0xce, 0xc3, 0x84, 0xbf, 0x0d, 0x7e, 0x26, 0x2c, + 0x30, 0x7a, 0x83, 0x50, 0x02, 0x94, 0xad, 0x78, 0x57, 0x02, 0x93, 0x1c, 0x31, 0xfe, 0x41, 0xa3, 0xd8, 0xae, 0xe4, 0xef, 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, 0x16, 0x06, 0x03, 0x55, 0x1d, 0x25, 0x01, 0x01, + 0xff, 0x04, 0x0c, 0x30, 0x0a, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x03, 0x30, 0x11, 0x06, 0x03, 0x55, 0x1d, + 0x0e, 0x04, 0x0a, 0x04, 0x08, 0x42, 0x8e, 0x80, 0x02, 0xa4, 0xbf, 0x23, 0x1d, 0x30, 0x13, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, + 0x0c, 0x30, 0x0a, 0x80, 0x08, 0x4d, 0xcb, 0xcd, 0x82, 0x9e, 0xbf, 0x5c, 0xeb, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, + 0x3d, 0x04, 0x03, 0x02, 0x03, 0x48, 0x00, 0x30, 0x45, 0x02, 0x21, 0x00, 0x9c, 0x97, 0xf5, 0x9b, 0x3a, 0xfb, 0x43, 0x95, 0xc1, + 0x7d, 0x3e, 0x4f, 0x50, 0x55, 0xaa, 0x29, 0xb6, 0xde, 0x4d, 0x53, 0x41, 0x00, 0x32, 0xc6, 0x8f, 0x54, 0xca, 0x4b, 0x46, 0x76, + 0x46, 0xd4, 0x02, 0x20, 0x5d, 0xb5, 0xb3, 0xb6, 0x72, 0x18, 0xcb, 0xb6, 0x64, 0xbd, 0x02, 0xfe, 0xab, 0x63, 0xe7, 0x48, 0x67, + 0xd6, 0x7a, 0x04, 0x1b, 0x1e, 0x1d, 0x2e, 0xb7, 0x4c, 0xbd, 0x71, 0xd4, 0x23, 0x83, 0x3e, +}; + +extern const uint32_t sTestCert_FirmwareSigning_DER_Len = sizeof(sTestCert_FirmwareSigning_DER); + +extern const uint8_t sTestCert_FirmwareSigning_PublicKey[] = { + 0x04, 0xdf, 0xfd, 0xb3, 0xfe, 0xde, 0xd3, 0x1f, 0x39, 0xf4, 0x04, 0x9a, 0xfd, 0x90, 0x58, 0xdd, 0x6d, + 0x88, 0x5a, 0x26, 0x52, 0x83, 0xa4, 0xfe, 0xb1, 0x26, 0x9a, 0x66, 0xdc, 0xc1, 0x11, 0x7d, 0x0d, 0xcc, + 0xea, 0xb7, 0x33, 0xce, 0xc3, 0x84, 0xbf, 0x0d, 0x7e, 0x26, 0x2c, 0x30, 0x7a, 0x83, 0x50, 0x02, 0x94, + 0xad, 0x78, 0x57, 0x02, 0x93, 0x1c, 0x31, 0xfe, 0x41, 0xa3, 0xd8, 0xae, 0xe4, 0xef, +}; + +extern const uint8_t sTestCert_FirmwareSigning_PublicKey_Len = sizeof(sTestCert_FirmwareSigning_PublicKey); + +extern const uint8_t sTestCert_FirmwareSigning_PrivateKey[] = { + 0xec, 0x81, 0xa8, 0xf5, 0xf6, 0x8e, 0x50, 0xc0, 0xde, 0xe8, 0x92, 0xf8, 0x6f, 0xad, 0xd0, 0x43, + 0x6b, 0x3d, 0x9f, 0xb7, 0x88, 0x97, 0x4f, 0x4e, 0x96, 0x9f, 0x2b, 0xac, 0xb1, 0x8c, 0xaa, 0xf8, +}; + +extern const uint8_t sTestCert_FirmwareSigning_PrivateKey_Len = sizeof(sTestCert_FirmwareSigning_PrivateKey); + +extern const uint8_t sTestCert_FirmwareSigning_SubjectKeyId[] = { + 0x42, 0x8E, 0x80, 0x02, 0xA4, 0xBF, 0x23, 0x1D, +}; + +extern const uint8_t sTestCert_FirmwareSigning_SubjectKeyId_Len = sizeof(sTestCert_FirmwareSigning_SubjectKeyId); + +extern const uint64_t sTestCert_FirmwareSigning_Id = 0xFFFFFFFF00000001ULL; + +} // namespace TestCerts +} // namespace chip diff --git a/src/credentials/tests/CHIPCert_test_vectors.h b/src/credentials/tests/CHIPCert_test_vectors.h new file mode 100644 index 00000000000000..3a2169405a9b44 --- /dev/null +++ b/src/credentials/tests/CHIPCert_test_vectors.h @@ -0,0 +1,131 @@ +/* + * + * Copyright (c) 2020-2021 Project CHIP Authors + * Copyright (c) 2019 Google LLC. + * Copyright (c) 2016-2017 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 + * This file contains definitions of test certificates used by various unit tests. + * + */ + +#pragma once + +#include +#include +#include + +namespace chip { +namespace TestCerts { + +using namespace chip::Credentials; +using namespace chip::ASN1; + +enum TestCertTypes +{ + kNone = 0x00, + kRoot = 0x01, + kRootKey = 0x02, + kNodeCA = 0x03, + kNode01 = 0x04, + kFirmwareSigningCA = 0x05, + kFirmwareSigning = 0x06, +}; + +// Special flags to alter how certificates are fetched/loaded. +enum class TestCertLoadFlags : uint8_t +{ + kDERForm = 0x01, + kSuppressIsCA = 0x02, + kSuppressKeyUsage = 0x04, + kSuppressKeyCertSign = 0x08, + kSetPathLenConstZero = 0x10, + kSetAppDefinedCertType = 0x20, +}; + +extern CHIP_ERROR GetTestCert(uint8_t certType, BitFlags certLoadFlags, const uint8_t *& certData, + uint32_t & certDataLen); +extern const char * GetTestCertName(uint8_t certType); +extern CHIP_ERROR LoadTestCert(ChipCertificateSet & certSet, uint8_t certType, BitFlags certLoadFlags, + BitFlags decodeFlags); + +extern const uint8_t gTestCerts[]; +extern const size_t gNumTestCerts; + +extern const uint8_t sTestCert_Root_Chip[]; +extern const uint32_t sTestCert_Root_Chip_Len; +extern const uint8_t sTestCert_Root_DER[]; +extern const uint32_t sTestCert_Root_DER_Len; +extern const uint8_t sTestCert_Root_PublicKey[]; +extern const uint8_t sTestCert_Root_PublicKey_Len; +extern const uint8_t sTestCert_Root_PrivateKey[]; +extern const uint8_t sTestCert_Root_PrivateKey_Len; +extern const uint8_t sTestCert_Root_SubjectKeyId[]; +extern const uint8_t sTestCert_Root_SubjectKeyId_Len; +extern const uint64_t sTestCert_Root_Id; + +extern const uint8_t sTestCert_NodeCA_Chip[]; +extern const uint32_t sTestCert_NodeCA_Chip_Len; +extern const uint8_t sTestCert_NodeCA_DER[]; +extern const uint32_t sTestCert_NodeCA_DER_Len; +extern const uint8_t sTestCert_NodeCA_PublicKey[]; +extern const uint8_t sTestCert_NodeCA_PublicKey_Len; +extern const uint8_t sTestCert_NodeCA_PrivateKey[]; +extern const uint8_t sTestCert_NodeCA_PrivateKey_Len; +extern const uint8_t sTestCert_NodeCA_SubjectKeyId[]; +extern const uint8_t sTestCert_NodeCA_SubjectKeyId_Len; +extern const uint64_t sTestCert_NodeCA_Id; + +extern const uint8_t sTestCert_Node01_Chip[]; +extern const uint32_t sTestCert_Node01_Chip_Len; +extern const uint8_t sTestCert_Node01_DER[]; +extern const uint32_t sTestCert_Node01_DER_Len; +extern const uint8_t sTestCert_Node01_PublicKey[]; +extern const uint8_t sTestCert_Node01_PublicKey_Len; +extern const uint8_t sTestCert_Node01_PrivateKey[]; +extern const uint8_t sTestCert_Node01_PrivateKey_Len; +extern const uint8_t sTestCert_Node01_SubjectKeyId[]; +extern const uint8_t sTestCert_Node01_SubjectKeyId_Len; +extern const uint64_t sTestCert_Node01_Id; + +extern const uint8_t sTestCert_FirmwareSigningCA_Chip[]; +extern const uint32_t sTestCert_FirmwareSigningCA_Chip_Len; +extern const uint8_t sTestCert_FirmwareSigningCA_DER[]; +extern const uint32_t sTestCert_FirmwareSigningCA_DER_Len; +extern const uint8_t sTestCert_FirmwareSigningCA_PublicKey[]; +extern const uint8_t sTestCert_FirmwareSigningCA_PublicKey_Len; +extern const uint8_t sTestCert_FirmwareSigningCA_PrivateKey[]; +extern const uint8_t sTestCert_FirmwareSigningCA_PrivateKey_Len; +extern const uint8_t sTestCert_FirmwareSigningCA_SubjectKeyId[]; +extern const uint8_t sTestCert_FirmwareSigningCA_SubjectKeyId_Len; +extern const uint64_t sTestCert_FirmwareSigningCA_Id; + +extern const uint8_t sTestCert_FirmwareSigning_Chip[]; +extern const uint32_t sTestCert_FirmwareSigning_Chip_Len; +extern const uint8_t sTestCert_FirmwareSigning_DER[]; +extern const uint32_t sTestCert_FirmwareSigning_DER_Len; +extern const uint8_t sTestCert_FirmwareSigning_PublicKey[]; +extern const uint8_t sTestCert_FirmwareSigning_PublicKey_Len; +extern const uint8_t sTestCert_FirmwareSigning_PrivateKey[]; +extern const uint8_t sTestCert_FirmwareSigning_PrivateKey_Len; +extern const uint8_t sTestCert_FirmwareSigning_SubjectKeyId[]; +extern const uint8_t sTestCert_FirmwareSigning_SubjectKeyId_Len; +extern const uint64_t sTestCert_FirmwareSigning_Id; + +} // namespace TestCerts +} // namespace chip diff --git a/src/credentials/tests/TestChipCert.cpp b/src/credentials/tests/TestChipCert.cpp new file mode 100644 index 00000000000000..9ad8eab6fafce7 --- /dev/null +++ b/src/credentials/tests/TestChipCert.cpp @@ -0,0 +1,665 @@ +/* + * + * Copyright (c) 2020-2021 Project CHIP Authors + * Copyright (c) 2019 Google LLC. + * Copyright (c) 2013-2017 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 + * Unit tests for CHIP certificate functionality. + * + */ + +#include +#include +#include +#include +#include +#include + +#include + +#include "CHIPCert_test_vectors.h" + +using namespace chip; +using namespace chip::ASN1; +using namespace chip::TLV; +using namespace chip::Credentials; +using namespace chip::TestCerts; + +enum +{ + kStandardCertsCount = 3, + kTestCertBufSize = 1024, // Size of buffer needed to hold any of the test certificates + // (in either CHIP or DER form), or to decode the certificates. +}; + +static const BitFlags sIgnoreNotBeforeFlag(CertValidateFlags::kIgnoreNotBefore); +static const BitFlags sIgnoreNotAfterFlag(CertValidateFlags::kIgnoreNotAfter); + +static const BitFlags sNullDecodeFlag; +static const BitFlags sGenTBSHashFlag(CertDecodeFlags::kGenerateTBSHash); +static const BitFlags sTrustAnchorFlag(CertDecodeFlags::kIsTrustAnchor); + +static const BitFlags sNullLoadFlag; +static const BitFlags sDerFormFlag(TestCertLoadFlags::kDERForm); +static const BitFlags sSupIsCAFlag(TestCertLoadFlags::kSuppressIsCA); +static const BitFlags sSupKeyUsageFlag(TestCertLoadFlags::kSuppressKeyUsage); +static const BitFlags sSupKeyCertSignFlag(TestCertLoadFlags::kSuppressKeyCertSign); +static const BitFlags sPathLenZeroFlag(TestCertLoadFlags::kSetPathLenConstZero); +static const BitFlags sAppDefCertTypeFlag(TestCertLoadFlags::kSetAppDefinedCertType); + +static const BitFlags sNullKPFlag; +static const BitFlags sSA(KeyPurposeFlags::kServerAuth); +static const BitFlags sCA(KeyPurposeFlags::kClientAuth); +static const BitFlags sCS(KeyPurposeFlags::kCodeSigning); +static const BitFlags sEP(KeyPurposeFlags::kEmailProtection); +static const BitFlags sTS(KeyPurposeFlags::kTimeStamping); +static const BitFlags sOS(KeyPurposeFlags::kOCSPSigning); +static const BitFlags sSAandCA(sSA.Raw() | sCA.Raw()); +static const BitFlags sSAandCS(sSA.Raw() | sCS.Raw()); +static const BitFlags sSAandEP(sSA.Raw() | sEP.Raw()); +static const BitFlags sSAandTS(sSA.Raw() | sTS.Raw()); + +static const BitFlags sNullKUFlag; +static const BitFlags sDS(KeyUsageFlags::kDigitalSignature); +static const BitFlags sNR(KeyUsageFlags::kNonRepudiation); +static const BitFlags sKE(KeyUsageFlags::kKeyEncipherment); +static const BitFlags sDE(KeyUsageFlags::kDataEncipherment); +static const BitFlags sKA(KeyUsageFlags::kKeyAgreement); +static const BitFlags sKC(KeyUsageFlags::kKeyCertSign); +static const BitFlags sCR(KeyUsageFlags::kCRLSign); +static const BitFlags sEO(KeyUsageFlags::kEncipherOnly); +static const BitFlags sDO(KeyUsageFlags::kDecipherOnly); +static const BitFlags sDSandNR(sDS.Raw() | sNR.Raw()); +static const BitFlags sDSandKE(sDS.Raw() | sKE.Raw()); +static const BitFlags sDSandDE(sDS.Raw() | sDE.Raw()); +static const BitFlags sDSandKA(sDS.Raw() | sKA.Raw()); +static const BitFlags sDSandKC(sDS.Raw() | sKC.Raw()); +static const BitFlags sDSandCR(sDS.Raw() | sCR.Raw()); +static const BitFlags sDSandEO(sDS.Raw() | sEO.Raw()); +static const BitFlags sDSandDO(sDS.Raw() | sDO.Raw()); +static const BitFlags sKCandDS(sKC.Raw() | sDS.Raw()); +static const BitFlags sKCandNR(sKC.Raw() | sNR.Raw()); +static const BitFlags sKCandKE(sKC.Raw() | sKE.Raw()); +static const BitFlags sKCandDE(sKC.Raw() | sDE.Raw()); +static const BitFlags sKCandKA(sKC.Raw() | sKA.Raw()); +static const BitFlags sKCandCR(sKC.Raw() | sCR.Raw()); +static const BitFlags sKCandEO(sKC.Raw() | sEO.Raw()); +static const BitFlags sKCandDO(sKC.Raw() | sDO.Raw()); + +static CHIP_ERROR LoadStandardCerts(ChipCertificateSet & certSet) +{ + CHIP_ERROR err; + + err = LoadTestCert(certSet, TestCertTypes::kRoot, sNullLoadFlag, sTrustAnchorFlag); + SuccessOrExit(err); + + err = LoadTestCert(certSet, TestCertTypes::kNodeCA, sNullLoadFlag, sGenTBSHashFlag); + SuccessOrExit(err); + + err = LoadTestCert(certSet, TestCertTypes::kNode01, sNullLoadFlag, sGenTBSHashFlag); + SuccessOrExit(err); + +exit: + return err; +} + +static CHIP_ERROR SetEffectiveTime(ValidationContext & validContext, uint16_t year, uint8_t mon, uint8_t day, uint8_t hour = 0, + uint8_t min = 0, uint8_t sec = 0) +{ + ASN1UniversalTime effectiveTime; + + effectiveTime.Year = year; + effectiveTime.Month = mon; + effectiveTime.Day = day; + effectiveTime.Hour = hour; + effectiveTime.Minute = min; + effectiveTime.Second = sec; + + return PackCertTime(effectiveTime, validContext.mEffectiveTime); +} + +static void TestChipCert_ChipToX509(nlTestSuite * inSuite, void * inContext) +{ + CHIP_ERROR err; + const uint8_t * inCert; + uint32_t inCertLen; + const uint8_t * expectedOutCert; + uint32_t expectedOutCertLen; + uint8_t outCertBuf[kTestCertBufSize]; + uint32_t outCertLen; + + for (size_t i = 0; i < gNumTestCerts; i++) + { + uint8_t certType = gTestCerts[i]; + + err = GetTestCert(certType, sNullLoadFlag, inCert, inCertLen); + NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + err = GetTestCert(certType, sDerFormFlag, expectedOutCert, expectedOutCertLen); + NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + + err = ConvertChipCertToX509Cert(inCert, inCertLen, outCertBuf, sizeof(outCertBuf), outCertLen); + NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + NL_TEST_ASSERT(inSuite, outCertLen == expectedOutCertLen); + NL_TEST_ASSERT(inSuite, memcmp(outCertBuf, expectedOutCert, outCertLen) == 0); + } +} + +static void TestChipCert_X509ToChip(nlTestSuite * inSuite, void * inContext) +{ + CHIP_ERROR err; + const uint8_t * inCert; + uint32_t inCertLen; + const uint8_t * expectedOutCert; + uint32_t expectedOutCertLen; + uint8_t outCertBuf[kTestCertBufSize]; + uint32_t outCertLen; + + for (size_t i = 0; i < gNumTestCerts; i++) + { + uint8_t certType = gTestCerts[i]; + + err = GetTestCert(certType, sDerFormFlag, inCert, inCertLen); + NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + err = GetTestCert(certType, sNullLoadFlag, expectedOutCert, expectedOutCertLen); + NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + + err = ConvertX509CertToChipCert(inCert, inCertLen, outCertBuf, sizeof(outCertBuf), outCertLen); + NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + NL_TEST_ASSERT(inSuite, outCertLen == expectedOutCertLen); + NL_TEST_ASSERT(inSuite, memcmp(outCertBuf, expectedOutCert, outCertLen) == 0); + } +} + +static void TestChipCert_CertValidation(nlTestSuite * inSuite, void * inContext) +{ + CHIP_ERROR err; + ChipCertificateSet certSet; + ValidationContext validContext; + enum + { + kMaxCertsPerTestCase = 10 + }; + + struct ValidationTestCase + { + int mSubjectCertIndex; + uint8_t mValidateFlags; + uint8_t mRequiredCertType; + CHIP_ERROR mExpectedResult; + int mExpectedCertIndex; + int mExpectedTrustAnchorIndex; + struct + { + uint8_t Type; + BitFlags DecodeFlags; + BitFlags LoadFlags; + } InputCerts[kMaxCertsPerTestCase]; + }; + + // Short-hand names to make the test cases table more concise. + enum + { + CTNS = kCertType_NotSpecified, + CTCA = kCertType_CA, + CTNode = kCertType_Node, + CTFS = kCertType_FirmwareSigning, + CTAD = kCertType_AppDefinedBase, + }; + + // clang-format off + static const ValidationTestCase sValidationTestCases[] = { + // Reqd Exp Exp Cert Cert + // Subj Valid Cert Cert TA Cert Decode Load + // Ind Flags Type Expected Result Index Index Type Flags Flags + // ================================================================================================================================== + + // Basic validation of leaf certificate with different load orders. + { 2, 0, CTNS, CHIP_NO_ERROR, 2, 0, { { TestCertTypes::kRoot, sTrustAnchorFlag, sNullLoadFlag }, + { TestCertTypes::kNodeCA, sGenTBSHashFlag, sNullLoadFlag }, + { TestCertTypes::kNode01, sGenTBSHashFlag, sNullLoadFlag } } }, + { 1, 0, CTNS, CHIP_NO_ERROR, 1, 0, { { TestCertTypes::kRoot, sTrustAnchorFlag, sNullLoadFlag }, + { TestCertTypes::kNode01, sGenTBSHashFlag, sNullLoadFlag }, + { TestCertTypes::kNodeCA, sGenTBSHashFlag, sNullLoadFlag } } }, + { 0, 0, CTNS, CHIP_NO_ERROR, 0, 2, { { TestCertTypes::kNode01, sGenTBSHashFlag, sNullLoadFlag }, + { TestCertTypes::kNodeCA, sGenTBSHashFlag, sNullLoadFlag }, + { TestCertTypes::kRoot, sTrustAnchorFlag, sNullLoadFlag } } }, + + // Validation of leaf certificate with root key only. + { 1, 0, CTNS, CHIP_NO_ERROR, 1, 0, { { TestCertTypes::kRootKey, sNullDecodeFlag, sNullLoadFlag }, + { TestCertTypes::kNode01, sGenTBSHashFlag, sNullLoadFlag }, + { TestCertTypes::kNodeCA, sGenTBSHashFlag, sNullLoadFlag } } }, + + // Validation with two copies of root certificate, one trusted, one untrusted. + { 2, 0, CTNS, CHIP_NO_ERROR, 2, 1, { { TestCertTypes::kRoot, sNullDecodeFlag, sNullLoadFlag }, + { TestCertTypes::kRoot, sTrustAnchorFlag, sNullLoadFlag }, + { TestCertTypes::kNode01, sGenTBSHashFlag, sNullLoadFlag }, + { TestCertTypes::kNodeCA, sGenTBSHashFlag, sNullLoadFlag } } }, + + // Validation with trusted root key and trusted root certificate. + { 2, 0, CTNS, CHIP_NO_ERROR, 2, 0, { { TestCertTypes::kRootKey, sNullDecodeFlag, sNullLoadFlag }, + { TestCertTypes::kRoot, sTrustAnchorFlag, sNullLoadFlag }, + { TestCertTypes::kNode01, sGenTBSHashFlag, sNullLoadFlag }, + { TestCertTypes::kNodeCA, sGenTBSHashFlag, sNullLoadFlag } } }, + + // Validation with trusted root key and untrusted root certificate. + { 3, 0, CTNS, CHIP_NO_ERROR, 3, 1, { { TestCertTypes::kRoot, sNullDecodeFlag, sNullLoadFlag }, + { TestCertTypes::kRootKey, sNullDecodeFlag, sNullLoadFlag }, + { TestCertTypes::kNodeCA, sGenTBSHashFlag, sNullLoadFlag }, + { TestCertTypes::kNode01, sGenTBSHashFlag, sNullLoadFlag } } }, + + // Failure due to missing CA certificate. + { 1, 0, CTNS, CHIP_ERROR_CA_CERT_NOT_FOUND, -1, -1, { { TestCertTypes::kRoot, sTrustAnchorFlag, sNullLoadFlag }, + { TestCertTypes::kNode01, sGenTBSHashFlag, sNullLoadFlag } } }, + + // Failure due to missing root certificate. + { 1, 0, CTNS, CHIP_ERROR_CA_CERT_NOT_FOUND, -1, -1, { { TestCertTypes::kNodeCA, sGenTBSHashFlag, sNullLoadFlag }, + { TestCertTypes::kNode01, sGenTBSHashFlag, sNullLoadFlag } } }, + + // Failure due to lack of TBS hash. + { 1, 0, CTNS, CHIP_ERROR_INVALID_ARGUMENT, -1, -1, { { TestCertTypes::kRoot, sTrustAnchorFlag, sNullLoadFlag }, + { TestCertTypes::kNode01, sNullDecodeFlag, sNullLoadFlag }, + { TestCertTypes::kNodeCA, sGenTBSHashFlag, sNullLoadFlag } } }, + + // Failure due to untrusted root. + { 1, 0, CTNS, CHIP_ERROR_CA_CERT_NOT_FOUND, -1, -1, { { TestCertTypes::kRoot, sNullDecodeFlag, sNullLoadFlag }, + { TestCertTypes::kNode01, sGenTBSHashFlag, sNullLoadFlag }, + { TestCertTypes::kNodeCA, sGenTBSHashFlag, sNullLoadFlag } } }, + + // Failure due to intermediate cert with isCA flag = false + { 2, 0, CTNS, CHIP_ERROR_CA_CERT_NOT_FOUND, -1, -1, { { TestCertTypes::kRoot, sTrustAnchorFlag, sNullLoadFlag }, + { TestCertTypes::kNodeCA, sGenTBSHashFlag, sSupIsCAFlag }, + { TestCertTypes::kNode01, sGenTBSHashFlag, sNullLoadFlag } } }, + + // Failure due to CA cert with no key usage. + { 2, 0, CTNS, CHIP_ERROR_CA_CERT_NOT_FOUND, -1, -1, { { TestCertTypes::kRoot, sTrustAnchorFlag, sNullLoadFlag }, + { TestCertTypes::kNodeCA, sGenTBSHashFlag, sSupKeyUsageFlag }, + { TestCertTypes::kNode01, sGenTBSHashFlag, sNullLoadFlag } } }, + + // Failure due to CA cert with no cert sign key usage. + { 2, 0, CTNS, CHIP_ERROR_CA_CERT_NOT_FOUND, -1, -1, { { TestCertTypes::kRoot, sTrustAnchorFlag, sNullLoadFlag }, + { TestCertTypes::kNodeCA, sGenTBSHashFlag, sSupKeyCertSignFlag }, + { TestCertTypes::kNode01, sGenTBSHashFlag, sNullLoadFlag } } }, + + // Failure due to 3-level deep cert chain and root cert with path constraint == 0 + { 2, 0, CTNS, CHIP_ERROR_CA_CERT_NOT_FOUND, -1, -1, { { TestCertTypes::kRoot, sTrustAnchorFlag, sPathLenZeroFlag }, + { TestCertTypes::kNodeCA, sGenTBSHashFlag, sNullLoadFlag }, + { TestCertTypes::kNode01, sGenTBSHashFlag, sNullLoadFlag } } }, + + // Require a specific certificate type. + { 2, 0, CTNode, CHIP_NO_ERROR, 2, 0, { { TestCertTypes::kRoot, sTrustAnchorFlag, sNullLoadFlag }, + { TestCertTypes::kNodeCA, sGenTBSHashFlag, sNullLoadFlag }, + { TestCertTypes::kNode01, sGenTBSHashFlag, sNullLoadFlag } } }, + + // Require a certificate with an application-defined type. + { 2, 0, CTAD, CHIP_NO_ERROR, 2, 0, { { TestCertTypes::kRoot, sTrustAnchorFlag, sNullLoadFlag }, + { TestCertTypes::kNodeCA, sGenTBSHashFlag, sNullLoadFlag }, + { TestCertTypes::kNode01, sGenTBSHashFlag, sAppDefCertTypeFlag } } }, + + // Select between two identical certificates with different types. + { 2, 0, CTAD, CHIP_NO_ERROR, 3, 0, { { TestCertTypes::kRoot, sTrustAnchorFlag, sNullLoadFlag }, + { TestCertTypes::kNodeCA, sGenTBSHashFlag, sNullLoadFlag }, + { TestCertTypes::kNode01, sGenTBSHashFlag, sNullLoadFlag }, + { TestCertTypes::kNode01, sGenTBSHashFlag, sAppDefCertTypeFlag } } }, + + // Failure due to required certificate type not found. + { 2, 0, CTCA, CHIP_ERROR_WRONG_CERT_TYPE, -1, -1, { { TestCertTypes::kRoot, sTrustAnchorFlag, sNullLoadFlag }, + { TestCertTypes::kNodeCA, sGenTBSHashFlag, sNullLoadFlag }, + { TestCertTypes::kNode01, sGenTBSHashFlag, sNullLoadFlag } } }, + + // Failure due to CA certificate having wrong type. + { 2, 0, CTNode, CHIP_ERROR_CA_CERT_NOT_FOUND, -1, -1, { { TestCertTypes::kRoot, sTrustAnchorFlag, sNullLoadFlag }, + { TestCertTypes::kNodeCA, sGenTBSHashFlag, sAppDefCertTypeFlag }, + { TestCertTypes::kNode01, sGenTBSHashFlag, sNullLoadFlag } } }, + + // Failure due to root certificate having wrong type. + { 2, 0, CTNode, CHIP_ERROR_CA_CERT_NOT_FOUND, -1, -1, { { TestCertTypes::kRoot, sTrustAnchorFlag, sAppDefCertTypeFlag }, + { TestCertTypes::kNodeCA, sGenTBSHashFlag, sNullLoadFlag }, + { TestCertTypes::kNode01, sGenTBSHashFlag, sNullLoadFlag } } }, + }; + // clang-format on + static const size_t sNumValidationTestCases = sizeof(sValidationTestCases) / sizeof(sValidationTestCases[0]); + + for (unsigned i = 0; i < sNumValidationTestCases; i++) + { + ChipCertificateData * resultCert = nullptr; + const ValidationTestCase & testCase = sValidationTestCases[i]; + + // Initialize the certificate set and load the specified test certificates. + certSet.Init(kMaxCertsPerTestCase, kTestCertBufSize); + for (size_t i2 = 0; i2 < kMaxCertsPerTestCase; i2++) + { + if (testCase.InputCerts[i2].Type != TestCertTypes::kNone) + { + err = LoadTestCert(certSet, testCase.InputCerts[i2].Type, testCase.InputCerts[i2].LoadFlags, + testCase.InputCerts[i2].DecodeFlags); + NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + } + } + // Make sure the test case is valid. + NL_TEST_ASSERT(inSuite, testCase.mSubjectCertIndex >= 0 && testCase.mSubjectCertIndex < certSet.GetCertCount()); + if (testCase.mExpectedResult == CHIP_NO_ERROR) + { + NL_TEST_ASSERT(inSuite, testCase.mExpectedCertIndex >= 0 && testCase.mExpectedCertIndex < certSet.GetCertCount()); + NL_TEST_ASSERT(inSuite, + testCase.mExpectedTrustAnchorIndex >= 0 && testCase.mExpectedTrustAnchorIndex < certSet.GetCertCount()); + } + + // Initialize the validation context. + validContext.Reset(); + err = SetEffectiveTime(validContext, 2021, 1, 1); + NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + validContext.mRequiredKeyUsages.Set(KeyUsageFlags::kDigitalSignature); + validContext.mRequiredKeyPurposes.Set(KeyPurposeFlags::kServerAuth); + validContext.mValidateFlags.SetRaw(testCase.mValidateFlags); + validContext.mRequiredCertType = testCase.mRequiredCertType; + + // Locate the subject DN and key id that will be used as input the FindValidCert() method. + const ChipDN & subjectDN = certSet.GetCertSet()[testCase.mSubjectCertIndex].mSubjectDN; + const CertificateKeyId & subjectKeyId = certSet.GetCertSet()[testCase.mSubjectCertIndex].mSubjectKeyId; + + // Invoke the FindValidCert() method (the method being tested). + err = certSet.FindValidCert(subjectDN, subjectKeyId, validContext, resultCert); + NL_TEST_ASSERT(inSuite, err == testCase.mExpectedResult); + + // If the test case is expected to be successful... + if (err == CHIP_NO_ERROR) + { + // Verify that the method found the correct certificate. + NL_TEST_ASSERT(inSuite, resultCert == &certSet.GetCertSet()[testCase.mExpectedCertIndex]); + + // Verify that the method selected the correct trust anchor. + NL_TEST_ASSERT(inSuite, validContext.mTrustAnchor == &certSet.GetCertSet()[testCase.mExpectedTrustAnchorIndex]); + } + + // Clear the certificate set. + certSet.Release(); + } +} + +static void TestChipCert_CertValidTime(nlTestSuite * inSuite, void * inContext) +{ + CHIP_ERROR err; + ChipCertificateSet certSet; + ValidationContext validContext; + + certSet.Init(kStandardCertsCount, kTestCertBufSize); + + err = LoadStandardCerts(certSet); + NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + + validContext.Reset(); + validContext.mRequiredKeyUsages.Set(KeyUsageFlags::kDigitalSignature); + validContext.mRequiredKeyPurposes.Set(KeyPurposeFlags::kServerAuth); + + // Before certificate validity period. + err = SetEffectiveTime(validContext, 2020, 1, 3); + NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + err = certSet.ValidateCert(certSet.GetLastCert(), validContext); + NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_CERT_NOT_VALID_YET); + + // 1 second before validity period. + err = SetEffectiveTime(validContext, 2020, 10, 14, 23, 59, 59); + NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + err = certSet.ValidateCert(certSet.GetLastCert(), validContext); + NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_CERT_NOT_VALID_YET); + + // 1st second of 1st day of validity period. + // NOTE: the given time is technically outside the stated certificate validity period, which starts mid-day. + // However for simplicity's sake, the Chip cert validation algorithm rounds the validity period to whole days. + err = SetEffectiveTime(validContext, 2020, 10, 15, 0, 0, 0); + NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + err = certSet.ValidateCert(certSet.GetLastCert(), validContext); + NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + + // Last second of last day of validity period. + // As above, this time is considered valid because of rounding to whole days. + err = SetEffectiveTime(validContext, 2040, 10, 15, 23, 59, 59); + NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + err = certSet.ValidateCert(certSet.GetLastCert(), validContext); + NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + + // 1 second after end of certificate validity period. + err = SetEffectiveTime(validContext, 2040, 10, 16, 0, 0, 0); + NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + err = certSet.ValidateCert(certSet.GetLastCert(), validContext); + NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_CERT_EXPIRED); + + // After end of certificate validity period. + err = SetEffectiveTime(validContext, 2042, 4, 25, 0, 0, 0); + NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + err = certSet.ValidateCert(certSet.GetLastCert(), validContext); + NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_CERT_EXPIRED); + + // Ignore 'not before' time. + validContext.mValidateFlags.Set(sIgnoreNotBeforeFlag); + err = SetEffectiveTime(validContext, 2020, 4, 23, 23, 59, 59); + NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + err = certSet.ValidateCert(certSet.GetLastCert(), validContext); + NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + + // Ignore 'not after' time. + validContext.mValidateFlags.Set(sIgnoreNotAfterFlag); + err = SetEffectiveTime(validContext, 2042, 5, 25, 0, 0, 0); + NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + err = certSet.ValidateCert(certSet.GetLastCert(), validContext); + NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + + certSet.Release(); +} + +static void TestChipCert_CertUsage(nlTestSuite * inSuite, void * inContext) +{ + CHIP_ERROR err; + ChipCertificateSet certSet; + ValidationContext validContext; + + struct UsageTestCase + { + uint8_t mCertIndex; + BitFlags mRequiredKeyUsages; + BitFlags mRequiredKeyPurposes; + CHIP_ERROR mExpectedResult; + }; + + // clang-format off + static UsageTestCase sUsageTestCases[] = { + // Cert Key + // Ind Usages Key Purposes Expected Result + // ========================================================================= + + // ----- Key Usages for leaf Certificate ----- + { 2, sDS, sNullKPFlag, CHIP_NO_ERROR }, + { 2, sNR, sNullKPFlag, CHIP_ERROR_CERT_USAGE_NOT_ALLOWED }, + { 2, sKE, sNullKPFlag, CHIP_NO_ERROR }, + { 2, sDE, sNullKPFlag, CHIP_ERROR_CERT_USAGE_NOT_ALLOWED }, + { 2, sKA, sNullKPFlag, CHIP_ERROR_CERT_USAGE_NOT_ALLOWED }, + { 2, sKC, sNullKPFlag, CHIP_ERROR_CERT_USAGE_NOT_ALLOWED }, + { 2, sCR, sNullKPFlag, CHIP_ERROR_CERT_USAGE_NOT_ALLOWED }, + { 2, sEO, sNullKPFlag, CHIP_ERROR_CERT_USAGE_NOT_ALLOWED }, + { 2, sDO, sNullKPFlag, CHIP_ERROR_CERT_USAGE_NOT_ALLOWED }, + { 2, sDSandNR, sNullKPFlag, CHIP_ERROR_CERT_USAGE_NOT_ALLOWED }, + { 2, sDSandKE, sNullKPFlag, CHIP_NO_ERROR }, + { 2, sDSandDE, sNullKPFlag, CHIP_ERROR_CERT_USAGE_NOT_ALLOWED }, + { 2, sDSandKA, sNullKPFlag, CHIP_ERROR_CERT_USAGE_NOT_ALLOWED }, + { 2, sDSandKC, sNullKPFlag, CHIP_ERROR_CERT_USAGE_NOT_ALLOWED }, + { 2, sDSandCR, sNullKPFlag, CHIP_ERROR_CERT_USAGE_NOT_ALLOWED }, + { 2, sDSandEO, sNullKPFlag, CHIP_ERROR_CERT_USAGE_NOT_ALLOWED }, + { 2, sDSandDO, sNullKPFlag, CHIP_ERROR_CERT_USAGE_NOT_ALLOWED }, + + // ----- Key Usages for CA Certificate ----- + { 1, sDS, sNullKPFlag, CHIP_ERROR_CERT_USAGE_NOT_ALLOWED }, + { 1, sNR, sNullKPFlag, CHIP_ERROR_CERT_USAGE_NOT_ALLOWED }, + { 1, sKE, sNullKPFlag, CHIP_ERROR_CERT_USAGE_NOT_ALLOWED }, + { 1, sDE, sNullKPFlag, CHIP_ERROR_CERT_USAGE_NOT_ALLOWED }, + { 1, sKA, sNullKPFlag, CHIP_ERROR_CERT_USAGE_NOT_ALLOWED }, + { 1, sKC, sNullKPFlag, CHIP_NO_ERROR }, + { 1, sCR, sNullKPFlag, CHIP_NO_ERROR }, + { 1, sEO, sNullKPFlag, CHIP_ERROR_CERT_USAGE_NOT_ALLOWED }, + { 1, sDO, sNullKPFlag, CHIP_ERROR_CERT_USAGE_NOT_ALLOWED }, + { 1, sKCandDS, sNullKPFlag, CHIP_ERROR_CERT_USAGE_NOT_ALLOWED }, + { 1, sKCandNR, sNullKPFlag, CHIP_ERROR_CERT_USAGE_NOT_ALLOWED }, + { 1, sKCandKE, sNullKPFlag, CHIP_ERROR_CERT_USAGE_NOT_ALLOWED }, + { 1, sKCandDE, sNullKPFlag, CHIP_ERROR_CERT_USAGE_NOT_ALLOWED }, + { 1, sKCandKA, sNullKPFlag, CHIP_ERROR_CERT_USAGE_NOT_ALLOWED }, + { 1, sKCandCR, sNullKPFlag, CHIP_NO_ERROR }, + { 1, sKCandEO, sNullKPFlag, CHIP_ERROR_CERT_USAGE_NOT_ALLOWED }, + { 1, sKCandDO, sNullKPFlag, CHIP_ERROR_CERT_USAGE_NOT_ALLOWED }, + + // ----- Key Purposes for leaf Certificate ----- + { 2, sNullKUFlag, sSA, CHIP_NO_ERROR }, + { 2, sNullKUFlag, sCA, CHIP_NO_ERROR }, + { 2, sNullKUFlag, sCS, CHIP_ERROR_CERT_USAGE_NOT_ALLOWED }, + { 2, sNullKUFlag, sEP, CHIP_ERROR_CERT_USAGE_NOT_ALLOWED }, + { 2, sNullKUFlag, sTS, CHIP_ERROR_CERT_USAGE_NOT_ALLOWED }, + { 2, sNullKUFlag, sSAandCA, CHIP_NO_ERROR }, + { 2, sNullKUFlag, sSAandCS, CHIP_ERROR_CERT_USAGE_NOT_ALLOWED }, + { 2, sNullKUFlag, sSAandEP, CHIP_ERROR_CERT_USAGE_NOT_ALLOWED }, + { 2, sNullKUFlag, sSAandTS, CHIP_ERROR_CERT_USAGE_NOT_ALLOWED }, + + // ----- Key Purposes for CA Certificate ----- + { 1, sNullKUFlag, sSA, CHIP_ERROR_CERT_USAGE_NOT_ALLOWED }, + { 1, sNullKUFlag, sCA, CHIP_ERROR_CERT_USAGE_NOT_ALLOWED }, + { 1, sNullKUFlag, sCS, CHIP_ERROR_CERT_USAGE_NOT_ALLOWED }, + { 1, sNullKUFlag, sEP, CHIP_ERROR_CERT_USAGE_NOT_ALLOWED }, + { 1, sNullKUFlag, sTS, CHIP_ERROR_CERT_USAGE_NOT_ALLOWED }, + { 1, sNullKUFlag, sSAandCA, CHIP_ERROR_CERT_USAGE_NOT_ALLOWED }, + { 1, sNullKUFlag, sSAandCS, CHIP_ERROR_CERT_USAGE_NOT_ALLOWED }, + { 1, sNullKUFlag, sSAandEP, CHIP_ERROR_CERT_USAGE_NOT_ALLOWED }, + { 1, sNullKUFlag, sSAandTS, CHIP_ERROR_CERT_USAGE_NOT_ALLOWED }, + + // ----- Combinations ----- + { 2, sDSandNR, sSAandCA, CHIP_ERROR_CERT_USAGE_NOT_ALLOWED }, + { 2, sDSandKE, sSAandCS, CHIP_ERROR_CERT_USAGE_NOT_ALLOWED }, + { 2, sDSandKE, sSAandCA, CHIP_NO_ERROR }, + }; + // clang-format on + size_t sNumUsageTestCases = sizeof(sUsageTestCases) / sizeof(sUsageTestCases[0]); + + certSet.Init(kStandardCertsCount, kTestCertBufSize); + + err = LoadStandardCerts(certSet); + NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + + for (size_t i = 0; i < sNumUsageTestCases; i++) + { + validContext.Reset(); + validContext.mRequiredKeyUsages = sUsageTestCases[i].mRequiredKeyUsages; + validContext.mRequiredKeyPurposes = sUsageTestCases[i].mRequiredKeyPurposes; + + err = SetEffectiveTime(validContext, 2020, 10, 16); + NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + + err = certSet.ValidateCert(&certSet.GetCertSet()[sUsageTestCases[i].mCertIndex], validContext); + NL_TEST_ASSERT(inSuite, err == sUsageTestCases[i].mExpectedResult); + } + + certSet.Release(); +} + +static void TestChipCert_CertType(nlTestSuite * inSuite, void * inContext) +{ + CHIP_ERROR err; + ChipCertificateSet certSet; + + struct TestCase + { + uint8_t Cert; + uint8_t ExpectedCertType; + }; + + // clang-format off + static TestCase sTestCases[] = { + // Cert ExpectedCertType + // ============================================================= + { TestCertTypes::kRoot, kCertType_CA }, + { TestCertTypes::kRootKey, kCertType_CA }, + { TestCertTypes::kNodeCA, kCertType_CA }, + { TestCertTypes::kNode01, kCertType_Node }, + { TestCertTypes::kFirmwareSigning, kCertType_FirmwareSigning }, + }; + // clang-format on + static const size_t sNumTestCases = sizeof(sTestCases) / sizeof(sTestCases[0]); + + for (unsigned i = 0; i < sNumTestCases; i++) + { + const TestCase & testCase = sTestCases[i]; + + // Initialize the certificate set and load the test certificate. + certSet.Init(1, kTestCertBufSize); + err = LoadTestCert(certSet, testCase.Cert, sNullLoadFlag, sNullDecodeFlag); + NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + NL_TEST_ASSERT(inSuite, certSet.GetCertSet()->mCertType == testCase.ExpectedCertType); + } +} + +/** + * Set up the test suite. + */ +int TestChipCert_Setup(void * inContext) +{ + CHIP_ERROR error = chip::Platform::MemoryInit(); + + if (error != CHIP_NO_ERROR) + { + return FAILURE; + } + + return SUCCESS; +} + +/** + * Tear down the test suite. + */ +int TestChipCert_Teardown(void * inContext) +{ + chip::Platform::MemoryShutdown(); + return SUCCESS; +} + +/** + * Test Suite. It lists all the test functions. + */ +// clang-format off +static const nlTest sTests[] = { + NL_TEST_DEF("Test CHIP Certificate CHIP to X509 Conversion", TestChipCert_ChipToX509), + NL_TEST_DEF("Test CHIP Certificate X509 to CHIP Conversion", TestChipCert_X509ToChip), + NL_TEST_DEF("Test CHIP Certificate Validation", TestChipCert_CertValidation), + NL_TEST_DEF("Test CHIP Certificate Validation time", TestChipCert_CertValidTime), + NL_TEST_DEF("Test CHIP Certificate Usage", TestChipCert_CertUsage), + NL_TEST_DEF("Test CHIP Certificate Type", TestChipCert_CertType), + NL_TEST_SENTINEL() +}; +// clang-format on + +int TestChipCert(void) +{ + // clang-format off + nlTestSuite theSuite = + { + "Credentials-CHIP-Certs", + &sTests[0], + TestChipCert_Setup, + TestChipCert_Teardown + }; + // clang-format on + nlTestRunner(&theSuite, nullptr); + return (nlTestRunnerStats(&theSuite)); +} + +CHIP_REGISTER_TEST_SUITE(TestChipCert); diff --git a/src/crypto/CHIPCryptoPAL.cpp b/src/crypto/CHIPCryptoPAL.cpp index a6b6085a515f8d..07f6156439e3ae 100644 --- a/src/crypto/CHIPCryptoPAL.cpp +++ b/src/crypto/CHIPCryptoPAL.cpp @@ -82,12 +82,12 @@ Spake2p::Spake2p(size_t _fe_size, size_t _point_size, size_t _hash_size) tempbn = nullptr; } -CHIP_ERROR Spake2p::Init(const uint8_t * context, size_t context_len) +CHIP_ERROR Spake2p::Init(const Hash_SHA256_stream * context) { CHIP_ERROR error = CHIP_ERROR_INTERNAL; state = CHIP_SPAKE2P_STATE::PREINIT; - error = InitImpl(); + error = InitImpl(context); VerifyOrExit(error == CHIP_NO_ERROR, error = CHIP_ERROR_INTERNAL); error = PointLoad(spake2p_M_p256, sizeof(spake2p_M_p256), M); @@ -96,9 +96,6 @@ CHIP_ERROR Spake2p::Init(const uint8_t * context, size_t context_len) error = PointLoad(spake2p_N_p256, sizeof(spake2p_N_p256), N); VerifyOrExit(error == CHIP_NO_ERROR, error = CHIP_ERROR_INTERNAL); - error = InternalHash(context, context_len); - VerifyOrExit(error == CHIP_NO_ERROR, error = CHIP_ERROR_INTERNAL); - state = CHIP_SPAKE2P_STATE::INIT; error = CHIP_NO_ERROR; exit: @@ -387,12 +384,19 @@ CHIP_ERROR Spake2p::GetKeys(uint8_t * out, size_t * out_len) return error; } -CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::InitImpl() +CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::InitImpl(const Hash_SHA256_stream * context) { CHIP_ERROR error = CHIP_ERROR_INTERNAL; - error = sha256_hash_ctx.Begin(); - VerifyOrExit(error == CHIP_NO_ERROR, error = CHIP_ERROR_INTERNAL); + if (context != nullptr) + { + sha256_hash_ctx = (*context); + } + else + { + error = sha256_hash_ctx.Begin(); + VerifyOrExit(error == CHIP_NO_ERROR, error = CHIP_ERROR_INTERNAL); + } error = InitInternal(); VerifyOrExit(error == CHIP_NO_ERROR, error = CHIP_ERROR_INTERNAL); diff --git a/src/crypto/CHIPCryptoPAL.h b/src/crypto/CHIPCryptoPAL.h index 59a66fc639c173..4d36017fab44eb 100644 --- a/src/crypto/CHIPCryptoPAL.h +++ b/src/crypto/CHIPCryptoPAL.h @@ -55,7 +55,7 @@ const size_t kP256_PublicKey_Length = 65; * the implementation files. */ const size_t kMAX_Spake2p_Context_Size = 1024; -const size_t kMAX_Hash_SHA256_Context_Size = 256; +const size_t kMAX_Hash_SHA256_Context_Size = 296; const size_t kMAX_P256Keypair_Context_Size = 512; /** @@ -350,6 +350,8 @@ CHIP_ERROR Hash_SHA256(const uint8_t * data, size_t data_length, uint8_t * out_b /** * @brief A class that defines stream based implementation of SHA-256 hash + * It's expected that the object of this class can be safely copied. + * All implementations must check for std::is_trivially_copyable. **/ struct HashSHA256OpaqueContext @@ -456,14 +458,13 @@ class Spake2p /** * @brief Initialize Spake2+ with some context specific information. * - * @param context The context is arbitrary but should include information about the - * protocol being run, contain the transcript for negotiation, include - * the PKBDF parameters, etc. - * @param context_len The length of the context. + * @param context The spake2p session will bootstrap from this hash context. + * If the provided context pointer is null, the spake2p session will bootstrap + * from a blank hash context. * * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise **/ - CHIP_ERROR Init(const uint8_t * context, size_t context_len); + CHIP_ERROR Init(const Hash_SHA256_stream * context); /** * @brief Start the Spake2+ process as a verifier (i.e. an accessory being provisioned). @@ -716,7 +717,7 @@ class Spake2p * * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise **/ - virtual CHIP_ERROR InitImpl() = 0; + virtual CHIP_ERROR InitImpl(const Hash_SHA256_stream * context) = 0; /** * @brief Hash in_len bytes of in into the internal hash context. @@ -828,7 +829,7 @@ class Spake2p_P256_SHA256_HKDF_HMAC : public Spake2p CHIP_ERROR ComputeL(uint8_t * Lout, size_t * L_len, const uint8_t * w1in, size_t w1in_len) override; protected: - CHIP_ERROR InitImpl() override; + CHIP_ERROR InitImpl(const Hash_SHA256_stream * context) override; CHIP_ERROR Hash(const uint8_t * in, size_t in_len) override; CHIP_ERROR HashFinalize(uint8_t * out) override; CHIP_ERROR KDF(const uint8_t * secret, size_t secret_length, const uint8_t * salt, size_t salt_length, const uint8_t * info, diff --git a/src/crypto/CHIPCryptoPALOpenSSL.cpp b/src/crypto/CHIPCryptoPALOpenSSL.cpp index 30ab992473b2fd..0733f9face0e92 100644 --- a/src/crypto/CHIPCryptoPALOpenSSL.cpp +++ b/src/crypto/CHIPCryptoPALOpenSSL.cpp @@ -22,6 +22,8 @@ #include "CHIPCryptoPAL.h" +#include + #include #include #include @@ -298,7 +300,8 @@ Hash_SHA256_stream::~Hash_SHA256_stream() {} static inline SHA256_CTX * to_inner_hash_sha256_context(HashSHA256OpaqueContext * context) { - nlSTATIC_ASSERT_PRINT(sizeof(HashSHA256OpaqueContext) >= sizeof(SHA256_CTX), "Need more memory for SHA256 Context"); + static_assert(sizeof(HashSHA256OpaqueContext) >= sizeof(SHA256_CTX), "Need more memory for SHA256 Context"); + static_assert(std::is_trivially_copyable(), "SHA256_CTX values must copyable"); return reinterpret_cast(context->mOpaque); } diff --git a/src/crypto/CHIPCryptoPALmbedTLS.cpp b/src/crypto/CHIPCryptoPALmbedTLS.cpp index fec42ed1ee6346..a98d7471378428 100644 --- a/src/crypto/CHIPCryptoPALmbedTLS.cpp +++ b/src/crypto/CHIPCryptoPALmbedTLS.cpp @@ -22,6 +22,8 @@ #include "CHIPCryptoPAL.h" +#include + #include #include #include @@ -192,7 +194,8 @@ Hash_SHA256_stream::~Hash_SHA256_stream(void) {} static inline mbedtls_sha256_context * to_inner_hash_sha256_context(HashSHA256OpaqueContext * context) { - nlSTATIC_ASSERT_PRINT(sizeof(context->mOpaque) >= sizeof(mbedtls_sha256_context), "Need more memory for SHA256 Context"); + static_assert(sizeof(context->mOpaque) >= sizeof(mbedtls_sha256_context), "Need more memory for SHA256 Context"); + static_assert(std::is_trivially_copyable(), "mbedtls_sha256_context values must copyable"); return reinterpret_cast(context->mOpaque); } diff --git a/src/crypto/tests/CHIPCryptoPALTest.cpp b/src/crypto/tests/CHIPCryptoPALTest.cpp index 0c27c6531a5a3b..576cfb033d5aef 100644 --- a/src/crypto/tests/CHIPCryptoPALTest.cpp +++ b/src/crypto/tests/CHIPCryptoPALTest.cpp @@ -989,7 +989,7 @@ static void TestSPAKE2P_spake2p_FEMul(nlTestSuite * inSuite, void * inContext) const struct spake2p_fe_mul_tv * vector = fe_mul_tvs[vectorIndex]; Spake2p_P256_SHA256_HKDF_HMAC spake2p; - CHIP_ERROR err = spake2p.Init(nullptr, 0); + CHIP_ERROR err = spake2p.Init(nullptr); NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); err = spake2p.FELoad(vector->fe1, vector->fe1_len, spake2p.w0); @@ -1022,7 +1022,7 @@ static void TestSPAKE2P_spake2p_FELoadWrite(nlTestSuite * inSuite, void * inCont const struct spake2p_fe_rw_tv * vector = fe_rw_tvs[vectorIndex]; Spake2p_P256_SHA256_HKDF_HMAC spake2p; - CHIP_ERROR err = spake2p.Init(nullptr, 0); + CHIP_ERROR err = spake2p.Init(nullptr); NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); err = spake2p.FELoad(vector->fe_in, vector->fe_in_len, spake2p.w0); @@ -1049,7 +1049,7 @@ static void TestSPAKE2P_spake2p_Mac(nlTestSuite * inSuite, void * inContext) const struct spake2p_hmac_tv * vector = hmac_tvs[vectorIndex]; Spake2p_P256_SHA256_HKDF_HMAC spake2p; - CHIP_ERROR err = spake2p.Init(nullptr, 0); + CHIP_ERROR err = spake2p.Init(nullptr); NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); err = spake2p.Mac(vector->key, vector->key_len, vector->input, vector->input_len, mac); @@ -1079,7 +1079,7 @@ static void TestSPAKE2P_spake2p_PointMul(nlTestSuite * inSuite, void * inContext const struct spake2p_point_mul_tv * vector = point_mul_tvs[vectorIndex]; Spake2p_P256_SHA256_HKDF_HMAC spake2p; - CHIP_ERROR err = spake2p.Init(nullptr, 0); + CHIP_ERROR err = spake2p.Init(nullptr); NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); err = spake2p.PointLoad(vector->point, vector->point_len, spake2p.L); @@ -1115,7 +1115,7 @@ static void TestSPAKE2P_spake2p_PointMulAdd(nlTestSuite * inSuite, void * inCont const struct spake2p_point_muladd_tv * vector = point_muladd_tvs[vectorIndex]; Spake2p_P256_SHA256_HKDF_HMAC spake2p; - CHIP_ERROR err = spake2p.Init(nullptr, 0); + CHIP_ERROR err = spake2p.Init(nullptr); NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); err = spake2p.PointLoad(vector->point1, vector->point1_len, spake2p.X); @@ -1157,7 +1157,7 @@ static void TestSPAKE2P_spake2p_PointLoadWrite(nlTestSuite * inSuite, void * inC const struct spake2p_point_rw_tv * vector = point_rw_tvs[vectorIndex]; Spake2p_P256_SHA256_HKDF_HMAC spake2p; - CHIP_ERROR err = spake2p.Init(nullptr, 0); + CHIP_ERROR err = spake2p.Init(nullptr); NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); err = spake2p.PointLoad(vector->point, vector->point_len, spake2p.L); @@ -1183,7 +1183,7 @@ static void TestSPAKE2P_spake2p_PointIsValid(nlTestSuite * inSuite, void * inCon const struct spake2p_point_valid_tv * vector = point_valid_tvs[vectorIndex]; Spake2p_P256_SHA256_HKDF_HMAC spake2p; - CHIP_ERROR err = spake2p.Init(nullptr, 0); + CHIP_ERROR err = spake2p.Init(nullptr); NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); err = spake2p.PointLoad(vector->point, vector->point_len, spake2p.L); @@ -1255,8 +1255,16 @@ static void TestSPAKE2P_RFC(nlTestSuite * inSuite, void * inContext) Test_Spake2p_P256_SHA256_HKDF_HMAC Verifier; Test_Spake2p_P256_SHA256_HKDF_HMAC Prover; + Hash_SHA256_stream hashContext; + + error = hashContext.Begin(); + NL_TEST_ASSERT(inSuite, error == CHIP_NO_ERROR); + + error = hashContext.AddData(vector->context, vector->context_len); + NL_TEST_ASSERT(inSuite, error == CHIP_NO_ERROR); + // First start the prover - error = Prover.Init(vector->context, vector->context_len); + error = Prover.Init(&hashContext); NL_TEST_ASSERT(inSuite, error == CHIP_NO_ERROR); error = Prover.BeginProver(vector->prover_identity, vector->prover_identity_len, vector->verifier_identity, @@ -1275,7 +1283,7 @@ static void TestSPAKE2P_RFC(nlTestSuite * inSuite, void * inContext) NL_TEST_ASSERT(inSuite, memcmp(X, vector->X, vector->X_len) == 0); // Start up the verifier - error = Verifier.Init(vector->context, vector->context_len); + error = Verifier.Init(&hashContext); NL_TEST_ASSERT(inSuite, error == CHIP_NO_ERROR); // First pre-compute L (accessories with dynamic setup codes will do this) diff --git a/src/crypto/tests/SPAKE2P_RFC_test_vectors.h b/src/crypto/tests/SPAKE2P_RFC_test_vectors.h index 20a77596a7a874..40d31a43da0c45 100644 --- a/src/crypto/tests/SPAKE2P_RFC_test_vectors.h +++ b/src/crypto/tests/SPAKE2P_RFC_test_vectors.h @@ -104,18 +104,18 @@ static const uint8_t chiptest_e4836c3b50dd_V_9[] = { 0x04, 0x67, 0x18, 0x98, 0 0x28, 0x53, 0xa4, 0x07, 0x12, 0x51, 0xa3, 0x9f, 0xbe, 0x8c, 0xfc, 0x39, 0xbc }; static const uint8_t chiptest_e4836c3b50dd_Ka_10[] = { 0xf9, 0xca, 0xb9, 0xad, 0xcc, 0x0e, 0xd8, 0xe5, 0xa4, 0xdb, 0x11, 0xa8, 0x50, 0x59, 0x14, 0xb2 }; -static const uint8_t chiptest_e4836c3b50dd_Ke_11[] = { 0x80, 0x1d, 0xb2, 0x97, 0x65, 0x48, 0x16, 0xeb, - 0x4f, 0x02, 0x86, 0x81, 0x29, 0xb9, 0xdc, 0x89 }; +static const uint8_t chiptest_e4836c3b50dd_Ke_11[] = { 0x19, 0x29, 0x9c, 0x25, 0x57, 0x7d, 0xef, 0x6a, + 0xca, 0x4f, 0x21, 0x98, 0xd8, 0xb9, 0x18, 0x5c }; static const uint8_t chiptest_e4836c3b50dd_KcA_12[] = { 0x0d, 0x24, 0x8d, 0x7d, 0x19, 0x23, 0x4f, 0x14, 0x86, 0xb2, 0xef, 0xba, 0x51, 0x79, 0xc5, 0x2d }; static const uint8_t chiptest_e4836c3b50dd_KcB_13[] = { 0x55, 0x62, 0x91, 0xdf, 0x26, 0xd7, 0x05, 0xa2, 0xca, 0xed, 0xd6, 0x47, 0x4d, 0xd0, 0x07, 0x9b }; -static const uint8_t chiptest_e4836c3b50dd_MAC_KcA_14[] = { 0xd4, 0x37, 0x6f, 0x2d, 0xa9, 0xc7, 0x22, 0x26, 0xdd, 0x15, 0x1b, - 0x77, 0xc2, 0x91, 0x90, 0x71, 0x15, 0x5f, 0xc2, 0x2a, 0x20, 0x68, - 0xd9, 0x0b, 0x5f, 0xaa, 0x6c, 0x78, 0xc1, 0x1e, 0x77, 0xdd }; -static const uint8_t chiptest_e4836c3b50dd_MAC_KcB_15[] = { 0x06, 0x60, 0xa6, 0x80, 0x66, 0x3e, 0x8c, 0x56, 0x95, 0x95, 0x6f, - 0xb2, 0x2d, 0xff, 0x29, 0x8b, 0x1d, 0x07, 0xa5, 0x26, 0xcf, 0x3c, - 0xc5, 0x91, 0xad, 0xfe, 0xcd, 0x1f, 0x6e, 0xf6, 0xe0, 0x2e }; +static const uint8_t chiptest_e4836c3b50dd_MAC_KcA_14[] = { 0xe0, 0x2d, 0x9e, 0x25, 0x6b, 0xe6, 0xc4, 0xa9, 0x34, 0x6f, 0x0d, + 0x76, 0x67, 0xae, 0xcd, 0x61, 0xaf, 0x7c, 0x63, 0xfe, 0xfb, 0xb4, + 0xf7, 0x1b, 0x84, 0xd4, 0x01, 0x15, 0x9f, 0xaa, 0xbe, 0xce }; +static const uint8_t chiptest_e4836c3b50dd_MAC_KcB_15[] = { 0xf7, 0xae, 0x1b, 0xeb, 0x80, 0xd5, 0x74, 0x33, 0x12, 0x88, 0x6b, + 0x0d, 0xcb, 0xce, 0x62, 0x02, 0x23, 0x4a, 0x20, 0xa6, 0x11, 0x9e, + 0x95, 0x31, 0x0a, 0xad, 0xaf, 0x32, 0x3a, 0x2a, 0xcd, 0x39 }; static const struct spake2p_rfc_tv chiptest_e4836c3b50dd_test_vector_16 = { .context = reinterpret_cast("SPAKE2+-P256-SHA256-HKDF draft-01"), .context_len = 33, @@ -198,18 +198,18 @@ static const uint8_t chiptest_e4836c3b50dd_V_25[] = { }; static const uint8_t chiptest_e4836c3b50dd_Ka_26[] = { 0xe2, 0xcb, 0xee, 0x3a, 0xe1, 0x9a, 0x4d, 0xbe, 0x9f, 0x14, 0x6b, 0xe6, 0xbe, 0xe9, 0xbf, 0xa1 }; -static const uint8_t chiptest_e4836c3b50dd_Ke_27[] = { 0x69, 0x89, 0xd8, 0xf9, 0x17, 0x7e, 0xf7, 0xdf, - 0x67, 0xda, 0x43, 0x79, 0x87, 0xf0, 0x72, 0x55 }; +static const uint8_t chiptest_e4836c3b50dd_Ke_27[] = { 0x65, 0x2a, 0x19, 0x95, 0x9d, 0x48, 0xc9, 0xcc, + 0x1b, 0x87, 0x6e, 0x2f, 0x2a, 0x3c, 0xe4, 0x38 }; static const uint8_t chiptest_e4836c3b50dd_KcA_28[] = { 0x2f, 0x9e, 0x0b, 0xb6, 0x69, 0xd2, 0xc2, 0x26, 0x45, 0xbc, 0xe3, 0x4d, 0xa0, 0x4a, 0xc1, 0x6a }; static const uint8_t chiptest_e4836c3b50dd_KcB_29[] = { 0xeb, 0x7a, 0x35, 0x16, 0x87, 0x59, 0xdd, 0x8e, 0x9c, 0xe4, 0x4e, 0x4d, 0xc5, 0x12, 0x77, 0xce }; -static const uint8_t chiptest_e4836c3b50dd_MAC_KcA_30[] = { 0xe1, 0xb9, 0x25, 0x88, 0x07, 0xba, 0x47, 0x50, 0xda, 0xe1, 0xd7, - 0xf3, 0xc3, 0xc2, 0x94, 0xf1, 0x3d, 0xc4, 0xfa, 0x60, 0xcd, 0xe3, - 0x46, 0xd5, 0xde, 0x7d, 0x20, 0x0e, 0x2f, 0x8f, 0xd3, 0xfc }; -static const uint8_t chiptest_e4836c3b50dd_MAC_KcB_31[] = { 0xb9, 0xc3, 0x9d, 0xfa, 0x49, 0xc4, 0x77, 0x57, 0xde, 0x77, 0x8d, - 0x9b, 0xed, 0xea, 0xca, 0x24, 0x48, 0xb9, 0x05, 0xbe, 0x19, 0xa4, - 0x3b, 0x94, 0xee, 0x24, 0xb7, 0x70, 0x20, 0x81, 0x35, 0xe3 }; +static const uint8_t chiptest_e4836c3b50dd_MAC_KcA_30[] = { 0xfa, 0xda, 0x17, 0xfa, 0xeb, 0x1a, 0xb8, 0x7d, 0x1d, 0x56, 0xef, + 0xea, 0x91, 0xac, 0x5b, 0x04, 0xb6, 0x92, 0x6c, 0xe7, 0x8d, 0x1d, + 0x2f, 0x6d, 0x2e, 0xd9, 0xc2, 0x3f, 0x4c, 0xc8, 0xcc, 0x3b }; +static const uint8_t chiptest_e4836c3b50dd_MAC_KcB_31[] = { 0xe4, 0x26, 0x7d, 0x40, 0x78, 0xa4, 0xef, 0x9c, 0xd2, 0xf6, 0xef, + 0xc7, 0x6d, 0x65, 0xb4, 0x9f, 0xb8, 0xd7, 0x80, 0xb0, 0x0a, 0x45, + 0xb8, 0x92, 0x0b, 0xc5, 0xe1, 0xe8, 0x0e, 0x97, 0x02, 0xe4 }; static const struct spake2p_rfc_tv chiptest_e4836c3b50dd_test_vector_32 = { .context = reinterpret_cast("SPAKE2+-P256-SHA256-HKDF draft-01"), .context_len = 33, @@ -292,18 +292,18 @@ static const uint8_t chiptest_e4836c3b50dd_V_41[] = { }; static const uint8_t chiptest_e4836c3b50dd_Ka_42[] = { 0xec, 0x8d, 0x19, 0xb8, 0x07, 0xff, 0xb1, 0xd1, 0xee, 0xa8, 0x1a, 0x93, 0xba, 0x35, 0xcd, 0xfe }; -static const uint8_t chiptest_e4836c3b50dd_Ke_43[] = { 0x2e, 0xa4, 0x0e, 0x4b, 0xad, 0xfa, 0x54, 0x52, - 0xb5, 0x74, 0x4d, 0xc5, 0x98, 0x3e, 0x99, 0xba }; +static const uint8_t chiptest_e4836c3b50dd_Ke_43[] = { 0x26, 0xed, 0x24, 0xeb, 0x31, 0xb0, 0x7b, 0x28, + 0x6a, 0x3d, 0x5f, 0xe6, 0x26, 0x37, 0xf1, 0xa7 }; static const uint8_t chiptest_e4836c3b50dd_KcA_44[] = { 0x66, 0xde, 0x53, 0x4d, 0x9b, 0xf1, 0xe4, 0x4e, 0x96, 0xa5, 0x3a, 0x4b, 0x48, 0xd6, 0xb3, 0x53 }; static const uint8_t chiptest_e4836c3b50dd_KcB_45[] = { 0x49, 0x45, 0xc3, 0x8b, 0xb4, 0x76, 0xcb, 0x0f, 0x34, 0x7f, 0x32, 0x22, 0xbe, 0x9b, 0x64, 0xa2 }; -static const uint8_t chiptest_e4836c3b50dd_MAC_KcA_46[] = { 0xe5, 0x64, 0xc9, 0x3b, 0x30, 0x15, 0xef, 0xb9, 0x46, 0xdc, 0x16, - 0xd6, 0x42, 0xbb, 0xe7, 0xd1, 0xc8, 0xda, 0x5b, 0xe1, 0x64, 0xed, - 0x9f, 0xc3, 0xba, 0xe4, 0xe0, 0xff, 0x86, 0xe1, 0xbd, 0x3c }; -static const uint8_t chiptest_e4836c3b50dd_MAC_KcB_47[] = { 0x07, 0x2a, 0x94, 0xd9, 0xa5, 0x4e, 0xdc, 0x20, 0x1d, 0x88, 0x91, - 0x53, 0x4c, 0x23, 0x17, 0xca, 0xdf, 0x3e, 0xa3, 0x79, 0x28, 0x27, - 0xf4, 0x79, 0xe8, 0x73, 0xf9, 0x3e, 0x90, 0xf2, 0x15, 0x52 }; +static const uint8_t chiptest_e4836c3b50dd_MAC_KcA_46[] = { 0x3e, 0x65, 0xa5, 0x4e, 0x88, 0x94, 0xe6, 0x8d, 0x10, 0x0e, 0x91, + 0xf5, 0xe8, 0x55, 0xd0, 0x1b, 0x9c, 0x6c, 0x33, 0xb4, 0x27, 0x2f, + 0x5b, 0xa2, 0x2a, 0x1d, 0x09, 0x85, 0x76, 0x6e, 0x3d, 0x2c }; +static const uint8_t chiptest_e4836c3b50dd_MAC_KcB_47[] = { 0xef, 0x57, 0xce, 0x5a, 0x96, 0x62, 0x06, 0x59, 0x10, 0x49, 0xfd, + 0xde, 0x1c, 0x35, 0x09, 0xa5, 0xcb, 0x6c, 0x4d, 0xa8, 0x00, 0x01, + 0x55, 0x5c, 0xcb, 0x13, 0xb5, 0x88, 0x08, 0x41, 0xd7, 0xb0 }; static const struct spake2p_rfc_tv chiptest_e4836c3b50dd_test_vector_48 = { .context = reinterpret_cast("SPAKE2+-P256-SHA256-HKDF draft-01"), .context_len = 33, @@ -386,18 +386,18 @@ static const uint8_t chiptest_e4836c3b50dd_V_57[] = { }; static const uint8_t chiptest_e4836c3b50dd_Ka_58[] = { 0x59, 0x29, 0xa3, 0xce, 0x98, 0x22, 0xc8, 0x14, 0x01, 0xbf, 0x0f, 0x76, 0x4f, 0x69, 0xaf, 0x08 }; -static const uint8_t chiptest_e4836c3b50dd_Ke_59[] = { 0xea, 0x32, 0x76, 0xd6, 0x83, 0x34, 0x57, 0x60, - 0x97, 0xe0, 0x4b, 0x19, 0xee, 0x5a, 0x3a, 0x8b }; +static const uint8_t chiptest_e4836c3b50dd_Ke_59[] = { 0x02, 0xe6, 0x6a, 0xfc, 0x73, 0x1e, 0x20, 0x74, + 0x46, 0xcf, 0x30, 0x31, 0xb2, 0x22, 0xd9, 0x79 }; static const uint8_t chiptest_e4836c3b50dd_KcA_60[] = { 0x7f, 0x84, 0xb9, 0x39, 0xd6, 0x00, 0x11, 0x72, 0x56, 0xb0, 0xc8, 0xa6, 0xd4, 0x0c, 0xf1, 0x81 }; static const uint8_t chiptest_e4836c3b50dd_KcB_61[] = { 0xf7, 0xd7, 0x54, 0x7c, 0xed, 0x93, 0xf6, 0x81, 0xe8, 0xdf, 0x4c, 0x25, 0x8c, 0x45, 0x16, 0xfd }; -static const uint8_t chiptest_e4836c3b50dd_MAC_KcA_62[] = { 0x71, 0xd9, 0x41, 0x27, 0x79, 0xb6, 0xc4, 0x5a, 0x2c, 0x61, 0x5c, - 0x9d, 0xf3, 0xf1, 0xfd, 0x93, 0xdc, 0x0a, 0xaf, 0x63, 0x10, 0x4d, - 0xa8, 0xec, 0xe4, 0xaa, 0x1b, 0x5a, 0x3a, 0x41, 0x5f, 0xea }; -static const uint8_t chiptest_e4836c3b50dd_MAC_KcB_63[] = { 0x09, 0x5d, 0xc0, 0x40, 0x03, 0x55, 0xcc, 0x23, 0x3f, 0xde, 0x74, - 0x37, 0x81, 0x18, 0x15, 0xb3, 0xc1, 0x52, 0x4a, 0xae, 0x80, 0xfd, - 0x4e, 0x68, 0x10, 0xcf, 0x53, 0x1c, 0xf1, 0x1d, 0x20, 0xe3 }; +static const uint8_t chiptest_e4836c3b50dd_MAC_KcA_62[] = { 0x3e, 0x1b, 0xab, 0x1b, 0x88, 0xa9, 0x55, 0x87, 0x91, 0x2c, 0x2d, + 0x4a, 0xcb, 0xde, 0xaa, 0x5f, 0xcf, 0xe9, 0xda, 0xf1, 0x89, 0x3e, + 0xbe, 0xb5, 0x2d, 0x07, 0xe9, 0xf8, 0xe5, 0x4b, 0x85, 0x3d }; +static const uint8_t chiptest_e4836c3b50dd_MAC_KcB_63[] = { 0xaf, 0x83, 0xd2, 0xd0, 0x03, 0xf9, 0x42, 0x5c, 0x6a, 0x5c, 0xe1, + 0x52, 0x46, 0x10, 0x74, 0x5e, 0xb6, 0xb9, 0x4f, 0x0e, 0x62, 0xc4, + 0xf4, 0x2a, 0x4b, 0x16, 0x39, 0xd8, 0x34, 0x74, 0x0b, 0x67 }; static const struct spake2p_rfc_tv chiptest_e4836c3b50dd_test_vector_64 = { .context = reinterpret_cast("SPAKE2+-P256-SHA256-HKDF draft-01"), .context_len = 33, diff --git a/src/darwin/CHIPTool/CHIPTool/View Controllers/OnOffCluster/OnOffViewController.m b/src/darwin/CHIPTool/CHIPTool/View Controllers/OnOffCluster/OnOffViewController.m index 567f928f3314af..ec2ea26868d527 100644 --- a/src/darwin/CHIPTool/CHIPTool/View Controllers/OnOffCluster/OnOffViewController.m +++ b/src/darwin/CHIPTool/CHIPTool/View Controllers/OnOffCluster/OnOffViewController.m @@ -143,7 +143,7 @@ - (IBAction)onButtonTapped:(id)sender CHIPDeviceCallback completionHandler = ^(NSError * error) { NSLog(@"Status: On command completed with error %@", [error description]); }; - [self.onOff lightOn:completionHandler]; + [self.onOff on:completionHandler]; } - (IBAction)offButtonTapped:(id)sender @@ -151,7 +151,7 @@ - (IBAction)offButtonTapped:(id)sender CHIPDeviceCallback completionHandler = ^(NSError * error) { NSLog(@"Status: Off command completed with error %@", [error description]); }; - [self.onOff lightOff:completionHandler]; + [self.onOff off:completionHandler]; } - (IBAction)toggleButtonTapped:(id)sender @@ -159,7 +159,7 @@ - (IBAction)toggleButtonTapped:(id)sender CHIPDeviceCallback completionHandler = ^(NSError * error) { NSLog(@"Status: Toggle command completed with error %@", [error description]); }; - [self.onOff toggleLight:completionHandler]; + [self.onOff toggle:completionHandler]; } // MARK: CHIPDeviceControllerDelegate diff --git a/src/darwin/Framework/CHIP.xcodeproj/project.pbxproj b/src/darwin/Framework/CHIP.xcodeproj/project.pbxproj index 3d1763ec80c6cb..7e6b0ce0bae85d 100644 --- a/src/darwin/Framework/CHIP.xcodeproj/project.pbxproj +++ b/src/darwin/Framework/CHIP.xcodeproj/project.pbxproj @@ -7,6 +7,8 @@ objects = { /* Begin PBXBuildFile section */ + 1EF8B75425782A9E009AA59C /* CHIPClustersObjc.h in Headers */ = {isa = PBXBuildFile; fileRef = 1EF8B75325782A9E009AA59C /* CHIPClustersObjc.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1EF8B75625782AAC009AA59C /* CHIPClustersObjc.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1EF8B75525782AAC009AA59C /* CHIPClustersObjc.mm */; }; 2C222AD0255C620600E446B9 /* CHIPDevice.h in Headers */ = {isa = PBXBuildFile; fileRef = 2C222ACE255C620600E446B9 /* CHIPDevice.h */; settings = {ATTRIBUTES = (Public, ); }; }; 2C222AD1255C620600E446B9 /* CHIPDevice.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2C222ACF255C620600E446B9 /* CHIPDevice.mm */; }; 2C222ADB255C74D100E446B9 /* CHIPDeviceStatusDelegateBridge.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2C222AD8255C74D100E446B9 /* CHIPDeviceStatusDelegateBridge.mm */; }; @@ -23,8 +25,6 @@ 2CB7163B252E8A7B0026E2BB /* CHIPDevicePairingDelegateBridge.h in Headers */ = {isa = PBXBuildFile; fileRef = 2CB71638252E8A7B0026E2BB /* CHIPDevicePairingDelegateBridge.h */; }; 2CB7163C252E8A7C0026E2BB /* CHIPDevicePairingDelegateBridge.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2CB71639252E8A7B0026E2BB /* CHIPDevicePairingDelegateBridge.mm */; }; 2CB7163F252F731E0026E2BB /* CHIPDevicePairingDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 2CB7163E252F731E0026E2BB /* CHIPDevicePairingDelegate.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 515C401C2486BF43004C4DB3 /* CHIPOnOff.mm in Sources */ = {isa = PBXBuildFile; fileRef = 515C401A2486BF43004C4DB3 /* CHIPOnOff.mm */; }; - 515C401D2486BF43004C4DB3 /* CHIPOnOff.h in Headers */ = {isa = PBXBuildFile; fileRef = 515C401B2486BF43004C4DB3 /* CHIPOnOff.h */; settings = {ATTRIBUTES = (Public, ); }; }; 991DC0842475F45400C13860 /* CHIPDeviceController.h in Headers */ = {isa = PBXBuildFile; fileRef = 991DC0822475F45400C13860 /* CHIPDeviceController.h */; settings = {ATTRIBUTES = (Public, ); }; }; 991DC0892475F47D00C13860 /* CHIPDeviceController.mm in Sources */ = {isa = PBXBuildFile; fileRef = 991DC0872475F47D00C13860 /* CHIPDeviceController.mm */; }; 991DC08B247704DC00C13860 /* CHIPLogging.h in Headers */ = {isa = PBXBuildFile; fileRef = 991DC08A247704DC00C13860 /* CHIPLogging.h */; }; @@ -53,6 +53,8 @@ /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ + 1EF8B75325782A9E009AA59C /* CHIPClustersObjc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CHIPClustersObjc.h; sourceTree = ""; }; + 1EF8B75525782AAC009AA59C /* CHIPClustersObjc.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = CHIPClustersObjc.mm; sourceTree = ""; }; 2C222ACE255C620600E446B9 /* CHIPDevice.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CHIPDevice.h; sourceTree = ""; }; 2C222ACF255C620600E446B9 /* CHIPDevice.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = CHIPDevice.mm; sourceTree = ""; }; 2C222AD8255C74D100E446B9 /* CHIPDeviceStatusDelegateBridge.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = CHIPDeviceStatusDelegateBridge.mm; sourceTree = ""; }; @@ -69,8 +71,6 @@ 2CB71638252E8A7B0026E2BB /* CHIPDevicePairingDelegateBridge.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CHIPDevicePairingDelegateBridge.h; sourceTree = ""; }; 2CB71639252E8A7B0026E2BB /* CHIPDevicePairingDelegateBridge.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = CHIPDevicePairingDelegateBridge.mm; sourceTree = ""; }; 2CB7163E252F731E0026E2BB /* CHIPDevicePairingDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CHIPDevicePairingDelegate.h; sourceTree = ""; }; - 515C401A2486BF43004C4DB3 /* CHIPOnOff.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = CHIPOnOff.mm; sourceTree = ""; }; - 515C401B2486BF43004C4DB3 /* CHIPOnOff.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CHIPOnOff.h; sourceTree = ""; }; 991DC0822475F45400C13860 /* CHIPDeviceController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CHIPDeviceController.h; sourceTree = ""; }; 991DC0872475F47D00C13860 /* CHIPDeviceController.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = CHIPDeviceController.mm; sourceTree = ""; }; 991DC08A247704DC00C13860 /* CHIPLogging.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CHIPLogging.h; sourceTree = ""; }; @@ -136,6 +136,8 @@ B202528F2459E34F00F97062 /* CHIP */ = { isa = PBXGroup; children = ( + 1EF8B75525782AAC009AA59C /* CHIPClustersObjc.mm */, + 1EF8B75325782A9E009AA59C /* CHIPClustersObjc.h */, 2C222AEF25646BB100E446B9 /* CHIPCallbackBridge.h */, 2C222AEE25646BB100E446B9 /* CHIPCallbackBridge.mm */, 2C222AEC25634E5300E446B9 /* CHIPDeviceCallback.h */, @@ -163,8 +165,6 @@ B2E0D7B0245B0B5C003C5B48 /* CHIPSetupPayload.mm */, 991DC0822475F45400C13860 /* CHIPDeviceController.h */, 991DC0872475F47D00C13860 /* CHIPDeviceController.mm */, - 515C401B2486BF43004C4DB3 /* CHIPOnOff.h */, - 515C401A2486BF43004C4DB3 /* CHIPOnOff.mm */, B20252912459E34F00F97062 /* Info.plist */, ); path = CHIP; @@ -209,8 +209,8 @@ B2E0D7B5245B0B5C003C5B48 /* CHIPQRCodeSetupPayloadParser.h in Headers */, 2C222AF125646BB100E446B9 /* CHIPCallbackBridge.h in Headers */, 2C8C8FC0253E0C2100797F05 /* CHIPPersistentStorageDelegateBridge.h in Headers */, + 1EF8B75425782A9E009AA59C /* CHIPClustersObjc.h in Headers */, 2C222ADF255C811800E446B9 /* CHIPDevice_Internal.h in Headers */, - 515C401D2486BF43004C4DB3 /* CHIPOnOff.h in Headers */, 991DC08B247704DC00C13860 /* CHIPLogging.h in Headers */, B2E0D7B4245B0B5C003C5B48 /* CHIPError.h in Headers */, ); @@ -338,10 +338,10 @@ files = ( 2C8C8FC2253E0C2100797F05 /* CHIPPersistentStorageDelegateBridge.mm in Sources */, 2CB7163C252E8A7C0026E2BB /* CHIPDevicePairingDelegateBridge.mm in Sources */, - 515C401C2486BF43004C4DB3 /* CHIPOnOff.mm in Sources */, 2C222AD1255C620600E446B9 /* CHIPDevice.mm in Sources */, 991DC0892475F47D00C13860 /* CHIPDeviceController.mm in Sources */, 2C222AF025646BB100E446B9 /* CHIPCallbackBridge.mm in Sources */, + 1EF8B75625782AAC009AA59C /* CHIPClustersObjc.mm in Sources */, B2E0D7B7245B0B5C003C5B48 /* CHIPQRCodeSetupPayloadParser.mm in Sources */, B2E0D7B3245B0B5C003C5B48 /* CHIPError.mm in Sources */, 2C222ADB255C74D100E446B9 /* CHIPDeviceStatusDelegateBridge.mm in Sources */, diff --git a/src/darwin/Framework/CHIP/CHIP.h b/src/darwin/Framework/CHIP/CHIP.h index be8dbe756a05c5..3a8126a8210c33 100644 --- a/src/darwin/Framework/CHIP/CHIP.h +++ b/src/darwin/Framework/CHIP/CHIP.h @@ -16,13 +16,13 @@ */ // pull together CHIP headers +#import #import #import #import #import #import #import -#import #import #import #import diff --git a/src/darwin/Framework/CHIP/CHIPClustersObjc.h b/src/darwin/Framework/CHIP/CHIPClustersObjc.h new file mode 100644 index 00000000000000..b3e9fd5831f379 --- /dev/null +++ b/src/darwin/Framework/CHIP/CHIPClustersObjc.h @@ -0,0 +1,504 @@ +/* + * + * 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. + */ + +#ifndef CHIP_CLUSTERS_H +#define CHIP_CLUSTERS_H + +#import +#import + +@class CHIPDevice; + +NS_ASSUME_NONNULL_BEGIN + +@interface CHIPBarrierControl : NSObject + +- (nullable instancetype)initWithDevice:(CHIPDevice *)device endpoint:(uint8_t)endpoint queue:(dispatch_queue_t)queue; +- (BOOL)barrierControlGoToPercent:(CHIPDeviceCallback)onCompletion percentOpen:(uint8_t)percentOpen; +- (BOOL)barrierControlStop:(CHIPDeviceCallback)onCompletion; + +- (BOOL)readAttributeBarrierMovingState:(CHIPDeviceCallback)onCompletion; +- (BOOL)readAttributeBarrierSafetyStatus:(CHIPDeviceCallback)onCompletion; +- (BOOL)readAttributeBarrierCapabilities:(CHIPDeviceCallback)onCompletion; +- (BOOL)readAttributeBarrierPosition:(CHIPDeviceCallback)onCompletion; +- (BOOL)readAttributeClusterRevision:(CHIPDeviceCallback)onCompletion; + +- (instancetype)init NS_UNAVAILABLE; ++ (instancetype)new NS_UNAVAILABLE; + +@end + +NS_ASSUME_NONNULL_END + +NS_ASSUME_NONNULL_BEGIN + +@interface CHIPBasic : NSObject + +- (nullable instancetype)initWithDevice:(CHIPDevice *)device endpoint:(uint8_t)endpoint queue:(dispatch_queue_t)queue; +- (BOOL)mfgSpecificPing:(CHIPDeviceCallback)onCompletion; +- (BOOL)resetToFactoryDefaults:(CHIPDeviceCallback)onCompletion; + +- (BOOL)readAttributeZclVersion:(CHIPDeviceCallback)onCompletion; +- (BOOL)readAttributePowerSource:(CHIPDeviceCallback)onCompletion; +- (BOOL)readAttributeClusterRevision:(CHIPDeviceCallback)onCompletion; + +- (instancetype)init NS_UNAVAILABLE; ++ (instancetype)new NS_UNAVAILABLE; + +@end + +NS_ASSUME_NONNULL_END + +NS_ASSUME_NONNULL_BEGIN + +@interface CHIPColorControl : NSObject + +- (nullable instancetype)initWithDevice:(CHIPDevice *)device endpoint:(uint8_t)endpoint queue:(dispatch_queue_t)queue; +- (BOOL)moveColor:(CHIPDeviceCallback)onCompletion + rateX:(int16_t)rateX + rateY:(int16_t)rateY + optionsMask:(uint8_t)optionsMask + optionsOverride:(uint8_t)optionsOverride; +- (BOOL)moveColorTemperature:(CHIPDeviceCallback)onCompletion + moveMode:(uint8_t)moveMode + rate:(uint16_t)rate + colorTemperatureMinimum:(uint16_t)colorTemperatureMinimum + colorTemperatureMaximum:(uint16_t)colorTemperatureMaximum + optionsMask:(uint8_t)optionsMask + optionsOverride:(uint8_t)optionsOverride; +- (BOOL)moveHue:(CHIPDeviceCallback)onCompletion + moveMode:(uint8_t)moveMode + rate:(uint8_t)rate + optionsMask:(uint8_t)optionsMask + optionsOverride:(uint8_t)optionsOverride; +- (BOOL)moveSaturation:(CHIPDeviceCallback)onCompletion + moveMode:(uint8_t)moveMode + rate:(uint8_t)rate + optionsMask:(uint8_t)optionsMask + optionsOverride:(uint8_t)optionsOverride; +- (BOOL)moveToColor:(CHIPDeviceCallback)onCompletion + colorX:(uint16_t)colorX + colorY:(uint16_t)colorY + transitionTime:(uint16_t)transitionTime + optionsMask:(uint8_t)optionsMask + optionsOverride:(uint8_t)optionsOverride; +- (BOOL)moveToColorTemperature:(CHIPDeviceCallback)onCompletion + colorTemperature:(uint16_t)colorTemperature + transitionTime:(uint16_t)transitionTime + optionsMask:(uint8_t)optionsMask + optionsOverride:(uint8_t)optionsOverride; +- (BOOL)moveToHue:(CHIPDeviceCallback)onCompletion + hue:(uint8_t)hue + direction:(uint8_t)direction + transitionTime:(uint16_t)transitionTime + optionsMask:(uint8_t)optionsMask + optionsOverride:(uint8_t)optionsOverride; +- (BOOL)moveToHueAndSaturation:(CHIPDeviceCallback)onCompletion + hue:(uint8_t)hue + saturation:(uint8_t)saturation + transitionTime:(uint16_t)transitionTime + optionsMask:(uint8_t)optionsMask + optionsOverride:(uint8_t)optionsOverride; +- (BOOL)moveToSaturation:(CHIPDeviceCallback)onCompletion + saturation:(uint8_t)saturation + transitionTime:(uint16_t)transitionTime + optionsMask:(uint8_t)optionsMask + optionsOverride:(uint8_t)optionsOverride; +- (BOOL)stepColor:(CHIPDeviceCallback)onCompletion + stepX:(int16_t)stepX + stepY:(int16_t)stepY + transitionTime:(uint16_t)transitionTime + optionsMask:(uint8_t)optionsMask + optionsOverride:(uint8_t)optionsOverride; +- (BOOL)stepColorTemperature:(CHIPDeviceCallback)onCompletion + stepMode:(uint8_t)stepMode + stepSize:(uint16_t)stepSize + transitionTime:(uint16_t)transitionTime + colorTemperatureMinimum:(uint16_t)colorTemperatureMinimum + colorTemperatureMaximum:(uint16_t)colorTemperatureMaximum + optionsMask:(uint8_t)optionsMask + optionsOverride:(uint8_t)optionsOverride; +- (BOOL)stepHue:(CHIPDeviceCallback)onCompletion + stepMode:(uint8_t)stepMode + stepSize:(uint8_t)stepSize + transitionTime:(uint8_t)transitionTime + optionsMask:(uint8_t)optionsMask + optionsOverride:(uint8_t)optionsOverride; +- (BOOL)stepSaturation:(CHIPDeviceCallback)onCompletion + stepMode:(uint8_t)stepMode + stepSize:(uint8_t)stepSize + transitionTime:(uint8_t)transitionTime + optionsMask:(uint8_t)optionsMask + optionsOverride:(uint8_t)optionsOverride; +- (BOOL)stopMoveStep:(CHIPDeviceCallback)onCompletion optionsMask:(uint8_t)optionsMask optionsOverride:(uint8_t)optionsOverride; + +- (BOOL)readAttributeCurrentHue:(CHIPDeviceCallback)onCompletion; +- (BOOL)reportAttributeCurrentHue:(CHIPDeviceCallback)onCompletion + onChange:(CHIPDeviceCallback)onChange + minInterval:(uint16_t)minInterval + maxInterval:(uint16_t)maxInterval + change:(uint8_t)change; +- (BOOL)readAttributeCurrentSaturation:(CHIPDeviceCallback)onCompletion; +- (BOOL)reportAttributeCurrentSaturation:(CHIPDeviceCallback)onCompletion + onChange:(CHIPDeviceCallback)onChange + minInterval:(uint16_t)minInterval + maxInterval:(uint16_t)maxInterval + change:(uint8_t)change; +- (BOOL)readAttributeRemainingTime:(CHIPDeviceCallback)onCompletion; +- (BOOL)readAttributeCurrentX:(CHIPDeviceCallback)onCompletion; +- (BOOL)reportAttributeCurrentX:(CHIPDeviceCallback)onCompletion + onChange:(CHIPDeviceCallback)onChange + minInterval:(uint16_t)minInterval + maxInterval:(uint16_t)maxInterval + change:(uint16_t)change; +- (BOOL)readAttributeCurrentY:(CHIPDeviceCallback)onCompletion; +- (BOOL)reportAttributeCurrentY:(CHIPDeviceCallback)onCompletion + onChange:(CHIPDeviceCallback)onChange + minInterval:(uint16_t)minInterval + maxInterval:(uint16_t)maxInterval + change:(uint16_t)change; +- (BOOL)readAttributeDriftCompensation:(CHIPDeviceCallback)onCompletion; +- (BOOL)readAttributeCompensationText:(CHIPDeviceCallback)onCompletion; +- (BOOL)readAttributeColorTemperature:(CHIPDeviceCallback)onCompletion; +- (BOOL)reportAttributeColorTemperature:(CHIPDeviceCallback)onCompletion + onChange:(CHIPDeviceCallback)onChange + minInterval:(uint16_t)minInterval + maxInterval:(uint16_t)maxInterval + change:(uint16_t)change; +- (BOOL)readAttributeColorMode:(CHIPDeviceCallback)onCompletion; +- (BOOL)readAttributeColorControlOptions:(CHIPDeviceCallback)onCompletion; +- (BOOL)writeAttributeColorControlOptions:(CHIPDeviceCallback)onCompletion value:(uint8_t)value; +- (BOOL)readAttributeNumberOfPrimaries:(CHIPDeviceCallback)onCompletion; +- (BOOL)readAttributePrimary1X:(CHIPDeviceCallback)onCompletion; +- (BOOL)readAttributePrimary1Y:(CHIPDeviceCallback)onCompletion; +- (BOOL)readAttributePrimary1Intensity:(CHIPDeviceCallback)onCompletion; +- (BOOL)readAttributePrimary2X:(CHIPDeviceCallback)onCompletion; +- (BOOL)readAttributePrimary2Y:(CHIPDeviceCallback)onCompletion; +- (BOOL)readAttributePrimary2Intensity:(CHIPDeviceCallback)onCompletion; +- (BOOL)readAttributePrimary3X:(CHIPDeviceCallback)onCompletion; +- (BOOL)readAttributePrimary3Y:(CHIPDeviceCallback)onCompletion; +- (BOOL)readAttributePrimary3Intensity:(CHIPDeviceCallback)onCompletion; +- (BOOL)readAttributePrimary4X:(CHIPDeviceCallback)onCompletion; +- (BOOL)readAttributePrimary4Y:(CHIPDeviceCallback)onCompletion; +- (BOOL)readAttributePrimary4Intensity:(CHIPDeviceCallback)onCompletion; +- (BOOL)readAttributePrimary5X:(CHIPDeviceCallback)onCompletion; +- (BOOL)readAttributePrimary5Y:(CHIPDeviceCallback)onCompletion; +- (BOOL)readAttributePrimary5Intensity:(CHIPDeviceCallback)onCompletion; +- (BOOL)readAttributePrimary6X:(CHIPDeviceCallback)onCompletion; +- (BOOL)readAttributePrimary6Y:(CHIPDeviceCallback)onCompletion; +- (BOOL)readAttributePrimary6Intensity:(CHIPDeviceCallback)onCompletion; +- (BOOL)readAttributeWhitePointX:(CHIPDeviceCallback)onCompletion; +- (BOOL)writeAttributeWhitePointX:(CHIPDeviceCallback)onCompletion value:(uint16_t)value; +- (BOOL)readAttributeWhitePointY:(CHIPDeviceCallback)onCompletion; +- (BOOL)writeAttributeWhitePointY:(CHIPDeviceCallback)onCompletion value:(uint16_t)value; +- (BOOL)readAttributeColorPointRX:(CHIPDeviceCallback)onCompletion; +- (BOOL)writeAttributeColorPointRX:(CHIPDeviceCallback)onCompletion value:(uint16_t)value; +- (BOOL)readAttributeColorPointRY:(CHIPDeviceCallback)onCompletion; +- (BOOL)writeAttributeColorPointRY:(CHIPDeviceCallback)onCompletion value:(uint16_t)value; +- (BOOL)readAttributeColorPointRIntensity:(CHIPDeviceCallback)onCompletion; +- (BOOL)writeAttributeColorPointRIntensity:(CHIPDeviceCallback)onCompletion value:(uint8_t)value; +- (BOOL)readAttributeColorPointGX:(CHIPDeviceCallback)onCompletion; +- (BOOL)writeAttributeColorPointGX:(CHIPDeviceCallback)onCompletion value:(uint16_t)value; +- (BOOL)readAttributeColorPointGY:(CHIPDeviceCallback)onCompletion; +- (BOOL)writeAttributeColorPointGY:(CHIPDeviceCallback)onCompletion value:(uint16_t)value; +- (BOOL)readAttributeColorPointGIntensity:(CHIPDeviceCallback)onCompletion; +- (BOOL)writeAttributeColorPointGIntensity:(CHIPDeviceCallback)onCompletion value:(uint8_t)value; +- (BOOL)readAttributeColorPointBX:(CHIPDeviceCallback)onCompletion; +- (BOOL)writeAttributeColorPointBX:(CHIPDeviceCallback)onCompletion value:(uint16_t)value; +- (BOOL)readAttributeColorPointBY:(CHIPDeviceCallback)onCompletion; +- (BOOL)writeAttributeColorPointBY:(CHIPDeviceCallback)onCompletion value:(uint16_t)value; +- (BOOL)readAttributeColorPointBIntensity:(CHIPDeviceCallback)onCompletion; +- (BOOL)writeAttributeColorPointBIntensity:(CHIPDeviceCallback)onCompletion value:(uint8_t)value; +- (BOOL)readAttributeEnhancedCurrentHue:(CHIPDeviceCallback)onCompletion; +- (BOOL)readAttributeEnhancedColorMode:(CHIPDeviceCallback)onCompletion; +- (BOOL)readAttributeColorLoopActive:(CHIPDeviceCallback)onCompletion; +- (BOOL)readAttributeColorLoopDirection:(CHIPDeviceCallback)onCompletion; +- (BOOL)readAttributeColorLoopTime:(CHIPDeviceCallback)onCompletion; +- (BOOL)readAttributeColorCapabilities:(CHIPDeviceCallback)onCompletion; +- (BOOL)readAttributeColorTempPhysicalMin:(CHIPDeviceCallback)onCompletion; +- (BOOL)readAttributeColorTempPhysicalMax:(CHIPDeviceCallback)onCompletion; +- (BOOL)readAttributeCoupleColorTempToLevelMinMireds:(CHIPDeviceCallback)onCompletion; +- (BOOL)readAttributeStartUpColorTemperatureMireds:(CHIPDeviceCallback)onCompletion; +- (BOOL)writeAttributeStartUpColorTemperatureMireds:(CHIPDeviceCallback)onCompletion value:(uint16_t)value; +- (BOOL)readAttributeClusterRevision:(CHIPDeviceCallback)onCompletion; + +- (instancetype)init NS_UNAVAILABLE; ++ (instancetype)new NS_UNAVAILABLE; + +@end + +NS_ASSUME_NONNULL_END + +NS_ASSUME_NONNULL_BEGIN + +@interface CHIPDoorLock : NSObject + +- (nullable instancetype)initWithDevice:(CHIPDevice *)device endpoint:(uint8_t)endpoint queue:(dispatch_queue_t)queue; +- (BOOL)clearAllPins:(CHIPDeviceCallback)onCompletion; +- (BOOL)clearAllRfids:(CHIPDeviceCallback)onCompletion; +- (BOOL)clearHolidaySchedule:(CHIPDeviceCallback)onCompletion scheduleId:(uint8_t)scheduleId; +- (BOOL)clearPin:(CHIPDeviceCallback)onCompletion userId:(uint16_t)userId; +- (BOOL)clearRfid:(CHIPDeviceCallback)onCompletion userId:(uint16_t)userId; +- (BOOL)clearWeekdaySchedule:(CHIPDeviceCallback)onCompletion scheduleId:(uint8_t)scheduleId userId:(uint16_t)userId; +- (BOOL)clearYeardaySchedule:(CHIPDeviceCallback)onCompletion scheduleId:(uint8_t)scheduleId userId:(uint16_t)userId; +- (BOOL)getHolidaySchedule:(CHIPDeviceCallback)onCompletion scheduleId:(uint8_t)scheduleId; +- (BOOL)getLogRecord:(CHIPDeviceCallback)onCompletion logIndex:(uint16_t)logIndex; +- (BOOL)getPin:(CHIPDeviceCallback)onCompletion userId:(uint16_t)userId; +- (BOOL)getRfid:(CHIPDeviceCallback)onCompletion userId:(uint16_t)userId; +- (BOOL)getUserType:(CHIPDeviceCallback)onCompletion userId:(uint16_t)userId; +- (BOOL)getWeekdaySchedule:(CHIPDeviceCallback)onCompletion scheduleId:(uint8_t)scheduleId userId:(uint16_t)userId; +- (BOOL)getYeardaySchedule:(CHIPDeviceCallback)onCompletion scheduleId:(uint8_t)scheduleId userId:(uint16_t)userId; +- (BOOL)lockDoor:(CHIPDeviceCallback)onCompletion pin:(char *)pin; +- (BOOL)setHolidaySchedule:(CHIPDeviceCallback)onCompletion + scheduleId:(uint8_t)scheduleId + localStartTime:(uint32_t)localStartTime + localEndTime:(uint32_t)localEndTime + operatingModeDuringHoliday:(uint8_t)operatingModeDuringHoliday; +- (BOOL)setPin:(CHIPDeviceCallback)onCompletion + userId:(uint16_t)userId + userStatus:(uint8_t)userStatus + userType:(uint8_t)userType + pin:(char *)pin; +- (BOOL)setRfid:(CHIPDeviceCallback)onCompletion + userId:(uint16_t)userId + userStatus:(uint8_t)userStatus + userType:(uint8_t)userType + id:(char *)id; +- (BOOL)setUserType:(CHIPDeviceCallback)onCompletion userId:(uint16_t)userId userType:(uint8_t)userType; +- (BOOL)setWeekdaySchedule:(CHIPDeviceCallback)onCompletion + scheduleId:(uint8_t)scheduleId + userId:(uint16_t)userId + daysMask:(uint8_t)daysMask + startHour:(uint8_t)startHour + startMinute:(uint8_t)startMinute + endHour:(uint8_t)endHour + endMinute:(uint8_t)endMinute; +- (BOOL)setYeardaySchedule:(CHIPDeviceCallback)onCompletion + scheduleId:(uint8_t)scheduleId + userId:(uint16_t)userId + localStartTime:(uint32_t)localStartTime + localEndTime:(uint32_t)localEndTime; +- (BOOL)unlockDoor:(CHIPDeviceCallback)onCompletion pin:(char *)pin; +- (BOOL)unlockWithTimeout:(CHIPDeviceCallback)onCompletion timeoutInSeconds:(uint16_t)timeoutInSeconds pin:(char *)pin; + +- (BOOL)readAttributeLockState:(CHIPDeviceCallback)onCompletion; +- (BOOL)reportAttributeLockState:(CHIPDeviceCallback)onCompletion + onChange:(CHIPDeviceCallback)onChange + minInterval:(uint16_t)minInterval + maxInterval:(uint16_t)maxInterval; +- (BOOL)readAttributeLockType:(CHIPDeviceCallback)onCompletion; +- (BOOL)readAttributeActuatorEnabled:(CHIPDeviceCallback)onCompletion; +- (BOOL)readAttributeClusterRevision:(CHIPDeviceCallback)onCompletion; + +- (instancetype)init NS_UNAVAILABLE; ++ (instancetype)new NS_UNAVAILABLE; + +@end + +NS_ASSUME_NONNULL_END + +NS_ASSUME_NONNULL_BEGIN + +@interface CHIPGroups : NSObject + +- (nullable instancetype)initWithDevice:(CHIPDevice *)device endpoint:(uint8_t)endpoint queue:(dispatch_queue_t)queue; +- (BOOL)addGroup:(CHIPDeviceCallback)onCompletion groupId:(uint16_t)groupId groupName:(char *)groupName; +- (BOOL)addGroupIfIdentifying:(CHIPDeviceCallback)onCompletion groupId:(uint16_t)groupId groupName:(char *)groupName; +- (BOOL)getGroupMembership:(CHIPDeviceCallback)onCompletion groupCount:(uint8_t)groupCount groupList:(uint16_t)groupList; +- (BOOL)removeAllGroups:(CHIPDeviceCallback)onCompletion; +- (BOOL)removeGroup:(CHIPDeviceCallback)onCompletion groupId:(uint16_t)groupId; +- (BOOL)viewGroup:(CHIPDeviceCallback)onCompletion groupId:(uint16_t)groupId; + +- (BOOL)readAttributeNameSupport:(CHIPDeviceCallback)onCompletion; +- (BOOL)readAttributeClusterRevision:(CHIPDeviceCallback)onCompletion; + +- (instancetype)init NS_UNAVAILABLE; ++ (instancetype)new NS_UNAVAILABLE; + +@end + +NS_ASSUME_NONNULL_END + +NS_ASSUME_NONNULL_BEGIN + +@interface CHIPIasZone : NSObject + +- (nullable instancetype)initWithDevice:(CHIPDevice *)device endpoint:(uint8_t)endpoint queue:(dispatch_queue_t)queue; + +- (BOOL)readAttributeZoneState:(CHIPDeviceCallback)onCompletion; +- (BOOL)readAttributeZoneType:(CHIPDeviceCallback)onCompletion; +- (BOOL)readAttributeZoneStatus:(CHIPDeviceCallback)onCompletion; +- (BOOL)readAttributeIasCieAddress:(CHIPDeviceCallback)onCompletion; +- (BOOL)writeAttributeIasCieAddress:(CHIPDeviceCallback)onCompletion value:(uint64_t)value; +- (BOOL)readAttributeZoneId:(CHIPDeviceCallback)onCompletion; +- (BOOL)readAttributeClusterRevision:(CHIPDeviceCallback)onCompletion; + +- (instancetype)init NS_UNAVAILABLE; ++ (instancetype)new NS_UNAVAILABLE; + +@end + +NS_ASSUME_NONNULL_END + +NS_ASSUME_NONNULL_BEGIN + +@interface CHIPIdentify : NSObject + +- (nullable instancetype)initWithDevice:(CHIPDevice *)device endpoint:(uint8_t)endpoint queue:(dispatch_queue_t)queue; +- (BOOL)identify:(CHIPDeviceCallback)onCompletion identifyTime:(uint16_t)identifyTime; +- (BOOL)identifyQuery:(CHIPDeviceCallback)onCompletion; + +- (BOOL)readAttributeIdentifyTime:(CHIPDeviceCallback)onCompletion; +- (BOOL)writeAttributeIdentifyTime:(CHIPDeviceCallback)onCompletion value:(uint16_t)value; +- (BOOL)readAttributeClusterRevision:(CHIPDeviceCallback)onCompletion; + +- (instancetype)init NS_UNAVAILABLE; ++ (instancetype)new NS_UNAVAILABLE; + +@end + +NS_ASSUME_NONNULL_END + +NS_ASSUME_NONNULL_BEGIN + +@interface CHIPLevelControl : NSObject + +- (nullable instancetype)initWithDevice:(CHIPDevice *)device endpoint:(uint8_t)endpoint queue:(dispatch_queue_t)queue; +- (BOOL)move:(CHIPDeviceCallback)onCompletion + moveMode:(uint8_t)moveMode + rate:(uint8_t)rate + optionMask:(uint8_t)optionMask + optionOverride:(uint8_t)optionOverride; +- (BOOL)moveToLevel:(CHIPDeviceCallback)onCompletion + level:(uint8_t)level + transitionTime:(uint16_t)transitionTime + optionMask:(uint8_t)optionMask + optionOverride:(uint8_t)optionOverride; +- (BOOL)moveToLevelWithOnOff:(CHIPDeviceCallback)onCompletion level:(uint8_t)level transitionTime:(uint16_t)transitionTime; +- (BOOL)moveWithOnOff:(CHIPDeviceCallback)onCompletion moveMode:(uint8_t)moveMode rate:(uint8_t)rate; +- (BOOL)step:(CHIPDeviceCallback)onCompletion + stepMode:(uint8_t)stepMode + stepSize:(uint8_t)stepSize + transitionTime:(uint16_t)transitionTime + optionMask:(uint8_t)optionMask + optionOverride:(uint8_t)optionOverride; +- (BOOL)stepWithOnOff:(CHIPDeviceCallback)onCompletion + stepMode:(uint8_t)stepMode + stepSize:(uint8_t)stepSize + transitionTime:(uint16_t)transitionTime; +- (BOOL)stop:(CHIPDeviceCallback)onCompletion optionMask:(uint8_t)optionMask optionOverride:(uint8_t)optionOverride; +- (BOOL)stopWithOnOff:(CHIPDeviceCallback)onCompletion; + +- (BOOL)readAttributeCurrentLevel:(CHIPDeviceCallback)onCompletion; +- (BOOL)reportAttributeCurrentLevel:(CHIPDeviceCallback)onCompletion + onChange:(CHIPDeviceCallback)onChange + minInterval:(uint16_t)minInterval + maxInterval:(uint16_t)maxInterval + change:(uint8_t)change; +- (BOOL)readAttributeClusterRevision:(CHIPDeviceCallback)onCompletion; + +- (instancetype)init NS_UNAVAILABLE; ++ (instancetype)new NS_UNAVAILABLE; + +@end + +NS_ASSUME_NONNULL_END + +NS_ASSUME_NONNULL_BEGIN + +@interface CHIPOnOff : NSObject + +- (nullable instancetype)initWithDevice:(CHIPDevice *)device endpoint:(uint8_t)endpoint queue:(dispatch_queue_t)queue; +- (BOOL)off:(CHIPDeviceCallback)onCompletion; +- (BOOL)on:(CHIPDeviceCallback)onCompletion; +- (BOOL)toggle:(CHIPDeviceCallback)onCompletion; + +- (BOOL)readAttributeOnOff:(CHIPDeviceCallback)onCompletion; +- (BOOL)reportAttributeOnOff:(CHIPDeviceCallback)onCompletion + onChange:(CHIPDeviceCallback)onChange + minInterval:(uint16_t)minInterval + maxInterval:(uint16_t)maxInterval; +- (BOOL)readAttributeClusterRevision:(CHIPDeviceCallback)onCompletion; + +- (instancetype)init NS_UNAVAILABLE; ++ (instancetype)new NS_UNAVAILABLE; + +@end + +NS_ASSUME_NONNULL_END + +NS_ASSUME_NONNULL_BEGIN + +@interface CHIPScenes : NSObject + +- (nullable instancetype)initWithDevice:(CHIPDevice *)device endpoint:(uint8_t)endpoint queue:(dispatch_queue_t)queue; +- (BOOL)addScene:(CHIPDeviceCallback)onCompletion + groupId:(uint16_t)groupId + sceneId:(uint8_t)sceneId + transitionTime:(uint16_t)transitionTime + sceneName:(char *)sceneName + clusterId:(uint16_t)clusterId + length:(uint8_t)length + value:(uint8_t)value; +- (BOOL)getSceneMembership:(CHIPDeviceCallback)onCompletion groupId:(uint16_t)groupId; +- (BOOL)recallScene:(CHIPDeviceCallback)onCompletion + groupId:(uint16_t)groupId + sceneId:(uint8_t)sceneId + transitionTime:(uint16_t)transitionTime; +- (BOOL)removeAllScenes:(CHIPDeviceCallback)onCompletion groupId:(uint16_t)groupId; +- (BOOL)removeScene:(CHIPDeviceCallback)onCompletion groupId:(uint16_t)groupId sceneId:(uint8_t)sceneId; +- (BOOL)storeScene:(CHIPDeviceCallback)onCompletion groupId:(uint16_t)groupId sceneId:(uint8_t)sceneId; +- (BOOL)viewScene:(CHIPDeviceCallback)onCompletion groupId:(uint16_t)groupId sceneId:(uint8_t)sceneId; + +- (BOOL)readAttributeSceneCount:(CHIPDeviceCallback)onCompletion; +- (BOOL)readAttributeCurrentScene:(CHIPDeviceCallback)onCompletion; +- (BOOL)readAttributeCurrentGroup:(CHIPDeviceCallback)onCompletion; +- (BOOL)readAttributeSceneValid:(CHIPDeviceCallback)onCompletion; +- (BOOL)readAttributeNameSupport:(CHIPDeviceCallback)onCompletion; +- (BOOL)readAttributeClusterRevision:(CHIPDeviceCallback)onCompletion; + +- (instancetype)init NS_UNAVAILABLE; ++ (instancetype)new NS_UNAVAILABLE; + +@end + +NS_ASSUME_NONNULL_END + +NS_ASSUME_NONNULL_BEGIN + +@interface CHIPTemperatureMeasurement : NSObject + +- (nullable instancetype)initWithDevice:(CHIPDevice *)device endpoint:(uint8_t)endpoint queue:(dispatch_queue_t)queue; + +- (BOOL)readAttributeMeasuredValue:(CHIPDeviceCallback)onCompletion; +- (BOOL)reportAttributeMeasuredValue:(CHIPDeviceCallback)onCompletion + onChange:(CHIPDeviceCallback)onChange + minInterval:(uint16_t)minInterval + maxInterval:(uint16_t)maxInterval + change:(int16_t)change; +- (BOOL)readAttributeMinMeasuredValue:(CHIPDeviceCallback)onCompletion; +- (BOOL)readAttributeMaxMeasuredValue:(CHIPDeviceCallback)onCompletion; +- (BOOL)readAttributeClusterRevision:(CHIPDeviceCallback)onCompletion; + +- (instancetype)init NS_UNAVAILABLE; ++ (instancetype)new NS_UNAVAILABLE; + +@end + +NS_ASSUME_NONNULL_END + +#endif /* CHIP_CLUSTERS_H */ diff --git a/src/darwin/Framework/CHIP/CHIPClustersObjc.mm b/src/darwin/Framework/CHIP/CHIPClustersObjc.mm new file mode 100644 index 00000000000000..fad2a2c056e051 --- /dev/null +++ b/src/darwin/Framework/CHIP/CHIPClustersObjc.mm @@ -0,0 +1,3299 @@ +/* + * + * Copyright (c) 2020 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "CHIPCallbackBridge.h" +#import "CHIPClustersObjc.h" +#import "CHIPDevice.h" +#import "CHIPDevice_Internal.h" + +#include + +@interface CHIPBarrierControl () + +@property (readonly) chip::Controller::BarrierControlCluster cppCluster; +@property (readonly, nonatomic) dispatch_queue_t callbackQueue; +@end + +@implementation CHIPBarrierControl + +- (instancetype)initWithDevice:(CHIPDevice *)device endpoint:(chip::EndpointId)endpoint queue:(dispatch_queue_t)queue +{ + CHIP_ERROR err = _cppCluster.Associate([device internalDevice], endpoint); + + if (err != CHIP_NO_ERROR) { + return nil; + } + + if (self = [super init]) { + _callbackQueue = queue; + } + return self; +} + +- (BOOL)barrierControlGoToPercent:(CHIPDeviceCallback)onCompletion percentOpen:(uint8_t)percentOpen +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.BarrierControlGoToPercent(callback, percentOpen); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} +- (BOOL)barrierControlStop:(CHIPDeviceCallback)onCompletion +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.BarrierControlStop(callback); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} + +- (BOOL)readAttributeBarrierMovingState:(CHIPDeviceCallback)onCompletion +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.ReadAttributeBarrierMovingState(callback); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} + +- (BOOL)readAttributeBarrierSafetyStatus:(CHIPDeviceCallback)onCompletion +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.ReadAttributeBarrierSafetyStatus(callback); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} + +- (BOOL)readAttributeBarrierCapabilities:(CHIPDeviceCallback)onCompletion +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.ReadAttributeBarrierCapabilities(callback); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} + +- (BOOL)readAttributeBarrierPosition:(CHIPDeviceCallback)onCompletion +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.ReadAttributeBarrierPosition(callback); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} + +- (BOOL)readAttributeClusterRevision:(CHIPDeviceCallback)onCompletion +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.ReadAttributeClusterRevision(callback); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} + +@end + +@interface CHIPBasic () + +@property (readonly) chip::Controller::BasicCluster cppCluster; +@property (readonly, nonatomic) dispatch_queue_t callbackQueue; +@end + +@implementation CHIPBasic + +- (instancetype)initWithDevice:(CHIPDevice *)device endpoint:(chip::EndpointId)endpoint queue:(dispatch_queue_t)queue +{ + CHIP_ERROR err = _cppCluster.Associate([device internalDevice], endpoint); + + if (err != CHIP_NO_ERROR) { + return nil; + } + + if (self = [super init]) { + _callbackQueue = queue; + } + return self; +} + +- (BOOL)mfgSpecificPing:(CHIPDeviceCallback)onCompletion +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.MfgSpecificPing(callback); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} +- (BOOL)resetToFactoryDefaults:(CHIPDeviceCallback)onCompletion +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.ResetToFactoryDefaults(callback); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} + +- (BOOL)readAttributeZclVersion:(CHIPDeviceCallback)onCompletion +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.ReadAttributeZclVersion(callback); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} + +- (BOOL)readAttributePowerSource:(CHIPDeviceCallback)onCompletion +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.ReadAttributePowerSource(callback); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} + +- (BOOL)readAttributeClusterRevision:(CHIPDeviceCallback)onCompletion +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.ReadAttributeClusterRevision(callback); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} + +@end + +@interface CHIPColorControl () + +@property (readonly) chip::Controller::ColorControlCluster cppCluster; +@property (readonly, nonatomic) dispatch_queue_t callbackQueue; +@end + +@implementation CHIPColorControl + +- (instancetype)initWithDevice:(CHIPDevice *)device endpoint:(chip::EndpointId)endpoint queue:(dispatch_queue_t)queue +{ + CHIP_ERROR err = _cppCluster.Associate([device internalDevice], endpoint); + + if (err != CHIP_NO_ERROR) { + return nil; + } + + if (self = [super init]) { + _callbackQueue = queue; + } + return self; +} + +- (BOOL)moveColor:(CHIPDeviceCallback)onCompletion + rateX:(int16_t)rateX + rateY:(int16_t)rateY + optionsMask:(uint8_t)optionsMask + optionsOverride:(uint8_t)optionsOverride +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.MoveColor(callback, rateX, rateY, optionsMask, optionsOverride); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} +- (BOOL)moveColorTemperature:(CHIPDeviceCallback)onCompletion + moveMode:(uint8_t)moveMode + rate:(uint16_t)rate + colorTemperatureMinimum:(uint16_t)colorTemperatureMinimum + colorTemperatureMaximum:(uint16_t)colorTemperatureMaximum + optionsMask:(uint8_t)optionsMask + optionsOverride:(uint8_t)optionsOverride +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.MoveColorTemperature( + callback, moveMode, rate, colorTemperatureMinimum, colorTemperatureMaximum, optionsMask, optionsOverride); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} +- (BOOL)moveHue:(CHIPDeviceCallback)onCompletion + moveMode:(uint8_t)moveMode + rate:(uint8_t)rate + optionsMask:(uint8_t)optionsMask + optionsOverride:(uint8_t)optionsOverride +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.MoveHue(callback, moveMode, rate, optionsMask, optionsOverride); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} +- (BOOL)moveSaturation:(CHIPDeviceCallback)onCompletion + moveMode:(uint8_t)moveMode + rate:(uint8_t)rate + optionsMask:(uint8_t)optionsMask + optionsOverride:(uint8_t)optionsOverride +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.MoveSaturation(callback, moveMode, rate, optionsMask, optionsOverride); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} +- (BOOL)moveToColor:(CHIPDeviceCallback)onCompletion + colorX:(uint16_t)colorX + colorY:(uint16_t)colorY + transitionTime:(uint16_t)transitionTime + optionsMask:(uint8_t)optionsMask + optionsOverride:(uint8_t)optionsOverride +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.MoveToColor(callback, colorX, colorY, transitionTime, optionsMask, optionsOverride); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} +- (BOOL)moveToColorTemperature:(CHIPDeviceCallback)onCompletion + colorTemperature:(uint16_t)colorTemperature + transitionTime:(uint16_t)transitionTime + optionsMask:(uint8_t)optionsMask + optionsOverride:(uint8_t)optionsOverride +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err + = self.cppCluster.MoveToColorTemperature(callback, colorTemperature, transitionTime, optionsMask, optionsOverride); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} +- (BOOL)moveToHue:(CHIPDeviceCallback)onCompletion + hue:(uint8_t)hue + direction:(uint8_t)direction + transitionTime:(uint16_t)transitionTime + optionsMask:(uint8_t)optionsMask + optionsOverride:(uint8_t)optionsOverride +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.MoveToHue(callback, hue, direction, transitionTime, optionsMask, optionsOverride); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} +- (BOOL)moveToHueAndSaturation:(CHIPDeviceCallback)onCompletion + hue:(uint8_t)hue + saturation:(uint8_t)saturation + transitionTime:(uint16_t)transitionTime + optionsMask:(uint8_t)optionsMask + optionsOverride:(uint8_t)optionsOverride +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err + = self.cppCluster.MoveToHueAndSaturation(callback, hue, saturation, transitionTime, optionsMask, optionsOverride); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} +- (BOOL)moveToSaturation:(CHIPDeviceCallback)onCompletion + saturation:(uint8_t)saturation + transitionTime:(uint16_t)transitionTime + optionsMask:(uint8_t)optionsMask + optionsOverride:(uint8_t)optionsOverride +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.MoveToSaturation(callback, saturation, transitionTime, optionsMask, optionsOverride); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} +- (BOOL)stepColor:(CHIPDeviceCallback)onCompletion + stepX:(int16_t)stepX + stepY:(int16_t)stepY + transitionTime:(uint16_t)transitionTime + optionsMask:(uint8_t)optionsMask + optionsOverride:(uint8_t)optionsOverride +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.StepColor(callback, stepX, stepY, transitionTime, optionsMask, optionsOverride); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} +- (BOOL)stepColorTemperature:(CHIPDeviceCallback)onCompletion + stepMode:(uint8_t)stepMode + stepSize:(uint16_t)stepSize + transitionTime:(uint16_t)transitionTime + colorTemperatureMinimum:(uint16_t)colorTemperatureMinimum + colorTemperatureMaximum:(uint16_t)colorTemperatureMaximum + optionsMask:(uint8_t)optionsMask + optionsOverride:(uint8_t)optionsOverride +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.StepColorTemperature(callback, stepMode, stepSize, transitionTime, colorTemperatureMinimum, + colorTemperatureMaximum, optionsMask, optionsOverride); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} +- (BOOL)stepHue:(CHIPDeviceCallback)onCompletion + stepMode:(uint8_t)stepMode + stepSize:(uint8_t)stepSize + transitionTime:(uint8_t)transitionTime + optionsMask:(uint8_t)optionsMask + optionsOverride:(uint8_t)optionsOverride +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.StepHue(callback, stepMode, stepSize, transitionTime, optionsMask, optionsOverride); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} +- (BOOL)stepSaturation:(CHIPDeviceCallback)onCompletion + stepMode:(uint8_t)stepMode + stepSize:(uint8_t)stepSize + transitionTime:(uint8_t)transitionTime + optionsMask:(uint8_t)optionsMask + optionsOverride:(uint8_t)optionsOverride +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.StepSaturation(callback, stepMode, stepSize, transitionTime, optionsMask, optionsOverride); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} +- (BOOL)stopMoveStep:(CHIPDeviceCallback)onCompletion optionsMask:(uint8_t)optionsMask optionsOverride:(uint8_t)optionsOverride +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.StopMoveStep(callback, optionsMask, optionsOverride); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} + +- (BOOL)readAttributeCurrentHue:(CHIPDeviceCallback)onCompletion +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.ReadAttributeCurrentHue(callback); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} + +- (BOOL)reportAttributeCurrentHue:(CHIPDeviceCallback)onCompletion + onChange:(CHIPDeviceCallback)onChange + minInterval:(uint16_t)minInterval + maxInterval:(uint16_t)maxInterval + change:(uint8_t)change +{ + CHIPCallbackBridge * completionCallback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!completionCallback) { + return NO; + } + + CHIPCallbackBridge * changeCallback = new CHIPCallbackBridge(onChange, _callbackQueue); + if (!changeCallback) { + return NO; + } + + CHIP_ERROR err + = self.cppCluster.ReportAttributeCurrentHue(completionCallback, changeCallback, minInterval, maxInterval, change); + if (err != CHIP_NO_ERROR) { + completionCallback->Cancel(); + changeCallback->Cancel(); + delete completionCallback; + delete changeCallback; + return NO; + } + return YES; +} + +- (BOOL)readAttributeCurrentSaturation:(CHIPDeviceCallback)onCompletion +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.ReadAttributeCurrentSaturation(callback); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} + +- (BOOL)reportAttributeCurrentSaturation:(CHIPDeviceCallback)onCompletion + onChange:(CHIPDeviceCallback)onChange + minInterval:(uint16_t)minInterval + maxInterval:(uint16_t)maxInterval + change:(uint8_t)change +{ + CHIPCallbackBridge * completionCallback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!completionCallback) { + return NO; + } + + CHIPCallbackBridge * changeCallback = new CHIPCallbackBridge(onChange, _callbackQueue); + if (!changeCallback) { + return NO; + } + + CHIP_ERROR err + = self.cppCluster.ReportAttributeCurrentSaturation(completionCallback, changeCallback, minInterval, maxInterval, change); + if (err != CHIP_NO_ERROR) { + completionCallback->Cancel(); + changeCallback->Cancel(); + delete completionCallback; + delete changeCallback; + return NO; + } + return YES; +} + +- (BOOL)readAttributeRemainingTime:(CHIPDeviceCallback)onCompletion +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.ReadAttributeRemainingTime(callback); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} + +- (BOOL)readAttributeCurrentX:(CHIPDeviceCallback)onCompletion +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.ReadAttributeCurrentX(callback); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} + +- (BOOL)reportAttributeCurrentX:(CHIPDeviceCallback)onCompletion + onChange:(CHIPDeviceCallback)onChange + minInterval:(uint16_t)minInterval + maxInterval:(uint16_t)maxInterval + change:(uint16_t)change +{ + CHIPCallbackBridge * completionCallback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!completionCallback) { + return NO; + } + + CHIPCallbackBridge * changeCallback = new CHIPCallbackBridge(onChange, _callbackQueue); + if (!changeCallback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.ReportAttributeCurrentX(completionCallback, changeCallback, minInterval, maxInterval, change); + if (err != CHIP_NO_ERROR) { + completionCallback->Cancel(); + changeCallback->Cancel(); + delete completionCallback; + delete changeCallback; + return NO; + } + return YES; +} + +- (BOOL)readAttributeCurrentY:(CHIPDeviceCallback)onCompletion +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.ReadAttributeCurrentY(callback); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} + +- (BOOL)reportAttributeCurrentY:(CHIPDeviceCallback)onCompletion + onChange:(CHIPDeviceCallback)onChange + minInterval:(uint16_t)minInterval + maxInterval:(uint16_t)maxInterval + change:(uint16_t)change +{ + CHIPCallbackBridge * completionCallback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!completionCallback) { + return NO; + } + + CHIPCallbackBridge * changeCallback = new CHIPCallbackBridge(onChange, _callbackQueue); + if (!changeCallback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.ReportAttributeCurrentY(completionCallback, changeCallback, minInterval, maxInterval, change); + if (err != CHIP_NO_ERROR) { + completionCallback->Cancel(); + changeCallback->Cancel(); + delete completionCallback; + delete changeCallback; + return NO; + } + return YES; +} + +- (BOOL)readAttributeDriftCompensation:(CHIPDeviceCallback)onCompletion +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.ReadAttributeDriftCompensation(callback); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} + +- (BOOL)readAttributeCompensationText:(CHIPDeviceCallback)onCompletion +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.ReadAttributeCompensationText(callback); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} + +- (BOOL)readAttributeColorTemperature:(CHIPDeviceCallback)onCompletion +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.ReadAttributeColorTemperature(callback); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} + +- (BOOL)reportAttributeColorTemperature:(CHIPDeviceCallback)onCompletion + onChange:(CHIPDeviceCallback)onChange + minInterval:(uint16_t)minInterval + maxInterval:(uint16_t)maxInterval + change:(uint16_t)change +{ + CHIPCallbackBridge * completionCallback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!completionCallback) { + return NO; + } + + CHIPCallbackBridge * changeCallback = new CHIPCallbackBridge(onChange, _callbackQueue); + if (!changeCallback) { + return NO; + } + + CHIP_ERROR err + = self.cppCluster.ReportAttributeColorTemperature(completionCallback, changeCallback, minInterval, maxInterval, change); + if (err != CHIP_NO_ERROR) { + completionCallback->Cancel(); + changeCallback->Cancel(); + delete completionCallback; + delete changeCallback; + return NO; + } + return YES; +} + +- (BOOL)readAttributeColorMode:(CHIPDeviceCallback)onCompletion +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.ReadAttributeColorMode(callback); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} + +- (BOOL)readAttributeColorControlOptions:(CHIPDeviceCallback)onCompletion +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.ReadAttributeColorControlOptions(callback); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} + +- (BOOL)writeAttributeColorControlOptions:(CHIPDeviceCallback)onCompletion value:(uint8_t)value +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.WriteAttributeColorControlOptions(callback, value); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} + +- (BOOL)readAttributeNumberOfPrimaries:(CHIPDeviceCallback)onCompletion +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.ReadAttributeNumberOfPrimaries(callback); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} + +- (BOOL)readAttributePrimary1X:(CHIPDeviceCallback)onCompletion +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.ReadAttributePrimary1X(callback); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} + +- (BOOL)readAttributePrimary1Y:(CHIPDeviceCallback)onCompletion +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.ReadAttributePrimary1Y(callback); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} + +- (BOOL)readAttributePrimary1Intensity:(CHIPDeviceCallback)onCompletion +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.ReadAttributePrimary1Intensity(callback); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} + +- (BOOL)readAttributePrimary2X:(CHIPDeviceCallback)onCompletion +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.ReadAttributePrimary2X(callback); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} + +- (BOOL)readAttributePrimary2Y:(CHIPDeviceCallback)onCompletion +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.ReadAttributePrimary2Y(callback); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} + +- (BOOL)readAttributePrimary2Intensity:(CHIPDeviceCallback)onCompletion +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.ReadAttributePrimary2Intensity(callback); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} + +- (BOOL)readAttributePrimary3X:(CHIPDeviceCallback)onCompletion +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.ReadAttributePrimary3X(callback); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} + +- (BOOL)readAttributePrimary3Y:(CHIPDeviceCallback)onCompletion +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.ReadAttributePrimary3Y(callback); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} + +- (BOOL)readAttributePrimary3Intensity:(CHIPDeviceCallback)onCompletion +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.ReadAttributePrimary3Intensity(callback); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} + +- (BOOL)readAttributePrimary4X:(CHIPDeviceCallback)onCompletion +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.ReadAttributePrimary4X(callback); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} + +- (BOOL)readAttributePrimary4Y:(CHIPDeviceCallback)onCompletion +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.ReadAttributePrimary4Y(callback); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} + +- (BOOL)readAttributePrimary4Intensity:(CHIPDeviceCallback)onCompletion +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.ReadAttributePrimary4Intensity(callback); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} + +- (BOOL)readAttributePrimary5X:(CHIPDeviceCallback)onCompletion +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.ReadAttributePrimary5X(callback); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} + +- (BOOL)readAttributePrimary5Y:(CHIPDeviceCallback)onCompletion +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.ReadAttributePrimary5Y(callback); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} + +- (BOOL)readAttributePrimary5Intensity:(CHIPDeviceCallback)onCompletion +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.ReadAttributePrimary5Intensity(callback); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} + +- (BOOL)readAttributePrimary6X:(CHIPDeviceCallback)onCompletion +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.ReadAttributePrimary6X(callback); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} + +- (BOOL)readAttributePrimary6Y:(CHIPDeviceCallback)onCompletion +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.ReadAttributePrimary6Y(callback); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} + +- (BOOL)readAttributePrimary6Intensity:(CHIPDeviceCallback)onCompletion +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.ReadAttributePrimary6Intensity(callback); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} + +- (BOOL)readAttributeWhitePointX:(CHIPDeviceCallback)onCompletion +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.ReadAttributeWhitePointX(callback); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} + +- (BOOL)writeAttributeWhitePointX:(CHIPDeviceCallback)onCompletion value:(uint16_t)value +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.WriteAttributeWhitePointX(callback, value); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} + +- (BOOL)readAttributeWhitePointY:(CHIPDeviceCallback)onCompletion +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.ReadAttributeWhitePointY(callback); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} + +- (BOOL)writeAttributeWhitePointY:(CHIPDeviceCallback)onCompletion value:(uint16_t)value +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.WriteAttributeWhitePointY(callback, value); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} + +- (BOOL)readAttributeColorPointRX:(CHIPDeviceCallback)onCompletion +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.ReadAttributeColorPointRX(callback); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} + +- (BOOL)writeAttributeColorPointRX:(CHIPDeviceCallback)onCompletion value:(uint16_t)value +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.WriteAttributeColorPointRX(callback, value); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} + +- (BOOL)readAttributeColorPointRY:(CHIPDeviceCallback)onCompletion +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.ReadAttributeColorPointRY(callback); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} + +- (BOOL)writeAttributeColorPointRY:(CHIPDeviceCallback)onCompletion value:(uint16_t)value +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.WriteAttributeColorPointRY(callback, value); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} + +- (BOOL)readAttributeColorPointRIntensity:(CHIPDeviceCallback)onCompletion +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.ReadAttributeColorPointRIntensity(callback); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} + +- (BOOL)writeAttributeColorPointRIntensity:(CHIPDeviceCallback)onCompletion value:(uint8_t)value +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.WriteAttributeColorPointRIntensity(callback, value); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} + +- (BOOL)readAttributeColorPointGX:(CHIPDeviceCallback)onCompletion +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.ReadAttributeColorPointGX(callback); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} + +- (BOOL)writeAttributeColorPointGX:(CHIPDeviceCallback)onCompletion value:(uint16_t)value +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.WriteAttributeColorPointGX(callback, value); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} + +- (BOOL)readAttributeColorPointGY:(CHIPDeviceCallback)onCompletion +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.ReadAttributeColorPointGY(callback); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} + +- (BOOL)writeAttributeColorPointGY:(CHIPDeviceCallback)onCompletion value:(uint16_t)value +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.WriteAttributeColorPointGY(callback, value); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} + +- (BOOL)readAttributeColorPointGIntensity:(CHIPDeviceCallback)onCompletion +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.ReadAttributeColorPointGIntensity(callback); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} + +- (BOOL)writeAttributeColorPointGIntensity:(CHIPDeviceCallback)onCompletion value:(uint8_t)value +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.WriteAttributeColorPointGIntensity(callback, value); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} + +- (BOOL)readAttributeColorPointBX:(CHIPDeviceCallback)onCompletion +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.ReadAttributeColorPointBX(callback); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} + +- (BOOL)writeAttributeColorPointBX:(CHIPDeviceCallback)onCompletion value:(uint16_t)value +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.WriteAttributeColorPointBX(callback, value); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} + +- (BOOL)readAttributeColorPointBY:(CHIPDeviceCallback)onCompletion +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.ReadAttributeColorPointBY(callback); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} + +- (BOOL)writeAttributeColorPointBY:(CHIPDeviceCallback)onCompletion value:(uint16_t)value +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.WriteAttributeColorPointBY(callback, value); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} + +- (BOOL)readAttributeColorPointBIntensity:(CHIPDeviceCallback)onCompletion +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.ReadAttributeColorPointBIntensity(callback); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} + +- (BOOL)writeAttributeColorPointBIntensity:(CHIPDeviceCallback)onCompletion value:(uint8_t)value +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.WriteAttributeColorPointBIntensity(callback, value); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} + +- (BOOL)readAttributeEnhancedCurrentHue:(CHIPDeviceCallback)onCompletion +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.ReadAttributeEnhancedCurrentHue(callback); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} + +- (BOOL)readAttributeEnhancedColorMode:(CHIPDeviceCallback)onCompletion +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.ReadAttributeEnhancedColorMode(callback); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} + +- (BOOL)readAttributeColorLoopActive:(CHIPDeviceCallback)onCompletion +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.ReadAttributeColorLoopActive(callback); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} + +- (BOOL)readAttributeColorLoopDirection:(CHIPDeviceCallback)onCompletion +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.ReadAttributeColorLoopDirection(callback); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} + +- (BOOL)readAttributeColorLoopTime:(CHIPDeviceCallback)onCompletion +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.ReadAttributeColorLoopTime(callback); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} + +- (BOOL)readAttributeColorCapabilities:(CHIPDeviceCallback)onCompletion +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.ReadAttributeColorCapabilities(callback); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} + +- (BOOL)readAttributeColorTempPhysicalMin:(CHIPDeviceCallback)onCompletion +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.ReadAttributeColorTempPhysicalMin(callback); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} + +- (BOOL)readAttributeColorTempPhysicalMax:(CHIPDeviceCallback)onCompletion +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.ReadAttributeColorTempPhysicalMax(callback); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} + +- (BOOL)readAttributeCoupleColorTempToLevelMinMireds:(CHIPDeviceCallback)onCompletion +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.ReadAttributeCoupleColorTempToLevelMinMireds(callback); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} + +- (BOOL)readAttributeStartUpColorTemperatureMireds:(CHIPDeviceCallback)onCompletion +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.ReadAttributeStartUpColorTemperatureMireds(callback); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} + +- (BOOL)writeAttributeStartUpColorTemperatureMireds:(CHIPDeviceCallback)onCompletion value:(uint16_t)value +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.WriteAttributeStartUpColorTemperatureMireds(callback, value); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} + +- (BOOL)readAttributeClusterRevision:(CHIPDeviceCallback)onCompletion +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.ReadAttributeClusterRevision(callback); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} + +@end + +@interface CHIPDoorLock () + +@property (readonly) chip::Controller::DoorLockCluster cppCluster; +@property (readonly, nonatomic) dispatch_queue_t callbackQueue; +@end + +@implementation CHIPDoorLock + +- (instancetype)initWithDevice:(CHIPDevice *)device endpoint:(chip::EndpointId)endpoint queue:(dispatch_queue_t)queue +{ + CHIP_ERROR err = _cppCluster.Associate([device internalDevice], endpoint); + + if (err != CHIP_NO_ERROR) { + return nil; + } + + if (self = [super init]) { + _callbackQueue = queue; + } + return self; +} + +- (BOOL)clearAllPins:(CHIPDeviceCallback)onCompletion +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.ClearAllPins(callback); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} +- (BOOL)clearAllRfids:(CHIPDeviceCallback)onCompletion +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.ClearAllRfids(callback); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} +- (BOOL)clearHolidaySchedule:(CHIPDeviceCallback)onCompletion scheduleId:(uint8_t)scheduleId +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.ClearHolidaySchedule(callback, scheduleId); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} +- (BOOL)clearPin:(CHIPDeviceCallback)onCompletion userId:(uint16_t)userId +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.ClearPin(callback, userId); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} +- (BOOL)clearRfid:(CHIPDeviceCallback)onCompletion userId:(uint16_t)userId +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.ClearRfid(callback, userId); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} +- (BOOL)clearWeekdaySchedule:(CHIPDeviceCallback)onCompletion scheduleId:(uint8_t)scheduleId userId:(uint16_t)userId +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.ClearWeekdaySchedule(callback, scheduleId, userId); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} +- (BOOL)clearYeardaySchedule:(CHIPDeviceCallback)onCompletion scheduleId:(uint8_t)scheduleId userId:(uint16_t)userId +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.ClearYeardaySchedule(callback, scheduleId, userId); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} +- (BOOL)getHolidaySchedule:(CHIPDeviceCallback)onCompletion scheduleId:(uint8_t)scheduleId +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.GetHolidaySchedule(callback, scheduleId); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} +- (BOOL)getLogRecord:(CHIPDeviceCallback)onCompletion logIndex:(uint16_t)logIndex +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.GetLogRecord(callback, logIndex); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} +- (BOOL)getPin:(CHIPDeviceCallback)onCompletion userId:(uint16_t)userId +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.GetPin(callback, userId); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} +- (BOOL)getRfid:(CHIPDeviceCallback)onCompletion userId:(uint16_t)userId +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.GetRfid(callback, userId); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} +- (BOOL)getUserType:(CHIPDeviceCallback)onCompletion userId:(uint16_t)userId +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.GetUserType(callback, userId); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} +- (BOOL)getWeekdaySchedule:(CHIPDeviceCallback)onCompletion scheduleId:(uint8_t)scheduleId userId:(uint16_t)userId +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.GetWeekdaySchedule(callback, scheduleId, userId); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} +- (BOOL)getYeardaySchedule:(CHIPDeviceCallback)onCompletion scheduleId:(uint8_t)scheduleId userId:(uint16_t)userId +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.GetYeardaySchedule(callback, scheduleId, userId); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} +- (BOOL)lockDoor:(CHIPDeviceCallback)onCompletion pin:(char *)pin +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.LockDoor(callback, pin); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} +- (BOOL)setHolidaySchedule:(CHIPDeviceCallback)onCompletion + scheduleId:(uint8_t)scheduleId + localStartTime:(uint32_t)localStartTime + localEndTime:(uint32_t)localEndTime + operatingModeDuringHoliday:(uint8_t)operatingModeDuringHoliday +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err + = self.cppCluster.SetHolidaySchedule(callback, scheduleId, localStartTime, localEndTime, operatingModeDuringHoliday); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} +- (BOOL)setPin:(CHIPDeviceCallback)onCompletion + userId:(uint16_t)userId + userStatus:(uint8_t)userStatus + userType:(uint8_t)userType + pin:(char *)pin +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.SetPin(callback, userId, userStatus, userType, pin); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} +- (BOOL)setRfid:(CHIPDeviceCallback)onCompletion + userId:(uint16_t)userId + userStatus:(uint8_t)userStatus + userType:(uint8_t)userType + id:(char *)id +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.SetRfid(callback, userId, userStatus, userType, id); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} +- (BOOL)setUserType:(CHIPDeviceCallback)onCompletion userId:(uint16_t)userId userType:(uint8_t)userType +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.SetUserType(callback, userId, userType); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} +- (BOOL)setWeekdaySchedule:(CHIPDeviceCallback)onCompletion + scheduleId:(uint8_t)scheduleId + userId:(uint16_t)userId + daysMask:(uint8_t)daysMask + startHour:(uint8_t)startHour + startMinute:(uint8_t)startMinute + endHour:(uint8_t)endHour + endMinute:(uint8_t)endMinute +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err + = self.cppCluster.SetWeekdaySchedule(callback, scheduleId, userId, daysMask, startHour, startMinute, endHour, endMinute); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} +- (BOOL)setYeardaySchedule:(CHIPDeviceCallback)onCompletion + scheduleId:(uint8_t)scheduleId + userId:(uint16_t)userId + localStartTime:(uint32_t)localStartTime + localEndTime:(uint32_t)localEndTime +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.SetYeardaySchedule(callback, scheduleId, userId, localStartTime, localEndTime); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} +- (BOOL)unlockDoor:(CHIPDeviceCallback)onCompletion pin:(char *)pin +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.UnlockDoor(callback, pin); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} +- (BOOL)unlockWithTimeout:(CHIPDeviceCallback)onCompletion timeoutInSeconds:(uint16_t)timeoutInSeconds pin:(char *)pin +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.UnlockWithTimeout(callback, timeoutInSeconds, pin); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} + +- (BOOL)readAttributeLockState:(CHIPDeviceCallback)onCompletion +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.ReadAttributeLockState(callback); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} + +- (BOOL)reportAttributeLockState:(CHIPDeviceCallback)onCompletion + onChange:(CHIPDeviceCallback)onChange + minInterval:(uint16_t)minInterval + maxInterval:(uint16_t)maxInterval +{ + CHIPCallbackBridge * completionCallback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!completionCallback) { + return NO; + } + + CHIPCallbackBridge * changeCallback = new CHIPCallbackBridge(onChange, _callbackQueue); + if (!changeCallback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.ReportAttributeLockState(completionCallback, changeCallback, minInterval, maxInterval); + if (err != CHIP_NO_ERROR) { + completionCallback->Cancel(); + changeCallback->Cancel(); + delete completionCallback; + delete changeCallback; + return NO; + } + return YES; +} + +- (BOOL)readAttributeLockType:(CHIPDeviceCallback)onCompletion +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.ReadAttributeLockType(callback); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} + +- (BOOL)readAttributeActuatorEnabled:(CHIPDeviceCallback)onCompletion +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.ReadAttributeActuatorEnabled(callback); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} + +- (BOOL)readAttributeClusterRevision:(CHIPDeviceCallback)onCompletion +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.ReadAttributeClusterRevision(callback); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} + +@end + +@interface CHIPGroups () + +@property (readonly) chip::Controller::GroupsCluster cppCluster; +@property (readonly, nonatomic) dispatch_queue_t callbackQueue; +@end + +@implementation CHIPGroups + +- (instancetype)initWithDevice:(CHIPDevice *)device endpoint:(chip::EndpointId)endpoint queue:(dispatch_queue_t)queue +{ + CHIP_ERROR err = _cppCluster.Associate([device internalDevice], endpoint); + + if (err != CHIP_NO_ERROR) { + return nil; + } + + if (self = [super init]) { + _callbackQueue = queue; + } + return self; +} + +- (BOOL)addGroup:(CHIPDeviceCallback)onCompletion groupId:(uint16_t)groupId groupName:(char *)groupName +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.AddGroup(callback, groupId, groupName); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} +- (BOOL)addGroupIfIdentifying:(CHIPDeviceCallback)onCompletion groupId:(uint16_t)groupId groupName:(char *)groupName +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.AddGroupIfIdentifying(callback, groupId, groupName); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} +- (BOOL)getGroupMembership:(CHIPDeviceCallback)onCompletion groupCount:(uint8_t)groupCount groupList:(uint16_t)groupList +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.GetGroupMembership(callback, groupCount, groupList); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} +- (BOOL)removeAllGroups:(CHIPDeviceCallback)onCompletion +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.RemoveAllGroups(callback); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} +- (BOOL)removeGroup:(CHIPDeviceCallback)onCompletion groupId:(uint16_t)groupId +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.RemoveGroup(callback, groupId); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} +- (BOOL)viewGroup:(CHIPDeviceCallback)onCompletion groupId:(uint16_t)groupId +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.ViewGroup(callback, groupId); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} + +- (BOOL)readAttributeNameSupport:(CHIPDeviceCallback)onCompletion +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.ReadAttributeNameSupport(callback); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} + +- (BOOL)readAttributeClusterRevision:(CHIPDeviceCallback)onCompletion +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.ReadAttributeClusterRevision(callback); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} + +@end + +@interface CHIPIasZone () + +@property (readonly) chip::Controller::IasZoneCluster cppCluster; +@property (readonly, nonatomic) dispatch_queue_t callbackQueue; +@end + +@implementation CHIPIasZone + +- (instancetype)initWithDevice:(CHIPDevice *)device endpoint:(chip::EndpointId)endpoint queue:(dispatch_queue_t)queue +{ + CHIP_ERROR err = _cppCluster.Associate([device internalDevice], endpoint); + + if (err != CHIP_NO_ERROR) { + return nil; + } + + if (self = [super init]) { + _callbackQueue = queue; + } + return self; +} + +- (BOOL)readAttributeZoneState:(CHIPDeviceCallback)onCompletion +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.ReadAttributeZoneState(callback); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} + +- (BOOL)readAttributeZoneType:(CHIPDeviceCallback)onCompletion +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.ReadAttributeZoneType(callback); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} + +- (BOOL)readAttributeZoneStatus:(CHIPDeviceCallback)onCompletion +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.ReadAttributeZoneStatus(callback); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} + +- (BOOL)readAttributeIasCieAddress:(CHIPDeviceCallback)onCompletion +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.ReadAttributeIasCieAddress(callback); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} + +- (BOOL)writeAttributeIasCieAddress:(CHIPDeviceCallback)onCompletion value:(uint64_t)value +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.WriteAttributeIasCieAddress(callback, value); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} + +- (BOOL)readAttributeZoneId:(CHIPDeviceCallback)onCompletion +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.ReadAttributeZoneId(callback); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} + +- (BOOL)readAttributeClusterRevision:(CHIPDeviceCallback)onCompletion +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.ReadAttributeClusterRevision(callback); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} + +@end + +@interface CHIPIdentify () + +@property (readonly) chip::Controller::IdentifyCluster cppCluster; +@property (readonly, nonatomic) dispatch_queue_t callbackQueue; +@end + +@implementation CHIPIdentify + +- (instancetype)initWithDevice:(CHIPDevice *)device endpoint:(chip::EndpointId)endpoint queue:(dispatch_queue_t)queue +{ + CHIP_ERROR err = _cppCluster.Associate([device internalDevice], endpoint); + + if (err != CHIP_NO_ERROR) { + return nil; + } + + if (self = [super init]) { + _callbackQueue = queue; + } + return self; +} + +- (BOOL)identify:(CHIPDeviceCallback)onCompletion identifyTime:(uint16_t)identifyTime +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.Identify(callback, identifyTime); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} +- (BOOL)identifyQuery:(CHIPDeviceCallback)onCompletion +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.IdentifyQuery(callback); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} + +- (BOOL)readAttributeIdentifyTime:(CHIPDeviceCallback)onCompletion +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.ReadAttributeIdentifyTime(callback); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} + +- (BOOL)writeAttributeIdentifyTime:(CHIPDeviceCallback)onCompletion value:(uint16_t)value +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.WriteAttributeIdentifyTime(callback, value); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} + +- (BOOL)readAttributeClusterRevision:(CHIPDeviceCallback)onCompletion +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.ReadAttributeClusterRevision(callback); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} + +@end + +@interface CHIPLevelControl () + +@property (readonly) chip::Controller::LevelControlCluster cppCluster; +@property (readonly, nonatomic) dispatch_queue_t callbackQueue; +@end + +@implementation CHIPLevelControl + +- (instancetype)initWithDevice:(CHIPDevice *)device endpoint:(chip::EndpointId)endpoint queue:(dispatch_queue_t)queue +{ + CHIP_ERROR err = _cppCluster.Associate([device internalDevice], endpoint); + + if (err != CHIP_NO_ERROR) { + return nil; + } + + if (self = [super init]) { + _callbackQueue = queue; + } + return self; +} + +- (BOOL)move:(CHIPDeviceCallback)onCompletion + moveMode:(uint8_t)moveMode + rate:(uint8_t)rate + optionMask:(uint8_t)optionMask + optionOverride:(uint8_t)optionOverride +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.Move(callback, moveMode, rate, optionMask, optionOverride); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} +- (BOOL)moveToLevel:(CHIPDeviceCallback)onCompletion + level:(uint8_t)level + transitionTime:(uint16_t)transitionTime + optionMask:(uint8_t)optionMask + optionOverride:(uint8_t)optionOverride +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.MoveToLevel(callback, level, transitionTime, optionMask, optionOverride); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} +- (BOOL)moveToLevelWithOnOff:(CHIPDeviceCallback)onCompletion level:(uint8_t)level transitionTime:(uint16_t)transitionTime +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.MoveToLevelWithOnOff(callback, level, transitionTime); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} +- (BOOL)moveWithOnOff:(CHIPDeviceCallback)onCompletion moveMode:(uint8_t)moveMode rate:(uint8_t)rate +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.MoveWithOnOff(callback, moveMode, rate); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} +- (BOOL)step:(CHIPDeviceCallback)onCompletion + stepMode:(uint8_t)stepMode + stepSize:(uint8_t)stepSize + transitionTime:(uint16_t)transitionTime + optionMask:(uint8_t)optionMask + optionOverride:(uint8_t)optionOverride +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.Step(callback, stepMode, stepSize, transitionTime, optionMask, optionOverride); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} +- (BOOL)stepWithOnOff:(CHIPDeviceCallback)onCompletion + stepMode:(uint8_t)stepMode + stepSize:(uint8_t)stepSize + transitionTime:(uint16_t)transitionTime +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.StepWithOnOff(callback, stepMode, stepSize, transitionTime); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} +- (BOOL)stop:(CHIPDeviceCallback)onCompletion optionMask:(uint8_t)optionMask optionOverride:(uint8_t)optionOverride +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.Stop(callback, optionMask, optionOverride); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} +- (BOOL)stopWithOnOff:(CHIPDeviceCallback)onCompletion +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.StopWithOnOff(callback); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} + +- (BOOL)readAttributeCurrentLevel:(CHIPDeviceCallback)onCompletion +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.ReadAttributeCurrentLevel(callback); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} + +- (BOOL)reportAttributeCurrentLevel:(CHIPDeviceCallback)onCompletion + onChange:(CHIPDeviceCallback)onChange + minInterval:(uint16_t)minInterval + maxInterval:(uint16_t)maxInterval + change:(uint8_t)change +{ + CHIPCallbackBridge * completionCallback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!completionCallback) { + return NO; + } + + CHIPCallbackBridge * changeCallback = new CHIPCallbackBridge(onChange, _callbackQueue); + if (!changeCallback) { + return NO; + } + + CHIP_ERROR err + = self.cppCluster.ReportAttributeCurrentLevel(completionCallback, changeCallback, minInterval, maxInterval, change); + if (err != CHIP_NO_ERROR) { + completionCallback->Cancel(); + changeCallback->Cancel(); + delete completionCallback; + delete changeCallback; + return NO; + } + return YES; +} + +- (BOOL)readAttributeClusterRevision:(CHIPDeviceCallback)onCompletion +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.ReadAttributeClusterRevision(callback); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} + +@end + +@interface CHIPOnOff () + +@property (readonly) chip::Controller::OnOffCluster cppCluster; +@property (readonly, nonatomic) dispatch_queue_t callbackQueue; +@end + +@implementation CHIPOnOff + +- (instancetype)initWithDevice:(CHIPDevice *)device endpoint:(chip::EndpointId)endpoint queue:(dispatch_queue_t)queue +{ + CHIP_ERROR err = _cppCluster.Associate([device internalDevice], endpoint); + + if (err != CHIP_NO_ERROR) { + return nil; + } + + if (self = [super init]) { + _callbackQueue = queue; + } + return self; +} + +- (BOOL)off:(CHIPDeviceCallback)onCompletion +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.Off(callback); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} +- (BOOL)on:(CHIPDeviceCallback)onCompletion +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.On(callback); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} +- (BOOL)toggle:(CHIPDeviceCallback)onCompletion +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.Toggle(callback); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} + +- (BOOL)readAttributeOnOff:(CHIPDeviceCallback)onCompletion +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.ReadAttributeOnOff(callback); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} + +- (BOOL)reportAttributeOnOff:(CHIPDeviceCallback)onCompletion + onChange:(CHIPDeviceCallback)onChange + minInterval:(uint16_t)minInterval + maxInterval:(uint16_t)maxInterval +{ + CHIPCallbackBridge * completionCallback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!completionCallback) { + return NO; + } + + CHIPCallbackBridge * changeCallback = new CHIPCallbackBridge(onChange, _callbackQueue); + if (!changeCallback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.ReportAttributeOnOff(completionCallback, changeCallback, minInterval, maxInterval); + if (err != CHIP_NO_ERROR) { + completionCallback->Cancel(); + changeCallback->Cancel(); + delete completionCallback; + delete changeCallback; + return NO; + } + return YES; +} + +- (BOOL)readAttributeClusterRevision:(CHIPDeviceCallback)onCompletion +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.ReadAttributeClusterRevision(callback); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} + +@end + +@interface CHIPScenes () + +@property (readonly) chip::Controller::ScenesCluster cppCluster; +@property (readonly, nonatomic) dispatch_queue_t callbackQueue; +@end + +@implementation CHIPScenes + +- (instancetype)initWithDevice:(CHIPDevice *)device endpoint:(chip::EndpointId)endpoint queue:(dispatch_queue_t)queue +{ + CHIP_ERROR err = _cppCluster.Associate([device internalDevice], endpoint); + + if (err != CHIP_NO_ERROR) { + return nil; + } + + if (self = [super init]) { + _callbackQueue = queue; + } + return self; +} + +- (BOOL)addScene:(CHIPDeviceCallback)onCompletion + groupId:(uint16_t)groupId + sceneId:(uint8_t)sceneId + transitionTime:(uint16_t)transitionTime + sceneName:(char *)sceneName + clusterId:(chip::ClusterId)clusterId + length:(uint8_t)length + value:(uint8_t)value +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.AddScene(callback, groupId, sceneId, transitionTime, sceneName, clusterId, length, value); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} +- (BOOL)getSceneMembership:(CHIPDeviceCallback)onCompletion groupId:(uint16_t)groupId +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.GetSceneMembership(callback, groupId); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} +- (BOOL)recallScene:(CHIPDeviceCallback)onCompletion + groupId:(uint16_t)groupId + sceneId:(uint8_t)sceneId + transitionTime:(uint16_t)transitionTime +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.RecallScene(callback, groupId, sceneId, transitionTime); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} +- (BOOL)removeAllScenes:(CHIPDeviceCallback)onCompletion groupId:(uint16_t)groupId +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.RemoveAllScenes(callback, groupId); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} +- (BOOL)removeScene:(CHIPDeviceCallback)onCompletion groupId:(uint16_t)groupId sceneId:(uint8_t)sceneId +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.RemoveScene(callback, groupId, sceneId); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} +- (BOOL)storeScene:(CHIPDeviceCallback)onCompletion groupId:(uint16_t)groupId sceneId:(uint8_t)sceneId +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.StoreScene(callback, groupId, sceneId); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} +- (BOOL)viewScene:(CHIPDeviceCallback)onCompletion groupId:(uint16_t)groupId sceneId:(uint8_t)sceneId +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.ViewScene(callback, groupId, sceneId); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} + +- (BOOL)readAttributeSceneCount:(CHIPDeviceCallback)onCompletion +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.ReadAttributeSceneCount(callback); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} + +- (BOOL)readAttributeCurrentScene:(CHIPDeviceCallback)onCompletion +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.ReadAttributeCurrentScene(callback); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} + +- (BOOL)readAttributeCurrentGroup:(CHIPDeviceCallback)onCompletion +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.ReadAttributeCurrentGroup(callback); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} + +- (BOOL)readAttributeSceneValid:(CHIPDeviceCallback)onCompletion +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.ReadAttributeSceneValid(callback); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} + +- (BOOL)readAttributeNameSupport:(CHIPDeviceCallback)onCompletion +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.ReadAttributeNameSupport(callback); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} + +- (BOOL)readAttributeClusterRevision:(CHIPDeviceCallback)onCompletion +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.ReadAttributeClusterRevision(callback); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} + +@end + +@interface CHIPTemperatureMeasurement () + +@property (readonly) chip::Controller::TemperatureMeasurementCluster cppCluster; +@property (readonly, nonatomic) dispatch_queue_t callbackQueue; +@end + +@implementation CHIPTemperatureMeasurement + +- (instancetype)initWithDevice:(CHIPDevice *)device endpoint:(chip::EndpointId)endpoint queue:(dispatch_queue_t)queue +{ + CHIP_ERROR err = _cppCluster.Associate([device internalDevice], endpoint); + + if (err != CHIP_NO_ERROR) { + return nil; + } + + if (self = [super init]) { + _callbackQueue = queue; + } + return self; +} + +- (BOOL)readAttributeMeasuredValue:(CHIPDeviceCallback)onCompletion +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.ReadAttributeMeasuredValue(callback); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} + +- (BOOL)reportAttributeMeasuredValue:(CHIPDeviceCallback)onCompletion + onChange:(CHIPDeviceCallback)onChange + minInterval:(uint16_t)minInterval + maxInterval:(uint16_t)maxInterval + change:(int16_t)change +{ + CHIPCallbackBridge * completionCallback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!completionCallback) { + return NO; + } + + CHIPCallbackBridge * changeCallback = new CHIPCallbackBridge(onChange, _callbackQueue); + if (!changeCallback) { + return NO; + } + + CHIP_ERROR err + = self.cppCluster.ReportAttributeMeasuredValue(completionCallback, changeCallback, minInterval, maxInterval, change); + if (err != CHIP_NO_ERROR) { + completionCallback->Cancel(); + changeCallback->Cancel(); + delete completionCallback; + delete changeCallback; + return NO; + } + return YES; +} + +- (BOOL)readAttributeMinMeasuredValue:(CHIPDeviceCallback)onCompletion +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.ReadAttributeMinMeasuredValue(callback); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} + +- (BOOL)readAttributeMaxMeasuredValue:(CHIPDeviceCallback)onCompletion +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.ReadAttributeMaxMeasuredValue(callback); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} + +- (BOOL)readAttributeClusterRevision:(CHIPDeviceCallback)onCompletion +{ + CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); + if (!callback) { + return NO; + } + + CHIP_ERROR err = self.cppCluster.ReadAttributeClusterRevision(callback); + if (err != CHIP_NO_ERROR) { + callback->Cancel(); + delete callback; + return NO; + } + return YES; +} + +@end diff --git a/src/darwin/Framework/CHIP/CHIPDevice.mm b/src/darwin/Framework/CHIP/CHIPDevice.mm index 6112fb32240c17..f919dbb89ae6b9 100644 --- a/src/darwin/Framework/CHIP/CHIPDevice.mm +++ b/src/darwin/Framework/CHIP/CHIPDevice.mm @@ -91,20 +91,15 @@ - (BOOL)sendMessage:(NSData *)message error:(NSError * __autoreleasing *)error return YES; } -- (BOOL)sendCHIPCommand:(uint32_t (^)(const chip::System::PacketBufferHandle &, uint16_t))encodeCommandBlock +- (BOOL)sendCHIPCommand:(chip::System::PacketBufferHandle (^)())encodeCommandBlock { CHIP_ERROR err = CHIP_NO_ERROR; [self.lock lock]; - // FIXME: This needs a better buffersizing setup! - static const size_t bufferSize = 1024; - chip::System::PacketBufferHandle buffer = chip::System::PacketBuffer::NewWithAvailableSize(bufferSize); + chip::System::PacketBufferHandle buffer = encodeCommandBlock(); if (buffer.IsNull()) { err = CHIP_ERROR_NO_MEMORY; } else { - uint32_t dataLength = encodeCommandBlock(buffer, (uint16_t) bufferSize); - buffer->SetDataLength(dataLength); - err = self.cppDevice->SendMessage(std::move(buffer)); } [self.lock unlock]; @@ -122,9 +117,9 @@ - (BOOL)sendIdentifyCommandWithDuration:(NSTimeInterval)duration duration = UINT16_MAX; } - return [self sendCHIPCommand:^uint32_t(const chip::System::PacketBufferHandle & buffer, uint16_t bufferSize) { + return [self sendCHIPCommand:^chip::System::PacketBufferHandle() { // Hardcode endpoint to 1 for now - return encodeIdentifyClusterIdentifyCommand(buffer->Start(), bufferSize, 1, duration); + return encodeIdentifyClusterIdentifyCommand(1, duration); }]; } diff --git a/src/darwin/Framework/CHIP/CHIPOnOff.mm b/src/darwin/Framework/CHIP/CHIPOnOff.mm deleted file mode 100644 index 82db62f5741f93..00000000000000 --- a/src/darwin/Framework/CHIP/CHIPOnOff.mm +++ /dev/null @@ -1,97 +0,0 @@ -/** - * - * Copyright (c) 2020 Project CHIP Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#import - -#import "CHIPCallbackBridge.h" -#import "CHIPDevice.h" -#import "CHIPDevice_Internal.h" -#import "CHIPOnOff.h" - -#include - -@interface CHIPOnOff () - -@property (readonly) chip::Controller::OnOffCluster cppCluster; -@property (readonly, nonatomic) dispatch_queue_t callbackQueue; -@end - -@implementation CHIPOnOff - -- (instancetype)initWithDevice:(CHIPDevice *)device endpoint:(chip::EndpointId)endpoint queue:(dispatch_queue_t)queue -{ - CHIP_ERROR err = _cppCluster.Associate([device internalDevice], endpoint); - - if (err != CHIP_NO_ERROR) { - return nil; - } - - if (self = [super init]) { - _callbackQueue = queue; - } - return self; -} - -- (BOOL)lightOn:(CHIPDeviceCallback)onCompletion -{ - CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); - if (!callback) { - return NO; - } - - CHIP_ERROR err = self.cppCluster.On(callback); - if (err != CHIP_NO_ERROR) { - callback->Cancel(); - delete callback; - return NO; - } - return YES; -} - -- (BOOL)lightOff:(CHIPDeviceCallback)onCompletion -{ - CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); - if (!callback) { - return NO; - } - - CHIP_ERROR err = self.cppCluster.Off(callback); - if (err != CHIP_NO_ERROR) { - callback->Cancel(); - delete callback; - return NO; - } - return YES; -} - -- (BOOL)toggleLight:(CHIPDeviceCallback)onCompletion -{ - CHIPCallbackBridge * callback = new CHIPCallbackBridge(onCompletion, _callbackQueue); - if (!callback) { - return NO; - } - - CHIP_ERROR err = self.cppCluster.Toggle(callback); - if (err != CHIP_NO_ERROR) { - callback->Cancel(); - delete callback; - return NO; - } - return YES; -} - -@end diff --git a/src/include/platform/CHIPDeviceConfig.h b/src/include/platform/CHIPDeviceConfig.h index f44a9412dd9996..58a94bd6c832df 100644 --- a/src/include/platform/CHIPDeviceConfig.h +++ b/src/include/platform/CHIPDeviceConfig.h @@ -937,3 +937,12 @@ #ifndef CHIP_DEVICE_CONFIG_FIRMWARE_BUILD_TIME #define CHIP_DEVICE_CONFIG_FIRMWARE_BUILD_TIME __TIME__ #endif + +/** + * CHIP_ROTATING_DEVICE_ID + * + * Sample Rotating Device Id. + */ +#ifndef CHIP_ROTATING_DEVICE_ID +#define CHIP_ROTATING_DEVICE_ID "1122334455667788" +#endif diff --git a/src/include/platform/PersistedStorage.h b/src/include/platform/PersistedStorage.h index a5c591e5ae5c62..bc2e6cea37469d 100644 --- a/src/include/platform/PersistedStorage.h +++ b/src/include/platform/PersistedStorage.h @@ -26,6 +26,11 @@ #pragma once +#include +#include +#include +#include + #include #include @@ -87,6 +92,147 @@ CHIP_ERROR Read(Key aKey, uint32_t & aValue); */ CHIP_ERROR Write(Key aKey, uint32_t aValue); +class KeyValueStore +{ +public: + virtual ~KeyValueStore() = default; + /** + * @brief + * Reads the value of an entry in the KVS. The value is read into the + * provided buffer and the number of bytes read is returned. If desired, + * the read can be started at an offset. + * + * If the output buffer is too small for the value, Get returns + * CHIP_ERROR_BUFFER_TOO_SMALL with the number of bytes read returned in + * read_bytes_size, which should be the buffer_size. + * + * The remainder of the value can be read by calling get with an offset. + * + * @param[in] key The name of the key to get, this is a + * null-terminated string. + * @param[in,out] buffer A buffer to read the value into. + * @param[in] buffer_size The size of the buffer in bytes. + * @param[in] read_bytes_size The number of bytes which were + * copied into the buffer. Optionally can + * provide nullptr if not needed. + * @param[in] offset_bytes The offset byte index to start the read. + * + * @return CHIP_NO_ERROR the entry was successfully read + * CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND the key is not + * present in the KVS + * CHIP_ERROR_INTEGRITY_CHECK_FAILED found the entry, but the data + * was corrupted + * CHIP_ERROR_BUFFER_TOO_SMALL the buffer could not fit the entire + * value, but as many bytes as possible + * were written to it + * CHIP_ERROR_WELL_UNINITIALIZED the KVS is not initialized + * CHIP_ERROR_INVALID_ARGUMENT key is empty or too long or value is + * too large + */ + virtual CHIP_ERROR Get(const char * key, void * buffer, size_t buffer_size, size_t * read_bytes_size = nullptr, + size_t offset_bytes = 0) const = 0; + + /** + * @brief + * This overload of Get accepts a pointer to a trivially copyable object. + * The size of the object is inferred from the type. + * + * @param[in] key The name of the key in to get, this is a + * null-terminated string. + * @param[in,out] value Pointer to a trivially copyable object. + * + * @return CHIP_NO_ERROR the entry was successfully read + * CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND the key is not + * present in the KVS + * CHIP_ERROR_INTEGRITY_CHECK_FAILED found the entry, but the data + * was corrupted + * CHIP_ERROR_BUFFER_TOO_SMALL the buffer could not fit the entire + * value, but as many bytes as possible + * were written to it + * CHIP_ERROR_WELL_UNINITIALIZED the KVS is not initialized + * CHIP_ERROR_INVALID_ARGUMENT key is empty or too long or value is + * too large + */ + template + CHIP_ERROR Get(const char * key, T * value) + { + static_assert(std::is_trivially_copyable(), "KVS values must copyable"); + static_assert(!std::is_pointer(), "KVS values cannot be pointers"); + static_assert(CHAR_BIT == 8, "Current implementation assumes 8 bit."); + return Get(key, value, sizeof(T)); + } + + /** + * @brief + * Adds a key-value entry to the KVS. If the key was already present, its + * value is overwritten. + * + * @param[in] key The name of the key to update, this is a + * null-terminated string. + * @param[in] value Pointer to the data. + * @param[in] value_size Size of the data. + * + * @return CHIP_NO_ERROR the entry was successfully added or updated + * CHIP_ERROR_INTEGRITY_CHECK_FAILED checksum validation failed after + * writing the data + * CHIP_ERROR_PERSISTED_STORAGE_FAILED failed to write the value. + * CHIP_ERROR_WELL_UNINITIALIZED the KVS is not initialized + * CHIP_ERROR_INVALID_ARGUMENT key is empty or too long or value is + * too large + */ + virtual CHIP_ERROR Put(const char * key, const void * value, size_t value_size) = 0; + + /** + * @brief + * This overload of Put accepts a reference to a trivially copyable object. + * The size of the object is inferred from the type. + * + * @param[in] key The name of the key to update, this is a + * null-terminated string. + * @param[in] value Reference of a trivially copyable object. + * + * @return CHIP_NO_ERROR the entry was successfully added or updated + * CHIP_ERROR_INTEGRITY_CHECK_FAILED checksum validation failed after + * writing the data + * CHIP_ERROR_PERSISTED_STORAGE_FAILED failed to write the value. + * CHIP_ERROR_WELL_UNINITIALIZED the KVS is not initialized + * CHIP_ERROR_INVALID_ARGUMENT key is empty or too long or value is + * too large + */ + template + CHIP_ERROR Put(const char * key, const T & value) + { + static_assert(std::is_trivially_copyable(), "KVS values must copyable"); + static_assert(!std::is_pointer(), "KVS values cannot be pointers"); + static_assert(CHAR_BIT == 8, "Current implementation assumes 8 bit."); + return Put(key, &value, sizeof(T)); + } + + /** + * @brief + * Removes a key-value entry from the KVS. + * + * @param[in] key The name of the key to delete, this is a + * null-terminated string. + * + * @return CHIP_NO_ERROR the entry was successfully deleted. + * CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND the key is not + * present in the KVS + * CHIP_ERROR_INTEGRITY_CHECK_FAILED checksum validation failed after + * erasing data + * CHIP_ERROR_PERSISTED_STORAGE_FAILED failed to erase the value. + * CHIP_ERROR_WELL_UNINITIALIZED the KVS is not initialized + * CHIP_ERROR_INVALID_ARGUMENT key is empty or too long + */ + virtual CHIP_ERROR Delete(const char * key) = 0; +}; + +/** + * @brief + * Returns a reference to the singleton for the default Chip KVS storage. + */ +KeyValueStore & ChipKeyValueStoreInstance(); + } // namespace PersistedStorage } // namespace Platform } // namespace chip diff --git a/src/include/platform/PlatformManager.h b/src/include/platform/PlatformManager.h index e22a6526a3d71f..461e60faa4696c 100644 --- a/src/include/platform/PlatformManager.h +++ b/src/include/platform/PlatformManager.h @@ -53,8 +53,6 @@ class FabricProvisioningServer; class ServiceProvisioningServer; class BLEManagerImpl; template -class GenericBLEManagerImpl_Zephyr; -template class GenericConfigurationManagerImpl; template class GenericPlatformManagerImpl; @@ -109,8 +107,6 @@ class PlatformManager friend class Internal::ServiceProvisioningServer; friend class Internal::BLEManagerImpl; template - friend class Internal::GenericBLEManagerImpl_Zephyr; - template friend class Internal::GenericPlatformManagerImpl; template friend class Internal::GenericPlatformManagerImpl_FreeRTOS; diff --git a/src/include/platform/ThreadStackManager.h b/src/include/platform/ThreadStackManager.h index 6fc999213753a3..8453ffa1c36e93 100644 --- a/src/include/platform/ThreadStackManager.h +++ b/src/include/platform/ThreadStackManager.h @@ -35,8 +35,6 @@ class DeviceNetworkInfo; class DeviceControlServer; class BLEManagerImpl; template -class GenericBLEManagerImpl_Zephyr; -template class GenericPlatformManagerImpl; template class GenericConfigurationManagerImpl; @@ -89,8 +87,6 @@ class ThreadStackManager friend class ConfigurationManagerImpl; #if CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE friend class Internal::BLEManagerImpl; - template - friend class Internal::GenericBLEManagerImpl_Zephyr; #endif friend class Internal::DeviceControlServer; template diff --git a/src/include/platform/internal/GenericSoftwareUpdateManagerImpl.h b/src/include/platform/internal/GenericSoftwareUpdateManagerImpl.h index e018975356f1a6..92454fefb280ca 100644 --- a/src/include/platform/internal/GenericSoftwareUpdateManagerImpl.h +++ b/src/include/platform/internal/GenericSoftwareUpdateManagerImpl.h @@ -1,6 +1,6 @@ /* * - * Copyright (c) 2020 Project CHIP Authors + * Copyright (c) 2020-2021 Project CHIP Authors * Copyright (c) 2019 Google LLC. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -28,6 +28,8 @@ #include +#include + namespace chip { namespace DeviceLayer { namespace Internal { @@ -82,7 +84,7 @@ class GenericSoftwareUpdateManagerImpl void CheckImageIntegrity(); void DriveState(SoftwareUpdateManager::State aNextState); void GetEventState(int32_t & aEventState); - void HandleImageQueryResponse(PacketBuffer * aPayload); + void HandleImageQueryResponse(chip::System::PacketBuffer * aPayload); void SendQuery(); void StartImageInstall(); void PrepareImageStorage(); @@ -107,7 +109,7 @@ class GenericSoftwareUpdateManagerImpl SoftwareUpdateManager::EventCallback mEventHandlerCallback; SoftwareUpdateManager::RetryPolicyCallback mRetryPolicyCallback; - PacketBuffer * mImageQueryPacketBuffer; + chip::System::PacketBuffer * mImageQueryPacketBuffer; bool mScheduledCheckEnabled; bool mShouldRetry; diff --git a/src/inet/IPEndPointBasis.cpp b/src/inet/IPEndPointBasis.cpp index 33f250e0b2f865..0aede7110546a4 100644 --- a/src/inet/IPEndPointBasis.cpp +++ b/src/inet/IPEndPointBasis.cpp @@ -674,6 +674,20 @@ IPPacketInfo * IPEndPointBasis::GetPacketInfo(const System::PacketBufferHandle & done: return (lPacketInfo); } + +System::Error IPEndPointBasis::PostPacketBufferEvent(chip::System::Layer & aLayer, System::Object & aTarget, + System::EventType aEventType, System::PacketBufferHandle aBuffer) +{ + System::PacketBuffer * buf = aBuffer.Release_ForNow(); + System::Error error = aLayer.PostEvent(aTarget, aEventType, (uintptr_t) buf); + if (error != INET_NO_ERROR) + { + // If PostEvent() failed, it has not taken ownership of the buffer, so we need to retake it so that it will be freed. + (void) System::PacketBufferHandle::Adopt(buf); + } + return error; +} + #endif // CHIP_SYSTEM_CONFIG_USE_LWIP #if CHIP_SYSTEM_CONFIG_USE_SOCKETS @@ -793,7 +807,7 @@ INET_ERROR IPEndPointBasis::BindInterface(IPAddressType aAddressType, InterfaceI return (lRetval); } -INET_ERROR IPEndPointBasis::SendMsg(const IPPacketInfo * aPktInfo, chip::System::PacketBuffer * aBuffer, uint16_t aSendFlags) +INET_ERROR IPEndPointBasis::SendMsg(const IPPacketInfo * aPktInfo, chip::System::PacketBufferHandle aBuffer, uint16_t aSendFlags) { INET_ERROR res = INET_NO_ERROR; PeerSockAddr peerSockAddr; @@ -1233,7 +1247,7 @@ INET_ERROR IPEndPointBasis::Bind(IPAddressType aAddressType, const IPAddress & a return res; } -INET_ERROR IPEndPointBasis::SendMsg(const IPPacketInfo * aPktInfo, chip::System::PacketBuffer * aBuffer, uint16_t aSendFlags) +INET_ERROR IPEndPointBasis::SendMsg(const IPPacketInfo * aPktInfo, chip::System::PacketBufferHandle aBuffer, uint16_t aSendFlags) { __block INET_ERROR res = INET_NO_ERROR; dispatch_data_t content; diff --git a/src/inet/IPEndPointBasis.h b/src/inet/IPEndPointBasis.h index d6e274fa13d424..6271f263b4477e 100644 --- a/src/inet/IPEndPointBasis.h +++ b/src/inet/IPEndPointBasis.h @@ -122,6 +122,8 @@ class DLL_EXPORT IPEndPointBasis : public EndPointBasis #if CHIP_SYSTEM_CONFIG_USE_LWIP public: static struct netif * FindNetifFromInterfaceId(InterfaceId aInterfaceId); + static System::Error PostPacketBufferEvent(chip::System::Layer & aLayer, System::Object & aTarget, System::EventType aEventType, + System::PacketBufferHandle aBuffer); protected: void HandleDataReceived(chip::System::PacketBufferHandle aBuffer); @@ -134,7 +136,7 @@ class DLL_EXPORT IPEndPointBasis : public EndPointBasis INET_ERROR Bind(IPAddressType aAddressType, const IPAddress & aAddress, uint16_t aPort, InterfaceId aInterfaceId); INET_ERROR BindInterface(IPAddressType aAddressType, InterfaceId aInterfaceId); - INET_ERROR SendMsg(const IPPacketInfo * aPktInfo, chip::System::PacketBuffer * aBuffer, uint16_t aSendFlags); + INET_ERROR SendMsg(const IPPacketInfo * aPktInfo, chip::System::PacketBufferHandle aBuffer, uint16_t aSendFlags); INET_ERROR GetSocket(IPAddressType aAddressType, int aType, int aProtocol); SocketEvents PrepareIO(); void HandlePendingIO(uint16_t aPort); @@ -152,7 +154,7 @@ class DLL_EXPORT IPEndPointBasis : public EndPointBasis INET_ERROR Bind(IPAddressType aAddressType, const IPAddress & aAddress, uint16_t aPort, const nw_parameters_t & aParameters); INET_ERROR ConfigureProtocol(IPAddressType aAddressType, const nw_parameters_t & aParameters); - INET_ERROR SendMsg(const IPPacketInfo * aPktInfo, chip::System::PacketBuffer * aBuffer, uint16_t aSendFlags); + INET_ERROR SendMsg(const IPPacketInfo * aPktInfo, chip::System::PacketBufferHandle aBuffer, uint16_t aSendFlags); INET_ERROR StartListener(); INET_ERROR GetConnection(const IPPacketInfo * aPktInfo); INET_ERROR GetEndPoint(nw_endpoint_t & aEndpoint, const IPAddressType aAddressType, const IPAddress & aAddress, uint16_t aPort); diff --git a/src/inet/InetLayer.cpp b/src/inet/InetLayer.cpp index 9e698bb764bea2..e7fe2ac7320e00 100644 --- a/src/inet/InetLayer.cpp +++ b/src/inet/InetLayer.cpp @@ -1068,7 +1068,7 @@ chip::System::Error InetLayer::HandleInetLayerEvent(chip::System::Object & aTarg case kInetEvent_TCPDataReceived: static_cast(aTarget).HandleDataReceived( - System::PacketBufferHandle::Create(reinterpret_cast(aArgument))); + System::PacketBufferHandle::Adopt(reinterpret_cast(aArgument))); break; case kInetEvent_TCPDataSent: @@ -1083,14 +1083,14 @@ chip::System::Error InetLayer::HandleInetLayerEvent(chip::System::Object & aTarg #if INET_CONFIG_ENABLE_RAW_ENDPOINT case kInetEvent_RawDataReceived: static_cast(aTarget).HandleDataReceived( - System::PacketBufferHandle::Create(reinterpret_cast(aArgument))); + System::PacketBufferHandle::Adopt(reinterpret_cast(aArgument))); break; #endif // INET_CONFIG_ENABLE_RAW_ENDPOINT #if INET_CONFIG_ENABLE_UDP_ENDPOINT case kInetEvent_UDPDataReceived: static_cast(aTarget).HandleDataReceived( - System::PacketBufferHandle::Create(reinterpret_cast(aArgument))); + System::PacketBufferHandle::Adopt(reinterpret_cast(aArgument))); break; #endif // INET_CONFIG_ENABLE_UDP_ENDPOINT diff --git a/src/inet/RawEndPoint.cpp b/src/inet/RawEndPoint.cpp index e8bb78b2af1091..3d31c7284e3bc0 100644 --- a/src/inet/RawEndPoint.cpp +++ b/src/inet/RawEndPoint.cpp @@ -512,9 +512,9 @@ void RawEndPoint::Free() * A synonym for SendTo(addr, INET_NULL_INTERFACEID, msg, * sendFlags). */ -INET_ERROR RawEndPoint::SendTo(const IPAddress & addr, chip::System::PacketBuffer * msg, uint16_t sendFlags) +INET_ERROR RawEndPoint::SendTo(const IPAddress & addr, chip::System::PacketBufferHandle msg, uint16_t sendFlags) { - return SendTo(addr, INET_NULL_INTERFACEID, msg, sendFlags); + return SendTo(addr, INET_NULL_INTERFACEID, std::move(msg), sendFlags); } /** @@ -547,13 +547,13 @@ INET_ERROR RawEndPoint::SendTo(const IPAddress & addr, chip::System::PacketBuffe * @details * Send the ICMP message in \c msg to the destination given in \c addr. */ -INET_ERROR RawEndPoint::SendTo(const IPAddress & addr, InterfaceId intfId, chip::System::PacketBuffer * msg, uint16_t sendFlags) +INET_ERROR RawEndPoint::SendTo(const IPAddress & addr, InterfaceId intfId, chip::System::PacketBufferHandle msg, uint16_t sendFlags) { IPPacketInfo pktInfo; pktInfo.Clear(); pktInfo.DestAddress = addr; pktInfo.Interface = intfId; - return SendMsg(&pktInfo, msg, sendFlags); + return SendMsg(&pktInfo, std::move(msg), sendFlags); } /** @@ -585,13 +585,13 @@ INET_ERROR RawEndPoint::SendTo(const IPAddress & addr, InterfaceId intfId, chip: * @details * Send the ICMP message \c msg using the destination information given in \c addr. */ -INET_ERROR RawEndPoint::SendMsg(const IPPacketInfo * pktInfo, chip::System::PacketBuffer * msg, uint16_t sendFlags) +INET_ERROR RawEndPoint::SendMsg(const IPPacketInfo * pktInfo, chip::System::PacketBufferHandle msg, uint16_t sendFlags) { INET_ERROR res = INET_NO_ERROR; const IPAddress & addr = pktInfo->DestAddress; - INET_FAULT_INJECT(FaultInjection::kFault_Send, PacketBuffer::Free(msg); return INET_ERROR_UNKNOWN_INTERFACE;); - INET_FAULT_INJECT(FaultInjection::kFault_SendNonCritical, PacketBuffer::Free(msg); return INET_ERROR_NO_MEMORY;); + INET_FAULT_INJECT(FaultInjection::kFault_Send, return INET_ERROR_UNKNOWN_INTERFACE;); + INET_FAULT_INJECT(FaultInjection::kFault_SendNonCritical, return INET_ERROR_NO_MEMORY;); // Do not allow sending an IPv4 address on an IPv6 end point and // vice versa. @@ -623,20 +623,20 @@ INET_ERROR RawEndPoint::SendMsg(const IPPacketInfo * pktInfo, chip::System::Pack #if LWIP_VERSION_MAJOR > 1 || LWIP_VERSION_MINOR >= 5 ip_addr_t ipAddr = addr.ToLwIPAddr(); - lwipErr = raw_sendto(mRaw, (pbuf *) msg, &ipAddr); + lwipErr = raw_sendto(mRaw, msg.GetLwIPpbuf(), &ipAddr); #else // LWIP_VERSION_MAJOR <= 1 && LWIP_VERSION_MINOR < 5 if (PCB_ISIPV6(mRaw)) { ip6_addr_t ipv6Addr = addr.ToIPv6(); - lwipErr = raw_sendto_ip6(mRaw, (pbuf *) msg, &ipv6Addr); + lwipErr = raw_sendto_ip6(mRaw, msg.GetLwIPpbuf(), &ipv6Addr); } #if INET_CONFIG_ENABLE_IPV4 else { ip4_addr_t ipv4Addr = addr.ToIPv4(); - lwipErr = raw_sendto(mRaw, (pbuf *) msg, &ipv4Addr); + lwipErr = raw_sendto(mRaw, msg.GetLwIPpbuf(), &ipv4Addr); } #endif // INET_CONFIG_ENABLE_IPV4 #endif // LWIP_VERSION_MAJOR <= 1 || LWIP_VERSION_MINOR >= 5 @@ -647,8 +647,6 @@ INET_ERROR RawEndPoint::SendMsg(const IPPacketInfo * pktInfo, chip::System::Pack // Unlock LwIP stack UNLOCK_TCPIP_CORE(); - - PacketBuffer::Free(msg); #endif // CHIP_SYSTEM_CONFIG_USE_LWIP #if CHIP_SYSTEM_CONFIG_USE_SOCKETS @@ -658,8 +656,7 @@ INET_ERROR RawEndPoint::SendMsg(const IPPacketInfo * pktInfo, chip::System::Pack res = GetSocket(addr.Type()); SuccessOrExit(res); - res = IPEndPointBasis::SendMsg(pktInfo, msg, sendFlags); - PacketBuffer::Free(msg); + res = IPEndPointBasis::SendMsg(pktInfo, std::move(msg), sendFlags); #endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS exit: @@ -957,10 +954,10 @@ u8_t RawEndPoint::LwIPReceiveRawMessage(void * arg, struct raw_pcb * pcb, struct #endif // LWIP_VERSION_MAJOR > 1 || LWIP_VERSION_MINOR >= 5 { RawEndPoint * ep = static_cast(arg); - PacketBuffer * buf = reinterpret_cast(static_cast(p)); chip::System::Layer & lSystemLayer = ep->SystemLayer(); IPPacketInfo * pktInfo = NULL; uint8_t enqueue = 1; + System::PacketBufferHandle buf = System::PacketBufferHandle::Adopt(p); // Filtering based on the saved ICMP6 types (the only protocol currently supported.) if ((ep->IPVer == kIPVersion_6) && (ep->IPProto == kIPProtocol_ICMPv6)) @@ -987,9 +984,7 @@ u8_t RawEndPoint::LwIPReceiveRawMessage(void * arg, struct raw_pcb * pcb, struct if (enqueue) { - System::PacketBufferHandle bufHandle; - bufHandle.Adopt(buf); - pktInfo = GetPacketInfo(bufHandle); + pktInfo = GetPacketInfo(buf); if (pktInfo != NULL) { @@ -1016,12 +1011,7 @@ u8_t RawEndPoint::LwIPReceiveRawMessage(void * arg, struct raw_pcb * pcb, struct pktInfo->DestPort = 0; } - buf = bufHandle.Release_ForNow(); - if (lSystemLayer.PostEvent(*ep, kInetEvent_RawDataReceived, (uintptr_t) buf) != INET_NO_ERROR) - { - // If PostEvent() failed, it has not taken ownership of the buffer, so we need to free it ourselves. - PacketBuffer::Free(buf); - } + PostPacketBufferEvent(lSystemLayer, *ep, kInetEvent_RawDataReceived, std::move(buf)); } return enqueue; diff --git a/src/inet/RawEndPoint.h b/src/inet/RawEndPoint.h index 5638549c657c05..acdba4b881e086 100644 --- a/src/inet/RawEndPoint.h +++ b/src/inet/RawEndPoint.h @@ -75,9 +75,9 @@ class DLL_EXPORT RawEndPoint : public IPEndPointBasis INET_ERROR BindInterface(IPAddressType addrType, InterfaceId intfId); InterfaceId GetBoundInterface(); INET_ERROR Listen(); - INET_ERROR SendTo(const IPAddress & addr, chip::System::PacketBuffer * msg, uint16_t sendFlags = 0); - INET_ERROR SendTo(const IPAddress & addr, InterfaceId intfId, chip::System::PacketBuffer * msg, uint16_t sendFlags = 0); - INET_ERROR SendMsg(const IPPacketInfo * pktInfo, chip::System::PacketBuffer * msg, uint16_t sendFlags = 0); + INET_ERROR SendTo(const IPAddress & addr, chip::System::PacketBufferHandle msg, uint16_t sendFlags = 0); + INET_ERROR SendTo(const IPAddress & addr, InterfaceId intfId, chip::System::PacketBufferHandle msg, uint16_t sendFlags = 0); + INET_ERROR SendMsg(const IPPacketInfo * pktInfo, chip::System::PacketBufferHandle msg, uint16_t sendFlags = 0); INET_ERROR SetICMPFilter(uint8_t numICMPTypes, const uint8_t * aICMPTypes); void Close(); void Free(); diff --git a/src/inet/TCPEndPoint.cpp b/src/inet/TCPEndPoint.cpp index b4dcd321959aaa..ee38cb730eff01 100644 --- a/src/inet/TCPEndPoint.cpp +++ b/src/inet/TCPEndPoint.cpp @@ -691,20 +691,19 @@ INET_ERROR TCPEndPoint::GetLocalInfo(IPAddress * retAddr, uint16_t * retPort) return res; } -INET_ERROR TCPEndPoint::Send(PacketBuffer * data, bool push) +INET_ERROR TCPEndPoint::Send(System::PacketBufferHandle data, bool push) { INET_ERROR res = INET_NO_ERROR; if (State != kState_Connected && State != kState_ReceiveShutdown) { - PacketBuffer::Free(data); return INET_ERROR_INCORRECT_STATE; } - if (mSendQueue == nullptr) - mSendQueue = data; + if (mSendQueue.IsNull()) + mSendQueue = std::move(data); else - mSendQueue->AddToEnd_ForNow(data); + mSendQueue->AddToEnd(std::move(data)); #if CHIP_SYSTEM_CONFIG_USE_LWIP @@ -1031,7 +1030,7 @@ INET_ERROR TCPEndPoint::PutBackReceivedData(System::PacketBufferHandle data) uint32_t TCPEndPoint::PendingSendLength() { - if (mSendQueue != nullptr) + if (!mSendQueue.IsNull()) return mSendQueue->TotalLength(); return 0; } @@ -1197,22 +1196,20 @@ INET_ERROR TCPEndPoint::DriveSending() { // Find first packet buffer with remaining data to send by skipping // all sent but un-acked data. - TCPEndPoint::BufferOffset startOfUnsent = FindStartOfUnsent(); - const chip::System::PacketBuffer * currentUnsentBuf = startOfUnsent.buffer; - uint16_t unsentOffset = startOfUnsent.offset; + TCPEndPoint::BufferOffset startOfUnsent = FindStartOfUnsent(); // While there's data to be sent and a window to send it in... do { - VerifyOrDie(currentUnsentBuf != NULL); + VerifyOrDie(!startOfUnsent.buffer.IsNull()); - uint16_t bufDataLen = currentUnsentBuf->DataLength(); + uint16_t bufDataLen = startOfUnsent.buffer->DataLength(); // Get a pointer to the start of unsent data within the first buffer on the unsent queue. - const uint8_t * sendData = currentUnsentBuf->Start() + unsentOffset; + const uint8_t * sendData = startOfUnsent.buffer->Start() + startOfUnsent.offset; // Determine the amount of data to send from the current buffer. - uint16_t sendLen = static_cast(bufDataLen - unsentOffset); + uint16_t sendLen = static_cast(bufDataLen - startOfUnsent.offset); if (sendLen > sendWindowSize) sendLen = sendWindowSize; @@ -1235,12 +1232,12 @@ INET_ERROR TCPEndPoint::DriveSending() // Adjust the unsent data offset by the length of data that was written. // If the entire buffer has been sent advance to the next one. - // This cast is safe, because unsentOffset + sendLen <= bufDataLen, which fits in uint16_t. - unsentOffset = static_cast(unsentOffset + sendLen); - if (unsentOffset == bufDataLen) + // This cast is safe, because startOfUnsent.offset + sendLen <= bufDataLen, which fits in uint16_t. + startOfUnsent.offset = static_cast(startOfUnsent.offset + sendLen); + if (startOfUnsent.offset == bufDataLen) { - currentUnsentBuf = currentUnsentBuf->Next_ForNow(); - unsentOffset = 0; + startOfUnsent.buffer.Advance(); + startOfUnsent.offset = 0; } // Adjust the remaining window size. @@ -1297,7 +1294,7 @@ INET_ERROR TCPEndPoint::DriveSending() return err; }); - while (mSendQueue != nullptr) + while (!mSendQueue.IsNull()) { uint16_t bufLen = mSendQueue->DataLength(); @@ -1325,7 +1322,7 @@ INET_ERROR TCPEndPoint::DriveSending() if (lenSent < bufLen) mSendQueue->ConsumeHead(lenSent); else - mSendQueue = PacketBuffer::FreeHead_ForNow(mSendQueue); + mSendQueue.FreeHead(); if (OnDataSent != nullptr) OnDataSent(this, lenSent); @@ -1370,7 +1367,7 @@ INET_ERROR TCPEndPoint::DriveSending() if (err == INET_NO_ERROR) { // If we're in the SendShutdown state and the send queue is now empty, shutdown writing on the socket. - if (State == kState_SendShutdown && mSendQueue == nullptr) + if (State == kState_SendShutdown && mSendQueue.IsNull()) { if (shutdown(mSocket, SHUT_WR) != 0) err = chip::System::MapErrorPOSIX(errno); @@ -1436,7 +1433,7 @@ INET_ERROR TCPEndPoint::DoClose(INET_ERROR err, bool suppressCallback) // AND there is data waiting to be processed on either the send or receive queues // ... THEN enter the Closing state, allowing the queued data to drain, // ... OTHERWISE go straight to the Closed state. - if (IsConnected() && err == INET_NO_ERROR && (mSendQueue != nullptr || !mRcvQueue.IsNull())) + if (IsConnected() && err == INET_NO_ERROR && (!mSendQueue.IsNull() || !mRcvQueue.IsNull())) State = kState_Closing; else State = kState_Closed; @@ -1526,7 +1523,7 @@ INET_ERROR TCPEndPoint::DoClose(INET_ERROR err, bool suppressCallback) // If entering the Closed state // OR if entering the Closing state, and there's no unsent data in the send queue // THEN close the socket. - if (State == kState_Closed || (State == kState_Closing && mSendQueue == nullptr)) + if (State == kState_Closed || (State == kState_Closing && mSendQueue.IsNull())) { chip::System::Layer & lSystemLayer = SystemLayer(); @@ -1563,7 +1560,6 @@ INET_ERROR TCPEndPoint::DoClose(INET_ERROR err, bool suppressCallback) if (State == kState_Closed) { // Clear clear the send and receive queues. - PacketBuffer::Free(mSendQueue); mSendQueue = nullptr; mRcvQueue = nullptr; #if CHIP_SYSTEM_CONFIG_USE_LWIP @@ -1628,7 +1624,7 @@ void TCPEndPoint::TCPUserTimeoutHandler(chip::System::Layer * aSystemLayer, void // send queue have been flushed then notify application // that all data has been acknowledged. - if (tcpEndPoint->mSendQueue == NULL) + if (tcpEndPoint->mSendQueue.IsNull()) { tcpEndPoint->SetTCPSendIdleAndNotifyChange(true); } @@ -1750,7 +1746,7 @@ void TCPEndPoint::RestartTCPUserTimeoutTimer() uint16_t TCPEndPoint::RemainingToSend() { - if (mSendQueue == NULL) + if (mSendQueue.IsNull()) { return 0; } @@ -1776,36 +1772,31 @@ TCPEndPoint::BufferOffset TCPEndPoint::FindStartOfUnsent() // unsent data while retaining the buffers that have un-acked data is to // traverse all sent-but-unacked data in the chain to reach the beginning // of ready-to-send data. - chip::System::PacketBuffer * currentUnsentBuf = mSendQueue; - uint16_t unsentOffset = 0; - uint16_t leftToSkip = mUnackedLength; + TCPEndPoint::BufferOffset startOfUnsent(mSendQueue.Retain()); + uint16_t leftToSkip = mUnackedLength; VerifyOrDie(leftToSkip < mSendQueue->TotalLength()); while (leftToSkip > 0) { - VerifyOrDie(currentUnsentBuf != NULL); - uint16_t bufDataLen = currentUnsentBuf->DataLength(); + VerifyOrDie(!startOfUnsent.buffer.IsNull()); + uint16_t bufDataLen = startOfUnsent.buffer->DataLength(); if (leftToSkip >= bufDataLen) { // We have more to skip than current packet buffer size. // Follow the chain to continue. - currentUnsentBuf = currentUnsentBuf->Next_ForNow(); - leftToSkip = static_cast(leftToSkip - bufDataLen); + startOfUnsent.buffer.Advance(); + leftToSkip = static_cast(leftToSkip - bufDataLen); } else { // Done skipping all data, currentUnsentBuf is first packet buffer // containing unsent data. - unsentOffset = leftToSkip; - leftToSkip = 0; + startOfUnsent.offset = leftToSkip; + leftToSkip = 0; } } - TCPEndPoint::BufferOffset startOfUnsent; - startOfUnsent.buffer = currentUnsentBuf; - startOfUnsent.offset = unsentOffset; - return startOfUnsent; } @@ -1908,7 +1899,7 @@ void TCPEndPoint::HandleDataSent(uint16_t lenSent) DoClose(INET_ERROR_UNEXPECTED_EVENT, false); return; } - else if (mSendQueue == NULL) + else if (mSendQueue.IsNull()) { ChipLogError(Inet, "Got ACK for %d bytes but data backing gone", (int) lenSent); DoClose(INET_ERROR_UNEXPECTED_EVENT, false); @@ -1916,7 +1907,7 @@ void TCPEndPoint::HandleDataSent(uint16_t lenSent) } // Consume data off the head of the send queue equal to the amount of data being acknowledged. - mSendQueue = mSendQueue->Consume(lenSent); + mSendQueue.Consume(lenSent); mUnackedLength = static_cast(mUnackedLength - lenSent); #if INET_CONFIG_OVERRIDE_SYSTEM_TCP_USER_TIMEOUT @@ -2344,7 +2335,7 @@ SocketEvents TCPEndPoint::PrepareIO() // If initiating a new connection... // OR if connected and there is data to be sent... // THEN arrange for the kernel to alert us when the socket is ready to be written. - if (State == kState_Connecting || (IsConnected() && mSendQueue != nullptr)) + if (State == kState_Connecting || (IsConnected() && !mSendQueue.IsNull())) ioType.SetWrite(); // If listening for incoming connections and the app is ready to receive a connection... @@ -2392,7 +2383,7 @@ void TCPEndPoint::HandlePendingIO() { // If in a state where sending is allowed, and there is data to be sent, and the socket is ready for // writing, drive outbound data into the connection. - if (IsConnected() && mSendQueue != nullptr && mPendingIO.IsWriteable()) + if (IsConnected() && !mSendQueue.IsNull() && mPendingIO.IsWriteable()) DriveSending(); // If in a state were receiving is allowed, and the app is ready to receive data, and data is ready @@ -2409,19 +2400,16 @@ void TCPEndPoint::HandlePendingIO() void TCPEndPoint::ReceiveData() { - PacketBuffer * rcvBuf; + System::PacketBufferHandle rcvBuf; bool isNewBuf = true; if (mRcvQueue.IsNull()) - rcvBuf = PacketBuffer::New(0).Release_ForNow(); + rcvBuf = PacketBuffer::New(0); else { - rcvBuf = mRcvQueue.Get_ForNow(); - for (PacketBuffer * nextBuf = rcvBuf->Next_ForNow(); nextBuf != nullptr; rcvBuf = nextBuf, nextBuf = nextBuf->Next_ForNow()) - ; - + rcvBuf = mRcvQueue->Last(); if (rcvBuf->AvailableDataLength() == 0) - rcvBuf = PacketBuffer::New(0).Release_ForNow(); + rcvBuf = PacketBuffer::New(0); else { isNewBuf = false; @@ -2429,7 +2417,7 @@ void TCPEndPoint::ReceiveData() } } - if (rcvBuf == nullptr) + if (rcvBuf.IsNull()) { DoClose(INET_ERROR_NO_MEMORY, false); return; @@ -2459,7 +2447,7 @@ void TCPEndPoint::ReceiveData() #if INET_CONFIG_ENABLE_TCP_SEND_IDLE_CALLBACKS // Notify up if all outstanding data has been acknowledged - if (mSendQueue == NULL) + if (mSendQueue.IsNull()) { SetTCPSendIdleAndNotifyChange(true); } @@ -2476,12 +2464,6 @@ void TCPEndPoint::ReceiveData() if (rcvLen < 0) { int systemErrno = errno; - - if (isNewBuf) - { - PacketBuffer::Free(rcvBuf); - } - if (systemErrno == EAGAIN) { // Note: in this case, we opt to not retry the recv call, @@ -2504,9 +2486,6 @@ void TCPEndPoint::ReceiveData() // If the peer closed their end of the connection... if (rcvLen == 0) { - if (isNewBuf) - PacketBuffer::Free(rcvBuf); - // If in the Connected state and the app has provided an OnPeerClose callback, // enter the ReceiveShutdown state. Providing an OnPeerClose callback allows // the app to decide whether to keep the send side of the connection open after @@ -2530,9 +2509,9 @@ void TCPEndPoint::ReceiveData() VerifyOrDie(CanCastTo(newDataLength)); rcvBuf->SetDataLength(static_cast(newDataLength)); if (mRcvQueue.IsNull()) - mRcvQueue.Adopt(rcvBuf); + mRcvQueue = std::move(rcvBuf); else - mRcvQueue->AddToEnd_ForNow(rcvBuf); + mRcvQueue->AddToEnd(std::move(rcvBuf)); } else @@ -2540,7 +2519,7 @@ void TCPEndPoint::ReceiveData() VerifyOrDie(rcvLen > 0); size_t newDataLength = rcvBuf->DataLength() + static_cast(rcvLen); VerifyOrDie(CanCastTo(newDataLength)); - rcvBuf->SetDataLength(static_cast(newDataLength), mRcvQueue.Get_ForNow()); + rcvBuf->SetDataLength(static_cast(newDataLength), mRcvQueue); } } diff --git a/src/inet/TCPEndPoint.h b/src/inet/TCPEndPoint.h index 929ec36d9025b5..f6471971cbb9b5 100644 --- a/src/inet/TCPEndPoint.h +++ b/src/inet/TCPEndPoint.h @@ -32,6 +32,8 @@ #include +#include + namespace chip { namespace Inet { @@ -192,12 +194,8 @@ class DLL_EXPORT TCPEndPoint : public EndPointBasis * * @retval INET_NO_ERROR success: address and port extracted. * @retval INET_ERROR_INCORRECT_STATE TCP connection not established. - * - * @details - * The chip::System::PacketBuffer::Free method is called on the \c data argument - * regardless of whether the transmission is successful or failed. */ - INET_ERROR Send(chip::System::PacketBuffer * data, bool push = true); + INET_ERROR Send(chip::System::PacketBufferHandle data, bool push = true); /** * @brief Disable reception. @@ -565,7 +563,7 @@ class DLL_EXPORT TCPEndPoint : public EndPointBasis static chip::System::ObjectPool sPool; chip::System::PacketBufferHandle mRcvQueue; - chip::System::PacketBuffer * mSendQueue; + chip::System::PacketBufferHandle mSendQueue; #if INET_TCP_IDLE_CHECK_INTERVAL > 0 uint16_t mIdleTimeout; // in units of INET_TCP_IDLE_CHECK_INTERVAL; zero means no timeout uint16_t mRemainingIdleTime; // in units of INET_TCP_IDLE_CHECK_INTERVAL @@ -636,7 +634,13 @@ class DLL_EXPORT TCPEndPoint : public EndPointBasis #if CHIP_SYSTEM_CONFIG_USE_LWIP struct BufferOffset { - const chip::System::PacketBuffer * buffer; + BufferOffset(System::PacketBufferHandle && aBuffer) : buffer(std::move(aBuffer)), offset(0) {} + BufferOffset(BufferOffset && aOther) + { + buffer = std::move(aOther.buffer); + offset = aOther.offset; + } + chip::System::PacketBufferHandle buffer; uint16_t offset; }; diff --git a/src/inet/UDPEndPoint.cpp b/src/inet/UDPEndPoint.cpp index bd05f6785a02fa..94f3c649f13244 100644 --- a/src/inet/UDPEndPoint.cpp +++ b/src/inet/UDPEndPoint.cpp @@ -452,9 +452,9 @@ void UDPEndPoint::Free() /** * A synonym for SendTo(addr, port, INET_NULL_INTERFACEID, msg, sendFlags). */ -INET_ERROR UDPEndPoint::SendTo(const IPAddress & addr, uint16_t port, chip::System::PacketBuffer * msg, uint16_t sendFlags) +INET_ERROR UDPEndPoint::SendTo(const IPAddress & addr, uint16_t port, chip::System::PacketBufferHandle msg, uint16_t sendFlags) { - return SendTo(addr, port, INET_NULL_INTERFACEID, msg, sendFlags); + return SendTo(addr, port, INET_NULL_INTERFACEID, std::move(msg), sendFlags); } /** @@ -491,7 +491,7 @@ INET_ERROR UDPEndPoint::SendTo(const IPAddress & addr, uint16_t port, chip::Syst * identifier for IPv6 link-local destinations) and \c port with the * transmit option flags encoded in \c sendFlags. */ -INET_ERROR UDPEndPoint::SendTo(const IPAddress & addr, uint16_t port, InterfaceId intfId, chip::System::PacketBuffer * msg, +INET_ERROR UDPEndPoint::SendTo(const IPAddress & addr, uint16_t port, InterfaceId intfId, chip::System::PacketBufferHandle msg, uint16_t sendFlags) { IPPacketInfo pktInfo; @@ -499,7 +499,7 @@ INET_ERROR UDPEndPoint::SendTo(const IPAddress & addr, uint16_t port, InterfaceI pktInfo.DestAddress = addr; pktInfo.DestPort = port; pktInfo.Interface = intfId; - return SendMsg(&pktInfo, msg, sendFlags); + return SendMsg(&pktInfo, std::move(msg), sendFlags); } /** @@ -535,13 +535,13 @@ INET_ERROR UDPEndPoint::SendTo(const IPAddress & addr, uint16_t port, InterfaceI * over the specified interface. If \c pktInfo contains a source address, the * given address will be used as the source of the UDP message. */ -INET_ERROR UDPEndPoint::SendMsg(const IPPacketInfo * pktInfo, PacketBuffer * msg, uint16_t sendFlags) +INET_ERROR UDPEndPoint::SendMsg(const IPPacketInfo * pktInfo, System::PacketBufferHandle msg, uint16_t sendFlags) { INET_ERROR res = INET_NO_ERROR; const IPAddress & destAddr = pktInfo->DestAddress; - INET_FAULT_INJECT(FaultInjection::kFault_Send, PacketBuffer::Free(msg); return INET_ERROR_UNKNOWN_INTERFACE;); - INET_FAULT_INJECT(FaultInjection::kFault_SendNonCritical, PacketBuffer::Free(msg); return INET_ERROR_NO_MEMORY;); + INET_FAULT_INJECT(FaultInjection::kFault_Send, return INET_ERROR_UNKNOWN_INTERFACE;); + INET_FAULT_INJECT(FaultInjection::kFault_SendNonCritical, return INET_ERROR_NO_MEMORY;); #if CHIP_SYSTEM_CONFIG_USE_LWIP @@ -578,9 +578,9 @@ INET_ERROR UDPEndPoint::SendMsg(const IPPacketInfo * pktInfo, PacketBuffer * msg } if (intfId != INET_NULL_INTERFACEID) - lwipErr = udp_sendto_if(mUDP, (pbuf *) msg, &lwipDestAddr, destPort, intfId); + lwipErr = udp_sendto_if(mUDP, msg.GetLwIPpbuf(), &lwipDestAddr, destPort, intfId); else - lwipErr = udp_sendto(mUDP, (pbuf *) msg, &lwipDestAddr, destPort); + lwipErr = udp_sendto(mUDP, msg.GetLwIPpbuf(), &lwipDestAddr, destPort); ip_addr_copy(mUDP->local_ip, boundAddr); @@ -600,9 +600,9 @@ INET_ERROR UDPEndPoint::SendMsg(const IPPacketInfo * pktInfo, PacketBuffer * msg } if (intfId != INET_NULL_INTERFACEID) - lwipErr = udp_sendto_if_ip6(mUDP, (pbuf *) msg, &lwipDestAddr, destPort, intfId); + lwipErr = udp_sendto_if_ip6(mUDP, msg.GetLwIPpbuf(), &lwipDestAddr, destPort, intfId); else - lwipErr = udp_sendto_ip6(mUDP, (pbuf *) msg, &lwipDestAddr, destPort); + lwipErr = udp_sendto_ip6(mUDP, msg.GetLwIPpbuf(), &lwipDestAddr, destPort); } #if INET_CONFIG_ENABLE_IPV4 @@ -619,9 +619,9 @@ INET_ERROR UDPEndPoint::SendMsg(const IPPacketInfo * pktInfo, PacketBuffer * msg } if (intfId != INET_NULL_INTERFACEID) - lwipErr = udp_sendto_if(mUDP, (pbuf *) msg, &lwipDestAddr, destPort, intfId); + lwipErr = udp_sendto_if(mUDP, msg.GetLwIPpbuf(), &lwipDestAddr, destPort, intfId); else - lwipErr = udp_sendto(mUDP, (pbuf *) msg, &lwipDestAddr, destPort); + lwipErr = udp_sendto(mUDP, msg.GetLwIPpbuf(), &lwipDestAddr, destPort); } ipX_addr_copy(mUDP->local_ip, boundAddr); @@ -635,8 +635,6 @@ INET_ERROR UDPEndPoint::SendMsg(const IPPacketInfo * pktInfo, PacketBuffer * msg // Unlock LwIP stack UNLOCK_TCPIP_CORE(); - - PacketBuffer::Free(msg); #endif // CHIP_SYSTEM_CONFIG_USE_LWIP #if CHIP_SYSTEM_CONFIG_USE_SOCKETS @@ -647,13 +645,11 @@ INET_ERROR UDPEndPoint::SendMsg(const IPPacketInfo * pktInfo, PacketBuffer * msg res = GetSocket(destAddr.Type()); SuccessOrExit(res); - res = IPEndPointBasis::SendMsg(pktInfo, msg, sendFlags); - PacketBuffer::Free(msg); + res = IPEndPointBasis::SendMsg(pktInfo, std::move(msg), sendFlags); #endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS #if CHIP_SYSTEM_CONFIG_USE_NETWORK_FRAMEWORK - res = IPEndPointBasis::SendMsg(pktInfo, msg, sendFlags); - PacketBuffer::Free(msg); + res = IPEndPointBasis::SendMsg(pktInfo, std::move(msg), sendFlags); #endif // CHIP_SYSTEM_CONFIG_USE_NETWORK_FRAMEWORK exit: @@ -871,13 +867,11 @@ void UDPEndPoint::LwIPReceiveUDPMessage(void * arg, struct udp_pcb * pcb, struct #endif // LWIP_VERSION_MAJOR > 1 || LWIP_VERSION_MINOR >= 5 { UDPEndPoint * ep = static_cast(arg); - PacketBuffer * buf = reinterpret_cast(static_cast(p)); chip::System::Layer & lSystemLayer = ep->SystemLayer(); IPPacketInfo * pktInfo = NULL; + System::PacketBufferHandle buf = System::PacketBufferHandle::Adopt(p); - System::PacketBufferHandle buf_ForNow; - buf_ForNow.Adopt(buf); - pktInfo = GetPacketInfo(buf_ForNow); + pktInfo = GetPacketInfo(buf); if (pktInfo != NULL) { #if LWIP_VERSION_MAJOR > 1 || LWIP_VERSION_MINOR >= 5 @@ -903,12 +897,7 @@ void UDPEndPoint::LwIPReceiveUDPMessage(void * arg, struct udp_pcb * pcb, struct pktInfo->DestPort = pcb->local_port; } - buf = buf_ForNow.Release_ForNow(); - if (lSystemLayer.PostEvent(*ep, kInetEvent_UDPDataReceived, (uintptr_t) buf) != INET_NO_ERROR) - { - // If PostEvent() failed, it has not taken ownership of the buffer, so we need to free it ourselves. - PacketBuffer::Free(buf); - } + PostPacketBufferEvent(lSystemLayer, *ep, kInetEvent_UDPDataReceived, std::move(buf)); } #endif // CHIP_SYSTEM_CONFIG_USE_LWIP diff --git a/src/inet/UDPEndPoint.h b/src/inet/UDPEndPoint.h index 7092c35bc111ee..7fd96f37f34267 100644 --- a/src/inet/UDPEndPoint.h +++ b/src/inet/UDPEndPoint.h @@ -57,10 +57,10 @@ class DLL_EXPORT UDPEndPoint : public IPEndPointBasis InterfaceId GetBoundInterface(); uint16_t GetBoundPort(); INET_ERROR Listen(); - INET_ERROR SendTo(const IPAddress & addr, uint16_t port, chip::System::PacketBuffer * msg, uint16_t sendFlags = 0); - INET_ERROR SendTo(const IPAddress & addr, uint16_t port, InterfaceId intfId, chip::System::PacketBuffer * msg, + INET_ERROR SendTo(const IPAddress & addr, uint16_t port, chip::System::PacketBufferHandle msg, uint16_t sendFlags = 0); + INET_ERROR SendTo(const IPAddress & addr, uint16_t port, InterfaceId intfId, chip::System::PacketBufferHandle msg, uint16_t sendFlags = 0); - INET_ERROR SendMsg(const IPPacketInfo * pktInfo, chip::System::PacketBuffer * msg, uint16_t sendFlags = 0); + INET_ERROR SendMsg(const IPPacketInfo * pktInfo, chip::System::PacketBufferHandle msg, uint16_t sendFlags = 0); void Close(); void Free(); diff --git a/src/inet/tests/TestInetEndPoint.cpp b/src/inet/tests/TestInetEndPoint.cpp index 8d10b04a9e420f..492d7647583aa4 100644 --- a/src/inet/tests/TestInetEndPoint.cpp +++ b/src/inet/tests/TestInetEndPoint.cpp @@ -405,7 +405,7 @@ static void TestInetEndPointInternal(nlTestSuite * inSuite, void * inContext) NL_TEST_ASSERT(inSuite, addr.Type() == kIPAddressType_IPv6); - err = testRaw4EP->SendTo(addr, buf.Release_ForNow()); + err = testRaw4EP->SendTo(addr, std::move(buf)); NL_TEST_ASSERT(inSuite, err == INET_ERROR_WRONG_ADDRESS_TYPE); testRaw4EP->Free(); #endif // INET_CONFIG_ENABLE_IPV4 @@ -441,7 +441,7 @@ static void TestInetEndPointInternal(nlTestSuite * inSuite, void * inContext) err = testUDPEP->Bind(kIPAddressType_IPv4, addr_v4, 3000, intId); NL_TEST_ASSERT(inSuite, err != INET_NO_ERROR); buf = PacketBuffer::New(); - err = testUDPEP->SendTo(addr_v4, 3000, buf.Release_ForNow()); + err = testUDPEP->SendTo(addr_v4, 3000, std::move(buf)); testUDPEP->Free(); #endif // INET_CONFIG_ENABLE_IPV4 @@ -449,7 +449,7 @@ static void TestInetEndPointInternal(nlTestSuite * inSuite, void * inContext) err = testTCPEP1->GetPeerInfo(nullptr, nullptr); NL_TEST_ASSERT(inSuite, err == INET_ERROR_INCORRECT_STATE); buf = PacketBuffer::New(); - err = testTCPEP1->Send(buf.Release_ForNow(), false); + err = testTCPEP1->Send(std::move(buf), false); NL_TEST_ASSERT(inSuite, err == INET_ERROR_INCORRECT_STATE); err = testTCPEP1->EnableKeepAlive(10, 100); NL_TEST_ASSERT(inSuite, err == INET_ERROR_INCORRECT_STATE); diff --git a/src/inet/tests/TestInetLayer.cpp b/src/inet/tests/TestInetLayer.cpp index 022b8ffc86fd86..f377482acb332a 100644 --- a/src/inet/tests/TestInetLayer.cpp +++ b/src/inet/tests/TestInetLayer.cpp @@ -830,7 +830,7 @@ static INET_ERROR DriveSendForDestination(const IPAddress & aAddress, uint16_t a } #endif // INET_CONFIG_ENABLE_IPV4 - lStatus = sRawIPEndPoint->SendTo(aAddress, lBuffer.Release_ForNow()); + lStatus = sRawIPEndPoint->SendTo(aAddress, std::move(lBuffer)); SuccessOrExit(lStatus); } else @@ -845,7 +845,7 @@ static INET_ERROR DriveSendForDestination(const IPAddress & aAddress, uint16_t a lBuffer = Common::MakeDataBuffer(aSize, lFirstValue); VerifyOrExit(!lBuffer.IsNull(), lStatus = INET_ERROR_NO_MEMORY); - lStatus = sUDPIPEndPoint->SendTo(aAddress, kUDPPort, lBuffer.Release_ForNow()); + lStatus = sUDPIPEndPoint->SendTo(aAddress, kUDPPort, std::move(lBuffer)); SuccessOrExit(lStatus); } else if ((gOptFlags & kOptFlagUseTCPIP) == kOptFlagUseTCPIP) @@ -861,7 +861,7 @@ static INET_ERROR DriveSendForDestination(const IPAddress & aAddress, uint16_t a lBuffer = Common::MakeDataBuffer(aSize, uint8_t(lFirstValue)); VerifyOrExit(!lBuffer.IsNull(), lStatus = INET_ERROR_NO_MEMORY); - lStatus = sTCPIPEndPoint->Send(lBuffer.Release_ForNow()); + lStatus = sTCPIPEndPoint->Send(std::move(lBuffer)); SuccessOrExit(lStatus); } } diff --git a/src/inet/tests/TestInetLayerMulticast.cpp b/src/inet/tests/TestInetLayerMulticast.cpp index 277ff0d737e90a..04a06b6939379c 100644 --- a/src/inet/tests/TestInetLayerMulticast.cpp +++ b/src/inet/tests/TestInetLayerMulticast.cpp @@ -769,7 +769,7 @@ static INET_ERROR DriveSendForDestination(const IPAddress & aAddress, uint16_t a } #endif // INET_CONFIG_ENABLE_IPV4 - lStatus = sRawIPEndPoint->SendTo(aAddress, lBuffer.Release_ForNow()); + lStatus = sRawIPEndPoint->SendTo(aAddress, std::move(lBuffer)); SuccessOrExit(lStatus); } else @@ -784,7 +784,7 @@ static INET_ERROR DriveSendForDestination(const IPAddress & aAddress, uint16_t a lBuffer = Common::MakeDataBuffer(aSize, lFirstValue); VerifyOrExit(!lBuffer.IsNull(), lStatus = INET_ERROR_NO_MEMORY); - lStatus = sUDPIPEndPoint->SendTo(aAddress, kUDPPort, lBuffer.Release_ForNow()); + lStatus = sUDPIPEndPoint->SendTo(aAddress, kUDPPort, std::move(lBuffer)); SuccessOrExit(lStatus); } } diff --git a/src/lib/BUILD.gn b/src/lib/BUILD.gn index 6ce4097f3d0839..fd7a191eaee59a 100644 --- a/src/lib/BUILD.gn +++ b/src/lib/BUILD.gn @@ -36,6 +36,10 @@ static_library("lib") { "${chip_root}/src/transport", ] + if (chip_device_platform != "none") { + public_deps += [ "${chip_root}/src/app/server" ] + } + if (chip_enable_mdns) { public_deps += [ "${chip_root}/src/lib/mdns" ] } diff --git a/src/lib/asn1/ASN1.h b/src/lib/asn1/ASN1.h index 80bdbe7f3b2043..54a6e6f22f4d88 100755 --- a/src/lib/asn1/ASN1.h +++ b/src/lib/asn1/ASN1.h @@ -208,7 +208,7 @@ ASN1_ERROR DumpASN1(ASN1Reader & reader, const char * prefix, const char * inden inline OID GetOID(OIDCategory category, uint8_t id) { - return (category | id); + return static_cast(category | id); } inline uint8_t GetOIDEnum(OID oid) diff --git a/src/lib/asn1/gen_asn1oid.py b/src/lib/asn1/gen_asn1oid.py index 1d7a79b6469b94..ae081a76fb7b70 100755 --- a/src/lib/asn1/gen_asn1oid.py +++ b/src/lib/asn1/gen_asn1oid.py @@ -118,6 +118,7 @@ def identity(n): ( "AttributeType", "ChipNodeId", 17, [ iso(1), organization(3), dod(6), internet(1), private(4), enterprise(1), zigbee(37244), chip(1), 1 ] ), ( "AttributeType", "ChipCAId", 18, [ iso(1), organization(3), dod(6), internet(1), private(4), enterprise(1), zigbee(37244), chip(1), 2 ] ), ( "AttributeType", "ChipSoftwarePublisherId", 19, [ iso(1), organization(3), dod(6), internet(1), private(4), enterprise(1), zigbee(37244), chip(1), 3 ] ), + ( "AttributeType", "ChipFabricId", 20, [ iso(1), organization(3), dod(6), internet(1), private(4), enterprise(1), zigbee(37244), chip(1), 4 ] ), # Elliptic Curves ( "EllipticCurve", "prime256v1", 1, [ iso(1), member_body(2), us(840), ansi_X9_62(10045), curves(3), prime(1), 7 ] ), diff --git a/src/lib/core/BUILD.gn b/src/lib/core/BUILD.gn index 9b0b5a5f7b457c..91e80c94fa43b6 100644 --- a/src/lib/core/BUILD.gn +++ b/src/lib/core/BUILD.gn @@ -117,7 +117,6 @@ static_library("core") { public_deps = [ ":chip_config_header", - "${chip_root}/src/app", "${chip_root}/src/ble", "${chip_root}/src/inet", "${chip_root}/src/lib/support", @@ -130,6 +129,5 @@ static_library("core") { "${chip_root}/src/lib/support", "${chip_root}/src/inet", "${chip_root}/src/system", - "${chip_root}/src/app", ] } diff --git a/src/lib/core/CHIPCircularTLVBuffer.cpp b/src/lib/core/CHIPCircularTLVBuffer.cpp index 64653accbd68ef..e1869428ba0438 100644 --- a/src/lib/core/CHIPCircularTLVBuffer.cpp +++ b/src/lib/core/CHIPCircularTLVBuffer.cpp @@ -1,6 +1,6 @@ /* * - * Copyright (c) 2020 Project CHIP Authors + * Copyright (c) 2020-2021 Project CHIP Authors * Copyright (c) 2016-2017 Nest Labs, Inc. * All rights reserved. * @@ -122,7 +122,7 @@ CHIP_ERROR CHIPCircularTLVBuffer::EvictHead() CHIP_ERROR err; // find the boundaries of an event to throw away - reader.Init(this); + reader.Init(*this); reader.ImplicitProfileId = mImplicitProfileId; // position the reader on the first element @@ -142,7 +142,7 @@ CHIP_ERROR CHIPCircularTLVBuffer::EvictHead() if (mProcessEvictedElement != nullptr) { // Reinitialize the reader - reader.Init(this); + reader.Init(*this); reader.ImplicitProfileId = mImplicitProfileId; err = mProcessEvictedElement(*this, mAppData, reader); @@ -157,6 +157,15 @@ CHIP_ERROR CHIPCircularTLVBuffer::EvictHead() return err; } +/** + * @brief + * Implements TLVBackingStore::OnInit(TLVWriter) for circular buffers. + */ +CHIP_ERROR CHIPCircularTLVBuffer::OnInit(TLVWriter & writer, uint8_t *& bufStart, uint32_t & bufLen) +{ + return GetNewBuffer(writer, bufStart, bufLen); +} + /** * @brief * Get additional space for the TLVWriter. In actuality, the @@ -238,6 +247,15 @@ CHIP_ERROR CHIPCircularTLVBuffer::FinalizeBuffer(TLVWriter & ioWriter, uint8_t * return err; } +/** + * @brief + * Implements TLVBackingStore::OnInit(TVLReader) for circular buffers. + */ +CHIP_ERROR CHIPCircularTLVBuffer::OnInit(TLVReader & reader, const uint8_t *& bufStart, uint32_t & bufLen) +{ + return GetNextBuffer(reader, bufStart, bufLen); +} + /** * @brief * Get additional space for the TLVReader. @@ -304,167 +322,5 @@ CHIP_ERROR CHIPCircularTLVBuffer::GetNextBuffer(TLVReader & ioReader, const uint return err; } -/** - * @brief - * A trampoline to fetch more space for the TLVWriter. - * - * @param[in,out] ioWriter TLVWriter calling this function - * - * @param[in,out] inBufHandle A handle to the `CircularTLVWriter` object - * - * @param[out] outBufStart The pointer to the new buffer - * - * @param[out] outBufLen The available length for writing - * - * @retval #CHIP_NO_ERROR On success. - * - * @retval other If the function was unable to elide a complete - * top-level TLV element. - */ -CHIP_ERROR CHIPCircularTLVBuffer::GetNewBufferFunct(TLVWriter & ioWriter, uintptr_t & inBufHandle, uint8_t *& outBufStart, - uint32_t & outBufLen) -{ - CHIP_ERROR err = CHIP_NO_ERROR; - CHIPCircularTLVBuffer * buf; - - VerifyOrExit(inBufHandle != 0, err = CHIP_ERROR_INVALID_ARGUMENT); - - buf = reinterpret_cast(inBufHandle); - - err = buf->GetNewBuffer(ioWriter, outBufStart, outBufLen); - -exit: - return err; -} - -/** - * @brief - * A trampoline to CHIPCircularTLVBuffer::FinalizeBuffer - * - * @param[in,out] ioWriter TLVWriter calling this function - * - * @param[in,out] inBufHandle A handle to the `CircularTLVWriter` object - * - * @param[in] inBufStart pointer to the start of data (from `TLVWriter` - * perspective) - * - * @param[in] inBufLen length of data in the buffer pointed to by - * `inbufStart` - * - * @retval #CHIP_NO_ERROR Unconditionally. - */ -CHIP_ERROR CHIPCircularTLVBuffer::FinalizeBufferFunct(TLVWriter & ioWriter, uintptr_t inBufHandle, uint8_t * inBufStart, - uint32_t inBufLen) -{ - CHIP_ERROR err = CHIP_NO_ERROR; - CHIPCircularTLVBuffer * buf; - - VerifyOrExit(inBufHandle != 0, err = CHIP_ERROR_INVALID_ARGUMENT); - - buf = reinterpret_cast(inBufHandle); - - err = buf->FinalizeBuffer(ioWriter, inBufStart, inBufLen); - -exit: - return err; -} - -/** - * @brief - * A trampoline to CHIPCircularTLVBuffer::GetNextBuffer - * - * @param[in,out] ioReader TLVReader calling this function - * - * @param[in,out] inBufHandle A handle to the `CircularTLVWriter` object - * - * @param[in,out] outBufStart The reference to the data buffer. On - * return, it is set to a value within this - * buffer. - * - * @param[out] outBufLen On return, set to the number of continuous - * bytes that could be read out of the buffer. - * - * @retval #CHIP_NO_ERROR Succeeds unconditionally. - */ -CHIP_ERROR CHIPCircularTLVBuffer::GetNextBufferFunct(TLVReader & ioReader, uintptr_t & inBufHandle, const uint8_t *& outBufStart, - uint32_t & outBufLen) -{ - CHIP_ERROR err = CHIP_NO_ERROR; - CHIPCircularTLVBuffer * buf; - - VerifyOrExit(inBufHandle != 0, err = CHIP_ERROR_INVALID_ARGUMENT); - - buf = reinterpret_cast(inBufHandle); - - err = buf->GetNextBuffer(ioReader, outBufStart, outBufLen); - -exit: - return err; -} - -/** - * @brief - * Initializes a TLVWriter object to write from a single CHIPCircularTLVBuffer - * - * Writing begins at the last byte of the buffer. The number of bytes - * to be written is not constrained by the underlying circular buffer: - * writing new elements to the buffer will kick out previous elements - * as long as an individual top-level TLV structure fits within the - * buffer. For example, writing a 7-byte top-level boolean TLV into a - * 7 byte buffer will work indefinitely, but writing an 8-byte TLV - * structure will result in an error. - * - * @param[in] buf A pointer to a fully initialized CHIPCircularTLVBuffer - * - */ -void CircularTLVWriter::Init(CHIPCircularTLVBuffer * buf) -{ - mBufHandle = reinterpret_cast(buf); - mLenWritten = 0; - mMaxLen = UINT32_MAX; - mContainerType = kTLVType_NotSpecified; - SetContainerOpen(false); - SetCloseContainerReserved(false); - - ImplicitProfileId = kProfileIdNotSpecified; - GetNewBuffer = CHIPCircularTLVBuffer::GetNewBufferFunct; - FinalizeBuffer = CHIPCircularTLVBuffer::FinalizeBufferFunct; - - GetNewBuffer(*this, mBufHandle, mBufStart, mRemainingLen); - mWritePoint = mBufStart; -} - -/** - * @brief - * Initializes a TLVReader object to read from a single CHIPCircularTLVBuffer - * - * Parsing begins at the start of the buffer (obtained by the - * buffer->Start() position) and continues until the end of the buffer - * Parsing may wraparound within the buffer (on any element). At most - * buffer->GetQueueSize() bytes are read out. - * - * @param[in] buf A pointer to a fully initialized CHIPCircularTLVBuffer - * - */ -void CircularTLVReader::Init(CHIPCircularTLVBuffer * buf) -{ - uint32_t bufLen = 0; - - mBufHandle = reinterpret_cast(buf); - GetNextBuffer = CHIPCircularTLVBuffer::GetNextBufferFunct; - mLenRead = 0; - mReadPoint = nullptr; - GetNextBuffer(*this, mBufHandle, mReadPoint, bufLen); - mBufEnd = mReadPoint + bufLen; - mMaxLen = buf->DataLength(); - mControlByte = kTLVControlByte_NotSpecified; - mElemTag = AnonymousTag; - mElemLenOrVal = 0; - mContainerType = kTLVType_NotSpecified; - SetContainerOpen(false); - ImplicitProfileId = kProfileIdNotSpecified; - AppData = nullptr; -} - } // namespace TLV } // namespace chip diff --git a/src/lib/core/CHIPCircularTLVBuffer.h b/src/lib/core/CHIPCircularTLVBuffer.h index 33ea23c196719f..04d0b87e48a740 100644 --- a/src/lib/core/CHIPCircularTLVBuffer.h +++ b/src/lib/core/CHIPCircularTLVBuffer.h @@ -1,6 +1,6 @@ /* * - * Copyright (c) 2020 Project CHIP Authors + * Copyright (c) 2020-2021 Project CHIP Authors * Copyright (c) 2016-2017 Nest Labs, Inc. * All rights reserved. * @@ -54,16 +54,12 @@ namespace TLV { * buffer. * */ -class DLL_EXPORT CHIPCircularTLVBuffer +class DLL_EXPORT CHIPCircularTLVBuffer : public chip::TLV::TLVBackingStore { public: CHIPCircularTLVBuffer(uint8_t * inBuffer, uint32_t inBufferLength); CHIPCircularTLVBuffer(uint8_t * inBuffer, uint32_t inBufferLength, uint8_t * inHead); - CHIP_ERROR GetNewBuffer(TLVWriter & ioWriter, uint8_t *& outBufStart, uint32_t & outBufLen); - CHIP_ERROR FinalizeBuffer(TLVWriter & ioWriter, uint8_t * inBufStart, uint32_t inBufLen); - CHIP_ERROR GetNextBuffer(TLVReader & ioReader, const uint8_t *& outBufStart, uint32_t & outBufLen); - inline uint8_t * QueueHead() const { return mQueueHead; } inline uint8_t * QueueTail() const { return mQueue + ((static_cast(mQueueHead - mQueue) + mQueueLength) % mQueueSize); } inline uint32_t DataLength() const { return mQueueLength; } @@ -73,11 +69,12 @@ class DLL_EXPORT CHIPCircularTLVBuffer CHIP_ERROR EvictHead(); - static CHIP_ERROR GetNewBufferFunct(TLVWriter & ioWriter, uintptr_t & inBufHandle, uint8_t *& outBufStart, - uint32_t & outBufLen); - static CHIP_ERROR FinalizeBufferFunct(TLVWriter & ioWriter, uintptr_t inBufHandle, uint8_t * inBufStart, uint32_t inBufLen); - static CHIP_ERROR GetNextBufferFunct(TLVReader & ioReader, uintptr_t & inBufHandle, const uint8_t *& outBufStart, - uint32_t & outBufLen); + // chip::TLV::TLVBackingStore overrides: + CHIP_ERROR OnInit(TLVReader & reader, const uint8_t *& bufStart, uint32_t & bufLen) override; + CHIP_ERROR GetNextBuffer(TLVReader & ioReader, const uint8_t *& outBufStart, uint32_t & outBufLen) override; + CHIP_ERROR OnInit(TLVWriter & writer, uint8_t *& bufStart, uint32_t & bufLen) override; + CHIP_ERROR GetNewBuffer(TLVWriter & ioWriter, uint8_t *& outBufStart, uint32_t & outBufLen) override; + CHIP_ERROR FinalizeBuffer(TLVWriter & ioWriter, uint8_t * inBufStart, uint32_t inBufLen) override; /** * @typedef CHIP_ERROR (*ProcessEvictedElementFunct)(CHIPCircularTLVBuffer &inBuffer, void * inAppData, TLVReader &inReader) @@ -140,13 +137,40 @@ class DLL_EXPORT CHIPCircularTLVBuffer class DLL_EXPORT CircularTLVReader : public TLVReader { public: - void Init(CHIPCircularTLVBuffer * buf); + /** + * @brief + * Initializes a TLVReader object to read from a single CHIPCircularTLVBuffer + * + * Parsing begins at the start of the buffer (obtained by the + * buffer->Start() position) and continues until the end of the buffer + * Parsing may wraparound within the buffer (on any element). At most + * buffer->GetQueueSize() bytes are read out. + * + * @param[in] buf A pointer to a fully initialized CHIPCircularTLVBuffer + * + */ + void Init(CHIPCircularTLVBuffer & buf) { TLVReader::Init(buf, buf.DataLength()); } }; class DLL_EXPORT CircularTLVWriter : public TLVWriter { public: - void Init(CHIPCircularTLVBuffer * buf); + /** + * @brief + * Initializes a TLVWriter object to write from a single CHIPCircularTLVBuffer + * + * Writing begins at the last byte of the buffer. The number of bytes + * to be written is not constrained by the underlying circular buffer: + * writing new elements to the buffer will kick out previous elements + * as long as an individual top-level TLV structure fits within the + * buffer. For example, writing a 7-byte top-level boolean TLV into a + * 7 byte buffer will work indefinitely, but writing an 8-byte TLV + * structure will result in an error. + * + * @param[in] buf A pointer to a fully initialized CHIPCircularTLVBuffer + * + */ + void Init(CHIPCircularTLVBuffer & buf) { TLVWriter::Init(buf, UINT32_MAX); } }; } // namespace TLV diff --git a/src/lib/core/CHIPTLV.h b/src/lib/core/CHIPTLV.h index 8b5330143bfd1d..8ea06f8cebd3be 100644 --- a/src/lib/core/CHIPTLV.h +++ b/src/lib/core/CHIPTLV.h @@ -1,6 +1,6 @@ /* * - * Copyright (c) 2020 Project CHIP Authors + * Copyright (c) 2020-2021 Project CHIP Authors * Copyright (c) 2013-2017 Nest Labs, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -36,15 +36,6 @@ #include #include -// forward declaration of the PacketBuffer class used within the header. -namespace chip { -namespace System { - -class PacketBuffer; - -} // namespace System -} // namespace chip - /** * @namespace chip::TLV * @@ -67,13 +58,13 @@ inline uint8_t operator|(TLVTagControl lhs, TLVElementType rhs) return static_cast(lhs) | static_cast(rhs); } -using chip::System::PacketBuffer; - enum { kTLVControlByte_NotSpecified = 0xFFFF }; +class TLVBackingStore; + /** * Provides a memory efficient parser for data encoded in CHIP TLV format. * @@ -95,10 +86,8 @@ enum * The reader will continue to return CHIP_END_OF_TLV until it is reinitialized, or the current * container is exited (via CloseContainer() / ExitContainer()). * - * A TLVReader object can parse data directly from a fixed input buffer, or from a chain of one - * or more PacketBuffers. Additionally, applications can supply a @p GetNextBuffer function to - * feed data to the reader from an arbitrary source, e.g. a socket or a serial port. - * + * A TLVReader object can parse data directly from a fixed input buffer, or from memory provided + * by a TLVBackingStore. */ class DLL_EXPORT TLVReader { @@ -106,66 +95,692 @@ class DLL_EXPORT TLVReader friend class TLVUpdater; public: - // *** See CHIPTLVReader.cpp file for API documentation *** - + /** + * Initializes a TLVReader object from another TLVReader object. + * + * @param[in] aReader A read-only reference to the TLVReader to initialize + * this from. + * + */ void Init(const TLVReader & aReader); + + /** + * Initializes a TLVReader object to read from a single input buffer. + * + * @param[in] data A pointer to a buffer containing the TLV data to be parsed. + * @param[in] dataLen The length of the TLV data to be parsed. + * + */ void Init(const uint8_t * data, uint32_t dataLen); - void Init(PacketBuffer * buf, uint32_t maxLen = 0xFFFFFFFFUL); - void Init(PacketBuffer * buf, uint32_t maxLen, bool allowDiscontiguousBuffers); + /** + * Initializes a TLVReader object to read from a TLVBackingStore. + * + * Parsing begins at the backing store's start position and continues until the + * end of the data in the buffer, or maxLen bytes have been parsed. + * + * @param[in] backingStore A reference to a TLVBackingStore providing the TLV data to be parsed. + * @param[in] maxLen The maximum number of bytes to parse. Defaults to the amount of data + * in the input buffer. + * + * @retval #CHIP_NO_ERROR If the method succeeded. + * @retval other Other error codes returned by TLVBackingStore::OnInit(). + */ + CHIP_ERROR Init(TLVBackingStore & backingStore, uint32_t maxLen = UINT32_MAX); + + /** + * Advances the TLVReader object to the next TLV element to be read. + * + * The Next() method positions the reader object on the next element in a TLV encoding that resides + * in the same containment context. In particular, if the reader is positioned at the outer-most + * level of a TLV encoding, calling Next() will advance the reader to the next, top-most element. + * If the reader is positioned within a TLV container element (a structure, array or path), calling + * Next() will advance the reader to the next member element of the container. + * + * Since Next() constrains reader motion to the current containment context, calling Next() when + * the reader is positioned on a container element will advance @em over the container, skipping + * its member elements (and the members of any nested containers) until it reaches the first element + * after the container. + * + * When there are no further elements within a particular containment context the Next() method will + * return a #CHIP_END_OF_TLV error and the position of the reader will remain unchanged. + * + * @retval #CHIP_NO_ERROR If the reader was successfully positioned on a new element. + * @retval #CHIP_END_OF_TLV If no further elements are available. + * @retval #CHIP_ERROR_TLV_UNDERRUN If the underlying TLV encoding ended prematurely. + * @retval #CHIP_ERROR_INVALID_TLV_ELEMENT + * If the reader encountered an invalid or unsupported TLV element + * type. + * @retval #CHIP_ERROR_INVALID_TLV_TAG If the reader encountered a TLV tag in an invalid context. + * @retval #CHIP_ERROR_UNKNOWN_IMPLICIT_TLV_TAG + * If the reader encountered a implicitly-encoded TLV tag for which + * the corresponding profile id is unknown. + * @retval other Other CHIP or platform error codes returned by the configured + * TLVBackingStore. + * + */ CHIP_ERROR Next(); + + /** + * Advances the TLVReader object to the next TLV element to be read, asserting the type and tag of + * the new element. + * + * The Next(TLVType expectedType, uint64_t expectedTag) method is a convenience method that has the + * same behavior as Next(), but also verifies that the type and tag of the new TLV element match + * the supplied arguments. + * + * @param[in] expectedType The expected data type for the next element. + * @param[in] expectedTag The expected tag for the next element. + * + * @retval #CHIP_NO_ERROR If the reader was successfully positioned on a new element. + * @retval #CHIP_END_OF_TLV If no further elements are available. + * @retval #CHIP_ERROR_WRONG_TLV_TYPE If the type of the new element does not match the value + * of the @p expectedType argument. + * @retval #CHIP_ERROR_UNEXPECTED_TLV_ELEMENT + * If the tag associated with the new element does not match the + * value of the @p expectedTag argument. + * @retval #CHIP_ERROR_TLV_UNDERRUN If the underlying TLV encoding ended prematurely. + * @retval #CHIP_ERROR_INVALID_TLV_ELEMENT + * If the reader encountered an invalid or unsupported TLV + * element type. + * @retval #CHIP_ERROR_INVALID_TLV_TAG If the reader encountered a TLV tag in an invalid context. + * @retval other Other CHIP or platform error codes returned by the configured + * TLVBackingStore. + * + */ CHIP_ERROR Next(TLVType expectedType, uint64_t expectedTag); + /** + * Returns the type of the current TLV element. + * + * @return A TLVType value describing the data type of the current TLV element. If the reader + * is not positioned on a TLV element, the return value will be kTLVType_NotSpecified. + */ TLVType GetType() const; - uint64_t GetTag() const; + + /** + * Returns the tag associated with current TLV element. + * + * The value returned by GetTag() can be used with the tag utility functions (IsProfileTag(), + * IsContextTag(), ProfileIdFromTag(), etc.) to determine the type of tag and to extract various tag + * field values. + * + * @note If the reader is not positioned on a TLV element when GetTag() is called, the return value + * is undefined. Therefore whenever the position of the reader is uncertain applications should call + * GetType() to determine if the reader is position on an element (GetType() != kTLVType_NotSpecified) + * before calling GetTag(). + * + * @return An unsigned integer containing information about the tag associated with the current + * TLV element. + */ + uint64_t GetTag() const { return mElemTag; } + + /** + * Returns the length of data associated with current TLV element. + * + * Data length only applies to elements of type UTF8 string or byte string. For UTF8 strings, the + * value returned is the number of bytes in the string, not the number of characters. + * + * @return The length (in bytes) of data associated with the current TLV element, or 0 if the + * current element is not a UTF8 string or byte string, or if the reader is not + * positioned on an element. + */ uint32_t GetLength() const; - uint16_t GetControlByte() const; + /** + * Returns the control byte associated with current TLV element. + * + * Ideally, nobody ever needs to know about the control byte and only the + * internal implementation of TLV should have access to it. But, nevertheless, + * having access to the control byte is helpful for debugging purposes by the + * TLV Debug Utilities (that try to decode the tag control byte when pretty + * printing the TLV buffer contents). + * + * @note Unless you really know what you are doing, please refrain from using + * this method and the associated control byte information. + * + * @return An unsigned integer containing the control byte associated with + * the current TLV element. kTLVControlByte_NotSpecified is + * returned if the reader is not positioned @em on an element. + */ + uint16_t GetControlByte() const { return mControlByte; } + + /** + * Get the value of the current element as a bool type. + * + * @param[out] v Receives the value associated with current TLV element. + * + * @retval #CHIP_NO_ERROR If the method succeeded. + * @retval #CHIP_ERROR_WRONG_TLV_TYPE If the current element is not a TLV boolean type, or the + * reader is not positioned on an element. + */ CHIP_ERROR Get(bool & v); + + /** + * Get the value of the current element as an 8-bit signed integer. + * + * If the encoded integer value is larger than the output data type the resultant value will be + * truncated. + * + * @param[out] v Receives the value associated with current TLV element. + * + * @retval #CHIP_NO_ERROR If the method succeeded. + * @retval #CHIP_ERROR_WRONG_TLV_TYPE If the current element is not a TLV integer type (signed or + * unsigned), or the reader is not positioned on an element. + * + */ CHIP_ERROR Get(int8_t & v); + + /** + * Get the value of the current element as a 16-bit signed integer. + * + * If the encoded integer value is larger than the output data type the resultant value will be + * truncated. + * + * @param[out] v Receives the value associated with current TLV element. + * + * @retval #CHIP_NO_ERROR If the method succeeded. + * @retval #CHIP_ERROR_WRONG_TLV_TYPE If the current element is not a TLV integer type (signed or + * unsigned), or the reader is not positioned on an element. + * + */ CHIP_ERROR Get(int16_t & v); + + /** + * Get the value of the current element as a 32-bit signed integer. + * + * If the encoded integer value is larger than the output data type the resultant value will be + * truncated. + * + * @param[out] v Receives the value associated with current TLV element. + * + * @retval #CHIP_NO_ERROR If the method succeeded. + * @retval #CHIP_ERROR_WRONG_TLV_TYPE If the current element is not a TLV integer type (signed or + * unsigned), or the reader is not positioned on an element. + * + */ CHIP_ERROR Get(int32_t & v); + + /** + * Get the value of the current element as a 64-bit signed integer. + * + * If the encoded integer value is larger than the output data type the resultant value will be + * truncated. + * + * @param[out] v Receives the value associated with current TLV element. + * + * @retval #CHIP_NO_ERROR If the method succeeded. + * @retval #CHIP_ERROR_WRONG_TLV_TYPE If the current element is not a TLV integer type (signed or + * unsigned), or the reader is not positioned on an element. + * + */ CHIP_ERROR Get(int64_t & v); + + /** + * Get the value of the current element as an 8-bit unsigned integer. + * + * If the encoded integer value is larger than the output data type the resultant value will be + * truncated. Similarly, if the encoded integer value is negative, the value will be converted + * to unsigned. + * + * @param[out] v Receives the value associated with current TLV element. + * + * @retval #CHIP_NO_ERROR If the method succeeded. + * @retval #CHIP_ERROR_WRONG_TLV_TYPE If the current element is not a TLV integer type (signed or + * unsigned), or the reader is not positioned on an element. + * + */ CHIP_ERROR Get(uint8_t & v); + + /** + * Get the value of the current element as a 16-bit unsigned integer. + * + * If the encoded integer value is larger than the output data type the resultant value will be + * truncated. Similarly, if the encoded integer value is negative, the value will be converted + * to unsigned. + * + * @param[out] v Receives the value associated with current TLV element. + * + * @retval #CHIP_NO_ERROR If the method succeeded. + * @retval #CHIP_ERROR_WRONG_TLV_TYPE If the current element is not a TLV integer type (signed or + * unsigned), or the reader is not positioned on an element. + * + */ CHIP_ERROR Get(uint16_t & v); + + /** + * Get the value of the current element as a 32-bit unsigned integer. + * + * If the encoded integer value is larger than the output data type the resultant value will be + * truncated. Similarly, if the encoded integer value is negative, the value will be converted + * to unsigned. + * + * @param[out] v Receives the value associated with current TLV element. + * + * @retval #CHIP_NO_ERROR If the method succeeded. + * @retval #CHIP_ERROR_WRONG_TLV_TYPE If the current element is not a TLV integer type (signed or + unsigned), or the reader is not positioned on an element. + * + */ CHIP_ERROR Get(uint32_t & v); + + /** + * Get the value of the current element as a 64-bit unsigned integer. + * + * If the encoded integer value is negative, the value will be converted to unsigned. + * + * @param[out] v Receives the value associated with current TLV element. + * + * @retval #CHIP_NO_ERROR If the method succeeded. + * @retval #CHIP_ERROR_WRONG_TLV_TYPE If the current element is not a TLV integer type (signed or + * unsigned), or the reader is not positioned on an element. + * + */ CHIP_ERROR Get(uint64_t & v); - CHIP_ERROR Get(float & v); + + /** + * Get the value of the current element as a double-precision floating point number. + * + * @param[out] v Receives the value associated with current TLV element. + * + * @retval #CHIP_NO_ERROR If the method succeeded. + * @retval #CHIP_ERROR_WRONG_TLV_TYPE If the current element is not a TLV floating point type, or + * the reader is not positioned on an element. + * + */ CHIP_ERROR Get(double & v); + + /** + * Get the value of the current element as a single-precision floating point number. + * + * @param[out] v Receives the value associated with current TLV element. + * + * @retval #CHIP_NO_ERROR If the method succeeded. + * @retval #CHIP_ERROR_WRONG_TLV_TYPE If the current element is not a TLV floating point type, or + * the reader is not positioned on an element. + * + */ + CHIP_ERROR Get(float & v); + + /** + * Get the value of the current byte or UTF8 string element. + * + * To determine the required input buffer size, call the GetLength() method before calling GetBytes(). + * + * @note The data output by this method is NOT null-terminated. + * + * @param[in] buf A pointer to a buffer to receive the string data. + * @param[in] bufSize The size in bytes of the buffer pointed to by @p buf. + * + * @retval #CHIP_NO_ERROR If the method succeeded. + * @retval #CHIP_ERROR_WRONG_TLV_TYPE If the current element is not a TLV byte or UTF8 string, or + * the reader is not positioned on an element. + * @retval #CHIP_ERROR_BUFFER_TOO_SMALL + * If the supplied buffer is too small to hold the data associated + * with the current element. + * @retval #CHIP_ERROR_TLV_UNDERRUN If the underlying TLV encoding ended prematurely. + * @retval other Other CHIP or platform error codes returned by the configured + * TLVBackingStore. + * + */ CHIP_ERROR GetBytes(uint8_t * buf, uint32_t bufSize); + + /** + * Allocates and returns a buffer containing the value of the current byte or UTF8 string. + * + * This method creates a buffer for and returns a copy of the data associated with the byte + * or UTF-8 string element at the current position. Memory for the buffer is obtained with + * Platform::MemoryAlloc() and should be freed with Platform::MemoryFree() by the caller when + * it is no longer needed. + * + * @note The data returned by this method is NOT null-terminated. + * + * @param[out] buf A reference to a pointer to which a heap-allocated buffer of + * @p dataLen bytes will be assigned on success. + * @param[out] dataLen A reference to storage for the size, in bytes, of @p buf on + * success. + * + * @retval #CHIP_NO_ERROR If the method succeeded. + * @retval #CHIP_ERROR_WRONG_TLV_TYPE If the current element is not a TLV byte or UTF8 string, or + * the reader is not positioned on an element. + * @retval #CHIP_ERROR_NO_MEMORY If memory could not be allocated for the output buffer. + * @retval #CHIP_ERROR_TLV_UNDERRUN If the underlying TLV encoding ended prematurely. + * @retval other Other CHIP or platform error codes returned by the configured + * TLVBackingStore. + * + */ CHIP_ERROR DupBytes(uint8_t *& buf, uint32_t & dataLen); + + /** + * Get the value of the current byte or UTF8 string element as a null terminated string. + * + * To determine the required input buffer size, call the GetLength() method before calling GetBytes(). + * The input buffer should be at least one byte bigger than the string length to accommodate the null + * character. + * + * @param[in] buf A pointer to a buffer to receive the byte string data. + * @param[in] bufSize The size in bytes of the buffer pointed to by @p buf. + * + * @retval #CHIP_NO_ERROR If the method succeeded. + * @retval #CHIP_ERROR_WRONG_TLV_TYPE If the current element is not a TLV byte or UTF8 string, or + * the reader is not positioned on an element. + * @retval #CHIP_ERROR_BUFFER_TOO_SMALL + * If the supplied buffer is too small to hold the data associated + * with the current element. + * @retval #CHIP_ERROR_TLV_UNDERRUN If the underlying TLV encoding ended prematurely. + * @retval other Other CHIP or platform error codes returned by the configured + * TLVBackingStore. + * + */ CHIP_ERROR GetString(char * buf, uint32_t bufSize); + + /** + * Allocates and returns a buffer containing the null-terminated value of the current byte or UTF8 + * string. + * + * This method creates a buffer for and returns a null-terminated copy of the data associated with + * the byte or UTF-8 string element at the current position. Memory for the buffer is obtained with + * Platform::MemoryAlloc() and should be freed with chip::Platform::MemoryFree() by the caller when + * it is no longer needed. + * + * @param[out] buf A reference to a pointer to which a heap-allocated buffer of + * will be assigned on success. + * + * @retval #CHIP_NO_ERROR If the method succeeded. + * @retval #CHIP_ERROR_WRONG_TLV_TYPE If the current element is not a TLV byte or UTF8 string, or + * the reader is not positioned on an element. + * @retval #CHIP_ERROR_NO_MEMORY If memory could not be allocated for the output buffer. + * @retval #CHIP_ERROR_TLV_UNDERRUN If the underlying TLV encoding ended prematurely. + * @retval other Other CHIP or platform error codes returned by the configured + * TLVBackingStore. + * + */ CHIP_ERROR DupString(char *& buf); + + /** + * Get a pointer to the initial encoded byte of a TLV byte or UTF8 string element. + * + * This method returns a direct pointer the encoded string value within the underlying input buffer. + * To succeed, the method requires that the entirety of the string value be present in a single buffer. + * Otherwise the method returns #CHIP_ERROR_TLV_UNDERRUN. This makes the method of limited use when + * reading data from multiple discontiguous buffers. + * + * @param[out] data A reference to a const pointer that will receive a pointer to + * the underlying string data. + * + * @retval #CHIP_NO_ERROR If the method succeeded. + * @retval #CHIP_ERROR_WRONG_TLV_TYPE If the current element is not a TLV byte or UTF8 string, or the + * reader is not positioned on an element. + * @retval #CHIP_ERROR_TLV_UNDERRUN If the underlying TLV encoding ended prematurely or the value + * of the current string element is not contained within a single + * contiguous buffer. + * @retval other Other CHIP or platform error codes returned by the configured + * TLVBackingStore. + * + */ CHIP_ERROR GetDataPtr(const uint8_t *& data); + /** + * Prepares a TLVReader object for reading the members of TLV container element. + * + * The EnterContainer() method prepares the current TLVReader object to begin reading the member + * elements of a TLV container (a structure, array or path). For every call to EnterContainer() + * applications must make a corresponding call to ExitContainer(). + * + * When EnterContainer() is called the TLVReader object must be positioned on the container element + * to be read. The method takes as an argument a reference to a TLVType value which will be used + * to save the context of the reader while it is reading the container. + * + * When the EnterContainer() method returns, the reader is positioned immediately @em before the + * first member of the container. Repeatedly calling Next() will advance the reader through the members + * of the collection until the end is reached, at which point the reader will return CHIP_END_OF_TLV. + * + * Once the application has finished reading a container it can continue reading the elements after + * the container by calling the ExitContainer() method. + * + * @param[out] outerContainerType A reference to a TLVType value that will receive the context + * of the reader. + * + * @retval #CHIP_NO_ERROR If the method succeeded. + * @retval #CHIP_ERROR_INCORRECT_STATE If the current element is not positioned on a container element. + * + */ CHIP_ERROR EnterContainer(TLVType & outerContainerType); + + /** + * Completes the reading of a TLV container and prepares a TLVReader object to read elements + * after the container. + * + * The ExitContainer() method restores the state of a TLVReader object after a call to + * EnterContainer(). For every call to EnterContainer() applications must make a corresponding + * call to ExitContainer(), passing the context value returned by the EnterContainer() method. + * + * When ExitContainer() returns, the reader is positioned immediately before the first element that + * follows the container. From this point an application can use the Next() method to advance + * through any remaining elements. + * + * Once EnterContainer() has been called, applications can call ExitContainer() on a reader at any + * point in time, regardless of whether all elements in the underlying container have been read. + * + * @note Any changes made to the configuration of the reader between the calls to EnterContainer() + * and ExitContainer() are NOT undone by the call to ExitContainer(). For example, a change to the + * implicit profile id (@p ImplicitProfileId) will not be reversed when a container is exited. Thus + * it is the application's responsibility to adjust the configuration accordingly at the appropriate + * times. + * + * @param[in] outerContainerType The TLVType value that was returned by the EnterContainer() method. + * + * @retval #CHIP_NO_ERROR If the method succeeded. + * @retval #CHIP_ERROR_INCORRECT_STATE If OpenContainer() has not been called on the reader, or if + * the container reader does not match the one passed to the + * OpenContainer() method. + * @retval #CHIP_ERROR_TLV_UNDERRUN If the underlying TLV encoding ended prematurely. + * @retval #CHIP_ERROR_INVALID_TLV_ELEMENT + * If the reader encountered an invalid or unsupported TLV element type. + * @retval #CHIP_ERROR_INVALID_TLV_TAG If the reader encountered a TLV tag in an invalid context. + * @retval other Other CHIP or platform error codes returned by the configured + * TLVBackingStore. + * + */ CHIP_ERROR ExitContainer(TLVType outerContainerType); + + /** + * Initializes a new TLVReader object for reading the members of a TLV container element. + * + * The OpenContainer() method initializes a new TLVReader object for reading the member elements of a + * TLV container (a structure, array or path). When OpenContainer() is called, the current TLVReader + * object must be positioned on the container element to be read. The method takes as its sole argument + * a reference to a new reader that will be initialized to read the container. This reader is known as + * the container reader while the reader on which OpenContainer() is called is known as the parent + * reader. + * + * When the OpenContainer() method returns, the container reader is positioned immediately before the + * first member of the container. Calling Next() on the container reader will advance through the members + * of the collection until the end is reached, at which point the reader will return CHIP_END_OF_TLV. + * + * While the container reader is open, applications must not make calls on or otherwise alter the state + * of the parent reader. Once an application has finished using the container reader it must close it + * by calling CloseContainer() on the parent reader, passing the container reader as an argument. + * Applications may close the container reader at any point, with or without reading all elements + * contained in the underlying container. After the container reader is closed, applications may + * continue their use of the parent reader. + * + * The container reader inherits various configuration properties from the parent reader. These are: + * + * @li The implicit profile id (ImplicitProfileId) + * @li The application data pointer (AppData) + * @li The GetNextBuffer function pointer + * + * @note The EnterContainer() method can be used as an alternative to OpenContainer() to read a + * container element without initializing a new reader object. + * + * @param[out] containerReader A reference to a TLVReader object that will be initialized for + * reading the members of the current container element. Any data + * associated with the supplied object is overwritten. + * + * @retval #CHIP_NO_ERROR If the method succeeded. + * @retval #CHIP_ERROR_INCORRECT_STATE If the current element is not positioned on a container element. + * + */ CHIP_ERROR OpenContainer(TLVReader & containerReader); + + /** + * Completes the reading of a TLV container after a call to OpenContainer(). + * + * The CloseContainer() method restores the state of a parent TLVReader object after a call to + * OpenContainer(). For every call to OpenContainer() applications must make a corresponding + * call to CloseContainer(), passing a reference to the same container reader to both methods. + * + * When CloseContainer() returns, the parent reader is positioned immediately before the first + * element that follows the container. From this point an application can use the Next() method + * to advance through any remaining elements. + * + * Applications can call close CloseContainer() on a parent reader at any point in time, regardless + * of whether all elements in the underlying container have been read. After CloseContainer() has + * been called, the application should consider the container reader 'de-initialized' and must not + * use it further without re-initializing it. + * + * @param[in] containerReader A reference to the TLVReader object that was supplied to the + * OpenContainer() method. + * + * @retval #CHIP_NO_ERROR If the method succeeded. + * @retval #CHIP_ERROR_INCORRECT_STATE If OpenContainer() has not been called on the reader, or if + * the container reader does not match the one passed to the + * OpenContainer() method. + * @retval #CHIP_ERROR_TLV_UNDERRUN If the underlying TLV encoding ended prematurely. + * @retval #CHIP_ERROR_INVALID_TLV_ELEMENT + * If the reader encountered an invalid or unsupported TLV + * element type. + * @retval #CHIP_ERROR_INVALID_TLV_TAG If the reader encountered a TLV tag in an invalid context. + * @retval other Other CHIP or platform error codes returned by the configured + * TLVBackingStore. + * + */ CHIP_ERROR CloseContainer(TLVReader & containerReader); - TLVType GetContainerType() const; + + /** + * Returns the type of the container within which the TLVReader is currently reading. + * + * The GetContainerType() method returns the type of the TLV container within which the TLVReader + * is reading. If the TLVReader is positioned at the outer-most level of a TLV encoding (i.e. before, + * on or after the outer-most TLV element), the method will return kTLVType_NotSpecified. + * + * @return The TLVType of the current container, or kTLVType_NotSpecified if the TLVReader is not + * positioned within a container. + */ + TLVType GetContainerType() const { return mContainerType; } + + /** + * Verifies that the TLVReader object is at the end of a TLV container. + * + * The VerifyEndOfContainer() method verifies that there are no further TLV elements to be read + * within the current TLV container. This is a convenience method that is equivalent to calling + * Next() and checking for a return value of CHIP_END_OF_TLV. + * + * @note When there are more TLV elements in the collection, this method will change the position + * of the reader. + * + * @retval #CHIP_NO_ERROR If there are no further TLV elements to be read. + * @retval #CHIP_ERROR_UNEXPECTED_TLV_ELEMENT + * If another TLV element was found in the collection. + * @retval #CHIP_ERROR_TLV_UNDERRUN If the underlying TLV encoding ended prematurely. + * @retval #CHIP_ERROR_INVALID_TLV_ELEMENT + * If the reader encountered an invalid or unsupported TLV element + * type. + * @retval #CHIP_ERROR_INVALID_TLV_TAG If the reader encountered a TLV tag in an invalid context. + * @retval other Other CHIP or platform error codes returned by the configured + * TLVBackingStore. + * + */ CHIP_ERROR VerifyEndOfContainer(); + /** + * Returns the total number of bytes read since the reader was initialized. + * + * @return Total number of bytes read since the reader was initialized. + */ uint32_t GetLengthRead() const { return mLenRead; } + + /** + * Returns the total number of bytes that can be read until the max read length is reached. + * + * @return Total number of bytes that can be read until the max read length is reached. + */ uint32_t GetRemainingLength() const { return mMaxLen - mLenRead; } + /** + * Gets the point in the underlying input buffer that corresponds to the reader's current position. + * + * @note Depending on the type of the current element, GetReadPoint() will return a pointer that + * is some number of bytes *after* the first byte of the element. For string types (UTF8 and byte + * strings), the pointer will point to the first byte of the string's value. For container types + * (structures, arrays and paths), the pointer will point to the first member element within the + * container. For all other types, the pointer will point to the byte immediately after the element's + * encoding. + * + * @return A pointer into underlying input buffer that corresponds to the reader's current position. + */ const uint8_t * GetReadPoint() const { return mReadPoint; } - uintptr_t GetBufHandle() const { return mBufHandle; } + /** + * Advances the TLVReader object to immediately after the current TLV element. + * + * The Skip() method positions the reader object immediately @em after the current TLV element, such + * that a subsequent call to Next() will advance the reader to the following element. Like Next(), + * if the reader is positioned on a container element at the time of the call, the members of the + * container will be skipped. If the reader is not positioned on any element, its position remains + * unchanged. + * + * @retval #CHIP_NO_ERROR If the reader was successfully positioned on a new element. + * @retval #CHIP_END_OF_TLV If no further elements are available. + * @retval #CHIP_ERROR_TLV_UNDERRUN If the underlying TLV encoding ended prematurely. + * @retval #CHIP_ERROR_INVALID_TLV_ELEMENT + * If the reader encountered an invalid or unsupported TLV + * element type. + * @retval #CHIP_ERROR_INVALID_TLV_TAG If the reader encountered a TLV tag in an invalid context. + * @retval other Other CHIP or platform error codes returned by the configured + * TLVBackingStore. + * + */ CHIP_ERROR Skip(); + /** + * Position the destination reader on the next element with the given tag within this reader's current container context + * + * @param[in] tagInApiForm The destination context tag value + * @param[in] destReader The destination TLV reader value that was located by given tag + * + * @retval #CHIP_NO_ERROR If the reader was successfully positioned at the given tag + * @retval #CHIP_END_OF_TLV If the given tag cannot be found + * @retval other Other CHIP or platform error codes + */ CHIP_ERROR FindElementWithTag(const uint64_t tagInApiForm, TLVReader & destReader) const; + /** + * The profile id to be used for profile tags encoded in implicit form. + * + * When the reader encounters a profile-specific tag that has been encoded in implicit form, it + * uses the value of the @p ImplicitProfileId property as the assumed profile id for the tag. + * + * By default, the @p ImplicitProfileId property is set to kProfileIdNotSpecified. When decoding + * TLV that contains implicitly-encoded tags, applications must set @p ImplicitProfileId prior + * to reading any TLV elements having such tags. The appropriate profile id is usually dependent + * on the context of the application or protocol being spoken. + * + * If an implicitly-encoded tag is encountered while @p ImplicitProfileId is set to + * kProfileIdNotSpecified, the reader will return a #CHIP_ERROR_UNKNOWN_IMPLICIT_TLV_TAG error. + */ uint32_t ImplicitProfileId; - void * AppData; - typedef CHIP_ERROR (*GetNextBufferFunct)(TLVReader & reader, uintptr_t & bufHandle, const uint8_t *& bufStart, - uint32_t & bufLen); - GetNextBufferFunct GetNextBuffer; + /** + * A pointer field that can be used for application-specific data. + */ + void * AppData; protected: uint64_t mElemTag; uint64_t mElemLenOrVal; - uintptr_t mBufHandle; + TLVBackingStore * mBackingStore; const uint8_t * mReadPoint; const uint8_t * mBufEnd; uint32_t mLenRead; @@ -190,9 +805,6 @@ class DLL_EXPORT TLVReader CHIP_ERROR ReadData(uint8_t * buf, uint32_t len); CHIP_ERROR GetElementHeadLength(uint8_t & elemHeadBytes) const; TLVElementType ElementType() const; - - static CHIP_ERROR GetNextPacketBuffer(TLVReader & reader, uintptr_t & bufHandle, const uint8_t *& bufStart, uint32_t & bufLen); - static CHIP_ERROR FailGetNextBuffer(TLVReader & reader, uintptr_t & bufHandle, const uint8_t *& bufStart, uint32_t & bufLen); }; /** @@ -204,81 +816,988 @@ class DLL_EXPORT TLVReader * (structures, arrays or paths) by calling the writer's OpenContainer() or EnterContainer() * methods. * - * A TLVWriter object can write data directly to a fixed output buffer, or to a chain of one or - * more PacketBuffer objects. Additionally, applications can supply their own @p GetNewBuffer and - * @p FinalizeBuffer functions to direct output to an arbitrary destination, e.g. a socket or an - * event queue. - * + * A TLVWriter object can write data directly to a fixed output buffer, or to memory provided by + * a TLVBackingStore. */ class DLL_EXPORT TLVWriter { friend class TLVUpdater; public: - // *** See CHIPTLVWriter.cpp file for API documentation *** - + /** + * Initializes a TLVWriter object to write into a single output buffer. + * + * @note Applications must call Finalize() on the writer before using the contents of the output + * buffer. + * + * @param[in] buf A pointer to the buffer into which TLV should be written. + * @param[in] maxLen The maximum number of bytes that should be written to the output buffer. + * + */ void Init(uint8_t * buf, uint32_t maxLen); - void Init(PacketBuffer * buf, uint32_t maxLen = 0xFFFFFFFFUL); - void Init(PacketBuffer * buf, uint32_t maxLen, bool allowDiscontiguousBuffers); + /** + * Initializes a TLVWriter object to write into memory provided by a TLVBackingStore. + * + * @note Applications must call Finalize() on the writer before using the contents of the buffer. + * + * @param[in] backingStore A TLVBackingStore providing memory, which must outlive the TVLWriter. + * @param[in] maxLen The maximum number of bytes that should be written to the output buffer. + * + * @retval #CHIP_NO_ERROR If the method succeeded. + * @retval other Other error codes returned by TLVBackingStore::OnInit(). + */ + CHIP_ERROR Init(TLVBackingStore & backingStore, uint32_t maxLen = UINT32_MAX); + + /** + * Finish the writing of a TLV encoding. + * + * The Finalize() method completes the process of writing a TLV encoding to the underlying output + * buffer. The method must be called by the application before it uses the contents of the buffer. + * Finalize() can only be called when there are no container writers open for the current writer. + * (See @p OpenContainer()). + * + * @retval #CHIP_NO_ERROR If the encoding was finalized successfully. + * @retval #CHIP_ERROR_TLV_CONTAINER_OPEN + * If a container writer has been opened on the current writer and not + * yet closed. + * @retval other Other CHIP or platform-specific errors returned by the configured + * FinalizeBuffer() function. + */ CHIP_ERROR Finalize(); + /** + * Encodes a TLV signed integer value. + * + * @param[in] tag The TLV tag to be encoded with the value, or @p AnonymousTag if the + * value should be encoded without a tag. Tag values should be + * constructed with one of the tag definition functions ProfileTag(), + * ContextTag() or CommonTag(). + * @param[in] v The value to be encoded. + * + * @retval #CHIP_NO_ERROR If the method succeeded. + * @retval #CHIP_ERROR_TLV_CONTAINER_OPEN + * If a container writer has been opened on the current writer and not + * yet closed. + * @retval #CHIP_ERROR_INVALID_TLV_TAG + * If the specified tag value is invalid or inappropriate in the context + * in which the value is being written. + * @retval #CHIP_ERROR_BUFFER_TOO_SMALL + * If writing the value would exceed the limit on the maximum number of + * bytes specified when the writer was initialized. + * @retval #CHIP_ERROR_NO_MEMORY + * If an attempt to allocate an output buffer failed due to lack of + * memory. + * @retval other Other CHIP or platform-specific errors returned by the configured + * TLVBackingStore. + * + */ CHIP_ERROR Put(uint64_t tag, int8_t v); + + /** + * Encodes a TLV signed integer value. + * + * @param[in] tag The TLV tag to be encoded with the value, or @p AnonymousTag if the + * value should be encoded without a tag. Tag values should be + * constructed with one of the tag definition functions ProfileTag(), + * ContextTag() or CommonTag(). + * @param[in] v The value to be encoded. + * @param[in] preserveSize True if the value should be encoded in the same number of bytes as + * at the input type. False if value should be encoded in the minimum + * number of bytes necessary to represent the value. Note: Applications + * are strongly encouraged to set this parameter to false. + * + * @retval #CHIP_NO_ERROR If the method succeeded. + * @retval #CHIP_ERROR_TLV_CONTAINER_OPEN + * If a container writer has been opened on the current writer and not + * yet closed. + * @retval #CHIP_ERROR_INVALID_TLV_TAG + * If the specified tag value is invalid or inappropriate in the context + * in which the value is being written. + * @retval #CHIP_ERROR_BUFFER_TOO_SMALL + * If writing the value would exceed the limit on the maximum number of + * bytes specified when the writer was initialized. + * @retval #CHIP_ERROR_NO_MEMORY + * If an attempt to allocate an output buffer failed due to lack of + * memory. + * @retval other Other CHIP or platform-specific errors returned by the configured + * TLVBackingStore. + * + */ CHIP_ERROR Put(uint64_t tag, int8_t v, bool preserveSize); + + /** + * @overload CHIP_ERROR TLVWriter::Put(uint64_t tag, int8_t v) + */ CHIP_ERROR Put(uint64_t tag, int16_t v); + + /** + * @overload CHIP_ERROR TLVWriter::Put(uint64_t tag, int8_t v, bool preserveSize) + */ CHIP_ERROR Put(uint64_t tag, int16_t v, bool preserveSize); + + /** + * @overload CHIP_ERROR TLVWriter::Put(uint64_t tag, int8_t v) + */ CHIP_ERROR Put(uint64_t tag, int32_t v); + + /** + * @overload CHIP_ERROR TLVWriter::Put(uint64_t tag, int8_t v, bool preserveSize) + */ CHIP_ERROR Put(uint64_t tag, int32_t v, bool preserveSize); + + /** + * @overload CHIP_ERROR TLVWriter::Put(uint64_t tag, int8_t v) + */ CHIP_ERROR Put(uint64_t tag, int64_t v); + + /** + * @overload CHIP_ERROR TLVWriter::Put(uint64_t tag, int8_t v, bool preserveSize) + */ CHIP_ERROR Put(uint64_t tag, int64_t v, bool preserveSize); + + /** + * Encodes a TLV unsigned integer value. + * + * @param[in] tag The TLV tag to be encoded with the value, or @p AnonymousTag if the + * value should be encoded without a tag. Tag values should be + * constructed with one of the tag definition functions ProfileTag(), + * ContextTag() or CommonTag(). + * @param[in] v The value to be encoded. + * + * @retval #CHIP_NO_ERROR If the method succeeded. + * @retval #CHIP_ERROR_TLV_CONTAINER_OPEN + * If a container writer has been opened on the current writer and not + * yet closed. + * @retval #CHIP_ERROR_INVALID_TLV_TAG + * If the specified tag value is invalid or inappropriate in the context + * in which the value is being written. + * @retval #CHIP_ERROR_BUFFER_TOO_SMALL + * If writing the value would exceed the limit on the maximum number of + * bytes specified when the writer was initialized. + * @retval #CHIP_ERROR_NO_MEMORY + * If an attempt to allocate an output buffer failed due to lack of + * memory. + * @retval other Other CHIP or platform-specific errors returned by the configured + * TLVBackingStore. + * + */ CHIP_ERROR Put(uint64_t tag, uint8_t v); + + /** + * Encodes a TLV unsigned integer value. + * + * @param[in] tag The TLV tag to be encoded with the value, or @p AnonymousTag if the + * value should be encoded without a tag. Tag values should be + * constructed with one of the tag definition functions ProfileTag(), + * ContextTag() or CommonTag(). + * @param[in] v The value to be encoded. + * @param[in] preserveSize True if the value should be encoded in the same number of bytes as + * at the input type. False if value should be encoded in the minimum + * number of bytes necessary to represent the value. Note: Applications + * are strongly encouraged to set this parameter to false. + * + * @retval #CHIP_NO_ERROR If the method succeeded. + * @retval #CHIP_ERROR_TLV_CONTAINER_OPEN + * If a container writer has been opened on the current writer and not + * yet closed. + * @retval #CHIP_ERROR_INVALID_TLV_TAG + * If the specified tag value is invalid or inappropriate in the context + * in which the value is being written. + * @retval #CHIP_ERROR_BUFFER_TOO_SMALL + * If writing the value would exceed the limit on the maximum number of + * bytes specified when the writer was initialized. + * @retval #CHIP_ERROR_NO_MEMORY + * If an attempt to allocate an output buffer failed due to lack of + * memory. + * @retval other Other CHIP or platform-specific errors returned by the configured + * TLVBackingStore. + * + */ CHIP_ERROR Put(uint64_t tag, uint8_t v, bool preserveSize); + + /** + * @overload CHIP_ERROR TLVWriter::Put(uint64_t tag, uint8_t v) + */ CHIP_ERROR Put(uint64_t tag, uint16_t v); + + /** + * @overload CHIP_ERROR TLVWriter::Put(uint64_t tag, uint8_t v, bool preserveSize) + */ CHIP_ERROR Put(uint64_t tag, uint16_t v, bool preserveSize); + + /** + * @overload CHIP_ERROR TLVWriter::Put(uint64_t tag, uint8_t v) + */ CHIP_ERROR Put(uint64_t tag, uint32_t v); + + /** + * @overload CHIP_ERROR TLVWriter::Put(uint64_t tag, uint8_t v, bool preserveSize) + */ CHIP_ERROR Put(uint64_t tag, uint32_t v, bool preserveSize); + + /** + * @overload CHIP_ERROR TLVWriter::Put(uint64_t tag, uint8_t v) + */ CHIP_ERROR Put(uint64_t tag, uint64_t v); + + /** + * @overload CHIP_ERROR TLVWriter::Put(uint64_t tag, uint8_t v, bool preserveSize) + */ CHIP_ERROR Put(uint64_t tag, uint64_t v, bool preserveSize); - CHIP_ERROR Put(uint64_t tag, float v); + + /** + * Encodes a TLV floating point value. + * + * @param[in] tag The TLV tag to be encoded with the value, or @p AnonymousTag if the + * value should be encoded without a tag. Tag values should be + * constructed with one of the tag definition functions ProfileTag(), + * ContextTag() or CommonTag(). + * @param[in] v The value to be encoded. + * + * @retval #CHIP_NO_ERROR If the method succeeded. + * @retval #CHIP_ERROR_TLV_CONTAINER_OPEN + * If a container writer has been opened on the current writer and not + * yet closed. + * @retval #CHIP_ERROR_INVALID_TLV_TAG + * If the specified tag value is invalid or inappropriate in the context + * in which the value is being written. + * @retval #CHIP_ERROR_BUFFER_TOO_SMALL + * If writing the value would exceed the limit on the maximum number of + * bytes specified when the writer was initialized. + * @retval #CHIP_ERROR_NO_MEMORY + * If an attempt to allocate an output buffer failed due to lack of + * memory. + * @retval other Other CHIP or platform-specific errors returned by the configured + * TLVBackingStore. + * + */ CHIP_ERROR Put(uint64_t tag, double v); + + /** + * @overload CHIP_ERROR TLVWriter::Put(uint64_t tag, double v) + */ + CHIP_ERROR Put(uint64_t tag, float v); + + /** + * Encodes a TLV boolean value. + * + * @param[in] tag The TLV tag to be encoded with the value, or @p AnonymousTag if the + * value should be encoded without a tag. Tag values should be + * constructed with one of the tag definition functions ProfileTag(), + * ContextTag() or CommonTag(). + * @param[in] v The value to be encoded. + * + * @retval #CHIP_NO_ERROR If the method succeeded. + * @retval #CHIP_ERROR_TLV_CONTAINER_OPEN + * If a container writer has been opened on the current writer and not + * yet closed. + * @retval #CHIP_ERROR_INVALID_TLV_TAG + * If the specified tag value is invalid or inappropriate in the context + * in which the value is being written. + * @retval #CHIP_ERROR_BUFFER_TOO_SMALL + * If writing the value would exceed the limit on the maximum number of + * bytes specified when the writer was initialized. + * @retval #CHIP_ERROR_NO_MEMORY + * If an attempt to allocate an output buffer failed due to lack of + * memory. + * @retval other Other CHIP or platform-specific errors returned by the configured + * TLVBackingStore. + * + */ CHIP_ERROR PutBoolean(uint64_t tag, bool v); + + /** + * Encodes a TLV byte string value. + * + * @param[in] tag The TLV tag to be encoded with the value, or @p AnonymousTag if the + * value should be encoded without a tag. Tag values should be + * constructed with one of the tag definition functions ProfileTag(), + * ContextTag() or CommonTag(). + * @param[in] buf A pointer to a buffer containing the bytes string to be encoded. + * @param[in] len The number of bytes to be encoded. + * + * @retval #CHIP_NO_ERROR If the method succeeded. + * @retval #CHIP_ERROR_TLV_CONTAINER_OPEN + * If a container writer has been opened on the current writer and not + * yet closed. + * @retval #CHIP_ERROR_INVALID_TLV_TAG + * If the specified tag value is invalid or inappropriate in the context + * in which the value is being written. + * @retval #CHIP_ERROR_BUFFER_TOO_SMALL + * If writing the value would exceed the limit on the maximum number of + * bytes specified when the writer was initialized. + * @retval #CHIP_ERROR_NO_MEMORY + * If an attempt to allocate an output buffer failed due to lack of + * memory. + * @retval other Other CHIP or platform-specific errors returned by the configured + * TLVBackingStore. + * + */ CHIP_ERROR PutBytes(uint64_t tag, const uint8_t * buf, uint32_t len); + + /** + * Encodes a TLV UTF8 string value. + * + * @param[in] tag The TLV tag to be encoded with the value, or @p AnonymousTag if the + * value should be encoded without a tag. Tag values should be + * constructed with one of the tag definition functions ProfileTag(), + * ContextTag() or CommonTag(). + * @param[in] buf A pointer to the null-terminated UTF-8 string to be encoded. + * + * @retval #CHIP_NO_ERROR If the method succeeded. + * @retval #CHIP_ERROR_TLV_CONTAINER_OPEN + * If a container writer has been opened on the current writer and not + * yet closed. + * @retval #CHIP_ERROR_INVALID_TLV_TAG + * If the specified tag value is invalid or inappropriate in the context + * in which the value is being written. + * @retval #CHIP_ERROR_BUFFER_TOO_SMALL + * If writing the value would exceed the limit on the maximum number of + * bytes specified when the writer was initialized. + * @retval #CHIP_ERROR_NO_MEMORY + * If an attempt to allocate an output buffer failed due to lack of + * memory. + * @retval other Other CHIP or platform-specific errors returned by the configured + * TLVBackingStore. + * + */ CHIP_ERROR PutString(uint64_t tag, const char * buf); + + /** + * Encodes a TLV UTF8 string value. + * + * @param[in] tag The TLV tag to be encoded with the value, or @p AnonymousTag if the + * value should be encoded without a tag. Tag values should be + * constructed with one of the tag definition functions ProfileTag(), + * ContextTag() or CommonTag(). + * @param[in] buf A pointer to the UTF-8 string to be encoded. + * @param[in] len The length (in bytes) of the string to be encoded. + * + * @retval #CHIP_NO_ERROR If the method succeeded. + * @retval #CHIP_ERROR_TLV_CONTAINER_OPEN + * If a container writer has been opened on the current writer and not + * yet closed. + * @retval #CHIP_ERROR_INVALID_TLV_TAG + * If the specified tag value is invalid or inappropriate in the context + * in which the value is being written. + * @retval #CHIP_ERROR_BUFFER_TOO_SMALL + * If writing the value would exceed the limit on the maximum number of + * bytes specified when the writer was initialized. + * @retval #CHIP_ERROR_NO_MEMORY + * If an attempt to allocate an output buffer failed due to lack of + * memory. + * @retval other Other CHIP or platform-specific errors returned by the configured + * TLVBackingStore. + * + */ CHIP_ERROR PutString(uint64_t tag, const char * buf, uint32_t len); + + /** + * @brief + * Encode the string output formatted according to the format in the TLV element. + * + * PutStringF is an analog of a sprintf where the output is stored in + * a TLV element as opposed to a character buffer. When extended + * printf functionality is available, the function is able to output + * the result string into a discontinuous underlying storage. The + * implementation supports the following printf enhancements: + * + * -- The platform supplies a callback-based `vcbprintf` that provides + * the ability to call a custom callback in place of putchar. + * + * -- The platform supplies a variant of `vsnprintf` called + * `vsnprintf_ex`, that behaves exactly like vsnprintf except it + * has provisions for omitting the first `n` characters of the + * output. + * + * Note that while the callback-based function may be the simplest and + * use the least amount of code, the `vsprintf_ex` variety of + * functions will consume less stack. + * + * If neither of the above is available, the function will allocate a + * temporary buffer to hold the output, using Platform::MemoryAlloc(). + * + * @param[in] tag The TLV tag to be encoded with the value, or @p + * AnonymousTag if the value should be encoded without + * a tag. Tag values should be constructed with one of + * the tag definition functions ProfileTag(), + * ContextTag() or CommonTag(). + * + * @param[in] fmt The format string used to format the argument list. + * Follows the same syntax and rules as the format + * string for `printf` family of functions. + * + * @param[in] ... A list of arguments to be formatted in the output value + * according to fmt. + * + * @retval #CHIP_NO_ERROR If the method succeeded. + * + * @retval other If underlying calls to TLVWriter methods -- + * `WriteElementHead` or `GetNewBuffer` -- failed, their + * error is immediately forwarded up the call stack. + */ CHIP_ERROR PutStringF(uint64_t tag, const char * fmt, ...); + + /** + * @brief + * Encode the string output formatted according to the format in the TLV element. + * + * PutStringF is an analog of a sprintf where the output is stored in + * a TLV element as opposed to a character buffer. When extended + * printf functionality is available, the function is able to output + * the result string into a discontinuous underlying storage. The + * implementation supports the following printf enhancements: + * + * -- The platform supplies a callback-based `vcbprintf` that provides + * the ability to call a custom callback in place of putchar. + * + * -- The platform supplies a variant of `vsnprintf` called + * `vsnprintf_ex`, that behaves exactly like vsnprintf except it + * has provisions for omitting the first `n` characters of the + * output. + * + * Note that while the callback-based function may be the simplest and + * use the least amount of code, the `vsprintf_ex` variety of + * functions will consume less stack. + * + * If neither of the above is available, the function will allocate a + * temporary buffer to hold the output, using Platform::MemoryAlloc(). + * + * @param[in] tag The TLV tag to be encoded with the value, or @p + * AnonymousTag if the value should be encoded without + * a tag. Tag values should be constructed with one of + * the tag definition functions ProfileTag(), + * ContextTag() or CommonTag(). + * + * @param[in] fmt The format string used to format the argument list. + * Follows the same syntax and rules as the format + * string for `printf` family of functions. + * + * @param[in] ap A list of arguments to be formatted in the output value + * according to fmt. + * + * @retval #CHIP_NO_ERROR If the method succeeded. + * + * @retval other If underlying calls to TLVWriter methods -- + * `WriteElementHead` or `GetNewBuffer` -- failed, their + * error is immediately forwarded up the call stack. + */ CHIP_ERROR VPutStringF(uint64_t tag, const char * fmt, va_list ap); + + /** + * Encodes a TLV null value. + * + * @param[in] tag The TLV tag to be encoded with the value, or @p AnonymousTag if the + * value should be encoded without a tag. Tag values should be + * constructed with one of the tag definition functions ProfileTag(), + * ContextTag() or CommonTag(). + * + * @retval #CHIP_NO_ERROR If the method succeeded. + * @retval #CHIP_ERROR_TLV_CONTAINER_OPEN + * If a container writer has been opened on the current writer and not + * yet closed. + * @retval #CHIP_ERROR_INVALID_TLV_TAG + * If the specified tag value is invalid or inappropriate in the context + * in which the value is being written. + * @retval #CHIP_ERROR_BUFFER_TOO_SMALL + * If writing the value would exceed the limit on the maximum number of + * bytes specified when the writer was initialized. + * @retval #CHIP_ERROR_NO_MEMORY + * If an attempt to allocate an output buffer failed due to lack of + * memory. + * @retval other Other CHIP or platform-specific errors returned by the configured + * TLVBackingStore. + * + */ CHIP_ERROR PutNull(uint64_t tag); + + /** + * Copies a TLV element from a reader object into the writer. + * + * The CopyElement() method encodes a new TLV element whose type, tag and value are taken from a TLVReader + * object. When the method is called, the supplied reader object is expected to be positioned on the + * source TLV element. The newly encoded element will have the same type, tag and contents as the input + * container. If the supplied element is a TLV container (structure, array or path), the entire contents + * of the container will be copied. + * + * @note This method requires the supplied TVLReader object to be reading from a single, contiguous + * input buffer that contains the entirety of the underlying TLV encoding. Supplying a reader in any + * other mode has undefined behavior. + * + * @param[in] reader A reference to a TLVReader object identifying a pre-encoded TLV + * element that should be copied. + * + * @retval #CHIP_NO_ERROR If the method succeeded. + * @retval #CHIP_ERROR_INCORRECT_STATE + * If the supplied reader is not positioned on an element. + * @retval #CHIP_ERROR_TLV_CONTAINER_OPEN + * If a container writer has been opened on the current writer and not + * yet closed. + * @retval #CHIP_ERROR_TLV_UNDERRUN + * If the underlying TLV encoding associated with the supplied reader ended + * prematurely. + * @retval #CHIP_ERROR_INVALID_TLV_ELEMENT + * If the supplied reader encountered an invalid or unsupported TLV element + * type. + * @retval #CHIP_ERROR_INVALID_TLV_TAG + * If the supplied reader encountered a TLV tag in an invalid context, + * or if the supplied tag is invalid or inappropriate in the context in + * which the new container is being written. + * @retval #CHIP_ERROR_BUFFER_TOO_SMALL + * If writing the value would exceed the limit on the maximum number of + * bytes specified when the writer was initialized. + * @retval #CHIP_ERROR_NO_MEMORY + * If an attempt to allocate an output buffer failed due to lack of + * memory. + * @retval other Other CHIP or platform-specific errors returned by the configured + * GetNewBuffer() or FinalizeBuffer() functions, or by the GetNextBuffer() + * function associated with the reader object. + * + */ CHIP_ERROR CopyElement(TLVReader & reader); + + /** + * Copies a TLV element from a reader object into the writer. + * + * The CopyElement() method encodes a new TLV element whose type and value are taken from a TLVReader + * object. When the method is called, the supplied reader object is expected to be positioned on the + * source TLV element. The newly encoded element will have the same type and contents as the input + * container, however the tag will be set to the specified argument. If the supplied element is a + * TLV container (structure, array or path), the entire contents of the container will be copied. + * + * @note This method requires the supplied TVLReader object to be reading from a single, contiguous + * input buffer that contains the entirety of the underlying TLV encoding. Supplying a reader in any + * other mode has undefined behavior. + * + * @param[in] tag The TLV tag to be encoded with the container, or @p AnonymousTag if + * the container should be encoded without a tag. Tag values should be + * constructed with one of the tag definition functions ProfileTag(), + * ContextTag() or CommonTag(). + * @param[in] reader A reference to a TLVReader object identifying a pre-encoded TLV + * element whose type and value should be copied. + * + * @retval #CHIP_NO_ERROR If the method succeeded. + * @retval #CHIP_ERROR_INCORRECT_STATE + * If the supplied reader is not positioned on an element. + * @retval #CHIP_ERROR_TLV_CONTAINER_OPEN + * If a container writer has been opened on the current writer and not + * yet closed. + * @retval #CHIP_ERROR_TLV_UNDERRUN + * If the underlying TLV encoding associated with the supplied reader ended + * prematurely. + * @retval #CHIP_ERROR_INVALID_TLV_ELEMENT + * If the supplied reader encountered an invalid or unsupported TLV element + * type. + * @retval #CHIP_ERROR_INVALID_TLV_TAG + * If the supplied reader encountered a TLV tag in an invalid context, + * or if the supplied tag is invalid or inappropriate in the context in + * which the new container is being written. + * @retval #CHIP_ERROR_BUFFER_TOO_SMALL + * If writing the value would exceed the limit on the maximum number of + * bytes specified when the writer was initialized. + * @retval #CHIP_ERROR_NO_MEMORY + * If an attempt to allocate an output buffer failed due to lack of + * memory. + * @retval other Other CHIP or platform-specific errors returned by the configured + * GetNewBuffer() or FinalizeBuffer() functions, or by the GetNextBuffer() + * function associated with the reader object. + * + */ CHIP_ERROR CopyElement(uint64_t tag, TLVReader & reader); + /** + * Begins encoding a new TLV container element. + * + * The StartContainer() method is used to write TLV container elements (structure, arrays or paths) + * to an encoding. The method takes the type and tag (if any) of the new container, and a reference + * to a TLVType value which will be used to save the current context of the writer while it is being + * used to write the container. + * + * Once the StartContainer() method returns, the application should use the current TLVWriter object to + * write the elements of the container. When finish, the application must call the EndContainer() + * method to finish the encoding of the container. + * + * @param[in] tag The TLV tag to be encoded with the container, or @p AnonymousTag if + * the container should be encoded without a tag. Tag values should be + * constructed with one of the tag definition functions ProfileTag(), + * ContextTag() or CommonTag(). + * @param[in] containerType The type of container to encode. Must be one of @p kTLVType_Structure, + * @p kTLVType_Array or @p kTLVType_Path. + * @param[out] outerContainerType + * A reference to a TLVType value that will receive the context of the + * writer. + * + * @retval #CHIP_NO_ERROR If the method succeeded. + * @retval #CHIP_ERROR_WRONG_TLV_TYPE + * If the value specified for containerType is incorrect. + * @retval #CHIP_ERROR_TLV_CONTAINER_OPEN + * If a container writer has been opened on the current writer and not + * yet closed. + * @retval #CHIP_ERROR_INVALID_TLV_TAG + * If the specified tag value is invalid or inappropriate in the context + * in which the value is being written. + * @retval #CHIP_ERROR_BUFFER_TOO_SMALL + * If writing the value would exceed the limit on the maximum number of + * bytes specified when the writer was initialized. + * @retval #CHIP_ERROR_NO_MEMORY + * If an attempt to allocate an output buffer failed due to lack of + * memory. + * @retval other Other CHIP or platform-specific errors returned by the configured + * TLVBackingStore. + * + */ CHIP_ERROR StartContainer(uint64_t tag, TLVType containerType, TLVType & outerContainerType); + + /** + * Completes the encoding of a TLV container element. + * + * The EndContainer() method completes the encoding of a TLV container element and restores the state + * of a TLVWrite object after an earlier call to StartContainer(). For every call to StartContainer() + * applications must make a corresponding call to EndContainer(), passing the TLVType value returned + * by the StartContainer() call. When EndContainer() returns, the writer object can be used to write + * additional TLV elements that follow the container element. + * + * @note Any changes made to the configuration of the writer between the calls to StartContainer() + * and EndContainer() are NOT undone by the call to EndContainer(). For example, a change to the + * implicit profile id (@p ImplicitProfileId) will not be reversed when a container is ended. Thus + * it is the application's responsibility to adjust the configuration accordingly at the appropriate + * times. + * + * @param[in] outerContainerType + * The TLVType value that was returned by the StartContainer() method. + * + * @retval #CHIP_NO_ERROR If the method succeeded. + * @retval #CHIP_ERROR_INCORRECT_STATE + * If a corresponding StartContainer() call was not made. + * @retval #CHIP_ERROR_TLV_CONTAINER_OPEN + * If a container writer has been opened on the current writer and not + * yet closed. + * @retval #CHIP_ERROR_BUFFER_TOO_SMALL + * If writing the value would exceed the limit on the maximum number of + * bytes specified when the writer was initialized. + * @retval #CHIP_ERROR_NO_MEMORY + * If an attempt to allocate an output buffer failed due to lack of + * memory. + * @retval other Other CHIP or platform-specific errors returned by the configured + * TLVBackingStore. + * + */ CHIP_ERROR EndContainer(TLVType outerContainerType); + + /** + * Initializes a new TLVWriter object for writing the members of a TLV container element. + * + * The OpenContainer() method is used to write TLV container elements (structure, arrays or paths) + * to an encoding. The method takes the type and tag (if any) of the new container, and a reference + * to a new writer object (the container writer) that will be initialized for the purpose + * of writing the container's elements. Applications write the members of the new container using + * the container writer and then call CloseContainer() to complete the container encoding. + * + * While the container writer is open, applications must not make calls on or otherwise alter the state + * of the parent writer. + * + * The container writer inherits various configuration properties from the parent writer. These are: + * + * @li The implicit profile id (ImplicitProfileId) + * @li The application data pointer (AppData) + * @li The GetNewBuffer and FinalizeBuffer function pointers + * + * @note The StartContainer() method can be used as an alternative to OpenContainer() to write a + * container element without initializing a new writer object. + * + * @param[in] tag The TLV tag to be encoded with the container, or @p AnonymousTag if + * the container should be encoded without a tag. Tag values should be + * constructed with one of the tag definition functions ProfileTag(), + * ContextTag() or CommonTag(). + * @param[in] containerType The type of container to encode. Must be one of @p kTLVType_Structure, + * @p kTLVType_Array or @p kTLVType_Path. + * @param[out] containerWriter A reference to a TLVWriter object that will be initialized for + * writing the members of the new container element. Any data + * associated with the supplied object is overwritten. + * + * @retval #CHIP_NO_ERROR If the method succeeded. + * @retval #CHIP_ERROR_WRONG_TLV_TYPE + * If the value specified for containerType is incorrect. + * @retval #CHIP_ERROR_TLV_CONTAINER_OPEN + * If a container writer has been opened on the current writer and not + * yet closed. + * @retval #CHIP_ERROR_INVALID_TLV_TAG + * If the specified tag value is invalid or inappropriate in the context + * in which the value is being written. + * @retval #CHIP_ERROR_BUFFER_TOO_SMALL + * If writing the value would exceed the limit on the maximum number of + * bytes specified when the writer was initialized. + * @retval #CHIP_ERROR_NO_MEMORY + * If an attempt to allocate an output buffer failed due to lack of + * memory. + * @retval other Other CHIP or platform-specific errors returned by the configured + * TLVBackingStore. + * + */ CHIP_ERROR OpenContainer(uint64_t tag, TLVType containerType, TLVWriter & containerWriter); + + /** + * Completes the writing of a TLV container after a call to OpenContainer(). + * + * The CloseContainer() method restores the state of a parent TLVWriter object after a call to + * OpenContainer(). For every call to OpenContainer() applications must make a corresponding + * call to CloseContainer(), passing a reference to the same container writer to both methods. + * + * When CloseContainer() returns, applications may continue to use the parent writer to write + * additional TLV elements that appear after the container element. At this point the supplied + * container writer should be considered 'de-initialized' and must not be used without + * re-initialization. + * + * @param[in] containerWriter A reference to the TLVWriter object that was supplied to the + * OpenContainer() method. + * + * @retval #CHIP_NO_ERROR If the method succeeded. + * @retval #CHIP_ERROR_INCORRECT_STATE + * If the supplied container writer is not in the correct state. + * @retval #CHIP_ERROR_TLV_CONTAINER_OPEN + * If another container writer has been opened on the supplied + * container writer and not yet closed. + * @retval #CHIP_ERROR_BUFFER_TOO_SMALL + * If completing the encoding of the container would exceed the + * limit on the maximum number of bytes specified when the writer + * was initialized. + * @retval #CHIP_ERROR_NO_MEMORY + * If an attempt to allocate an output buffer failed due to lack + * of memory. + * @retval other Other CHIP or platform-specific errors returned by the + * configured TLVBackingStore. + * + */ CHIP_ERROR CloseContainer(TLVWriter & containerWriter); + + /** + * Encodes a TLV container element from a pre-encoded set of member elements + * + * The PutPreEncodedContainer() method encodes a new TLV container element (a structure, array or path) + * containing a set of member elements taken from a pre-encoded buffer. The input buffer is expected to + * contain zero or more full-encoded TLV elements, with tags that conform to the rules associated with + * the specified container type (e.g. structure members must have tags, while array members must not). + * + * The method encodes the entirety of the container element in one call. When PutPreEncodedContainer() + * returns, the writer object can be used to write additional TLV elements following the container element. + * + * @param[in] tag The TLV tag to be encoded with the container, or @p AnonymousTag if + * the container should be encoded without a tag. Tag values should be + * constructed with one of the tag definition functions ProfileTag(), + * ContextTag() or CommonTag(). + * @param[in] containerType The type of container to encode. Must be one of @p kTLVType_Structure, + * @p kTLVType_Array or @p kTLVType_Path. + * @param[in] data A pointer to a buffer containing zero of more encoded TLV elements that + * will become the members of the new container. + * @param[in] dataLen The number of bytes in the @p data buffer. + * + * @retval #CHIP_NO_ERROR If the method succeeded. + * @retval #CHIP_ERROR_WRONG_TLV_TYPE + * If the value specified for containerType is incorrect. + * @retval #CHIP_ERROR_TLV_CONTAINER_OPEN + * If a container writer has been opened on the current writer and not + * yet closed. + * @retval #CHIP_ERROR_INVALID_TLV_TAG + * If the specified tag value is invalid or inappropriate in the context + * in which the value is being written. + * @retval #CHIP_ERROR_BUFFER_TOO_SMALL + * If writing the value would exceed the limit on the maximum number of + * bytes specified when the writer was initialized. + * @retval #CHIP_ERROR_NO_MEMORY + * If an attempt to allocate an output buffer failed due to lack of + * memory. + * @retval other Other CHIP or platform-specific errors returned by the configured + * TLVBackingStore. + * + */ CHIP_ERROR PutPreEncodedContainer(uint64_t tag, TLVType containerType, const uint8_t * data, uint32_t dataLen); + + /** + * Copies a TLV container element from TLVReader object + * + * The CopyContainer() encodes a new TLV container element by copying a pre-encoded container element + * located at the current position of a TLVReader object. The method writes the entirety of the new + * container element in one call, copying the container's type, tag and elements from the source + * encoding. When the method returns, the writer object can be used to write additional TLV elements + * following the container element. + * + * @note This method requires the supplied TVLReader object to be reading from a single, contiguous + * input buffer that contains the entirety of the underlying TLV encoding. + * + * @param[in] container A reference to a TLVReader object identifying the pre-encoded TLV + * container to be copied. + * + * @retval #CHIP_NO_ERROR If the method succeeded. + * @retval #CHIP_ERROR_INVALID_ARGUMENT + * If the supplied reader uses a TLVBackingStore rather than a simple buffer. + * @retval #CHIP_ERROR_INCORRECT_STATE + * If the supplied reader is not positioned on a container element. + * @retval #CHIP_ERROR_TLV_CONTAINER_OPEN + * If a container writer has been opened on the current writer and not + * yet closed. + * @retval #CHIP_ERROR_TLV_UNDERRUN + * If the underlying TLV encoding associated with the supplied reader ended + * prematurely. + * @retval #CHIP_ERROR_INVALID_TLV_ELEMENT + * If the supplied reader encountered an invalid or unsupported TLV element + * type. + * @retval #CHIP_ERROR_INVALID_TLV_TAG + * If the supplied reader encountered a TLV tag in an invalid context, + * or if the tag associated with the source container is invalid or + * inappropriate in the context in which the new container is being written. + * @retval #CHIP_ERROR_BUFFER_TOO_SMALL + * If writing the value would exceed the limit on the maximum number of + * bytes specified when the writer was initialized. + * @retval #CHIP_ERROR_NO_MEMORY + * If an attempt to allocate an output buffer failed due to lack of + * memory. + * @retval other Other CHIP or platform-specific errors returned by the configured + * TLVBackingStore. + * + */ CHIP_ERROR CopyContainer(TLVReader & container); + + /** + * Encodes a TLV container element from a pre-encoded set of member elements + * + * The CopyContainer() method encodes a new TLV container element (a structure, array or path) + * containing a set of member elements taken from a TLVReader object. When the method is called, the + * supplied reader object is expected to be positioned on a TLV container element. The newly encoded + * container will have the same type and members as the input container. The tag for the new + * container is specified as an input parameter. + * + * When the method returns, the writer object can be used to write additional TLV elements following + * the container element. + * + * @note This method requires the supplied TVLReader object to be reading from a single, contiguous + * input buffer that contains the entirety of the underlying TLV encoding. + * + * @param[in] tag The TLV tag to be encoded with the container, or @p AnonymousTag if + * the container should be encoded without a tag. Tag values should be + * constructed with one of the tag definition functions ProfileTag(), + * ContextTag() or CommonTag(). + * @param[in] container A reference to a TLVReader object identifying a pre-encoded TLV + * container whose type and members should be copied. + * + * @retval #CHIP_NO_ERROR If the method succeeded. + * @retval #CHIP_ERROR_INVALID_ARGUMENT + * If the supplied reader uses a TLVBackingStore rather than a simple buffer. + * @retval #CHIP_ERROR_INCORRECT_STATE + * If the supplied reader is not positioned on a container element. + * @retval #CHIP_ERROR_TLV_CONTAINER_OPEN + * If a container writer has been opened on the current writer and not + * yet closed. + * @retval #CHIP_ERROR_TLV_UNDERRUN + * If the underlying TLV encoding associated with the supplied reader ended + * prematurely. + * @retval #CHIP_ERROR_INVALID_TLV_ELEMENT + * If the supplied reader encountered an invalid or unsupported TLV element + * type. + * @retval #CHIP_ERROR_INVALID_TLV_TAG + * If the supplied reader encountered a TLV tag in an invalid context, + * or if the supplied tag is invalid or inappropriate in the context in + * which the new container is being written. + * @retval #CHIP_ERROR_BUFFER_TOO_SMALL + * If writing the value would exceed the limit on the maximum number of + * bytes specified when the writer was initialized. + * @retval #CHIP_ERROR_NO_MEMORY + * If an attempt to allocate an output buffer failed due to lack of + * memory. + * @retval other Other CHIP or platform-specific errors returned by the configured + * TLVBackingStore. + * + */ CHIP_ERROR CopyContainer(uint64_t tag, TLVReader & container); - CHIP_ERROR CopyContainer(uint64_t tag, const uint8_t * encodedContainer, uint16_t encodedContainerLen); - TLVType GetContainerType() const; - uint32_t GetLengthWritten(); + /** + * Encodes a TLV container element that contains member elements from a pre-encoded container + * + * The CopyContainer() method encodes a new TLV container element (a structure, array or path) + * containing a set of member elements taken from the contents of a supplied pre-encoded container. + * When the method is called, data in the supplied input buffer is parsed as a TLV container element + * an a new container is written that has the same type and members as the input container. The tag + * for the new container is specified as an input parameter. + * + * When the method returns, the writer object can be used to write additional TLV elements following + * the container element. + * + * @param[in] tag The TLV tag to be encoded with the container, or @p AnonymousTag if + * the container should be encoded without a tag. Tag values should be + * constructed with one of the tag definition functions ProfileTag(), + * ContextTag() or CommonTag(). + * @param[in] encodedContainer A buffer containing a pre-encoded TLV container whose type and members + * should be copied. + * @param[in] encodedContainerLen The length in bytes of the pre-encoded container. + * + * @retval #CHIP_NO_ERROR If the method succeeded. + * @retval #CHIP_ERROR_TLV_CONTAINER_OPEN + * If a container writer has been opened on the current writer and not + * yet closed. + * @retval #CHIP_ERROR_TLV_UNDERRUN + * If the encoded container ended prematurely. + * @retval #CHIP_ERROR_INVALID_TLV_ELEMENT + * If the encoded container contained an invalid or unsupported TLV element type. + * @retval #CHIP_ERROR_INVALID_TLV_TAG + * If the encoded container contained a TLV tag in an invalid context, + * or if the supplied tag is invalid or inappropriate in the context in + * which the new container is being written. + * @retval #CHIP_ERROR_BUFFER_TOO_SMALL + * If writing the value would exceed the limit on the maximum number of + * bytes specified when the writer was initialized. + * @retval #CHIP_ERROR_NO_MEMORY + * If an attempt to allocate an output buffer failed due to lack of + * memory. + * @retval other Other CHIP or platform-specific errors returned by the configured + * TLVBackingStore. + * + */ + CHIP_ERROR CopyContainer(uint64_t tag, const uint8_t * encodedContainer, uint16_t encodedContainerLen); - uint32_t ImplicitProfileId; - void * AppData; + /** + * Returns the type of container within which the TLVWriter is currently writing. + * + * The GetContainerType() method returns the type of the TLV container within which the TLVWriter + * is currently writing. If the TLVWriter is not writing elements within a container (i.e. if writing + * at the outer-most level of an encoding) the method returns kTLVType_NotSpecified. + * + * @return The TLVType of the current container, or kTLVType_NotSpecified if the TLVWriter is not + * writing elements within a container. + */ + TLVType GetContainerType() const { return mContainerType; } - typedef CHIP_ERROR (*GetNewBufferFunct)(TLVWriter & writer, uintptr_t & bufHandle, uint8_t *& bufStart, uint32_t & bufLen); - GetNewBufferFunct GetNewBuffer; + /** + * Returns the total number of bytes written since the writer was initialized. + * + * @return Total number of bytes written since the writer was initialized. + */ + uint32_t GetLengthWritten() const { return mLenWritten; } - typedef CHIP_ERROR (*FinalizeBufferFunct)(TLVWriter & writer, uintptr_t bufHandle, uint8_t * bufStart, uint32_t bufLen); - FinalizeBufferFunct FinalizeBuffer; + /** + * The profile id of tags that should be encoded in implicit form. + * + * When a writer is asked to encode a new element, if the profile id of the tag associated with the + * new element matches the value of the @p ImplicitProfileId member, the writer will encode the tag + * in implicit form, omitting the profile id in the process. + * + * By default, the @p ImplicitProfileId property is set to kProfileIdNotSpecified, which instructs + * the writer not to emit implicitly encoded tags. Applications can set @p ImplicitProfileId at any + * time to enable encoding tags in implicit form starting at the current point in the encoding. The + * appropriate profile id to set is usually dependent on the context of the application or protocol + * being spoken. + * + * @note The value of the @p ImplicitProfileId member affects the encoding of profile-specific + * tags only; the encoding of context-specific tags is unchanged. + */ + uint32_t ImplicitProfileId; - // Implementations of GetNewBufferFunct/FinalizeBufferFunct that support writing into one or more - // PacketBuffers. - static CHIP_ERROR GetNewPacketBuffer(TLVWriter & writer, uintptr_t & bufHandle, uint8_t *& bufStart, uint32_t & bufLen); - static CHIP_ERROR FinalizePacketBuffer(TLVWriter & writer, uintptr_t bufHandle, uint8_t * bufStart, uint32_t dataLen); + /** + * A pointer field that can be used for application-specific data. + */ + void * AppData; protected: - uintptr_t mBufHandle; + TLVBackingStore * mBackingStore; uint8_t * mBufStart; uint8_t * mWritePoint; uint32_t mRemainingLen; @@ -354,26 +1873,259 @@ class DLL_EXPORT TLVWriter * @note The application is expected to use the TLVUpdater object atomically from the time it calls * Init() till it calls Finalize(). The same buffer should NOT be used with other TLVWriter objects. * - * @note The TLVUpdater currently only supports single static buffers. Support for chain of buffers - * (PacketBuffer) is NOT supported. + * @note The TLVUpdater currently only supports single static buffers. TLVBackingStore is NOT supported. */ class DLL_EXPORT TLVUpdater { public: + /** + * Initialize a TLVUpdater object to edit a single input buffer. + * + * On calling this method, the TLV data in the buffer is moved to the end of the + * buffer and a private TLVReader object is initialized on this relocated + * buffer. A private TLVWriter object is also initialized on the free space that + * is now available at the beginning. Applications can use the TLVUpdater object + * to parse the TLV data and modify/delete existing elements or add new elements + * to the encoding. + * + * @param[in] buf A pointer to a buffer containing the TLV data to be edited. + * @param[in] dataLen The length of the TLV data in the buffer. + * @param[in] maxLen The total length of the buffer. + * + * @retval #CHIP_NO_ERROR If the method succeeded. + * @retval #CHIP_ERROR_INVALID_ARGUMENT If the buffer address is invalid. + * @retval #CHIP_ERROR_BUFFER_TOO_SMALL If the buffer is too small. + * + */ CHIP_ERROR Init(uint8_t * buf, uint32_t dataLen, uint32_t maxLen); + + /** + * Initialize a TLVUpdater object using a TLVReader. + * + * On calling this method, TLV data in the buffer pointed to by the TLVReader + * is moved from the current read point to the end of the buffer. A new + * private TLVReader object is initialized to read from this new location, while + * a new private TLVWriter object is initialized to write to the freed up buffer + * space. + * + * Note that if the TLVReader is already positioned "on" an element, it is first + * backed-off to the start of that element. Also note that this backing off + * works well with container elements, i.e., if the TLVReader was already used + * to call EnterContainer(), then there is nothing to back-off. But if the + * TLVReader was positioned on the container element and EnterContainer() was + * not yet called, then the TLVReader object is backed-off to the start of the + * container head. + * + * The input TLVReader object will be destroyed before returning and the + * application must not make use of the same on return. + * + * @param[in,out] aReader Reference to a TLVReader object that will be + * destroyed before returning. + * @param[in] freeLen The length of free space (in bytes) available + * in the pre-encoded data buffer. + * + * @retval #CHIP_NO_ERROR If the method succeeded. + * @retval #CHIP_ERROR_INVALID_ARGUMENT If the buffer address is invalid. + * @retval #CHIP_ERROR_NOT_IMPLEMENTED If reader was initialized on a chain + * of buffers. + */ CHIP_ERROR Init(TLVReader & aReader, uint32_t freeLen); + CHIP_ERROR Finalize() { return mUpdaterWriter.Finalize(); } // Common methods + + /** + * Set the Implicit Profile ID for the TLVUpdater object. + * + * This method sets the implicit profile ID for the TLVUpdater object. When the + * updater is asked to encode a new element, if the profile ID of the tag + * associated with the new element matches the value of the @p profileId, the + * updater will encode the tag in implicit form, thereby omitting the profile ID + * in the process. + * + * @param[in] profileId The profile id of tags that should be encoded in + * implicit form. + */ void SetImplicitProfileId(uint32_t profileId); uint32_t GetImplicitProfileId() { return mUpdaterReader.ImplicitProfileId; } + + /** + * Copies the current element from input TLV to output TLV. + * + * The Move() method copies the current element on which the TLVUpdater's reader + * is positioned on, to the TLVUpdater's writer. The application should call + * Next() and position the TLVUpdater's reader on an element before calling this + * method. Just like the TLVReader::Next() method, if the reader is positioned + * on a container element at the time of the call, all the members of the + * container will be copied. If the reader is not positioned on any element, + * nothing changes on calling this method. + * + * @retval #CHIP_NO_ERROR If the TLVUpdater reader was + * successfully positioned on a new + * element. + * @retval #CHIP_END_OF_TLV If the TLVUpdater's reader is pointing + * to end of container. + * @retval #CHIP_ERROR_INVALID_TLV_ELEMENT + * If the TLVIpdater's reader is not + * positioned on a valid TLV element. + * @retval other Returns other error codes returned by + * TLVReader::Skip() method. + * + */ CHIP_ERROR Move(); + + /** + * Move everything from the TLVUpdater's current read point till end of input + * TLV buffer over to output. + * + * This method supports moving everything from the TLVUpdater's current read + * point till the end of the reader buffer over to the TLVUpdater's writer. + * + * @note This method can be called with the TLVUpdater's reader positioned + * anywhere within the input TLV. The reader can also be positioned under + * multiple levels of nested containers and this method will still work. + * + * @note This method also changes the state of the TLVUpdater object to a state + * it would be in if the application had painstakingly parsed each element from + * the current read point till the end of the input encoding and copied them to + * the output TLV. + */ void MoveUntilEnd(); + + /** + * Prepares a TLVUpdater object for reading elements of a container. It also + * encodes a start of container object in the output TLV. + * + * The EnterContainer() method prepares the current TLVUpdater object to begin + * reading the member elements of a TLV container (a structure, array or path). + * For every call to EnterContainer() applications must make a corresponding + * call to ExitContainer(). + * + * When EnterContainer() is called the TLVUpdater's reader must be positioned on + * the container element. The method takes as an argument a reference to a + * TLVType value which will be used to save the context of the updater while it + * is reading the container. + * + * When the EnterContainer() method returns, the updater is positioned + * immediately @em before the first member of the container. Repeatedly calling + * Next() will advance the updater through the members of the collection until + * the end is reached, at which point the updater will return CHIP_END_OF_TLV. + * + * Once the application has finished reading a container it can continue reading + * the elements after the container by calling the ExitContainer() method. + * + * @note This method implicitly encodes a start of container element in the + * output TLV buffer. + * + * @param[out] outerContainerType A reference to a TLVType value that will + * receive the context of the updater. + * + * @retval #CHIP_NO_ERROR If the method succeeded. + * @retval #CHIP_ERROR_INCORRECT_STATE If the TLVUpdater reader is not + * positioned on a container element. + * @retval other Any other CHIP or platform error code + * returned by TLVWriter::StartContainer() + * or TLVReader::EnterContainer(). + * + */ CHIP_ERROR EnterContainer(TLVType & outerContainerType); + + /** + * Completes the reading of a TLV container element and encodes an end of TLV + * element in the output TLV. + * + * The ExitContainer() method restores the state of a TLVUpdater object after a + * call to EnterContainer(). For every call to EnterContainer() applications + * must make a corresponding call to ExitContainer(), passing the context value + * returned by the EnterContainer() method. + * + * When ExitContainer() returns, the TLVUpdater reader is positioned immediately + * before the first element that follows the container in the input TLV. From + * this point applications can call Next() to advance through any remaining + * elements. + * + * Once EnterContainer() has been called, applications can call ExitContainer() + * on the updater at any point in time, regardless of whether all elements in + * the underlying container have been read. Also, note that calling + * ExitContainer() before reading all the elements in the container, will result + * in the updated container getting truncated in the output TLV. + * + * @note Any changes made to the configuration of the updater between the calls + * to EnterContainer() and ExitContainer() are NOT undone by the call to + * ExitContainer(). For example, a change to the implicit profile id + * (@p ImplicitProfileId) will not be reversed when a container is exited. Thus + * it is the application's responsibility to adjust the configuration + * accordingly at the appropriate times. + * + * @param[in] outerContainerType The TLVType value that was returned by + * the EnterContainer() method. + * + * @retval #CHIP_NO_ERROR If the method succeeded. + * @retval #CHIP_ERROR_TLV_UNDERRUN If the underlying TLV encoding ended + * prematurely. + * @retval #CHIP_ERROR_INVALID_TLV_ELEMENT + * If the updater encountered an invalid or + * unsupported TLV element type. + * @retval #CHIP_ERROR_INVALID_TLV_TAG If the updater encountered a TLV tag in + * an invalid context. + * @retval other Any other CHIP or platform error code + * returned by TLVWriter::EndContainer() or + * TLVReader::ExitContainer(). + * + */ CHIP_ERROR ExitContainer(TLVType outerContainerType); + void GetReader(TLVReader & containerReader) { containerReader = mUpdaterReader; } // Reader methods + + /** + * Skip the current element and advance the TLVUpdater object to the next + * element in the input TLV. + * + * The Next() method skips the current element in the input TLV and advances the + * TLVUpdater's reader to the next element that resides in the same containment + * context. In particular, if the reader is positioned at the outer most level + * of a TLV encoding, calling Next() will advance it to the next, top most + * element. If the reader is positioned within a TLV container element (a + * structure, array or path), calling Next() will advance it to the next member + * element of the container. + * + * Since Next() constrains reader motion to the current containment context, + * calling Next() when the reader is positioned on a container element will + * advance @em over the container, skipping its member elements (and the members + * of any nested containers) until it reaches the first element after the + * container. + * + * When there are no further elements within a particular containment context + * the Next() method will return a #CHIP_END_OF_TLV error and the position of + * the reader will remain unchanged. + * + * @note The Next() method implicitly skips the current element. Hence, the + * TLVUpdater's private writer state variables will be adjusted to account for + * the new freed space (made available by skipping). This means that the + * application is expected to call Next() on the TLVUpdater object after a Get() + * whose value the application does @em not write back (which from the + * TLVUpdater's view is equivalent to skipping that element). + * + * @note Applications are also expected to call Next() when they are at the end + * of a container, and want to add new elements there. This is particularly + * important in situations where there is a fixed schema. Applications that have + * fixed schemas and know where the container end is cannot just add new + * elements at the end, because the TLVUpdater writer's state will not reflect + * the correct free space available for the Put() operation. Hence, applications + * must call Next() (and possibly also test for CHIP_END_OF_TLV) before adding + * elements at the end of a container. + * + * @retval #CHIP_NO_ERROR If the TLVUpdater reader was + * successfully positioned on a new + * element. + * @retval other Returns the CHIP or platform error + * codes returned by the TLVReader::Skip() + * and TLVReader::Next() method. + * + */ CHIP_ERROR Next(); CHIP_ERROR Get(bool & v) { return mUpdaterReader.Get(v); } @@ -443,5 +2195,119 @@ class DLL_EXPORT TLVUpdater const uint8_t * mElementStartAddr; }; +/** + * Provides an interface for TLVReader or TLVWriter to use memory other than a simple contiguous buffer. + */ +class DLL_EXPORT TLVBackingStore +{ +public: + virtual ~TLVBackingStore() {} + + /** + * A function to provide a backing store's initial start position and data length to a reader. + * + * @param[in] reader A reference to the TLVReader object that is requesting input data. + * @param[out] bufStart A reference to a data pointer. On exit, bufStart is expected to point + * to the first byte of TLV data to be parsed. + * @param[out] bufLen A reference to an unsigned integer that the function must set to + * the number of TLV data bytes being returned. If the end of the + * input TLV data has been reached, the function should set this value + * to 0. + * + * @retval #CHIP_NO_ERROR If the function successfully produced TLV data. + * @retval other Other CHIP or platform-specific error codes indicating that an error + * occurred preventing the function from producing the requested data. + */ + virtual CHIP_ERROR OnInit(TLVReader & reader, const uint8_t *& bufStart, uint32_t & bufLen) = 0; + + /** + * A function that can be used to retrieve additional TLV data to be parsed. + * + * When called, the function is expected to produce additional data for the reader to parse or signal + * the reader that no more data is available. + * + * @param[in] reader A reference to the TLVReader object that is requesting input data. + * @param[in,out] bufStart A reference to a data pointer. On entry to the function, @p bufStart + * points to one byte beyond the last TLV data byte consumed by the + * reader. On exit, bufStart is expected to point to the first byte + * of new TLV data to be parsed. The new pointer value can be within + * the same buffer as the previously consumed data, or it can point + * to an entirely new buffer. + * @param[out] bufLen A reference to an unsigned integer that the function must set to + * the number of TLV data bytes being returned. If the end of the + * input TLV data has been reached, the function should set this value + * to 0. + * + * @retval #CHIP_NO_ERROR If the function successfully produced more TLV data, or the end of + * the input data was reached (@p bufLen should be set to 0 in this case). + * @retval other Other CHIP or platform-specific error codes indicating that an error + * occurred preventing the function from producing the requested data. + */ + virtual CHIP_ERROR GetNextBuffer(TLVReader & reader, const uint8_t *& bufStart, uint32_t & bufLen) = 0; + + /** + * A function to provide a backing store's initial start position and data length to a writer. + * + * @param[in] writer A reference to the TLVWriter object that is requesting new buffer + * space. + * @param[out] bufStart A reference to a data pointer. On exit, @p bufStart is expected to + * point to the beginning of the new output buffer. + * @param[out] bufLen A reference to an unsigned integer. On exit, @p bufLen is expected + * to contain the maximum number of bytes that can be written to the + * new output buffer. + * + * @retval #CHIP_NO_ERROR If the function was able to supply buffer space for the writer. + * @retval other Other CHIP or platform-specific error codes indicating that an error + * occurred preventing the function from producing buffer space. + */ + virtual CHIP_ERROR OnInit(TLVWriter & writer, uint8_t *& bufStart, uint32_t & bufLen) = 0; + + /** + * A function that supplies new output buffer space to a TLVWriter. + * + * The function is expected to return a pointer to a memory location where new data should be written, + * along with an associated maximum length. The function can supply write space either by allocating + * a new buffer to hold the data or by clearing out previously written data from an existing buffer. + * + * @param[in] writer A reference to the TLVWriter object that is requesting new buffer + * space. + * @param[in,out] bufStart A reference to a data pointer. On entry to the function, @p bufStart + * points the beginning of the current output buffer. On exit, @p bufStart + * is expected to point to the beginning of the new output buffer. + * The new pointer value can be the same as the previous value (e.g. + * if the function copied the existing data elsewhere), or it can point + * to an entirely new location. + * @param[in,out] bufLen A reference to an unsigned integer. On entry to the function, + * @p bufLen contains the number of byte of @em unused space in the + * current buffer. On exit, @p bufLen is expected to contain the maximum + * number of bytes that can be written to the new output buffer. + * + * @retval #CHIP_NO_ERROR If the function was able to supply more buffer space for the writer. + * @retval other Other CHIP or platform-specific error codes indicating that an error + * occurred preventing the function from producing additional buffer + * space. + */ + virtual CHIP_ERROR GetNewBuffer(TLVWriter & writer, uint8_t *& bufStart, uint32_t & bufLen) = 0; + + /** + * A function used to perform finalization of the output from a TLVWriter object. + * + * Functions of this type are called when a TLVWriter's Finalize() method is called. The function is + * expected to perform any necessary clean-up or finalization related to consuming the output of the + * writer object. Examples of this include such things as recording the final length of the encoding, + * or closing a file descriptor. + * + * @param[in] writer A reference to the TLVWriter object that is being finalized. + * @param[in,out] bufStart A pointer to the beginning of the current (and final) output buffer. + * @param[in,out] bufLen The number of bytes contained in the buffer pointed to by @p bufStart. + * + * @retval #CHIP_NO_ERROR If finalization was successful. + * @retval other Other CHIP or platform-specific error codes indicating that an error + * occurred during finalization. + * + */ + virtual CHIP_ERROR FinalizeBuffer(TLVWriter & writer, uint8_t * bufStart, uint32_t bufLen) = 0; +}; + } // namespace TLV } // namespace chip diff --git a/src/lib/core/CHIPTLVReader.cpp b/src/lib/core/CHIPTLVReader.cpp index 222a33d4378a74..4534eae58e89a4 100644 --- a/src/lib/core/CHIPTLVReader.cpp +++ b/src/lib/core/CHIPTLVReader.cpp @@ -1,6 +1,6 @@ /* * - * Copyright (c) 2020 Project CHIP Authors + * Copyright (c) 2020-2021 Project CHIP Authors * Copyright (c) 2013-2017 Nest Labs, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -30,7 +30,6 @@ #include #include #include -#include namespace chip { namespace TLV { @@ -39,209 +38,48 @@ using namespace chip::Encoding; static const uint8_t sTagSizes[] = { 0, 1, 2, 4, 2, 4, 6, 8 }; -/** - * @fn uint32_t TLVReader::GetLengthRead() const - * - * Returns the total number of bytes read since the reader was initialized. - * - * @return Total number of bytes read since the reader was initialized. - */ - -/** - * @fn uint32_t TLVReader::GetRemainingLength() const - * - * Returns the total number of bytes that can be read until the max read length is reached. - * - * @return Total number of bytes that can be read until the max read length is reached. - */ - -/** - * @fn const uint8_t *TLVReader::GetReadPoint() const - * - * Gets the point in the underlying input buffer that corresponds to the reader's current position. - * - * @note Depending on the type of the current element, GetReadPoint() will return a pointer that - * is some number of bytes *after* the first byte of the element. For string types (UTF8 and byte - * strings), the pointer will point to the first byte of the string's value. For container types - * (structures, arrays and paths), the pointer will point to the first member element within the - * container. For all other types, the pointer will point to the byte immediately after the element's - * encoding. - * - * @return A pointer into underlying input buffer that corresponds to the reader's current position. - */ - -/** - * - * @var uint32_t TLVReader::ImplicitProfileId - * - * The profile id to be used for profile tags encoded in implicit form. - * - * When the reader encounters a profile-specific tag that has been encoded in implicit form, it - * uses the value of the @p ImplicitProfileId property as the assumed profile id for the tag. - * - * By default, the @p ImplicitProfileId property is set to kProfileIdNotSpecified. When decoding - * TLV that contains implicitly-encoded tags, applications must set @p ImplicitProfileId prior - * to reading any TLV elements having such tags. The appropriate profile id is usually dependent - * on the context of the application or protocol being spoken. - * - * If an implicitly-encoded tag is encountered while @p ImplicitProfileId is set to - * kProfileIdNotSpecified, the reader will return a #CHIP_ERROR_UNKNOWN_IMPLICIT_TLV_TAG error. - */ - -/** - * @var void *TLVReader::AppData - * - * A pointer field that can be used for application-specific data. - */ - -/** - * @typedef CHIP_ERROR (*TLVReader::GetNextBufferFunct)(TLVReader& reader, uintptr_t& bufHandle, const uint8_t *& bufStart, - * uint32_t& bufLen) - * - * A function that can be used to retrieve additional TLV data to be parsed. - * - * Functions of this type are used to feed input data to a TLVReader. When called, the function is - * expected to produce additional data for the reader to parse or signal the reader that no more - * data is available. - * - * @param[in] reader A reference to the TLVReader object that is requesting input data. - * @param[in,out] bufHandle A reference to a uintptr_t value that the function can use to store - * context data between calls. This value is initialized to 0 - * prior to the first call. - * @param[in,out] bufStart A reference to a data pointer. On entry to the function, @p bufStart - * points to one byte beyond the last TLV data byte consumed by the - * reader. On exit, bufStart is expected to point to the first byte - * of new TLV data to be parsed. The new pointer value can be within - * the same buffer as the previously consumed data, or it can point - * to an entirely new buffer. - * @param[out] bufLen A reference to an unsigned integer that the function must set to - * the number of TLV data bytes being returned. If the end of the - * input TLV data has been reached, the function should set this value - * to 0. - * - * @retval #CHIP_NO_ERROR If the function successfully produced more TLV data, or the end of - * the input data was reached (@p bufLen should be set to 0 in this case). - * @retval other Other CHIP or platform-specific error codes indicating that an error - * occurred preventing the function from producing the requested data. - * - */ - -/** - * @var GetNextBufferFunct TLVReader::GetNextBuffer - * - * A pointer to a function that will produce input data for the TLVReader object. If set to NULL (the - * default value), the reader will assume that no further input data is available. - * - * GetNextBuffer can be set by an application at any time, but is typically set when the reader - * is initialized. - * - * See the GetNextBufferFunct type definition for additional information on implementing a - * GetNextBuffer function. - */ - -/** - * Initializes a TLVReader object to read from a single input buffer. - * - * @param[in] data A pointer to a buffer containing the TLV data to be parsed. - * @param[in] dataLen The length of the TLV data to be parsed. - * - */ void TLVReader::Init(const uint8_t * data, uint32_t dataLen) { - mBufHandle = 0; - mReadPoint = data; - mBufEnd = data + dataLen; - mLenRead = 0; - mMaxLen = dataLen; + mBackingStore = nullptr; + mReadPoint = data; + mBufEnd = data + dataLen; + mLenRead = 0; + mMaxLen = dataLen; ClearElementState(); mContainerType = kTLVType_NotSpecified; SetContainerOpen(false); ImplicitProfileId = kProfileIdNotSpecified; - AppData = nullptr; - GetNextBuffer = nullptr; } -/** - * Initializes a TLVReader object to read from a single PacketBuffer. - * - * Parsing begins at the buffer's start position (buf->DataStart()) and continues until the - * end of the data in the buffer (as denoted by buf->Datalen()), or maxLen bytes have been parsed. - * - * @param[in] buf A pointer to an PacketBuffer containing the TLV data to be parsed. - * @param[in] maxLen The maximum of bytes to parse. Defaults to the amount of data - * in the input buffer. - */ -void TLVReader::Init(PacketBuffer * buf, uint32_t maxLen) +CHIP_ERROR TLVReader::Init(TLVBackingStore & backingStore, uint32_t maxLen) { - mBufHandle = reinterpret_cast(buf); - mReadPoint = buf->Start(); - mBufEnd = mReadPoint + buf->DataLength(); - mLenRead = 0; - mMaxLen = maxLen; - ClearElementState(); - mContainerType = kTLVType_NotSpecified; - SetContainerOpen(false); - - ImplicitProfileId = kProfileIdNotSpecified; - AppData = nullptr; - GetNextBuffer = nullptr; -} + mBackingStore = &backingStore; + mReadPoint = nullptr; + uint32_t bufLen = 0; + CHIP_ERROR err = mBackingStore->OnInit(*this, mReadPoint, bufLen); + if (err != CHIP_NO_ERROR) + return err; -/** - * Initializes a TLVReader object to read from a one or more PacketBuffers. - * - * Parsing begins at the initial buffer's start position (buf->DataStart()). If - * allowDiscontiguousBuffers is true, the reader will advance through the chain of buffers linked - * by their Next() pointers. Parsing continues until all data in the buffer chain has been consumed - * (as denoted by buf->Datalen()), or maxLen bytes have been parsed. - * - * @param[in] buf A pointer to an PacketBuffer containing the TLV data to be parsed. - * @param[in] maxLen The maximum of bytes to parse. Defaults to the total amount of data - * in the input buffer chain. - * @param[in] allowDiscontiguousBuffers - * If true, advance to the next buffer in the chain once all data in the - * current buffer has been consumed. If false, stop parsing at the end - * of the initial buffer. - */ -void TLVReader::Init(PacketBuffer * buf, uint32_t maxLen, bool allowDiscontiguousBuffers) -{ - mBufHandle = reinterpret_cast(buf); - mReadPoint = buf->Start(); - mBufEnd = mReadPoint + buf->DataLength(); - mLenRead = 0; - mMaxLen = maxLen; + mBufEnd = mReadPoint + bufLen; + mLenRead = 0; + mMaxLen = maxLen; ClearElementState(); mContainerType = kTLVType_NotSpecified; SetContainerOpen(false); ImplicitProfileId = kProfileIdNotSpecified; AppData = nullptr; - - if (allowDiscontiguousBuffers) - { - GetNextBuffer = GetNextPacketBuffer; - } - else - { - GetNextBuffer = nullptr; - } + return CHIP_NO_ERROR; } -/** - * Initializes a TLVReader object from another TLVReader object. - * - * @param[in] aReader A read-only reference to the TLVReader to initialize - * this from. - * - */ void TLVReader::Init(const TLVReader & aReader) { // Initialize private data members mElemTag = aReader.mElemTag; mElemLenOrVal = aReader.mElemLenOrVal; - mBufHandle = aReader.mBufHandle; + mBackingStore = aReader.mBackingStore; mReadPoint = aReader.mReadPoint; mBufEnd = aReader.mBufEnd; mLenRead = aReader.mLenRead; @@ -254,15 +92,8 @@ void TLVReader::Init(const TLVReader & aReader) ImplicitProfileId = aReader.ImplicitProfileId; AppData = aReader.AppData; - GetNextBuffer = aReader.GetNextBuffer; } -/** - * Returns the type of the current TLV element. - * - * @return A TLVType value describing the data type of the current TLV element. If the reader - * is not positioned on a TLV element, the return value will be kTLVType_NotSpecified. - */ TLVType TLVReader::GetType() const { TLVElementType elemType = ElementType(); @@ -275,57 +106,6 @@ TLVType TLVReader::GetType() const return static_cast(static_cast(elemType) & ~kTLVTypeSizeMask); } -/** - * Returns the control byte associated with current TLV element. - * - * Ideally, nobody ever needs to know about the control byte and only the - * internal implementation of TLV should have access to it. But, nevertheless, - * having access to the control byte is helpful for debugging purposes by the - * TLV Debug Utilities (that try to decode the tag control byte when pretty - * printing the TLV buffer contents). - * - * @note Unless you really know what you are doing, please refrain from using - * this method and the associated control byte information. - * - * @return An unsigned integer containing the control byte associated with - * the current TLV element. kTLVControlByte_NotSpecified is - * returned if the reader is not positioned @em on an element. - */ -uint16_t TLVReader::GetControlByte() const -{ - return mControlByte; -} - -/** - * Returns the tag associated with current TLV element. - * - * The value returned by GetTag() can be used with the tag utility functions (IsProfileTag(), - * IsContextTag(), ProfileIdFromTag(), etc.) to determine the type of tag and to extract various tag - * field values. - * - * @note If the reader is not positioned on a TLV element when GetTag() is called, the return value - * is undefined. Therefore whenever the position of the reader is uncertain applications should call - * GetType() to determine if the reader is position on an element (GetType() != kTLVType_NotSpecified) - * before calling GetTag(). - * - * @return An unsigned integer containing information about the tag associated with the current - * TLV element. - */ -uint64_t TLVReader::GetTag() const -{ - return mElemTag; -} - -/** - * Returns the length of data associated with current TLV element. - * - * Data length only applies to elements of type UTF8 string or byte string. For UTF8 strings, the - * value returned is the number of bytes in the string, not the number of characters. - * - * @return The length (in bytes) of data associated with the current TLV element, or 0 if the - * current element is not a UTF8 string or byte string, or if the reader is not - * positioned on an element. - */ uint32_t TLVReader::GetLength() const { if (TLVTypeHasLength(ElementType())) @@ -333,16 +113,6 @@ uint32_t TLVReader::GetLength() const return 0; } -/** - * Get the value of the current element as a bool type. - * - * @param[out] v Receives the value associated with current TLV element. - * - * @retval #CHIP_NO_ERROR If the method succeeded. - * @retval #CHIP_ERROR_WRONG_TLV_TYPE If the current element is not a TLV boolean type, or the - * reader is not positioned on an element. - * - */ CHIP_ERROR TLVReader::Get(bool & v) { TLVElementType elemType = ElementType(); @@ -355,19 +125,6 @@ CHIP_ERROR TLVReader::Get(bool & v) return CHIP_NO_ERROR; } -/** - * Get the value of the current element as an 8-bit signed integer. - * - * If the encoded integer value is larger than the output data type the resultant value will be - * truncated. - * - * @param[out] v Receives the value associated with current TLV element. - * - * @retval #CHIP_NO_ERROR If the method succeeded. - * @retval #CHIP_ERROR_WRONG_TLV_TYPE If the current element is not a TLV integer type (signed or - * unsigned), or the reader is not positioned on an element. - * - */ CHIP_ERROR TLVReader::Get(int8_t & v) { uint64_t v64 = 0; @@ -376,19 +133,6 @@ CHIP_ERROR TLVReader::Get(int8_t & v) return err; } -/** - * Get the value of the current element as a 16-bit signed integer. - * - * If the encoded integer value is larger than the output data type the resultant value will be - * truncated. - * - * @param[out] v Receives the value associated with current TLV element. - * - * @retval #CHIP_NO_ERROR If the method succeeded. - * @retval #CHIP_ERROR_WRONG_TLV_TYPE If the current element is not a TLV integer type (signed or - * unsigned), or the reader is not positioned on an element. - * - */ CHIP_ERROR TLVReader::Get(int16_t & v) { uint64_t v64 = 0; @@ -397,19 +141,6 @@ CHIP_ERROR TLVReader::Get(int16_t & v) return err; } -/** - * Get the value of the current element as a 32-bit signed integer. - * - * If the encoded integer value is larger than the output data type the resultant value will be - * truncated. - * - * @param[out] v Receives the value associated with current TLV element. - * - * @retval #CHIP_NO_ERROR If the method succeeded. - * @retval #CHIP_ERROR_WRONG_TLV_TYPE If the current element is not a TLV integer type (signed or - * unsigned), or the reader is not positioned on an element. - * - */ CHIP_ERROR TLVReader::Get(int32_t & v) { uint64_t v64 = 0; @@ -418,19 +149,6 @@ CHIP_ERROR TLVReader::Get(int32_t & v) return err; } -/** - * Get the value of the current element as a 64-bit signed integer. - * - * If the encoded integer value is larger than the output data type the resultant value will be - * truncated. - * - * @param[out] v Receives the value associated with current TLV element. - * - * @retval #CHIP_NO_ERROR If the method succeeded. - * @retval #CHIP_ERROR_WRONG_TLV_TYPE If the current element is not a TLV integer type (signed or - * unsigned), or the reader is not positioned on an element. - * - */ CHIP_ERROR TLVReader::Get(int64_t & v) { uint64_t v64 = 0; @@ -439,20 +157,6 @@ CHIP_ERROR TLVReader::Get(int64_t & v) return err; } -/** - * Get the value of the current element as an 8-bit unsigned integer. - * - * If the encoded integer value is larger than the output data type the resultant value will be - * truncated. Similarly, if the encoded integer value is negative, the value will be converted - * to unsigned. - * - * @param[out] v Receives the value associated with current TLV element. - * - * @retval #CHIP_NO_ERROR If the method succeeded. - * @retval #CHIP_ERROR_WRONG_TLV_TYPE If the current element is not a TLV integer type (signed or - * unsigned), or the reader is not positioned on an element. - * - */ CHIP_ERROR TLVReader::Get(uint8_t & v) { uint64_t v64 = 0; @@ -461,20 +165,6 @@ CHIP_ERROR TLVReader::Get(uint8_t & v) return err; } -/** - * Get the value of the current element as a 16-bit unsigned integer. - * - * If the encoded integer value is larger than the output data type the resultant value will be - * truncated. Similarly, if the encoded integer value is negative, the value will be converted - * to unsigned. - * - * @param[out] v Receives the value associated with current TLV element. - * - * @retval #CHIP_NO_ERROR If the method succeeded. - * @retval #CHIP_ERROR_WRONG_TLV_TYPE If the current element is not a TLV integer type (signed or - * unsigned), or the reader is not positioned on an element. - * - */ CHIP_ERROR TLVReader::Get(uint16_t & v) { uint64_t v64 = 0; @@ -483,20 +173,6 @@ CHIP_ERROR TLVReader::Get(uint16_t & v) return err; } -/** - * Get the value of the current element as a 32-bit unsigned integer. - * - * If the encoded integer value is larger than the output data type the resultant value will be - * truncated. Similarly, if the encoded integer value is negative, the value will be converted - * to unsigned. - * - * @param[out] v Receives the value associated with current TLV element. - * - * @retval #CHIP_NO_ERROR If the method succeeded. - * @retval #CHIP_ERROR_WRONG_TLV_TYPE If the current element is not a TLV integer type (signed or - unsigned), or the reader is not positioned on an element. - * - */ CHIP_ERROR TLVReader::Get(uint32_t & v) { uint64_t v64 = 0; @@ -505,18 +181,6 @@ CHIP_ERROR TLVReader::Get(uint32_t & v) return err; } -/** - * Get the value of the current element as a 64-bit unsigned integer. - * - * If the encoded integer value is negative, the value will be converted to unsigned. - * - * @param[out] v Receives the value associated with current TLV element. - * - * @retval #CHIP_NO_ERROR If the method succeeded. - * @retval #CHIP_ERROR_WRONG_TLV_TYPE If the current element is not a TLV integer type (signed or - * unsigned), or the reader is not positioned on an element. - * - */ CHIP_ERROR TLVReader::Get(uint64_t & v) { switch (ElementType()) @@ -543,16 +207,6 @@ CHIP_ERROR TLVReader::Get(uint64_t & v) return CHIP_NO_ERROR; } -/** - * Get the value of the current element as a double-precision floating point number. - * - * @param[out] v Receives the value associated with current TLV element. - * - * @retval #CHIP_NO_ERROR If the method succeeded. - * @retval #CHIP_ERROR_WRONG_TLV_TYPE If the current element is not a TLV floating point type, or - * the reader is not positioned on an element. - * - */ CHIP_ERROR TLVReader::Get(double & v) { switch (ElementType()) @@ -583,28 +237,6 @@ CHIP_ERROR TLVReader::Get(double & v) return CHIP_NO_ERROR; } -/** - * Get the value of the current byte or UTF8 string element. - * - * To determine the required input buffer size, call the GetLength() method before calling GetBytes(). - * - * @note The data output by this method is NOT null-terminated. - * - * @param[in] buf A pointer to a buffer to receive the string data. - * @param[in] bufSize The size in bytes of the buffer pointed to by @p buf. - * - * @retval #CHIP_NO_ERROR If the method succeeded. - * @retval #CHIP_ERROR_WRONG_TLV_TYPE If the current element is not a TLV byte or UTF8 string, or - * the reader is not positioned on an element. - * @retval #CHIP_ERROR_BUFFER_TOO_SMALL - * If the supplied buffer is too small to hold the data associated - * with the current element. - * @retval #CHIP_ERROR_TLV_UNDERRUN If the underlying TLV encoding ended prematurely. - * @retval other Other CHIP or platform error codes returned by the configured - * GetNextBuffer() function. Only possible when GetNextBuffer is - * non-NULL. - * - */ CHIP_ERROR TLVReader::GetBytes(uint8_t * buf, uint32_t bufSize) { if (!TLVTypeIsString(ElementType())) @@ -622,28 +254,6 @@ CHIP_ERROR TLVReader::GetBytes(uint8_t * buf, uint32_t bufSize) return CHIP_NO_ERROR; } -/** - * Get the value of the current byte or UTF8 string element as a null terminated string. - * - * To determine the required input buffer size, call the GetLength() method before calling GetBytes(). - * The input buffer should be at least one byte bigger than the string length to accommodate the null - * character. - * - * @param[in] buf A pointer to a buffer to receive the byte string data. - * @param[in] bufSize The size in bytes of the buffer pointed to by @p buf. - * - * @retval #CHIP_NO_ERROR If the method succeeded. - * @retval #CHIP_ERROR_WRONG_TLV_TYPE If the current element is not a TLV byte or UTF8 string, or - * the reader is not positioned on an element. - * @retval #CHIP_ERROR_BUFFER_TOO_SMALL - * If the supplied buffer is too small to hold the data associated - * with the current element. - * @retval #CHIP_ERROR_TLV_UNDERRUN If the underlying TLV encoding ended prematurely. - * @retval other Other CHIP or platform error codes returned by the configured - * GetNextBuffer() function. Only possible when GetNextBuffer is - * non-NULL. - * - */ CHIP_ERROR TLVReader::GetString(char * buf, uint32_t bufSize) { if (!TLVTypeIsString(ElementType())) @@ -657,31 +267,6 @@ CHIP_ERROR TLVReader::GetString(char * buf, uint32_t bufSize) return GetBytes(reinterpret_cast(buf), bufSize - 1); } -/** - * Allocates and returns a buffer containing the value of the current byte or UTF8 string. - * - * This method creates a buffer for and returns a copy of the data associated with the byte - * or UTF-8 string element at the current position. Memory for the buffer is obtained with - * Platform::MemoryAlloc() and should be freed with Platform::MemoryFree() by the caller when - * it is no longer needed. - * - * @note The data returned by this method is NOT null-terminated. - * - * @param[out] buf A reference to a pointer to which a heap-allocated buffer of - * @p dataLen bytes will be assigned on success. - * @param[out] dataLen A reference to storage for the size, in bytes, of @p buf on - * success. - * - * @retval #CHIP_NO_ERROR If the method succeeded. - * @retval #CHIP_ERROR_WRONG_TLV_TYPE If the current element is not a TLV byte or UTF8 string, or - * the reader is not positioned on an element. - * @retval #CHIP_ERROR_NO_MEMORY If memory could not be allocated for the output buffer. - * @retval #CHIP_ERROR_TLV_UNDERRUN If the underlying TLV encoding ended prematurely. - * @retval other Other CHIP or platform error codes returned by the configured - * GetNextBuffer() function. Only possible when GetNextBuffer - * is non-NULL. - * - */ CHIP_ERROR TLVReader::DupBytes(uint8_t *& buf, uint32_t & dataLen) { if (!TLVTypeIsString(ElementType())) @@ -705,28 +290,6 @@ CHIP_ERROR TLVReader::DupBytes(uint8_t *& buf, uint32_t & dataLen) return CHIP_NO_ERROR; } -/** - * Allocates and returns a buffer containing the null-terminated value of the current byte or UTF8 - * string. - * - * This method creates a buffer for and returns a null-terminated copy of the data associated with - * the byte or UTF-8 string element at the current position. Memory for the buffer is obtained with - * Platform::MemoryAlloc() and should be freed with chip::Platform::MemoryFree() by the caller when - * it is no longer needed. - * - * @param[out] buf A reference to a pointer to which a heap-allocated buffer of - * will be assigned on success. - * - * @retval #CHIP_NO_ERROR If the method succeeded. - * @retval #CHIP_ERROR_WRONG_TLV_TYPE If the current element is not a TLV byte or UTF8 string, or - * the reader is not positioned on an element. - * @retval #CHIP_ERROR_NO_MEMORY If memory could not be allocated for the output buffer. - * @retval #CHIP_ERROR_TLV_UNDERRUN If the underlying TLV encoding ended prematurely. - * @retval other Other CHIP or platform error codes returned by the configured - * GetNextBuffer() function. Only possible when GetNextBuffer - * is non-NULL. - * - */ CHIP_ERROR TLVReader::DupString(char *& buf) { if (!TLVTypeIsString(ElementType())) @@ -753,28 +316,6 @@ CHIP_ERROR TLVReader::DupString(char *& buf) return err; } -/** - * Get a pointer to the initial encoded byte of a TLV byte or UTF8 string element. - * - * This method returns a direct pointer the encoded string value within the underlying input buffer. - * To succeed, the method requires that the entirety of the string value be present in a single buffer. - * Otherwise the method returns #CHIP_ERROR_TLV_UNDERRUN. This makes the method of limited use when - * reading data from multiple discontiguous buffers. - * - * @param[out] data A reference to a const pointer that will receive a pointer to - * the underlying string data. - * - * @retval #CHIP_NO_ERROR If the method succeeded. - * @retval #CHIP_ERROR_WRONG_TLV_TYPE If the current element is not a TLV byte or UTF8 string, or the - * reader is not positioned on an element. - * @retval #CHIP_ERROR_TLV_UNDERRUN If the underlying TLV encoding ended prematurely or the value - * of the current string element is not contained within a single - * contiguous buffer. - * @retval other Other CHIP or platform error codes returned by the configured - * GetNextBuffer() function. Only possible when GetNextBuffer is - * non-NULL. - * - */ CHIP_ERROR TLVReader::GetDataPtr(const uint8_t *& data) { CHIP_ERROR err; @@ -798,100 +339,28 @@ CHIP_ERROR TLVReader::GetDataPtr(const uint8_t *& data) return CHIP_NO_ERROR; } -/** - * Initializes a new TLVReader object for reading the members of a TLV container element. - * - * The OpenContainer() method initializes a new TLVReader object for reading the member elements of a - * TLV container (a structure, array or path). When OpenContainer() is called, the current TLVReader - * object must be positioned on the container element to be read. The method takes as its sole argument - * a reference to a new reader that will be initialized to read the container. This reader is known as - * the container reader while the reader on which OpenContainer() is called is known as the parent - * reader. - * - * When the OpenContainer() method returns, the container reader is positioned immediately before the - * first member of the container. Calling Next() on the container reader will advance through the members - * of the collection until the end is reached, at which point the reader will return CHIP_END_OF_TLV. - * - * While the container reader is open, applications must not make calls on or otherwise alter the state - * of the parent reader. Once an application has finished using the container reader it must close it - * by calling CloseContainer() on the parent reader, passing the container reader as an argument. - * Applications may close the container reader at any point, with or without reading all elements - * contained in the underlying container. After the container reader is closed, applications may - * continue their use of the parent reader. - * - * The container reader inherits various configuration properties from the parent reader. These are: - * - * @li The implicit profile id (ImplicitProfileId) - * @li The application data pointer (AppData) - * @li The GetNextBuffer function pointer - * - * @note The EnterContainer() method can be used as an alternative to OpenContainer() to read a - * container element without initializing a new reader object. - * - * @param[out] containerReader A reference to a TLVReader object that will be initialized for - * reading the members of the current container element. Any data - * associated with the supplied object is overwritten. - * - * @retval #CHIP_NO_ERROR If the method succeeded. - * @retval #CHIP_ERROR_INCORRECT_STATE If the current element is not positioned on a container element. - * - */ CHIP_ERROR TLVReader::OpenContainer(TLVReader & containerReader) { TLVElementType elemType = ElementType(); if (!TLVTypeIsContainer(elemType)) return CHIP_ERROR_INCORRECT_STATE; - containerReader.mBufHandle = mBufHandle; - containerReader.mReadPoint = mReadPoint; - containerReader.mBufEnd = mBufEnd; - containerReader.mLenRead = mLenRead; - containerReader.mMaxLen = mMaxLen; + containerReader.mBackingStore = mBackingStore; + containerReader.mReadPoint = mReadPoint; + containerReader.mBufEnd = mBufEnd; + containerReader.mLenRead = mLenRead; + containerReader.mMaxLen = mMaxLen; containerReader.ClearElementState(); containerReader.mContainerType = static_cast(elemType); containerReader.SetContainerOpen(false); containerReader.ImplicitProfileId = ImplicitProfileId; containerReader.AppData = AppData; - containerReader.GetNextBuffer = GetNextBuffer; SetContainerOpen(true); return CHIP_NO_ERROR; } -/** - * Completes the reading of a TLV container after a call to OpenContainer(). - * - * The CloseContainer() method restores the state of a parent TLVReader object after a call to - * OpenContainer(). For every call to OpenContainer() applications must make a corresponding - * call to CloseContainer(), passing a reference to the same container reader to both methods. - * - * When CloseContainer() returns, the parent reader is positioned immediately before the first - * element that follows the container. From this point an application can use the Next() method - * to advance through any remaining elements. - * - * Applications can call close CloseContainer() on a parent reader at any point in time, regardless - * of whether all elements in the underlying container have been read. After CloseContainer() has - * been called, the application should consider the container reader 'de-initialized' and must not - * use it further without re-initializing it. - * - * @param[in] containerReader A reference to the TLVReader object that was supplied to the - * OpenContainer() method. - * - * @retval #CHIP_NO_ERROR If the method succeeded. - * @retval #CHIP_ERROR_INCORRECT_STATE If OpenContainer() has not been called on the reader, or if - * the container reader does not match the one passed to the - * OpenContainer() method. - * @retval #CHIP_ERROR_TLV_UNDERRUN If the underlying TLV encoding ended prematurely. - * @retval #CHIP_ERROR_INVALID_TLV_ELEMENT - * If the reader encountered an invalid or unsupported TLV - * element type. - * @retval #CHIP_ERROR_INVALID_TLV_TAG If the reader encountered a TLV tag in an invalid context. - * @retval other Other CHIP or platform error codes returned by the configured - * GetNextBuffer() function. Only possible when GetNextBuffer is - * non-NULL. - * - */ CHIP_ERROR TLVReader::CloseContainer(TLVReader & containerReader) { CHIP_ERROR err; @@ -906,41 +375,16 @@ CHIP_ERROR TLVReader::CloseContainer(TLVReader & containerReader) if (err != CHIP_NO_ERROR) return err; - mBufHandle = containerReader.mBufHandle; - mReadPoint = containerReader.mReadPoint; - mBufEnd = containerReader.mBufEnd; - mLenRead = containerReader.mLenRead; - mMaxLen = containerReader.mMaxLen; + mBackingStore = containerReader.mBackingStore; + mReadPoint = containerReader.mReadPoint; + mBufEnd = containerReader.mBufEnd; + mLenRead = containerReader.mLenRead; + mMaxLen = containerReader.mMaxLen; ClearElementState(); return CHIP_NO_ERROR; } -/** - * Prepares a TLVReader object for reading the members of TLV container element. - * - * The EnterContainer() method prepares the current TLVReader object to begin reading the member - * elements of a TLV container (a structure, array or path). For every call to EnterContainer() - * applications must make a corresponding call to ExitContainer(). - * - * When EnterContainer() is called the TLVReader object must be positioned on the container element - * to be read. The method takes as an argument a reference to a TLVType value which will be used - * to save the context of the reader while it is reading the container. - * - * When the EnterContainer() method returns, the reader is positioned immediately @em before the - * first member of the container. Repeatedly calling Next() will advance the reader through the members - * of the collection until the end is reached, at which point the reader will return CHIP_END_OF_TLV. - * - * Once the application has finished reading a container it can continue reading the elements after - * the container by calling the ExitContainer() method. - * - * @param[out] outerContainerType A reference to a TLVType value that will receive the context - * of the reader. - * - * @retval #CHIP_NO_ERROR If the method succeeded. - * @retval #CHIP_ERROR_INCORRECT_STATE If the current element is not positioned on a container element. - * - */ CHIP_ERROR TLVReader::EnterContainer(TLVType & outerContainerType) { TLVElementType elemType = ElementType(); @@ -956,42 +400,6 @@ CHIP_ERROR TLVReader::EnterContainer(TLVType & outerContainerType) return CHIP_NO_ERROR; } -/** - * Completes the reading of a TLV container and prepares a TLVReader object to read elements - * after the container. - * - * The ExitContainer() method restores the state of a TLVReader object after a call to - * EnterContainer(). For every call to EnterContainer() applications must make a corresponding - * call to ExitContainer(), passing the context value returned by the EnterContainer() method. - * - * When ExitContainer() returns, the reader is positioned immediately before the first element that - * follows the container. From this point an application can use the Next() method to advance - * through any remaining elements. - * - * Once EnterContainer() has been called, applications can call ExitContainer() on a reader at any - * point in time, regardless of whether all elements in the underlying container have been read. - * - * @note Any changes made to the configuration of the reader between the calls to EnterContainer() - * and ExitContainer() are NOT undone by the call to ExitContainer(). For example, a change to the - * implicit profile id (@p ImplicitProfileId) will not be reversed when a container is exited. Thus - * it is the application's responsibility to adjust the configuration accordingly at the appropriate - * times. - * - * @param[in] outerContainerType The TLVType value that was returned by the EnterContainer() method. - * - * @retval #CHIP_NO_ERROR If the method succeeded. - * @retval #CHIP_ERROR_INCORRECT_STATE If OpenContainer() has not been called on the reader, or if - * the container reader does not match the one passed to the - * OpenContainer() method. - * @retval #CHIP_ERROR_TLV_UNDERRUN If the underlying TLV encoding ended prematurely. - * @retval #CHIP_ERROR_INVALID_TLV_ELEMENT - * If the reader encountered an invalid or unsupported TLV element type. - * @retval #CHIP_ERROR_INVALID_TLV_TAG If the reader encountered a TLV tag in an invalid context. - * @retval other Other CHIP or platform error codes returned by the configured - * GetNextBuffer() function. Only possible when GetNextBuffer is - * non-NULL. - * - */ CHIP_ERROR TLVReader::ExitContainer(TLVType outerContainerType) { CHIP_ERROR err; @@ -1006,29 +414,6 @@ CHIP_ERROR TLVReader::ExitContainer(TLVType outerContainerType) return CHIP_NO_ERROR; } -/** - * Verifies that the TVLReader object is at the end of a TLV container. - * - * The VerifyEndOfContainer() method verifies that there are no further TLV elements to be read - * within the current TLV container. This is a convenience method that is equivalent to calling - * Next() and checking for a return value of CHIP_END_OF_TLV. - * - * @note When there are more TLV elements in the collection, this method will change the position - * of the reader. - * - * @retval #CHIP_NO_ERROR If there are no further TLV elements to be read. - * @retval #CHIP_ERROR_UNEXPECTED_TLV_ELEMENT - * If another TLV element was found in the collection. - * @retval #CHIP_ERROR_TLV_UNDERRUN If the underlying TLV encoding ended prematurely. - * @retval #CHIP_ERROR_INVALID_TLV_ELEMENT - * If the reader encountered an invalid or unsupported TLV element - * type. - * @retval #CHIP_ERROR_INVALID_TLV_TAG If the reader encountered a TLV tag in an invalid context. - * @retval other Other CHIP or platform error codes returned by the configured - * GetNextBuffer() function. Only possible when GetNextBuffer is - * non-NULL. - * - */ CHIP_ERROR TLVReader::VerifyEndOfContainer() { CHIP_ERROR err = Next(); @@ -1039,53 +424,6 @@ CHIP_ERROR TLVReader::VerifyEndOfContainer() return err; } -/** - * Returns the type of the container within which the TLVReader is currently reading. - * - * The GetContainerType() method returns the type of the TLV container within which the TLVReader - * is reading. If the TLVReader is positioned at the outer-most level of a TLV encoding (i.e. before, - * on or after the outer-most TLV element), the method will return kTLVType_NotSpecified. - * - * @return The TLVType of the current container, or kTLVType_NotSpecified if the TLVReader is not - * positioned within a container. - */ -TLVType TLVReader::GetContainerType() const -{ - return mContainerType; -} - -/** - * Advances the TLVReader object to the next TLV element to be read. - * - * The Next() method positions the reader object on the next element in a TLV encoding that resides - * in the same containment context. In particular, if the reader is positioned at the outer-most - * level of a TLV encoding, calling Next() will advance the reader to the next, top-most element. - * If the reader is positioned within a TLV container element (a structure, array or path), calling - * Next() will advance the reader to the next member element of the container. - * - * Since Next() constrains reader motion to the current containment context, calling Next() when - * the reader is positioned on a container element will advance @em over the container, skipping - * its member elements (and the members of any nested containers) until it reaches the first element - * after the container. - * - * When there are no further elements within a particular containment context the Next() method will - * return a #CHIP_END_OF_TLV error and the position of the reader will remain unchanged. - * - * @retval #CHIP_NO_ERROR If the reader was successfully positioned on a new element. - * @retval #CHIP_END_OF_TLV If no further elements are available. - * @retval #CHIP_ERROR_TLV_UNDERRUN If the underlying TLV encoding ended prematurely. - * @retval #CHIP_ERROR_INVALID_TLV_ELEMENT - * If the reader encountered an invalid or unsupported TLV element - * type. - * @retval #CHIP_ERROR_INVALID_TLV_TAG If the reader encountered a TLV tag in an invalid context. - * @retval #CHIP_ERROR_UNKNOWN_IMPLICIT_TLV_TAG - * If the reader encountered a implicitly-encoded TLV tag for which - * the corresponding profile id is unknown. - * @retval other Other CHIP or platform error codes returned by the configured - * GetNextBuffer() function. Only possible when GetNextBuffer is - * non-NULL. - * - */ CHIP_ERROR TLVReader::Next() { CHIP_ERROR err; @@ -1106,34 +444,6 @@ CHIP_ERROR TLVReader::Next() return CHIP_NO_ERROR; } -/** - * Advances the TLVReader object to the next TLV element to be read, asserting the type and tag of - * the new element. - * - * The Next(TLVType expectedType, uint64_t expectedTag) method is a convenience method that has the - * same behavior as Next(), but also verifies that the type and tag of the new TLV element match - * the supplied arguments. - * - * @param[in] expectedType The expected data type for the next element. - * @param[in] expectedTag The expected tag for the next element. - * - * @retval #CHIP_NO_ERROR If the reader was successfully positioned on a new element. - * @retval #CHIP_END_OF_TLV If no further elements are available. - * @retval #CHIP_ERROR_WRONG_TLV_TYPE If the type of the new element does not match the value - * of the @p expectedType argument. - * @retval #CHIP_ERROR_UNEXPECTED_TLV_ELEMENT - * If the tag associated with the new element does not match the - * value of the @p expectedTag argument. - * @retval #CHIP_ERROR_TLV_UNDERRUN If the underlying TLV encoding ended prematurely. - * @retval #CHIP_ERROR_INVALID_TLV_ELEMENT - * If the reader encountered an invalid or unsupported TLV - * element type. - * @retval #CHIP_ERROR_INVALID_TLV_TAG If the reader encountered a TLV tag in an invalid context. - * @retval other Other CHIP or platform error codes returned by the configured - * GetNextBuffer() function. Only possible when GetNextBuffer is - * non-NULL. - * - */ CHIP_ERROR TLVReader::Next(TLVType expectedType, uint64_t expectedTag) { CHIP_ERROR err = Next(); @@ -1146,27 +456,6 @@ CHIP_ERROR TLVReader::Next(TLVType expectedType, uint64_t expectedTag) return CHIP_NO_ERROR; } -/** - * Advances the TLVReader object to immediately after the current TLV element. - * - * The Skip() method positions the reader object immediately @em after the current TLV element, such - * that a subsequent call to Next() will advance the reader to the following element. Like Next(), - * if the reader is positioned on a container element at the time of the call, the members of the - * container will be skipped. If the reader is not positioned on any element, its position remains - * unchanged. - * - * @retval #CHIP_NO_ERROR If the reader was successfully positioned on a new element. - * @retval #CHIP_END_OF_TLV If no further elements are available. - * @retval #CHIP_ERROR_TLV_UNDERRUN If the underlying TLV encoding ended prematurely. - * @retval #CHIP_ERROR_INVALID_TLV_ELEMENT - * If the reader encountered an invalid or unsupported TLV - * element type. - * @retval #CHIP_ERROR_INVALID_TLV_TAG If the reader encountered a TLV tag in an invalid context. - * @retval other Other CHIP or platform error codes returned by the configured - * GetNextBuffer() function. Only possible when GetNextBuffer is - * non-NULL. - * - */ CHIP_ERROR TLVReader::Skip() { CHIP_ERROR err; @@ -1217,8 +506,7 @@ void TLVReader::ClearElementState() * @retval #CHIP_NO_ERROR If the reader was successfully positioned at the end of the * data. * @retval other Other CHIP or platform error codes returned by the configured - * GetNextBuffer() function. Only possible when GetNextBuffer is - * non-NULL. + * TLVBackingStore. */ CHIP_ERROR TLVReader::SkipData() { @@ -1483,11 +771,11 @@ CHIP_ERROR TLVReader::EnsureData(CHIP_ERROR noDataErr) if (mLenRead == mMaxLen) return noDataErr; - if (GetNextBuffer == nullptr) + if (mBackingStore == nullptr) return noDataErr; uint32_t bufLen; - err = GetNextBuffer(*this, mBufHandle, mReadPoint, bufLen); + err = mBackingStore->GetNextBuffer(*this, mReadPoint, bufLen); if (err != CHIP_NO_ERROR) return err; if (bufLen == 0) @@ -1553,36 +841,6 @@ TLVElementType TLVReader::ElementType() const return static_cast(mControlByte & kTLVTypeMask); } -CHIP_ERROR TLVReader::GetNextPacketBuffer(TLVReader & reader, uintptr_t & bufHandle, const uint8_t *& bufStart, uint32_t & bufLen) -{ - PacketBuffer *& buf = reinterpret_cast(bufHandle); - - if (buf != nullptr) - buf = buf->Next_ForNow(); - if (buf != nullptr) - { - bufStart = buf->Start(); - bufLen = buf->DataLength(); - } - else - { - bufStart = nullptr; - bufLen = 0; - } - - return CHIP_NO_ERROR; -} - -/** - * Position the destination reader on the next element with the given tag within this reader's current container context - * - * @param[in] tag The destination context tag value - * @param[in] destReader The destination TLV reader value that was located by given tag - * - * @retval #CHIP_NO_ERROR If the reader was successfully positioned at the given tag - * @retval #CHIP_END_OF_TLV If the given tag cannot be found - * @retval other Other CHIP or platform error codes - */ CHIP_ERROR TLVReader::FindElementWithTag(const uint64_t tag, TLVReader & destReader) const { CHIP_ERROR err = CHIP_NO_ERROR; diff --git a/src/lib/core/CHIPTLVUpdater.cpp b/src/lib/core/CHIPTLVUpdater.cpp index 10df9678e3ed39..236f3bedb8ebbf 100644 --- a/src/lib/core/CHIPTLVUpdater.cpp +++ b/src/lib/core/CHIPTLVUpdater.cpp @@ -1,6 +1,6 @@ /* * - * Copyright (c) 2020 Project CHIP Authors + * Copyright (c) 2020-2021 Project CHIP Authors * Copyright (c) 2015-2017 Nest Labs, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -33,25 +33,6 @@ namespace TLV { using namespace chip::Encoding; -/** - * Initialize a TLVUpdater object to edit a single input buffer. - * - * On calling this method, the TLV data in the buffer is moved to the end of the - * buffer and a private TLVReader object is initialized on this relocated - * buffer. A private TLVWriter object is also initialized on the free space that - * is now available at the beginning. Applications can use the TLVUpdater object - * to parse the TLV data and modify/delete existing elements or add new elements - * to the encoding. - * - * @param[in] buf A pointer to a buffer containing the TLV data to be edited. - * @param[in] dataLen The length of the TLV data in the buffer. - * @param[in] maxLen The total length of the buffer. - * - * @retval #CHIP_NO_ERROR If the method succeeded. - * @retval #CHIP_ERROR_INVALID_ARGUMENT If the buffer address is invalid. - * @retval #CHIP_ERROR_BUFFER_TOO_SMALL If the buffer is too small. - * - */ CHIP_ERROR TLVUpdater::Init(uint8_t * buf, uint32_t dataLen, uint32_t maxLen) { CHIP_ERROR err = CHIP_NO_ERROR; @@ -77,36 +58,6 @@ CHIP_ERROR TLVUpdater::Init(uint8_t * buf, uint32_t dataLen, uint32_t maxLen) return err; } -/** - * Initialize a TLVUpdater object using a TLVReader. - * - * On calling this method, TLV data in the buffer pointed to by the TLVReader - * is moved from the current read point to the end of the buffer. A new - * private TLVReader object is initialized to read from this new location, while - * a new private TLVWriter object is initialized to write to the freed up buffer - * space. - * - * Note that if the TLVReader is already positioned "on" an element, it is first - * backed-off to the start of that element. Also note that this backing off - * works well with container elements, i.e., if the TLVReader was already used - * to call EnterContainer(), then there is nothing to back-off. But if the - * TLVReader was positioned on the container element and EnterContainer() was - * not yet called, then the TLVReader object is backed-off to the start of the - * container head. - * - * The input TLVReader object will be destroyed before returning and the - * application must not make use of the same on return. - * - * @param[in,out] aReader Reference to a TLVReader object that will be - * destroyed before returning. - * @param[in] freeLen The length of free space (in bytes) available - * in the pre-encoded data buffer. - * - * @retval #CHIP_NO_ERROR If the method succeeded. - * @retval #CHIP_ERROR_INVALID_ARGUMENT If the buffer address is invalid. - * @retval #CHIP_ERROR_NOT_IMPLEMENTED If reader was initialized on a chain - * of buffers. - */ CHIP_ERROR TLVUpdater::Init(TLVReader & aReader, uint32_t freeLen) { CHIP_ERROR err = CHIP_NO_ERROR; @@ -114,8 +65,8 @@ CHIP_ERROR TLVUpdater::Init(TLVReader & aReader, uint32_t freeLen) uint32_t remainingDataLen = aReader.GetRemainingLength(); uint32_t readDataLen = aReader.GetLengthRead(); - // TLVUpdater does not support chain of buffers yet - VerifyOrExit(aReader.mBufHandle == 0, err = CHIP_ERROR_NOT_IMPLEMENTED); + // TLVUpdater does not support backing stores yet + VerifyOrExit(aReader.mBackingStore == 0, err = CHIP_ERROR_NOT_IMPLEMENTED); // TLVReader should point to a non-NULL buffer VerifyOrExit(buf != nullptr, err = CHIP_ERROR_INVALID_ARGUMENT); @@ -137,7 +88,7 @@ CHIP_ERROR TLVUpdater::Init(TLVReader & aReader, uint32_t freeLen) memmove(buf + freeLen, buf, remainingDataLen); // Initialize the internal reader object - mUpdaterReader.mBufHandle = 0; + mUpdaterReader.mBackingStore = 0; mUpdaterReader.mReadPoint = buf + freeLen; mUpdaterReader.mBufEnd = buf + freeLen + remainingDataLen; mUpdaterReader.mLenRead = readDataLen; @@ -150,10 +101,9 @@ CHIP_ERROR TLVUpdater::Init(TLVReader & aReader, uint32_t freeLen) mUpdaterReader.ImplicitProfileId = aReader.ImplicitProfileId; mUpdaterReader.AppData = aReader.AppData; - mUpdaterReader.GetNextBuffer = nullptr; // Initialize the internal writer object - mUpdaterWriter.mBufHandle = 0; + mUpdaterWriter.mBackingStore = 0; mUpdaterWriter.mBufStart = buf - readDataLen; mUpdaterWriter.mWritePoint = buf; mUpdaterWriter.mRemainingLen = freeLen; @@ -164,8 +114,6 @@ CHIP_ERROR TLVUpdater::Init(TLVReader & aReader, uint32_t freeLen) mUpdaterWriter.SetCloseContainerReserved(false); mUpdaterWriter.ImplicitProfileId = aReader.ImplicitProfileId; - mUpdaterWriter.GetNewBuffer = nullptr; - mUpdaterWriter.FinalizeBuffer = nullptr; // Cache element start address for internal use mElementStartAddr = buf + freeLen; @@ -178,70 +126,12 @@ CHIP_ERROR TLVUpdater::Init(TLVReader & aReader, uint32_t freeLen) return err; } -/** - * Set the Implicit Profile ID for the TLVUpdater object. - * - * This method sets the implicit profile ID for the TLVUpdater object. When the - * updater is asked to encode a new element, if the profile ID of the tag - * associated with the new element matches the value of the @p profileId, the - * updater will encode the tag in implicit form, thereby omitting the profile ID - * in the process. - * - * @param[in] profileId The profile id of tags that should be encoded in - * implicit form. - */ void TLVUpdater::SetImplicitProfileId(uint32_t profileId) { mUpdaterReader.ImplicitProfileId = profileId; mUpdaterWriter.ImplicitProfileId = profileId; } -/** - * Skip the current element and advance the TLVUpdater object to the next - * element in the input TLV. - * - * The Next() method skips the current element in the input TLV and advances the - * TLVUpdater's reader to the next element that resides in the same containment - * context. In particular, if the reader is positioned at the outer most level - * of a TLV encoding, calling Next() will advance it to the next, top most - * element. If the reader is positioned within a TLV container element (a - * structure, array or path), calling Next() will advance it to the next member - * element of the container. - * - * Since Next() constrains reader motion to the current containment context, - * calling Next() when the reader is positioned on a container element will - * advance @em over the container, skipping its member elements (and the members - * of any nested containers) until it reaches the first element after the - * container. - * - * When there are no further elements within a particular containment context - * the Next() method will return a #CHIP_END_OF_TLV error and the position of - * the reader will remain unchanged. - * - * @note The Next() method implicitly skips the current element. Hence, the - * TLVUpdater's private writer state variables will be adjusted to account for - * the new freed space (made available by skipping). This means that the - * application is expected to call Next() on the TLVUpdater object after a Get() - * whose value the application does @em not write back (which from the - * TLVUpdater's view is equivalent to skipping that element). - * - * @note Applications are also expected to call Next() when they are at the end - * of a container, and want to add new elements there. This is particularly - * important in situations where there is a fixed schema. Applications that have - * fixed schemas and know where the container end is cannot just add new - * elements at the end, because the TLVUpdater writer's state will not reflect - * the correct free space available for the Put() operation. Hence, applications - * must call Next() (and possibly also test for CHIP_END_OF_TLV) before adding - * elements at the end of a container. - * - * @retval #CHIP_NO_ERROR If the TLVUpdater reader was - * successfully positioned on a new - * element. - * @retval other Returns the CHIP or platform error - * codes returned by the TLVReader::Skip() - * and TLVReader::Next() method. - * - */ CHIP_ERROR TLVUpdater::Next() { CHIP_ERROR err = CHIP_NO_ERROR; @@ -260,29 +150,6 @@ CHIP_ERROR TLVUpdater::Next() return err; } -/** - * Copies the current element from input TLV to output TLV. - * - * The Move() method copies the current element on which the TLVUpdater's reader - * is positioned on, to the TLVUpdater's writer. The application should call - * Next() and position the TLVUpdater's reader on an element before calling this - * method. Just like the TLVReader::Next() method, if the reader is positioned - * on a container element at the time of the call, all the members of the - * container will be copied. If the reader is not positioned on any element, - * nothing changes on calling this method. - * - * @retval #CHIP_NO_ERROR If the TLVUpdater reader was - * successfully positioned on a new - * element. - * @retval #CHIP_END_OF_TLV If the TLVUpdater's reader is pointing - * to end of container. - * @retval #CHIP_ERROR_INVALID_TLV_ELEMENT - * If the TLVIpdater's reader is not - * positioned on a valid TLV element. - * @retval other Returns other error codes returned by - * TLVReader::Skip() method. - * - */ CHIP_ERROR TLVUpdater::Move() { CHIP_ERROR err = CHIP_NO_ERROR; @@ -315,22 +182,6 @@ CHIP_ERROR TLVUpdater::Move() return err; } -/** - * Move everything from the TLVUpdater's current read point till end of input - * TLV buffer over to output. - * - * This method supports moving everything from the TLVUpdater's current read - * point till the end of the reader buffer over to the TLVUpdater's writer. - * - * @note This method can be called with the TLVUpdater's reader positioned - * anywhere within the input TLV. The reader can also be positioned under - * multiple levels of nested containers and this method will still work. - * - * @note This method also changes the state of the TLVUpdater object to a state - * it would be in if the application had painstakingly parsed each element from - * the current read point till the end of the input encoding and copied them to - * the output TLV. - */ void TLVUpdater::MoveUntilEnd() { const uint8_t * buffEnd = mUpdaterReader.GetReadPoint() + mUpdaterReader.GetRemainingLength(); @@ -357,42 +208,6 @@ void TLVUpdater::MoveUntilEnd() mUpdaterReader.SetContainerOpen(false); } -/** - * Prepares a TLVUpdater object for reading elements of a container. It also - * encodes a start of container object in the output TLV. - * - * The EnterContainer() method prepares the current TLVUpdater object to begin - * reading the member elements of a TLV container (a structure, array or path). - * For every call to EnterContainer() applications must make a corresponding - * call to ExitContainer(). - * - * When EnterContainer() is called the TLVUpdater's reader must be positioned on - * the container element. The method takes as an argument a reference to a - * TLVType value which will be used to save the context of the updater while it - * is reading the container. - * - * When the EnterContainer() method returns, the updater is positioned - * immediately @em before the first member of the container. Repeatedly calling - * Next() will advance the updater through the members of the collection until - * the end is reached, at which point the updater will return CHIP_END_OF_TLV. - * - * Once the application has finished reading a container it can continue reading - * the elements after the container by calling the ExitContainer() method. - * - * @note This method implicitly encodes a start of container element in the - * output TLV buffer. - * - * @param[out] outerContainerType A reference to a TLVType value that will - * receive the context of the updater. - * - * @retval #CHIP_NO_ERROR If the method succeeded. - * @retval #CHIP_ERROR_INCORRECT_STATE If the TLVUpdater reader is not - * positioned on a container element. - * @retval other Any other CHIP or platform error code - * returned by TLVWriter::StartContainer() - * or TLVReader::EnterContainer(). - * - */ CHIP_ERROR TLVUpdater::EnterContainer(TLVType & outerContainerType) { CHIP_ERROR err = CHIP_NO_ERROR; @@ -416,49 +231,6 @@ CHIP_ERROR TLVUpdater::EnterContainer(TLVType & outerContainerType) return err; } -/** - * Completes the reading of a TLV container element and encodes an end of TLV - * element in the output TLV. - * - * The ExitContainer() method restores the state of a TLVUpdater object after a - * call to EnterContainer(). For every call to EnterContainer() applications - * must make a corresponding call to ExitContainer(), passing the context value - * returned by the EnterContainer() method. - * - * When ExitContainer() returns, the TLVUpdater reader is positioned immediately - * before the first element that follows the container in the input TLV. From - * this point applications can call Next() to advance through any remaining - * elements. - * - * Once EnterContainer() has been called, applications can call ExitContainer() - * on the updater at any point in time, regardless of whether all elements in - * the underlying container have been read. Also, note that calling - * ExitContainer() before reading all the elements in the container, will result - * in the updated container getting truncated in the output TLV. - * - * @note Any changes made to the configuration of the updater between the calls - * to EnterContainer() and ExitContainer() are NOT undone by the call to - * ExitContainer(). For example, a change to the implicit profile id - * (@p ImplicitProfileId) will not be reversed when a container is exited. Thus - * it is the application's responsibility to adjust the configuration - * accordingly at the appropriate times. - * - * @param[in] outerContainerType The TLVType value that was returned by - * the EnterContainer() method. - * - * @retval #CHIP_NO_ERROR If the method succeeded. - * @retval #CHIP_ERROR_TLV_UNDERRUN If the underlying TLV encoding ended - * prematurely. - * @retval #CHIP_ERROR_INVALID_TLV_ELEMENT - * If the updater encountered an invalid or - * unsupported TLV element type. - * @retval #CHIP_ERROR_INVALID_TLV_TAG If the updater encountered a TLV tag in - * an invalid context. - * @retval other Any other CHIP or platform error code - * returned by TLVWriter::EndContainer() or - * TLVReader::ExitContainer(). - * - */ CHIP_ERROR TLVUpdater::ExitContainer(TLVType outerContainerType) { CHIP_ERROR err = CHIP_NO_ERROR; diff --git a/src/lib/core/CHIPTLVWriter.cpp b/src/lib/core/CHIPTLVWriter.cpp index 14c5d7ad6d8c9a..f2dd45f683ca69 100644 --- a/src/lib/core/CHIPTLVWriter.cpp +++ b/src/lib/core/CHIPTLVWriter.cpp @@ -1,6 +1,6 @@ /* * - * Copyright (c) 2020 Project CHIP Authors + * Copyright (c) 2020-2021 Project CHIP Authors * Copyright (c) 2013-2017 Nest Labs, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -33,10 +33,10 @@ #include #include #include -#include #include #include +#include // Doxygen is confused by the __attribute__ annotation #ifndef DOXYGEN @@ -48,130 +48,9 @@ namespace TLV { using namespace chip::Encoding; -/** - * @var uint32_t TLVWriter::ImplicitProfileId - * - * The profile id of tags that should be encoded in implicit form. - * - * When a writer is asked to encode a new element, if the profile id of the tag associated with the - * new element matches the value of the @p ImplicitProfileId member, the writer will encode the tag - * in implicit form, omitting the profile id in the process. - * - * By default, the @p ImplicitProfileId property is set to kProfileIdNotSpecified, which instructs - * the writer not to emit implicitly encoded tags. Applications can set @p ImplicitProfileId at any - * time to enable encoding tags in implicit form starting at the current point in the encoding. The - * appropriate profile id to set is usually dependent on the context of the application or protocol - * being spoken. - * - * @note The value of the @p ImplicitProfileId member affects the encoding of profile-specific - * tags only; the encoding of context-specific tags is unchanged. - */ - -/** - * @var void *TLVWriter::AppData - * - * A pointer field that can be used for application-specific data. - */ - -/** - * @typedef CHIP_ERROR (*TLVWriter::GetNewBufferFunct)(TLVWriter& writer, uintptr_t& bufHandle, uint8_t *& bufStart, uint32_t& - * bufLen) - * - * A function that supplies new output buffer space to a TLVWriter. - * - * Functions of this type are used to prepare new buffer space for a TLVWriter to write to. When called, - * the function is expected to return a pointer to a memory location where new data should be written, - * along with an associated maximum length. The function can supply write space either by allocating - * a new buffer to hold the data or by clearing out previously written data from an existing buffer. - * - * @param[in] writer A reference to the TLVWriter object that is requesting new buffer - * space. - * @param[in,out] bufHandle A reference to a uintptr_t value that the function can use to store - * context data between calls. This value is initialized to 0 - * prior to the first call. - * @param[in,out] bufStart A reference to a data pointer. On entry to the function, @p bufStart - * points the beginning of the current output buffer. On exit, @p bufStart - * is expected to point to the beginning of the new output buffer. - * The new pointer value can be the same as the previous value (e.g. - * if the function copied the existing data elsewhere), or it can point - * to an entirely new location. - * @param[in,out] bufLen A reference to an unsigned integer. On entry to the function, - * @p bufLen contains the number of byte of @em unused space in the - * current buffer. On exit, @p bufLen is expected to contain the maximum - * number of bytes that can be written to the new output buffer. - * - * @retval #CHIP_NO_ERROR If the function was able to supply more buffer space for the writer. - * @retval other Other CHIP or platform-specific error codes indicating that an error - * occurred preventing the function from producing additional buffer - * space. - * - */ - -/** - * @var GetNewBufferFunct TLVWriter::GetNewBuffer - * - * A pointer to a function that will supply new output buffer space to a TLVWriter. - * - * A TLVWriter object will call the GetNewBuffer function whenever an attempt is made to write data - * that exceeds the size of the current output buffer. If set to NULL (the default value), the - * writer will return a CHIP_ERROR_NO_MEMORY if the output data overflows the current buffer. - * - * GetNewBuffer can be set by an application at any time, but is typically set when the writer - * is initialized. - * - * See the GetNewBufferFunct type definition for additional information on implementing a - * GetNewBuffer function. - */ - -/** - * @typedef CHIP_ERROR (*TLVWriter::FinalizeBufferFunct)(TLVWriter& writer, uintptr_t bufHandle, uint8_t *bufStart, uint32_t bufLen) - * - * A function used to perform finalization of the output from a TLVWriter object. - * - * Functions of this type are called when a TLVWriter's Finalize() method is called. The function is - * expected to perform any necessary clean-up or finalization related to consuming the output of the - * writer object. Examples of this include such things as recording the final length of the encoding, - * or closing a file descriptor. - * - * @param[in] writer A reference to the TLVWriter object that is being finalized. - * @param[in,out] bufHandle A uintptr_t context value that was set by previous calls to the - * @p GetNewBuffer function. - * @param[in,out] bufStart A pointer to the beginning of the current (and final) output buffer. - * @param[in,out] bufLen The number of bytes contained in the buffer pointed to by @p bufStart. - * - * @retval #CHIP_NO_ERROR If finalization was successful. - * @retval other Other CHIP or platform-specific error codes indicating that an error - * occurred during finalization. - * - */ - -/** - * @var FinalizeBufferFunct TLVWriter::FinalizeBuffer - * - * A pointer to a function that will be called when the TLVWriter is finalized. - * - * A TLVWriter object will call the FinalizeBuffer function whenever its Finalize() method is - * called. Applications can set the function pointer at any point prior to calling Finalize(). - * By default the pointer is set to NULL, which causes the Finalize() method to forego calling - * the function. - * - * See the FinalizeBufferFunct type definition for additional information on implementing a - * FinalizeBuffer function. - */ - -/** - * Initializes a TLVWriter object to write into a single output buffer. - * - * @note Applications must call Finalize() on the writer before using the contents of the output - * buffer. - * - * @param[in] buf A pointer to the buffer into which TLV should be written. - * @param[in] maxLen The maximum number of bytes that should be written to the output buffer. - * - */ NO_INLINE void TLVWriter::Init(uint8_t * buf, uint32_t maxLen) { - mBufHandle = 0; + mBackingStore = nullptr; mBufStart = mWritePoint = buf; mRemainingLen = maxLen; mLenWritten = 0; @@ -181,30 +60,18 @@ NO_INLINE void TLVWriter::Init(uint8_t * buf, uint32_t maxLen) SetCloseContainerReserved(true); ImplicitProfileId = kProfileIdNotSpecified; - GetNewBuffer = nullptr; - FinalizeBuffer = nullptr; } -/** - * Initializes a TLVWriter object to write into a single PacketBuffer. - * - * Writing begins immediately after the last byte of existing data in the supplied buffer. - * - * @note If a chain of buffers is given, data will only be written to the first buffer. - * - * @note Applications must call Finalize() on the writer before using the contents of the buffer. - * - * @param[in] buf A pointer to an PacketBuffer into which TLV should be written. - * @param[in] maxLen The maximum number of bytes that should be written to the output buffer. - * - */ -void TLVWriter::Init(PacketBuffer * buf, uint32_t maxLen) +CHIP_ERROR TLVWriter::Init(TLVBackingStore & backingStore, uint32_t maxLen) { - mBufHandle = reinterpret_cast(buf); - mBufStart = mWritePoint = buf->Start() + buf->DataLength(); - mRemainingLen = buf->AvailableDataLength(); - if (mRemainingLen > maxLen) - mRemainingLen = maxLen; + mBackingStore = &backingStore; + mBufStart = nullptr; + mRemainingLen = 0; + CHIP_ERROR err = mBackingStore->OnInit(*this, mBufStart, mRemainingLen); + if (err != CHIP_NO_ERROR) + return err; + + mWritePoint = mBufStart; mLenWritten = 0; mMaxLen = maxLen; mContainerType = kTLVType_NotSpecified; @@ -212,172 +79,29 @@ void TLVWriter::Init(PacketBuffer * buf, uint32_t maxLen) SetCloseContainerReserved(true); ImplicitProfileId = kProfileIdNotSpecified; - GetNewBuffer = nullptr; - FinalizeBuffer = FinalizePacketBuffer; -} - -/** - * Initializes a TLVWriter object to write into one or more PacketBuffers - * - * Writing begins immediately after the last byte of existing data in the specified buffer. If - * @p allowDiscontiguousBuffers is true, additional PacketBuffers will be allocated and chained to - * the supplied buffer as needed to accommodate the amount of data written. If the specified output - * buffer is already the head of a chain of buffers, output will be written to the subsequent buffers - * in the chain before any new buffers are allocated. - * - * @note Applications must call Finalize() on the writer before using the contents of the output - * buffer(s). - * - * @param[in] buf A pointer to an PacketBuffer into which TLV data should be written. - * @param[in] maxLen The maximum number of bytes that should be written to the output buffer(s). - * @param[in] allowDiscontiguousBuffers - * If true, write data to a chain of PacketBuffers, allocating new buffers as - * needed to store the data written. If false, writing will fail with - * CHIP_ERROR_BUFFER_TOO_SMALL if the written data exceeds the space available - * in the initial output buffer. - * - */ -void TLVWriter::Init(PacketBuffer * buf, uint32_t maxLen, bool allowDiscontiguousBuffers) -{ - Init(buf, maxLen); - - if (allowDiscontiguousBuffers) - { - GetNewBuffer = GetNewPacketBuffer; - } - else - { - GetNewBuffer = nullptr; - } -} - -/** - * Returns the total number of bytes written since the writer was initialized. - * - * @return Total number of bytes written since the writer was initialized. - */ -uint32_t TLVWriter::GetLengthWritten() -{ - return mLenWritten; + return CHIP_NO_ERROR; } -/** - * Finish the writing of a TLV encoding. - * - * The Finalize() method completes the process of writing a TLV encoding to the underlying output - * buffer. The method must be called by the application before it uses the contents of the buffer. - * Finalize() can only be called when there are no container writers open for the current writer. - * (See @p OpenContainer()). - * - * @retval #CHIP_NO_ERROR If the encoding was finalized successfully. - * @retval #CHIP_ERROR_TLV_CONTAINER_OPEN - * If a container writer has been opened on the current writer and not - * yet closed. - * @retval other Other CHIP or platform-specific errors returned by the configured - * FinalizeBuffer() function. - */ CHIP_ERROR TLVWriter::Finalize() { CHIP_ERROR err = CHIP_NO_ERROR; if (IsContainerOpen()) return CHIP_ERROR_TLV_CONTAINER_OPEN; - if (FinalizeBuffer != nullptr) - err = FinalizeBuffer(*this, mBufHandle, mBufStart, static_cast(mWritePoint - mBufStart)); + if (mBackingStore != nullptr) + err = mBackingStore->FinalizeBuffer(*this, mBufStart, static_cast(mWritePoint - mBufStart)); return err; } -/** - * Encodes a TLV boolean value. - * - * @param[in] tag The TLV tag to be encoded with the value, or @p AnonymousTag if the - * value should be encoded without a tag. Tag values should be - * constructed with one of the tag definition functions ProfileTag(), - * ContextTag() or CommonTag(). - * @param[in] v The value to be encoded. - * - * @retval #CHIP_NO_ERROR If the method succeeded. - * @retval #CHIP_ERROR_TLV_CONTAINER_OPEN - * If a container writer has been opened on the current writer and not - * yet closed. - * @retval #CHIP_ERROR_INVALID_TLV_TAG - * If the specified tag value is invalid or inappropriate in the context - * in which the value is being written. - * @retval #CHIP_ERROR_BUFFER_TOO_SMALL - * If writing the value would exceed the limit on the maximum number of - * bytes specified when the writer was initialized. - * @retval #CHIP_ERROR_NO_MEMORY - * If an attempt to allocate an output buffer failed due to lack of - * memory. - * @retval other Other CHIP or platform-specific errors returned by the configured - * GetNewBuffer() or FinalizeBuffer() functions. - * - */ CHIP_ERROR TLVWriter::PutBoolean(uint64_t tag, bool v) { return WriteElementHead((v) ? TLVElementType::BooleanTrue : TLVElementType::BooleanFalse, tag, 0); } -/** - * Encodes a TLV unsigned integer value. - * - * @param[in] tag The TLV tag to be encoded with the value, or @p AnonymousTag if the - * value should be encoded without a tag. Tag values should be - * constructed with one of the tag definition functions ProfileTag(), - * ContextTag() or CommonTag(). - * @param[in] v The value to be encoded. - * - * @retval #CHIP_NO_ERROR If the method succeeded. - * @retval #CHIP_ERROR_TLV_CONTAINER_OPEN - * If a container writer has been opened on the current writer and not - * yet closed. - * @retval #CHIP_ERROR_INVALID_TLV_TAG - * If the specified tag value is invalid or inappropriate in the context - * in which the value is being written. - * @retval #CHIP_ERROR_BUFFER_TOO_SMALL - * If writing the value would exceed the limit on the maximum number of - * bytes specified when the writer was initialized. - * @retval #CHIP_ERROR_NO_MEMORY - * If an attempt to allocate an output buffer failed due to lack of - * memory. - * @retval other Other CHIP or platform-specific errors returned by the configured - * GetNewBuffer() or FinalizeBuffer() functions. - * - */ CHIP_ERROR TLVWriter::Put(uint64_t tag, uint8_t v) { return Put(tag, static_cast(v)); } -/** - * Encodes a TLV unsigned integer value. - * - * @param[in] tag The TLV tag to be encoded with the value, or @p AnonymousTag if the - * value should be encoded without a tag. Tag values should be - * constructed with one of the tag definition functions ProfileTag(), - * ContextTag() or CommonTag(). - * @param[in] v The value to be encoded. - * @param[in] preserveSize True if the value should be encoded in the same number of bytes as - * at the input type. False if value should be encoded in the minimum - * number of bytes necessary to represent the value. Note: Applications - * are strongly encouraged to set this parameter to false. - * - * @retval #CHIP_NO_ERROR If the method succeeded. - * @retval #CHIP_ERROR_TLV_CONTAINER_OPEN - * If a container writer has been opened on the current writer and not - * yet closed. - * @retval #CHIP_ERROR_INVALID_TLV_TAG - * If the specified tag value is invalid or inappropriate in the context - * in which the value is being written. - * @retval #CHIP_ERROR_BUFFER_TOO_SMALL - * If writing the value would exceed the limit on the maximum number of - * bytes specified when the writer was initialized. - * @retval #CHIP_ERROR_NO_MEMORY - * If an attempt to allocate an output buffer failed due to lack of - * memory. - * @retval other Other CHIP or platform-specific errors returned by the configured - * GetNewBuffer() or FinalizeBuffer() functions. - * - */ CHIP_ERROR TLVWriter::Put(uint64_t tag, uint8_t v, bool preserveSize) { if (preserveSize) @@ -385,17 +109,11 @@ CHIP_ERROR TLVWriter::Put(uint64_t tag, uint8_t v, bool preserveSize) return Put(tag, v); } -/** - * @overload CHIP_ERROR TLVWriter::Put(uint64_t tag, uint8_t v) - */ CHIP_ERROR TLVWriter::Put(uint64_t tag, uint16_t v) { return Put(tag, static_cast(v)); } -/** - * @overload CHIP_ERROR TLVWriter::Put(uint64_t tag, uint8_t v, bool preserveSize) - */ CHIP_ERROR TLVWriter::Put(uint64_t tag, uint16_t v, bool preserveSize) { if (preserveSize) @@ -403,17 +121,11 @@ CHIP_ERROR TLVWriter::Put(uint64_t tag, uint16_t v, bool preserveSize) return Put(tag, v); } -/** - * @overload CHIP_ERROR TLVWriter::Put(uint64_t tag, uint8_t v) - */ CHIP_ERROR TLVWriter::Put(uint64_t tag, uint32_t v) { return Put(tag, static_cast(v)); } -/** - * @overload CHIP_ERROR TLVWriter::Put(uint64_t tag, uint8_t v, bool preserveSize) - */ CHIP_ERROR TLVWriter::Put(uint64_t tag, uint32_t v, bool preserveSize) { if (preserveSize) @@ -421,9 +133,6 @@ CHIP_ERROR TLVWriter::Put(uint64_t tag, uint32_t v, bool preserveSize) return Put(tag, v); } -/** - * @overload CHIP_ERROR TLVWriter::Put(uint64_t tag, uint8_t v) - */ CHIP_ERROR TLVWriter::Put(uint64_t tag, uint64_t v) { TLVElementType elemType; @@ -438,9 +147,6 @@ CHIP_ERROR TLVWriter::Put(uint64_t tag, uint64_t v) return WriteElementHead(elemType, tag, v); } -/** - * @overload CHIP_ERROR TLVWriter::Put(uint64_t tag, uint8_t v, bool preserveSize) - */ CHIP_ERROR TLVWriter::Put(uint64_t tag, uint64_t v, bool preserveSize) { if (preserveSize) @@ -448,67 +154,11 @@ CHIP_ERROR TLVWriter::Put(uint64_t tag, uint64_t v, bool preserveSize) return Put(tag, v); } -/** - * Encodes a TLV signed integer value. - * - * @param[in] tag The TLV tag to be encoded with the value, or @p AnonymousTag if the - * value should be encoded without a tag. Tag values should be - * constructed with one of the tag definition functions ProfileTag(), - * ContextTag() or CommonTag(). - * @param[in] v The value to be encoded. - * - * @retval #CHIP_NO_ERROR If the method succeeded. - * @retval #CHIP_ERROR_TLV_CONTAINER_OPEN - * If a container writer has been opened on the current writer and not - * yet closed. - * @retval #CHIP_ERROR_INVALID_TLV_TAG - * If the specified tag value is invalid or inappropriate in the context - * in which the value is being written. - * @retval #CHIP_ERROR_BUFFER_TOO_SMALL - * If writing the value would exceed the limit on the maximum number of - * bytes specified when the writer was initialized. - * @retval #CHIP_ERROR_NO_MEMORY - * If an attempt to allocate an output buffer failed due to lack of - * memory. - * @retval other Other CHIP or platform-specific errors returned by the configured - * GetNewBuffer() or FinalizeBuffer() functions. - * - */ CHIP_ERROR TLVWriter::Put(uint64_t tag, int8_t v) { return Put(tag, static_cast(v)); } -/** - * Encodes a TLV signed integer value. - * - * @param[in] tag The TLV tag to be encoded with the value, or @p AnonymousTag if the - * value should be encoded without a tag. Tag values should be - * constructed with one of the tag definition functions ProfileTag(), - * ContextTag() or CommonTag(). - * @param[in] v The value to be encoded. - * @param[in] preserveSize True if the value should be encoded in the same number of bytes as - * at the input type. False if value should be encoded in the minimum - * number of bytes necessary to represent the value. Note: Applications - * are strongly encouraged to set this parameter to false. - * - * @retval #CHIP_NO_ERROR If the method succeeded. - * @retval #CHIP_ERROR_TLV_CONTAINER_OPEN - * If a container writer has been opened on the current writer and not - * yet closed. - * @retval #CHIP_ERROR_INVALID_TLV_TAG - * If the specified tag value is invalid or inappropriate in the context - * in which the value is being written. - * @retval #CHIP_ERROR_BUFFER_TOO_SMALL - * If writing the value would exceed the limit on the maximum number of - * bytes specified when the writer was initialized. - * @retval #CHIP_ERROR_NO_MEMORY - * If an attempt to allocate an output buffer failed due to lack of - * memory. - * @retval other Other CHIP or platform-specific errors returned by the configured - * GetNewBuffer() or FinalizeBuffer() functions. - * - */ CHIP_ERROR TLVWriter::Put(uint64_t tag, int8_t v, bool preserveSize) { if (preserveSize) @@ -516,17 +166,11 @@ CHIP_ERROR TLVWriter::Put(uint64_t tag, int8_t v, bool preserveSize) return Put(tag, v); } -/** - * @overload CHIP_ERROR TLVWriter::Put(uint64_t tag, int8_t v) - */ CHIP_ERROR TLVWriter::Put(uint64_t tag, int16_t v) { return Put(tag, static_cast(v)); } -/** - * @overload CHIP_ERROR TLVWriter::Put(uint64_t tag, int8_t v, bool preserveSize) - */ CHIP_ERROR TLVWriter::Put(uint64_t tag, int16_t v, bool preserveSize) { if (preserveSize) @@ -534,17 +178,11 @@ CHIP_ERROR TLVWriter::Put(uint64_t tag, int16_t v, bool preserveSize) return Put(tag, v); } -/** - * @overload CHIP_ERROR TLVWriter::Put(uint64_t tag, int8_t v) - */ CHIP_ERROR TLVWriter::Put(uint64_t tag, int32_t v) { return Put(tag, static_cast(v)); } -/** - * @overload CHIP_ERROR TLVWriter::Put(uint64_t tag, int8_t v, bool preserveSize) - */ CHIP_ERROR TLVWriter::Put(uint64_t tag, int32_t v, bool preserveSize) { if (preserveSize) @@ -552,9 +190,6 @@ CHIP_ERROR TLVWriter::Put(uint64_t tag, int32_t v, bool preserveSize) return Put(tag, v); } -/** - * @overload CHIP_ERROR TLVWriter::Put(uint64_t tag, int8_t v) - */ CHIP_ERROR TLVWriter::Put(uint64_t tag, int64_t v) { TLVElementType elemType; @@ -569,9 +204,6 @@ CHIP_ERROR TLVWriter::Put(uint64_t tag, int64_t v) return WriteElementHead(elemType, tag, static_cast(v)); } -/** - * @overload CHIP_ERROR TLVWriter::Put(uint64_t tag, int8_t v, bool preserveSize) - */ CHIP_ERROR TLVWriter::Put(uint64_t tag, int64_t v, bool preserveSize) { if (preserveSize) @@ -579,9 +211,6 @@ CHIP_ERROR TLVWriter::Put(uint64_t tag, int64_t v, bool preserveSize) return Put(tag, v); } -/** - * @overload CHIP_ERROR TLVWriter::Put(uint64_t tag, double v) - */ CHIP_ERROR TLVWriter::Put(uint64_t tag, float v) { union @@ -593,32 +222,6 @@ CHIP_ERROR TLVWriter::Put(uint64_t tag, float v) return WriteElementHead(TLVElementType::FloatingPointNumber32, tag, cvt.u32); } -/** - * Encodes a TLV floating point value. - * - * @param[in] tag The TLV tag to be encoded with the value, or @p AnonymousTag if the - * value should be encoded without a tag. Tag values should be - * constructed with one of the tag definition functions ProfileTag(), - * ContextTag() or CommonTag(). - * @param[in] v The value to be encoded. - * - * @retval #CHIP_NO_ERROR If the method succeeded. - * @retval #CHIP_ERROR_TLV_CONTAINER_OPEN - * If a container writer has been opened on the current writer and not - * yet closed. - * @retval #CHIP_ERROR_INVALID_TLV_TAG - * If the specified tag value is invalid or inappropriate in the context - * in which the value is being written. - * @retval #CHIP_ERROR_BUFFER_TOO_SMALL - * If writing the value would exceed the limit on the maximum number of - * bytes specified when the writer was initialized. - * @retval #CHIP_ERROR_NO_MEMORY - * If an attempt to allocate an output buffer failed due to lack of - * memory. - * @retval other Other CHIP or platform-specific errors returned by the configured - * GetNewBuffer() or FinalizeBuffer() functions. - * - */ CHIP_ERROR TLVWriter::Put(uint64_t tag, double v) { union @@ -630,64 +233,11 @@ CHIP_ERROR TLVWriter::Put(uint64_t tag, double v) return WriteElementHead(TLVElementType::FloatingPointNumber64, tag, cvt.u64); } -/** - * Encodes a TLV byte string value. - * - * @param[in] tag The TLV tag to be encoded with the value, or @p AnonymousTag if the - * value should be encoded without a tag. Tag values should be - * constructed with one of the tag definition functions ProfileTag(), - * ContextTag() or CommonTag(). - * @param[in] buf A pointer to a buffer containing the bytes string to be encoded. - * @param[in] len The number of bytes to be encoded. - * - * @retval #CHIP_NO_ERROR If the method succeeded. - * @retval #CHIP_ERROR_TLV_CONTAINER_OPEN - * If a container writer has been opened on the current writer and not - * yet closed. - * @retval #CHIP_ERROR_INVALID_TLV_TAG - * If the specified tag value is invalid or inappropriate in the context - * in which the value is being written. - * @retval #CHIP_ERROR_BUFFER_TOO_SMALL - * If writing the value would exceed the limit on the maximum number of - * bytes specified when the writer was initialized. - * @retval #CHIP_ERROR_NO_MEMORY - * If an attempt to allocate an output buffer failed due to lack of - * memory. - * @retval other Other CHIP or platform-specific errors returned by the configured - * GetNewBuffer() or FinalizeBuffer() functions. - * - */ CHIP_ERROR TLVWriter::PutBytes(uint64_t tag, const uint8_t * buf, uint32_t len) { return WriteElementWithData(kTLVType_ByteString, tag, buf, len); } -/** - * Encodes a TLV UTF8 string value. - * - * @param[in] tag The TLV tag to be encoded with the value, or @p AnonymousTag if the - * value should be encoded without a tag. Tag values should be - * constructed with one of the tag definition functions ProfileTag(), - * ContextTag() or CommonTag(). - * @param[in] buf A pointer to the null-terminated UTF-8 string to be encoded. - * - * @retval #CHIP_NO_ERROR If the method succeeded. - * @retval #CHIP_ERROR_TLV_CONTAINER_OPEN - * If a container writer has been opened on the current writer and not - * yet closed. - * @retval #CHIP_ERROR_INVALID_TLV_TAG - * If the specified tag value is invalid or inappropriate in the context - * in which the value is being written. - * @retval #CHIP_ERROR_BUFFER_TOO_SMALL - * If writing the value would exceed the limit on the maximum number of - * bytes specified when the writer was initialized. - * @retval #CHIP_ERROR_NO_MEMORY - * If an attempt to allocate an output buffer failed due to lack of - * memory. - * @retval other Other CHIP or platform-specific errors returned by the configured - * GetNewBuffer() or FinalizeBuffer() functions. - * - */ CHIP_ERROR TLVWriter::PutString(uint64_t tag, const char * buf) { size_t len = strlen(buf); @@ -698,82 +248,11 @@ CHIP_ERROR TLVWriter::PutString(uint64_t tag, const char * buf) return PutString(tag, buf, static_cast(len)); } -/** - * Encodes a TLV UTF8 string value. - * - * @param[in] tag The TLV tag to be encoded with the value, or @p AnonymousTag if the - * value should be encoded without a tag. Tag values should be - * constructed with one of the tag definition functions ProfileTag(), - * ContextTag() or CommonTag(). - * @param[in] buf A pointer to the UTF-8 string to be encoded. - * @param[in] len The length (in bytes) of the string to be encoded. - * - * @retval #CHIP_NO_ERROR If the method succeeded. - * @retval #CHIP_ERROR_TLV_CONTAINER_OPEN - * If a container writer has been opened on the current writer and not - * yet closed. - * @retval #CHIP_ERROR_INVALID_TLV_TAG - * If the specified tag value is invalid or inappropriate in the context - * in which the value is being written. - * @retval #CHIP_ERROR_BUFFER_TOO_SMALL - * If writing the value would exceed the limit on the maximum number of - * bytes specified when the writer was initialized. - * @retval #CHIP_ERROR_NO_MEMORY - * If an attempt to allocate an output buffer failed due to lack of - * memory. - * @retval other Other CHIP or platform-specific errors returned by the configured - * GetNewBuffer() or FinalizeBuffer() functions. - * - */ CHIP_ERROR TLVWriter::PutString(uint64_t tag, const char * buf, uint32_t len) { return WriteElementWithData(kTLVType_UTF8String, tag, reinterpret_cast(buf), len); } -/** - * @brief - * Encode the string output formatted according to the format in the TLV element. - * - * PutStringF is an analog of a sprintf where the output is stored in - * a TLV element as opposed to a character buffer. When extended - * printf functionality is available, the function is able to output - * the result string into a discontinuous underlying storage. The - * implementation supports the following printf enhancements: - * - * -- The platform supplies a callback-based `vcbprintf` that provides - * the ability to call a custom callback in place of putchar. - * - * -- The platform supplies a variant of `vsnprintf` called - * `vsnprintf_ex`, that behaves exactly like vsnprintf except it - * has provisions for omitting the first `n` characters of the - * output. - * - * Note that while the callback-based function may be the simplest and - * use the least amount of code, the `vsprintf_ex` variety of - * functions will consume less stack. - * - * If neither of the above is available, the function will allocate a - * temporary buffer to hold the output, using Platform::MemoryAlloc(). - * - * @param[in] tag The TLV tag to be encoded with the value, or @p - * AnonymousTag if the value should be encoded without - * a tag. Tag values should be constructed with one of - * the tag definition functions ProfileTag(), - * ContextTag() or CommonTag(). - * - * @param[in] fmt The format string used to format the argument list. - * Follows the same syntax and rules as the format - * string for `printf` family of functions. - * - * @param[in] ... A list of arguments to be formatted in the output value - * according to fmt. - * - * @retval #CHIP_NO_ERROR If the method succeeded. - * - * @retval other If underlying calls to TLVWriter methods -- - * `WriteElementHead` or `GetNewBuffer` -- failed, their - * error is immediately forwarded up the call stack. - */ CHIP_ERROR TLVWriter::PutStringF(uint64_t tag, const char * fmt, ...) { CHIP_ERROR err; @@ -800,50 +279,6 @@ void TLVWriter::CHIPTLVWriterPutcharCB(uint8_t c, void * appState) } #endif -/** - * @brief - * Encode the string output formatted according to the format in the TLV element. - * - * PutStringF is an analog of a sprintf where the output is stored in - * a TLV element as opposed to a character buffer. When extended - * printf functionality is available, the function is able to output - * the result string into a discontinuous underlying storage. The - * implementation supports the following printf enhancements: - * - * -- The platform supplies a callback-based `vcbprintf` that provides - * the ability to call a custom callback in place of putchar. - * - * -- The platform supplies a variant of `vsnprintf` called - * `vsnprintf_ex`, that behaves exactly like vsnprintf except it - * has provisions for omitting the first `n` characters of the - * output. - * - * Note that while the callback-based function may be the simplest and - * use the least amount of code, the `vsprintf_ex` variety of - * functions will consume less stack. - * - * If neither of the above is available, the function will allocate a - * temporary buffer to hold the output, using Platform::MemoryAlloc(). - * - * @param[in] tag The TLV tag to be encoded with the value, or @p - * AnonymousTag if the value should be encoded without - * a tag. Tag values should be constructed with one of - * the tag definition functions ProfileTag(), - * ContextTag() or CommonTag(). - * - * @param[in] fmt The format string used to format the argument list. - * Follows the same syntax and rules as the format - * string for `printf` family of functions. - * - * @param[in] ap A list of arguments to be formatted in the output value - * according to fmt. - * - * @retval #CHIP_NO_ERROR If the method succeeded. - * - * @retval other If underlying calls to TLVWriter methods -- - * `WriteElementHead` or `GetNewBuffer` -- failed, their - * error is immediately forwarded up the call stack. - */ CHIP_ERROR TLVWriter::VPutStringF(uint64_t tag, const char * fmt, va_list ap) { va_list aq; @@ -914,15 +349,12 @@ CHIP_ERROR TLVWriter::VPutStringF(uint64_t tag, const char * fmt, va_list ap) mLenWritten += writtenBytes; if (skipLen < dataLen) { - VerifyOrExit(GetNewBuffer != NULL, err = CHIP_ERROR_NO_MEMORY); + VerifyOrExit(mBackingStore != NULL, err = CHIP_ERROR_NO_MEMORY); - if (FinalizeBuffer != NULL) - { - err = FinalizeBuffer(*this, mBufHandle, mBufStart, mWritePoint - mBufStart); - SuccessOrExit(err); - } + err = mBackingStore->FinalizeBuffer(*this, mBufHandle, mBufStart, mWritePoint - mBufStart); + SuccessOrExit(err); - err = GetNewBuffer(*this, mBufHandle, mBufStart, mRemainingLen); + err = mBackingStore->GetNewBuffer(*this, mBufHandle, mBufStart, mRemainingLen); SuccessOrExit(err); mWritePoint = mBufStart; @@ -959,132 +391,16 @@ CHIP_ERROR TLVWriter::VPutStringF(uint64_t tag, const char * fmt, va_list ap) return err; } -/** - * Encodes a TLV null value. - * - * @param[in] tag The TLV tag to be encoded with the value, or @p AnonymousTag if the - * value should be encoded without a tag. Tag values should be - * constructed with one of the tag definition functions ProfileTag(), - * ContextTag() or CommonTag(). - * - * @retval #CHIP_NO_ERROR If the method succeeded. - * @retval #CHIP_ERROR_TLV_CONTAINER_OPEN - * If a container writer has been opened on the current writer and not - * yet closed. - * @retval #CHIP_ERROR_INVALID_TLV_TAG - * If the specified tag value is invalid or inappropriate in the context - * in which the value is being written. - * @retval #CHIP_ERROR_BUFFER_TOO_SMALL - * If writing the value would exceed the limit on the maximum number of - * bytes specified when the writer was initialized. - * @retval #CHIP_ERROR_NO_MEMORY - * If an attempt to allocate an output buffer failed due to lack of - * memory. - * @retval other Other CHIP or platform-specific errors returned by the configured - * GetNewBuffer() or FinalizeBuffer() functions. - * - */ CHIP_ERROR TLVWriter::PutNull(uint64_t tag) { return WriteElementHead(TLVElementType::Null, tag, 0); } -/** - * Copies a TLV element from a reader object into the writer. - * - * The CopyElement() method encodes a new TLV element whose type, tag and value are taken from a TLVReader - * object. When the method is called, the supplied reader object is expected to be positioned on the - * source TLV element. The newly encoded element will have the same type, tag and contents as the input - * container. If the supplied element is a TLV container (structure, array or path), the entire contents - * of the container will be copied. - * - * @note This method requires the supplied TVLReader object to be reading from a single, contiguous - * input buffer that contains the entirety of the underlying TLV encoding. Supplying a reader in any - * other mode has undefined behavior. - * - * @param[in] reader A reference to a TLVReader object identifying a pre-encoded TLV - * element that should be copied. - * - * @retval #CHIP_NO_ERROR If the method succeeded. - * @retval #CHIP_ERROR_INCORRECT_STATE - * If the supplied reader is not positioned on an element. - * @retval #CHIP_ERROR_TLV_CONTAINER_OPEN - * If a container writer has been opened on the current writer and not - * yet closed. - * @retval #CHIP_ERROR_TLV_UNDERRUN - * If the underlying TLV encoding associated with the supplied reader ended - * prematurely. - * @retval #CHIP_ERROR_INVALID_TLV_ELEMENT - * If the supplied reader encountered an invalid or unsupported TLV element - * type. - * @retval #CHIP_ERROR_INVALID_TLV_TAG - * If the supplied reader encountered a TLV tag in an invalid context, - * or if the supplied tag is invalid or inappropriate in the context in - * which the new container is being written. - * @retval #CHIP_ERROR_BUFFER_TOO_SMALL - * If writing the value would exceed the limit on the maximum number of - * bytes specified when the writer was initialized. - * @retval #CHIP_ERROR_NO_MEMORY - * If an attempt to allocate an output buffer failed due to lack of - * memory. - * @retval other Other CHIP or platform-specific errors returned by the configured - * GetNewBuffer() or FinalizeBuffer() functions, or by the GetNextBuffer() - * function associated with the reader object. - * - */ CHIP_ERROR TLVWriter::CopyElement(TLVReader & reader) { return CopyElement(reader.GetTag(), reader); } -/** - * Copies a TLV element from a reader object into the writer. - * - * The CopyElement() method encodes a new TLV element whose type and value are taken from a TLVReader - * object. When the method is called, the supplied reader object is expected to be positioned on the - * source TLV element. The newly encoded element will have the same type and contents as the input - * container, however the tag will be set to the specified argument. If the supplied element is a - * TLV container (structure, array or path), the entire contents of the container will be copied. - * - * @note This method requires the supplied TVLReader object to be reading from a single, contiguous - * input buffer that contains the entirety of the underlying TLV encoding. Supplying a reader in any - * other mode has undefined behavior. - * - * @param[in] tag The TLV tag to be encoded with the container, or @p AnonymousTag if - * the container should be encoded without a tag. Tag values should be - * constructed with one of the tag definition functions ProfileTag(), - * ContextTag() or CommonTag(). - * @param[in] reader A reference to a TLVReader object identifying a pre-encoded TLV - * element whose type and value should be copied. - * - * @retval #CHIP_NO_ERROR If the method succeeded. - * @retval #CHIP_ERROR_INCORRECT_STATE - * If the supplied reader is not positioned on an element. - * @retval #CHIP_ERROR_TLV_CONTAINER_OPEN - * If a container writer has been opened on the current writer and not - * yet closed. - * @retval #CHIP_ERROR_TLV_UNDERRUN - * If the underlying TLV encoding associated with the supplied reader ended - * prematurely. - * @retval #CHIP_ERROR_INVALID_TLV_ELEMENT - * If the supplied reader encountered an invalid or unsupported TLV element - * type. - * @retval #CHIP_ERROR_INVALID_TLV_TAG - * If the supplied reader encountered a TLV tag in an invalid context, - * or if the supplied tag is invalid or inappropriate in the context in - * which the new container is being written. - * @retval #CHIP_ERROR_BUFFER_TOO_SMALL - * If writing the value would exceed the limit on the maximum number of - * bytes specified when the writer was initialized. - * @retval #CHIP_ERROR_NO_MEMORY - * If an attempt to allocate an output buffer failed due to lack of - * memory. - * @retval other Other CHIP or platform-specific errors returned by the configured - * GetNewBuffer() or FinalizeBuffer() functions, or by the GetNextBuffer() - * function associated with the reader object. - * - */ - const size_t kCHIPTLVCopyChunkSize = 16; CHIP_ERROR TLVWriter::CopyElement(uint64_t tag, TLVReader & reader) @@ -1130,56 +446,6 @@ CHIP_ERROR TLVWriter::CopyElement(uint64_t tag, TLVReader & reader) return err; } -/** - * Initializes a new TLVWriter object for writing the members of a TLV container element. - * - * The OpenContainer() method is used to write TLV container elements (structure, arrays or paths) - * to an encoding. The method takes the type and tag (if any) of the new container, and a reference - * to a new writer object (the container writer) that will be initialized for the purpose - * of writing the container's elements. Applications write the members of the new container using - * the container writer and then call CloseContainer() to complete the container encoding. - * - * While the container writer is open, applications must not make calls on or otherwise alter the state - * of the parent writer. - * - * The container writer inherits various configuration properties from the parent writer. These are: - * - * @li The implicit profile id (ImplicitProfileId) - * @li The application data pointer (AppData) - * @li The GetNewBuffer and FinalizeBuffer function pointers - * - * @note The StartContainer() method can be used as an alternative to OpenContainer() to write a - * container element without initializing a new writer object. - * - * @param[in] tag The TLV tag to be encoded with the container, or @p AnonymousTag if - * the container should be encoded without a tag. Tag values should be - * constructed with one of the tag definition functions ProfileTag(), - * ContextTag() or CommonTag(). - * @param[in] containerType The type of container to encode. Must be one of @p kTLVType_Structure, - * @p kTLVType_Array or @p kTLVType_Path. - * @param[out] containerWriter A reference to a TLVWriter object that will be initialized for - * writing the members of the new container element. Any data - * associated with the supplied object is overwritten. - * - * @retval #CHIP_NO_ERROR If the method succeeded. - * @retval #CHIP_ERROR_WRONG_TLV_TYPE - * If the value specified for containerType is incorrect. - * @retval #CHIP_ERROR_TLV_CONTAINER_OPEN - * If a container writer has been opened on the current writer and not - * yet closed. - * @retval #CHIP_ERROR_INVALID_TLV_TAG - * If the specified tag value is invalid or inappropriate in the context - * in which the value is being written. - * @retval #CHIP_ERROR_BUFFER_TOO_SMALL - * If writing the value would exceed the limit on the maximum number of - * bytes specified when the writer was initialized. - * @retval #CHIP_ERROR_NO_MEMORY - * If an attempt to allocate an output buffer failed due to lack of - * memory. - * @retval other Other CHIP or platform-specific errors returned by the configured - * GetNewBuffer() or FinalizeBuffer() functions. - * - */ CHIP_ERROR TLVWriter::OpenContainer(uint64_t tag, TLVType containerType, TLVWriter & containerWriter) { CHIP_ERROR err = CHIP_NO_ERROR; @@ -1202,7 +468,7 @@ CHIP_ERROR TLVWriter::OpenContainer(uint64_t tag, TLVType containerType, TLVWrit ExitNow(); } - containerWriter.mBufHandle = mBufHandle; + containerWriter.mBackingStore = mBackingStore; containerWriter.mBufStart = mBufStart; containerWriter.mWritePoint = mWritePoint; containerWriter.mRemainingLen = mRemainingLen; @@ -1212,8 +478,6 @@ CHIP_ERROR TLVWriter::OpenContainer(uint64_t tag, TLVType containerType, TLVWrit containerWriter.SetContainerOpen(false); containerWriter.SetCloseContainerReserved(IsCloseContainerReserved()); containerWriter.ImplicitProfileId = ImplicitProfileId; - containerWriter.GetNewBuffer = GetNewBuffer; - containerWriter.FinalizeBuffer = FinalizeBuffer; SetContainerOpen(true); @@ -1221,38 +485,6 @@ CHIP_ERROR TLVWriter::OpenContainer(uint64_t tag, TLVType containerType, TLVWrit return err; } -/** - * Completes the writing of a TLV container after a call to OpenContainer(). - * - * The CloseContainer() method restores the state of a parent TLVWriter object after a call to - * OpenContainer(). For every call to OpenContainer() applications must make a corresponding - * call to CloseContainer(), passing a reference to the same container writer to both methods. - * - * When CloseContainer() returns, applications may continue to use the parent writer to write - * additional TLV elements that appear after the container element. At this point the supplied - * container writer should be considered 'de-initialized' and must not be used without - * re-initialization. - * - * @param[in] containerWriter A reference to the TLVWriter object that was supplied to the - * OpenContainer() method. - * - * @retval #CHIP_NO_ERROR If the method succeeded. - * @retval #CHIP_ERROR_INCORRECT_STATE - * If the supplied container writer is not in the correct state. - * @retval #CHIP_ERROR_TLV_CONTAINER_OPEN - * If another container writer has been opened on the supplied - * container writer and not yet closed. - * @retval #CHIP_ERROR_BUFFER_TOO_SMALL - * If completing the encoding of the container would exceed the - * limit on the maximum number of bytes specified when the writer - * was initialized. - * @retval #CHIP_ERROR_NO_MEMORY - * If an attempt to allocate an output buffer failed due to lack - * of memory. - * @retval other Other CHIP or platform-specific errors returned by the - * configured GetNewBuffer() or FinalizeBuffer() functions. - * - */ CHIP_ERROR TLVWriter::CloseContainer(TLVWriter & containerWriter) { if (!TLVTypeIsContainer(containerWriter.mContainerType)) @@ -1261,7 +493,7 @@ CHIP_ERROR TLVWriter::CloseContainer(TLVWriter & containerWriter) if (containerWriter.IsContainerOpen()) return CHIP_ERROR_TLV_CONTAINER_OPEN; - mBufHandle = containerWriter.mBufHandle; + mBackingStore = containerWriter.mBackingStore; mBufStart = containerWriter.mBufStart; mWritePoint = containerWriter.mWritePoint; mRemainingLen = containerWriter.mRemainingLen; @@ -1278,47 +510,6 @@ CHIP_ERROR TLVWriter::CloseContainer(TLVWriter & containerWriter) return WriteElementHead(TLVElementType::EndOfContainer, AnonymousTag, 0); } -/** - * Begins encoding a new TLV container element. - * - * The StartContainer() method is used to write TLV container elements (structure, arrays or paths) - * to an encoding. The method takes the type and tag (if any) of the new container, and a reference - * to a TLVType value which will be used to save the current context of the writer while it is being - * used to write the container. - * - * Once the StartContainer() method returns, the application should use the current TLVWriter object to - * write the elements of the container. When finish, the application must call the EndContainer() - * method to finish the encoding of the container. - * - * @param[in] tag The TLV tag to be encoded with the container, or @p AnonymousTag if - * the container should be encoded without a tag. Tag values should be - * constructed with one of the tag definition functions ProfileTag(), - * ContextTag() or CommonTag(). - * @param[in] containerType The type of container to encode. Must be one of @p kTLVType_Structure, - * @p kTLVType_Array or @p kTLVType_Path. - * @param[out] outerContainerType - * A reference to a TLVType value that will receive the context of the - * writer. - * - * @retval #CHIP_NO_ERROR If the method succeeded. - * @retval #CHIP_ERROR_WRONG_TLV_TYPE - * If the value specified for containerType is incorrect. - * @retval #CHIP_ERROR_TLV_CONTAINER_OPEN - * If a container writer has been opened on the current writer and not - * yet closed. - * @retval #CHIP_ERROR_INVALID_TLV_TAG - * If the specified tag value is invalid or inappropriate in the context - * in which the value is being written. - * @retval #CHIP_ERROR_BUFFER_TOO_SMALL - * If writing the value would exceed the limit on the maximum number of - * bytes specified when the writer was initialized. - * @retval #CHIP_ERROR_NO_MEMORY - * If an attempt to allocate an output buffer failed due to lack of - * memory. - * @retval other Other CHIP or platform-specific errors returned by the configured - * GetNewBuffer() or FinalizeBuffer() functions. - * - */ CHIP_ERROR TLVWriter::StartContainer(uint64_t tag, TLVType containerType, TLVType & outerContainerType) { CHIP_ERROR err = CHIP_NO_ERROR; @@ -1349,40 +540,6 @@ CHIP_ERROR TLVWriter::StartContainer(uint64_t tag, TLVType containerType, TLVTyp return err; } -/** - * Completes the encoding of a TLV container element. - * - * The EndContainer() method completes the encoding of a TLV container element and restores the state - * of a TLVWrite object after an earlier call to StartContainer(). For every call to StartContainer() - * applications must make a corresponding call to EndContainer(), passing the TLVType value returned - * by the StartContainer() call. When EndContainer() returns, the writer object can be used to write - * additional TLV elements that follow the container element. - * - * @note Any changes made to the configuration of the writer between the calls to StartContainer() - * and EndContainer() are NOT undone by the call to EndContainer(). For example, a change to the - * implicit profile id (@p ImplicitProfileId) will not be reversed when a container is ended. Thus - * it is the application's responsibility to adjust the configuration accordingly at the appropriate - * times. - * - * @param[in] outerContainerType - * The TLVType value that was returned by the StartContainer() method. - * - * @retval #CHIP_NO_ERROR If the method succeeded. - * @retval #CHIP_ERROR_INCORRECT_STATE - * If a corresponding StartContainer() call was not made. - * @retval #CHIP_ERROR_TLV_CONTAINER_OPEN - * If a container writer has been opened on the current writer and not - * yet closed. - * @retval #CHIP_ERROR_BUFFER_TOO_SMALL - * If writing the value would exceed the limit on the maximum number of - * bytes specified when the writer was initialized. - * @retval #CHIP_ERROR_NO_MEMORY - * If an attempt to allocate an output buffer failed due to lack of - * memory. - * @retval other Other CHIP or platform-specific errors returned by the configured - * GetNewBuffer() or FinalizeBuffer() functions. - * - */ CHIP_ERROR TLVWriter::EndContainer(TLVType outerContainerType) { if (!TLVTypeIsContainer(mContainerType)) @@ -1396,46 +553,6 @@ CHIP_ERROR TLVWriter::EndContainer(TLVType outerContainerType) return WriteElementHead(TLVElementType::EndOfContainer, AnonymousTag, 0); } -/** - * Encodes a TLV container element from a pre-encoded set of member elements - * - * The PutPreEncodedContainer() method encodes a new TLV container element (a structure, array or path) - * containing a set of member elements taken from a pre-encoded buffer. The input buffer is expected to - * contain zero or more full-encoded TLV elements, with tags that conform to the rules associated with - * the specified container type (e.g. structure members must have tags, while array members must not). - * - * The method encodes the entirety of the container element in one call. When PutPreEncodedContainer() - * returns, the writer object can be used to write additional TLV elements following the container element. - * - * @param[in] tag The TLV tag to be encoded with the container, or @p AnonymousTag if - * the container should be encoded without a tag. Tag values should be - * constructed with one of the tag definition functions ProfileTag(), - * ContextTag() or CommonTag(). - * @param[in] containerType The type of container to encode. Must be one of @p kTLVType_Structure, - * @p kTLVType_Array or @p kTLVType_Path. - * @param[in] data A pointer to a buffer containing zero of more encoded TLV elements that - * will become the members of the new container. - * @param[in] dataLen The number of bytes in the @p data buffer. - * - * @retval #CHIP_NO_ERROR If the method succeeded. - * @retval #CHIP_ERROR_WRONG_TLV_TYPE - * If the value specified for containerType is incorrect. - * @retval #CHIP_ERROR_TLV_CONTAINER_OPEN - * If a container writer has been opened on the current writer and not - * yet closed. - * @retval #CHIP_ERROR_INVALID_TLV_TAG - * If the specified tag value is invalid or inappropriate in the context - * in which the value is being written. - * @retval #CHIP_ERROR_BUFFER_TOO_SMALL - * If writing the value would exceed the limit on the maximum number of - * bytes specified when the writer was initialized. - * @retval #CHIP_ERROR_NO_MEMORY - * If an attempt to allocate an output buffer failed due to lack of - * memory. - * @retval other Other CHIP or platform-specific errors returned by the configured - * GetNewBuffer() or FinalizeBuffer() functions. - * - */ CHIP_ERROR TLVWriter::PutPreEncodedContainer(uint64_t tag, TLVType containerType, const uint8_t * data, uint32_t dataLen) { if (!TLVTypeIsContainer(containerType)) @@ -1448,107 +565,17 @@ CHIP_ERROR TLVWriter::PutPreEncodedContainer(uint64_t tag, TLVType containerType return WriteData(data, dataLen); } -/** - * Copies a TLV container element from TLVReader object - * - * The CopyContainer() encodes a new TLV container element by copying a pre-encoded container element - * located at the current position of a TLVReader object. The method writes the entirety of the new - * container element in one call, copying the container's type, tag and elements from the source - * encoding. When the method returns, the writer object can be used to write additional TLV elements - * following the container element. - * - * @note This method requires the supplied TVLReader object to be reading from a single, contiguous - * input buffer that contains the entirety of the underlying TLV encoding. Supplying a reader in any - * other mode has undefined behavior. - * - * @param[in] container A reference to a TLVReader object identifying the pre-encoded TLV - * container to be copied. - * - * @retval #CHIP_NO_ERROR If the method succeeded. - * @retval #CHIP_ERROR_INCORRECT_STATE - * If the supplied reader is not positioned on a container element. - * @retval #CHIP_ERROR_TLV_CONTAINER_OPEN - * If a container writer has been opened on the current writer and not - * yet closed. - * @retval #CHIP_ERROR_TLV_UNDERRUN - * If the underlying TLV encoding associated with the supplied reader ended - * prematurely. - * @retval #CHIP_ERROR_INVALID_TLV_ELEMENT - * If the supplied reader encountered an invalid or unsupported TLV element - * type. - * @retval #CHIP_ERROR_INVALID_TLV_TAG - * If the supplied reader encountered a TLV tag in an invalid context, - * or if the tag associated with the source container is invalid or - * inappropriate in the context in which the new container is being written. - * @retval #CHIP_ERROR_BUFFER_TOO_SMALL - * If writing the value would exceed the limit on the maximum number of - * bytes specified when the writer was initialized. - * @retval #CHIP_ERROR_NO_MEMORY - * If an attempt to allocate an output buffer failed due to lack of - * memory. - * @retval other Other CHIP or platform-specific errors returned by the configured - * GetNewBuffer() or FinalizeBuffer() functions, or by the GetNextBuffer() - * function associated with the reader object. - * - */ CHIP_ERROR TLVWriter::CopyContainer(TLVReader & container) { return CopyContainer(container.GetTag(), container); } -/** - * Encodes a TLV container element from a pre-encoded set of member elements - * - * The CopyContainer() method encodes a new TLV container element (a structure, array or path) - * containing a set of member elements taken from a TLVReader object. When the method is called, the - * supplied reader object is expected to be positioned on a TLV container element. The newly encoded - * container will have the same type and members as the input container. The tag for the new - * container is specified as an input parameter. - * - * When the method returns, the writer object can be used to write additional TLV elements following - * the container element. - * - * @note This method requires the supplied TVLReader object to be reading from a single, contiguous - * input buffer that contains the entirety of the underlying TLV encoding. Supplying a reader in any - * other mode has undefined behavior. - * - * @param[in] tag The TLV tag to be encoded with the container, or @p AnonymousTag if - * the container should be encoded without a tag. Tag values should be - * constructed with one of the tag definition functions ProfileTag(), - * ContextTag() or CommonTag(). - * @param[in] container A reference to a TLVReader object identifying a pre-encoded TLV - * container whose type and members should be copied. - * - * @retval #CHIP_NO_ERROR If the method succeeded. - * @retval #CHIP_ERROR_INCORRECT_STATE - * If the supplied reader is not positioned on a container element. - * @retval #CHIP_ERROR_TLV_CONTAINER_OPEN - * If a container writer has been opened on the current writer and not - * yet closed. - * @retval #CHIP_ERROR_TLV_UNDERRUN - * If the underlying TLV encoding associated with the supplied reader ended - * prematurely. - * @retval #CHIP_ERROR_INVALID_TLV_ELEMENT - * If the supplied reader encountered an invalid or unsupported TLV element - * type. - * @retval #CHIP_ERROR_INVALID_TLV_TAG - * If the supplied reader encountered a TLV tag in an invalid context, - * or if the supplied tag is invalid or inappropriate in the context in - * which the new container is being written. - * @retval #CHIP_ERROR_BUFFER_TOO_SMALL - * If writing the value would exceed the limit on the maximum number of - * bytes specified when the writer was initialized. - * @retval #CHIP_ERROR_NO_MEMORY - * If an attempt to allocate an output buffer failed due to lack of - * memory. - * @retval other Other CHIP or platform-specific errors returned by the configured - * GetNewBuffer() or FinalizeBuffer() functions, or by the GetNextBuffer() - * function associated with the reader object. - * - */ CHIP_ERROR TLVWriter::CopyContainer(uint64_t tag, TLVReader & container) { // NOTE: This function MUST be used with a TVLReader that is reading from a contiguous buffer. + if (container.mBackingStore != nullptr) + return CHIP_ERROR_INVALID_ARGUMENT; + CHIP_ERROR err; TLVType containerType, outerContainerType; const uint8_t * containerStart; @@ -1569,49 +596,6 @@ CHIP_ERROR TLVWriter::CopyContainer(uint64_t tag, TLVReader & container) static_cast(container.GetReadPoint() - containerStart)); } -/** - * Encodes a TLV container element that contains member elements from a pre-encoded container - * - * The CopyContainer() method encodes a new TLV container element (a structure, array or path) - * containing a set of member elements taken from the contents of a supplied pre-encoded container. - * When the method is called, data in the supplied input buffer is parsed as a TLV container element - * an a new container is written that has the same type and members as the input container. The tag - * for the new container is specified as an input parameter. - * - * When the method returns, the writer object can be used to write additional TLV elements following - * the container element. - * - * @param[in] tag The TLV tag to be encoded with the container, or @p AnonymousTag if - * the container should be encoded without a tag. Tag values should be - * constructed with one of the tag definition functions ProfileTag(), - * ContextTag() or CommonTag(). - * @param[in] encodedContainer A buffer containing a pre-encoded TLV container whose type and members - * should be copied. - * @param[in] encodedContainerLen The length in bytes of the pre-encoded container. - * - * @retval #CHIP_NO_ERROR If the method succeeded. - * @retval #CHIP_ERROR_TLV_CONTAINER_OPEN - * If a container writer has been opened on the current writer and not - * yet closed. - * @retval #CHIP_ERROR_TLV_UNDERRUN - * If the encoded container ended prematurely. - * @retval #CHIP_ERROR_INVALID_TLV_ELEMENT - * If the encoded container contained an invalid or unsupported TLV element type. - * @retval #CHIP_ERROR_INVALID_TLV_TAG - * If the encoded container contained a TLV tag in an invalid context, - * or if the supplied tag is invalid or inappropriate in the context in - * which the new container is being written. - * @retval #CHIP_ERROR_BUFFER_TOO_SMALL - * If writing the value would exceed the limit on the maximum number of - * bytes specified when the writer was initialized. - * @retval #CHIP_ERROR_NO_MEMORY - * If an attempt to allocate an output buffer failed due to lack of - * memory. - * @retval other Other CHIP or platform-specific errors returned by the configured - * GetNewBuffer() or FinalizeBuffer() functions, or by the GetNextBuffer() - * function associated with the reader object. - * - */ CHIP_ERROR TLVWriter::CopyContainer(uint64_t tag, const uint8_t * encodedContainer, uint16_t encodedContainerLen) { CHIP_ERROR err; @@ -1629,21 +613,6 @@ CHIP_ERROR TLVWriter::CopyContainer(uint64_t tag, const uint8_t * encodedContain return err; } -/** - * Returns the type of container within which the TLVWriter is currently writing. - * - * The GetContainerType() method returns the type of the TLV container within which the TLVWriter - * is currently writing. If the TLVWriter is not writing elements within a container (i.e. if writing - * at the outer-most level of an encoding) the method returns kTLVType_NotSpecified. - * - * @return The TLVType of the current container, or kTLVType_NotSpecified if the TLVWriter is not - * writing elements within a container. - */ -TLVType TLVWriter::GetContainerType() const -{ - return mContainerType; -} - CHIP_ERROR TLVWriter::WriteElementHead(TLVElementType elemType, uint64_t tag, uint64_t lenOrVal) { uint8_t * p; @@ -1797,16 +766,13 @@ CHIP_ERROR TLVWriter::WriteData(const uint8_t * p, uint32_t len) { if (mRemainingLen == 0) { - VerifyOrExit(GetNewBuffer != nullptr, err = CHIP_ERROR_NO_MEMORY); + VerifyOrExit(mBackingStore != nullptr, err = CHIP_ERROR_NO_MEMORY); - if (FinalizeBuffer != nullptr) - { - VerifyOrExit(CanCastTo(mWritePoint - mBufStart), err = CHIP_ERROR_INCORRECT_STATE); - err = FinalizeBuffer(*this, mBufHandle, mBufStart, static_cast(mWritePoint - mBufStart)); - SuccessOrExit(err); - } + VerifyOrExit(CanCastTo(mWritePoint - mBufStart), err = CHIP_ERROR_INCORRECT_STATE); + err = mBackingStore->FinalizeBuffer(*this, mBufStart, static_cast(mWritePoint - mBufStart)); + SuccessOrExit(err); - err = GetNewBuffer(*this, mBufHandle, mBufStart, mRemainingLen); + err = mBackingStore->GetNewBuffer(*this, mBufStart, mRemainingLen); SuccessOrExit(err); mWritePoint = mBufStart; @@ -1831,73 +797,5 @@ CHIP_ERROR TLVWriter::WriteData(const uint8_t * p, uint32_t len) return err; } -/** - * An implementation of a TLVWriter GetNewBuffer function for writing to a chain of PacketBuffers. - * - * The GetNewPacketBuffer() function supplies new output space to a TLVWriter by allocating a chain - * of one or more PacketBuffers as needed to store the encoding. The function is designed to be - * assigned to the TLVWriter GetNewBuffer function pointer. - * - * Note that when using the GetNewPacketBuffer with a TLVWriter, the corresponding FinalizePacketBuffer() - * function (or an equivalent) should also be used to finalize the buffer chain. - * - * See the GetNewBufferFunct type definition for additional information on the API of the - * GetNewPacketBuffer() function. - */ -CHIP_ERROR TLVWriter::GetNewPacketBuffer(TLVWriter & writer, uintptr_t & bufHandle, uint8_t *& bufStart, uint32_t & bufLen) -{ - PacketBuffer * buf = reinterpret_cast(bufHandle); - - PacketBuffer * newBuf = buf->Next_ForNow(); - if (newBuf == nullptr) - { - System::PacketBufferHandle newBufHandle = PacketBuffer::New(0); - if (!newBufHandle.IsNull()) - { - newBuf = newBufHandle.Get_ForNow(); - buf->AddToEnd(std::move(newBufHandle)); - } - } - - if (newBuf != nullptr) - { - bufHandle = reinterpret_cast(newBuf); - bufStart = newBuf->Start(); - bufLen = newBuf->MaxDataLength(); - } - else - { - bufStart = nullptr; - bufLen = 0; - } - - return CHIP_NO_ERROR; -} - -/** - * An implementation of a TLVWriter FinalizeBuffer function for writing to a chain of PacketBuffers. - * - * The FinalizePacketBuffer() function performs the necessary finalization required when using a - * TLVWriter to write to a chain of PacketBuffers. The function is designed to be used in conjunction - * with the GetNewPacketBuffer() function. - * - * See the FinalizeBufferFunct type definition for additional information on the API of the - * FinalizePacketBuffer() function. - */ -CHIP_ERROR TLVWriter::FinalizePacketBuffer(TLVWriter & writer, uintptr_t bufHandle, uint8_t * bufStart, uint32_t dataLen) -{ - PacketBuffer * buf = reinterpret_cast(bufHandle); - uint8_t * endPtr = bufStart + dataLen; - - intptr_t length = endPtr - buf->Start(); - if (!CanCastTo(length)) - { - return CHIP_ERROR_INVALID_ARGUMENT; - } - buf->SetDataLength(static_cast(length)); - - return CHIP_NO_ERROR; -} - } // namespace TLV } // namespace chip diff --git a/src/lib/core/Optional.h b/src/lib/core/Optional.h index d49ed49d88fcf6..922e8821326d3f 100644 --- a/src/lib/core/Optional.h +++ b/src/lib/core/Optional.h @@ -40,7 +40,25 @@ class Optional constexpr Optional(const Optional & other) = default; constexpr Optional(Optional && other) = default; - Optional & operator=(const Optional & other) = default; + + /** + * Assignment operator implementation. + * + * NOTE: Manually implemented instead of =default since other::mValue may not be initialized + * if it has no value. + */ + Optional & operator=(const Optional & other) + { + if (other.HasValue()) + { + SetValue(other.Value()); + } + else + { + ClearValue(); + } + return *this; + } /** Make the optional contain a specific value */ void SetValue(const T & value) diff --git a/src/lib/core/core.gni b/src/lib/core/core.gni index 937941ce2d06c6..deecc5075e87bc 100644 --- a/src/lib/core/core.gni +++ b/src/lib/core/core.gni @@ -56,7 +56,7 @@ if (chip_logging_style == "") { chip_logging_style = "android" } else if (current_os == "mac" || current_os == "ios") { chip_logging_style = "darwin" - } else if (current_os != "freertos") { + } else if (current_os != "freertos" && current_os != "zephyr") { chip_logging_style = "stdio" } else { chip_logging_style = "external" diff --git a/src/lib/core/tests/TestCHIPCallback.cpp b/src/lib/core/tests/TestCHIPCallback.cpp index 05a133f91545c6..c2e5d940a934f9 100644 --- a/src/lib/core/tests/TestCHIPCallback.cpp +++ b/src/lib/core/tests/TestCHIPCallback.cpp @@ -213,6 +213,9 @@ static void NotifierTest(nlTestSuite * inSuite, void * inContext) notifier.Register(&cb); notifier.Notify(8); NL_TEST_ASSERT(inSuite, n == 1); + + cb.Cancel(); + cancelcb.Cancel(); } /** diff --git a/src/lib/core/tests/TestCHIPTLV.cpp b/src/lib/core/tests/TestCHIPTLV.cpp index 9e840e52051b2e..f04a1e88890682 100644 --- a/src/lib/core/tests/TestCHIPTLV.cpp +++ b/src/lib/core/tests/TestCHIPTLV.cpp @@ -1,6 +1,6 @@ /* * - * Copyright (c) 2020 Project CHIP Authors + * Copyright (c) 2020-2021 Project CHIP Authors * Copyright (c) 2013-2017 Nest Labs, Inc. * All rights reserved. * @@ -39,6 +39,8 @@ #include #include +#include + #include using namespace chip; @@ -252,9 +254,11 @@ void TestDupBytes(nlTestSuite * inSuite, TLVReader & reader, uint64_t tag, const NL_TEST_ASSERT(inSuite, memcmp(val, expectedVal, expectedLen) == 0); } -void TestBufferContents(nlTestSuite * inSuite, PacketBuffer * buf, const uint8_t * expectedVal, uint32_t expectedLen) +void TestBufferContents(nlTestSuite * inSuite, const System::PacketBufferHandle & buffer, const uint8_t * expectedVal, + uint32_t expectedLen) { - while (buf != nullptr) + System::PacketBufferHandle buf = buffer.Retain(); + while (!buf.IsNull()) { uint16_t len = buf->DataLength(); NL_TEST_ASSERT(inSuite, len <= expectedLen); @@ -264,7 +268,7 @@ void TestBufferContents(nlTestSuite * inSuite, PacketBuffer * buf, const uint8_t expectedVal += len; expectedLen -= len; - buf = buf->Next_ForNow(); + buf.Advance(); } NL_TEST_ASSERT(inSuite, expectedLen == 0); @@ -639,7 +643,8 @@ void WriteEncoding3(nlTestSuite * inSuite, TLVWriter & writer) TLVWriter writer1; err = writer.OpenContainer(ProfileTag(TestProfile_1, 1), kTLVType_Structure, writer1); - NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + if (err) + NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); err = writer1.PutBoolean(ProfileTag(TestProfile_2, 2), false); NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); @@ -1943,23 +1948,23 @@ void WriteDeleteReadTest(nlTestSuite * inSuite) */ void CheckPacketBuffer(nlTestSuite * inSuite, void * inContext) { - System::PacketBufferHandle buf = PacketBuffer::New(0); - TLVWriter writer; - TLVReader reader; + System::PacketBufferHandle buf = System::PacketBuffer::New(0); + System::PacketBufferTLVWriter writer; + System::PacketBufferTLVReader reader; - writer.Init(buf.Get_ForNow()); + writer.Init(buf.Retain()); writer.ImplicitProfileId = TestProfile_2; WriteEncoding1(inSuite, writer); - TestBufferContents(inSuite, buf.Get_ForNow(), Encoding1, sizeof(Encoding1)); + TestBufferContents(inSuite, buf, Encoding1, sizeof(Encoding1)); - reader.Init(buf.Get_ForNow()); + reader.Init(buf.Retain()); reader.ImplicitProfileId = TestProfile_2; ReadEncoding1(inSuite, reader); - reader.Init(buf.Get_ForNow(), buf->MaxDataLength(), false); + reader.Init(buf.Retain(), buf->MaxDataLength()); reader.ImplicitProfileId = TestProfile_2; ReadEncoding1(inSuite, reader); @@ -1995,7 +2000,7 @@ void CheckCircularTLVBufferSimple(nlTestSuite * inSuite, void * inContext) CircularTLVReader reader; TestTLVContext * context = static_cast(inContext); CHIPCircularTLVBuffer buffer(backingStore, 30); - writer.Init(&buffer); + writer.Init(buffer); writer.ImplicitProfileId = TestProfile_2; context->mEvictionCount = 0; @@ -2018,7 +2023,7 @@ void CheckCircularTLVBufferSimple(nlTestSuite * inSuite, void * inContext) NL_TEST_ASSERT(inSuite, (buffer.DataLength() + context->mEvictedBytes) == writer.GetLengthWritten()); // At this point the buffer should contain 2 instances of Encoding3. - reader.Init(&buffer); + reader.Init(buffer); reader.ImplicitProfileId = TestProfile_2; TestNext(inSuite, reader); @@ -2045,7 +2050,7 @@ void CheckCircularTLVBufferStartMidway(nlTestSuite * inSuite, void * inContext) CircularTLVReader reader; TestTLVContext * context = static_cast(inContext); CHIPCircularTLVBuffer buffer(backingStore, 30, &(backingStore[15])); - writer.Init(&buffer); + writer.Init(buffer); writer.ImplicitProfileId = TestProfile_2; context->mEvictionCount = 0; @@ -2068,7 +2073,7 @@ void CheckCircularTLVBufferStartMidway(nlTestSuite * inSuite, void * inContext) NL_TEST_ASSERT(inSuite, (buffer.DataLength() + context->mEvictedBytes) == writer.GetLengthWritten()); // At this point the buffer should contain 2 instances of Encoding3. - reader.Init(&buffer); + reader.Init(buffer); reader.ImplicitProfileId = TestProfile_2; TestNext(inSuite, reader); @@ -2096,7 +2101,7 @@ void CheckCircularTLVBufferEvictStraddlingEvent(nlTestSuite * inSuite, void * in CircularTLVWriter writer; CircularTLVReader reader; CHIPCircularTLVBuffer buffer(backingStore, 30); - writer.Init(&buffer); + writer.Init(buffer); writer.ImplicitProfileId = TestProfile_2; context->mEvictionCount = 0; @@ -2132,7 +2137,7 @@ void CheckCircularTLVBufferEvictStraddlingEvent(nlTestSuite * inSuite, void * in NL_TEST_ASSERT(inSuite, context->mEvictionCount == 7); // At this point the buffer should contain 2 instances of Encoding3. - reader.Init(&buffer); + reader.Init(buffer); reader.ImplicitProfileId = TestProfile_2; TestNext(inSuite, reader); @@ -2159,7 +2164,7 @@ void CheckCircularTLVBufferEdge(nlTestSuite * inSuite, void * inContext) CHIPCircularTLVBuffer buffer(backingStore, sizeof(backingStore)); CHIPCircularTLVBuffer buffer1(backingStore1, sizeof(backingStore1)); - writer.Init(&buffer); + writer.Init(buffer); writer.ImplicitProfileId = TestProfile_2; context->mEvictionCount = 0; @@ -2178,7 +2183,7 @@ void CheckCircularTLVBufferEdge(nlTestSuite * inSuite, void * inContext) err = writer.Finalize(); NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); // At this point the buffer should contain only the boolean we just wrote - reader.Init(&buffer); + reader.Init(buffer); reader.ImplicitProfileId = TestProfile_2; TestNext(inSuite, reader); @@ -2202,7 +2207,7 @@ void CheckCircularTLVBufferEdge(nlTestSuite * inSuite, void * inContext) int i = 0; for (i = 0; i < 2; i++) { - writer.Init(&buffer1); + writer.Init(buffer1); writer.ImplicitProfileId = TestProfile_2; err = writer.PutBoolean(ProfileTag(TestProfile_1, 2), true); @@ -2211,7 +2216,7 @@ void CheckCircularTLVBufferEdge(nlTestSuite * inSuite, void * inContext) err = writer.Finalize(); NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); - reader.Init(&buffer1); + reader.Init(buffer1); reader.ImplicitProfileId = TestProfile_2; TestNext(inSuite, reader); @@ -2220,12 +2225,12 @@ void CheckCircularTLVBufferEdge(nlTestSuite * inSuite, void * inContext) buffer1.EvictHead(); - reader.Init(&buffer1); + reader.Init(buffer1); reader.ImplicitProfileId = TestProfile_2; TestEnd(inSuite, reader); } - writer.Init(&buffer1); + writer.Init(buffer1); writer.ImplicitProfileId = TestProfile_2; context->mEvictionCount = 0; @@ -2244,7 +2249,7 @@ void CheckCircularTLVBufferEdge(nlTestSuite * inSuite, void * inContext) err = writer.Finalize(); // Verify that we can read out two elements from the buffer - reader.Init(&buffer1); + reader.Init(buffer1); reader.ImplicitProfileId = TestProfile_2; TestNext(inSuite, reader); @@ -2260,7 +2265,7 @@ void CheckCircularTLVBufferEdge(nlTestSuite * inSuite, void * inContext) buffer1.EvictHead(); // At this point the buffer should contain only the second boolean - reader.Init(&buffer1); + reader.Init(buffer1); reader.ImplicitProfileId = TestProfile_2; TestNext(inSuite, reader); @@ -2271,7 +2276,7 @@ void CheckCircularTLVBufferEdge(nlTestSuite * inSuite, void * inContext) // Write another boolean, verify that the buffer is full and contains two booleans - writer.Init(&buffer1); + writer.Init(buffer1); writer.ImplicitProfileId = TestProfile_2; err = writer.PutBoolean(ProfileTag(TestProfile_1, 2), true); @@ -2281,7 +2286,7 @@ void CheckCircularTLVBufferEdge(nlTestSuite * inSuite, void * inContext) NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); // Verify that we can read out two elements from the buffer - reader.Init(&buffer1); + reader.Init(buffer1); reader.ImplicitProfileId = TestProfile_2; TestNext(inSuite, reader); @@ -2298,7 +2303,7 @@ void CheckCircularTLVBufferEdge(nlTestSuite * inSuite, void * inContext) buffer1.EvictHead(); buffer1.EvictHead(); - reader.Init(&buffer1); + reader.Init(buffer1); reader.ImplicitProfileId = TestProfile_2; TestEnd(inSuite, reader); @@ -2347,7 +2352,7 @@ void CheckCHIPTLVPutStringFCircular(nlTestSuite * inSuite, void * inContext) // Initial test: Verify that a straight printf works as expected into continuous buffer. - writer.Init(&buffer); + writer.Init(buffer); snprintf(strBuffer, sizeof(strBuffer), "Sample string %zu", num); err = writer.PutBoolean(ProfileTag(TestProfile_1, 2), true); @@ -2362,7 +2367,7 @@ void CheckCHIPTLVPutStringFCircular(nlTestSuite * inSuite, void * inContext) err = writer.Finalize(); NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); - reader.Init(&buffer); + reader.Init(buffer); // Skip over the initial element err = reader.Next(); @@ -2388,7 +2393,7 @@ void CheckCHIPTLVPutStringFCircular(nlTestSuite * inSuite, void * inContext) err = writer.Finalize(); NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); - reader.Init(&buffer); + reader.Init(buffer); err = reader.Next(); NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); @@ -2409,7 +2414,7 @@ void CheckCHIPTLVSkipCircular(nlTestSuite * inSuite, void * inContext) CHIPCircularTLVBuffer buffer(backingStore, bufsize); CHIP_ERROR err = CHIP_NO_ERROR; - writer.Init(&buffer); + writer.Init(buffer); err = writer.PutString(AnonymousTag, testString); NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); @@ -2426,7 +2431,7 @@ void CheckCHIPTLVSkipCircular(nlTestSuite * inSuite, void * inContext) err = writer.Finalize(); NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); - reader.Init(&buffer); + reader.Init(buffer); err = reader.Next(); // position the reader at the straddling element NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); @@ -2440,10 +2445,10 @@ void CheckCHIPTLVSkipCircular(nlTestSuite * inSuite, void * inContext) */ void CheckBufferOverflow(nlTestSuite * inSuite, void * inContext) { - TLVWriter writer; - TLVReader reader; + System::PacketBufferTLVWriter writer; + System::PacketBufferTLVReader reader; - System::PacketBufferHandle buf = PacketBuffer::New(0); + System::PacketBufferHandle buf = System::PacketBuffer::New(0); uint16_t maxDataLen = buf->MaxDataLength(); uint16_t reserve = static_cast((sizeof(Encoding1) < maxDataLen) ? (maxDataLen - sizeof(Encoding1)) + 2 : 0); @@ -2454,20 +2459,19 @@ void CheckBufferOverflow(nlTestSuite * inSuite, void * inContext) { buf->SetStart(buf->Start() + reserve); - writer.Init(buf.Get_ForNow()); - writer.GetNewBuffer = TLVWriter::GetNewPacketBuffer; + writer.Init(buf.Retain(), /* useChainedBuffers = */ true); writer.ImplicitProfileId = TestProfile_2; WriteEncoding1(inSuite, writer); - TestBufferContents(inSuite, buf.Get_ForNow(), Encoding1, sizeof(Encoding1)); + TestBufferContents(inSuite, buf, Encoding1, sizeof(Encoding1)); - reader.Init(buf.Get_ForNow(), 0xFFFFFFFFUL, true); + reader.Init(buf.Retain(), /* useChainedBuffers = */ true); reader.ImplicitProfileId = TestProfile_2; ReadEncoding1(inSuite, reader); - buf = PacketBuffer::New(0); + buf = System::PacketBuffer::New(0); } } diff --git a/src/lib/mdns/Advertiser.h b/src/lib/mdns/Advertiser.h new file mode 100644 index 00000000000000..1b6bf9770b424f --- /dev/null +++ b/src/lib/mdns/Advertiser.h @@ -0,0 +1,194 @@ +/* + * + * 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. + */ + +#pragma once + +#include + +#include +#include +#include + +namespace chip { +namespace Mdns { + +static constexpr uint16_t kMdnsPort = 5353; + +template +class BaseAdvertisingParams +{ +public: + Derived & SetPort(uint16_t port) + { + mPort = port; + return *reinterpret_cast(this); + } + uint64_t GetPort() const { return mPort; } + + Derived & EnableIpV4(bool enable) + { + mEnableIPv4 = enable; + return *reinterpret_cast(this); + } + bool IsIPv4Enabled() const { return mEnableIPv4; } + +private: + uint16_t mPort = CHIP_PORT; + bool mEnableIPv4 = true; +}; + +/// Defines parameters required for advertising a CHIP node +/// over mDNS as an 'operationally ready' node. +class OperationalAdvertisingParameters : public BaseAdvertisingParams +{ +public: + OperationalAdvertisingParameters & SetFabricId(uint64_t fabricId) + { + mFabricId = fabricId; + return *this; + } + uint64_t GetFabricId() const { return mFabricId; } + + OperationalAdvertisingParameters & SetNodeId(uint64_t nodeId) + { + mNodeId = nodeId; + return *this; + } + uint64_t GetNodeId() const { return mNodeId; } + +private: + uint64_t mFabricId = 0; + uint64_t mNodeId = 0; +}; + +class CommisioningAdvertisingParameters : public BaseAdvertisingParams +{ +public: + CommisioningAdvertisingParameters & SetShortDiscriminator(uint8_t discriminator) + { + mShortDiscriminator = discriminator; + return *this; + } + uint8_t GetShortDiscriminator() const { return mShortDiscriminator; } + + CommisioningAdvertisingParameters & SetLongDiscrimininator(uint16_t discriminator) + { + mLongDiscriminator = discriminator; + return *this; + } + uint16_t GetLongDiscriminator() const { return mLongDiscriminator; } + + CommisioningAdvertisingParameters & SetVendorId(Optional vendorId) + { + mVendorId = vendorId; + return *this; + } + Optional GetVendorId() const { return mVendorId; } + + CommisioningAdvertisingParameters & SetProductId(Optional productId) + { + mProductId = productId; + return *this; + } + Optional GetProductId() const { return mProductId; } + +private: + uint8_t mShortDiscriminator = 0; + uint16_t mLongDiscriminator = 0; // 12-bit according to spec + chip::Optional mVendorId; + chip::Optional mProductId; +}; + +class CommisionableAdvertisingParameters : public BaseAdvertisingParams +{ +public: + CommisionableAdvertisingParameters & SetShortDiscriminator(uint8_t discriminator) + { + mShortDiscriminator = discriminator; + return *this; + } + uint8_t GetShortDiscriminator() const { return mShortDiscriminator; } + + CommisionableAdvertisingParameters & SetLongDiscrimininator(uint16_t discriminator) + { + mLongDiscriminator = discriminator; + return *this; + } + uint16_t GetLongDiscriminator() const { return mLongDiscriminator; } + + CommisionableAdvertisingParameters & SetVendorId(Optional vendorId) + { + mVendorId = vendorId; + return *this; + } + Optional GetVendorId() const { return mVendorId; } + + CommisionableAdvertisingParameters & SetProductId(Optional productId) + { + mProductId = productId; + return *this; + } + Optional GetProductId() const { return mProductId; } + + CommisionableAdvertisingParameters & SetPairingInstr(Optional pairingInstr) + { + mPairingInstr = pairingInstr; + return *this; + } + Optional GetPairingInstr() const { return mPairingInstr; } + + CommisionableAdvertisingParameters & SetPairingHint(Optional pairingHint) + { + mPairingHint = pairingHint; + return *this; + } + Optional GetPairingHint() const { return mPairingHint; } + +private: + uint8_t mShortDiscriminator = 0; + uint16_t mLongDiscriminator = 0; // 12-bit according to spec + chip::Optional mVendorId; + chip::Optional mProductId; + chip::Optional mPairingInstr; + chip::Optional mPairingHint; +}; + +/// Handles advertising of CHIP nodes +class ServiceAdvertiser +{ +public: + virtual ~ServiceAdvertiser() {} + + /// Starts the advertiser. Items 'Advertised' will become visible. + /// May be called before OR after Advertise() calls. + virtual CHIP_ERROR Start(chip::Inet::InetLayer * inetLayer, uint16_t port) = 0; + + /// Advertises the CHIP node as an operational node + virtual CHIP_ERROR Advertise(const OperationalAdvertisingParameters & params) = 0; + + /// Advertises the CHIP node as a commisioning node + virtual CHIP_ERROR Advertise(const CommisioningAdvertisingParameters & params) = 0; + + /// Advertises the CHIP node as a commisionable node + virtual CHIP_ERROR Advertise(const CommisionableAdvertisingParameters & params) = 0; + + /// Provides the system-wide implementation of the service advertiser + static ServiceAdvertiser & Instance(); +}; + +} // namespace Mdns +} // namespace chip diff --git a/src/lib/mdns/Advertiser_ImplMinimalMdns.cpp b/src/lib/mdns/Advertiser_ImplMinimalMdns.cpp new file mode 100644 index 00000000000000..e5a407d55236e1 --- /dev/null +++ b/src/lib/mdns/Advertiser_ImplMinimalMdns.cpp @@ -0,0 +1,715 @@ +/* + * + * 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 "Advertiser.h" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace chip { +namespace Mdns { +namespace { + +using namespace mdns::Minimal; + +const char * ToString(QClass qClass) +{ + switch (qClass) + { + case QClass::IN: + return "IN"; + default: + return "???"; + } +} + +const char * ToString(QType qType) +{ + switch (qType) + { + case QType::ANY: + return "ANY"; + case QType::A: + return "A"; + case QType::AAAA: + return "AAAA"; + case QType::TXT: + return "TXT"; + case QType::SRV: + return "SRV"; + case QType::PTR: + return "PTR"; + default: + return "???"; + } +} + +void LogQuery(const QueryData & data) +{ + StringBuilder<128> logString; + + logString.Add("QUERY ").Add(ToString(data.GetClass())).Add("/").Add(ToString(data.GetType())).Add(": "); + + SerializedQNameIterator name = data.GetName(); + while (name.Next()) + { + logString.Add(name.Value()).Add("."); + } + + ChipLogDetail(Discovery, "%s", logString.c_str()); +} + +class AllInterfaces : public ListenIterator +{ +public: + AllInterfaces() {} + + bool Next(chip::Inet::InterfaceId * id, chip::Inet::IPAddressType * type) override + { +#if INET_CONFIG_ENABLE_IPV4 + if (mState == State::kIpV4) + { + *id = INET_NULL_INTERFACEID; + *type = chip::Inet::kIPAddressType_IPv4; + mState = State::kIpV6; + + SkipToFirstValidInterface(); + return true; + } +#else + mState = State::kIpV6; + SkipToFirstValidInterface(); +#endif + + if (!mIterator.HasCurrent()) + { + return false; + } + + *id = mIterator.GetInterfaceId(); + *type = chip::Inet::kIPAddressType_IPv6; + + for (mIterator.Next(); SkipCurrentInterface(); mIterator.Next()) + { + } + return true; + } + +private: + enum class State + { + kIpV4, + kIpV6, + }; + State mState = State::kIpV4; + chip::Inet::InterfaceIterator mIterator; + + void SkipToFirstValidInterface() + { + do + { + if (!SkipCurrentInterface()) + { + break; + } + } while (mIterator.Next()); + } + + bool SkipCurrentInterface() + { + if (!mIterator.HasCurrent()) + { + return false; // nothing to try. + } + + if (!mIterator.IsUp() || !mIterator.SupportsMulticast()) + { + return true; // not a usable interface + } + char name[64]; + if (mIterator.GetInterfaceName(name, sizeof(name)) != CHIP_NO_ERROR) + { + ChipLogError(Discovery, "Interface iterator failed to get interface name."); + return true; + } + + if (strncmp(name, "lo", 2) == 0) + { + ChipLogDetail(Discovery, "Skipping interface '%s' (assume local loopback)", name); + return true; + } + return false; + } +}; + +class AdvertiserMinMdns : public ServiceAdvertiser, + public ServerDelegate, // gets queries + public ParserDelegate // parses queries +{ +public: + AdvertiserMinMdns() : mResponseSender(&mServer, &mQueryResponder) + + { + mServer.SetDelegate(this); + + for (size_t i = 0; i < kMaxAllocatedResponders; i++) + { + mAllocatedResponders[i] = nullptr; + } + for (size_t i = 0; i < kMaxAllocatedQNameData; i++) + { + mAllocatedQNameParts[i] = nullptr; + } + } + ~AdvertiserMinMdns() { Clear(); } + + // Service advertiser + CHIP_ERROR Start(chip::Inet::InetLayer * inetLayer, uint16_t port) override; + CHIP_ERROR Advertise(const OperationalAdvertisingParameters & params) override; + CHIP_ERROR Advertise(const CommisioningAdvertisingParameters & params) override; + CHIP_ERROR Advertise(const CommisionableAdvertisingParameters & params) override; + + // ServerDelegate + void OnQuery(const BytesRange & data, const chip::Inet::IPPacketInfo * info) override; + void OnResponse(const BytesRange & data, const chip::Inet::IPPacketInfo * info) override {} + + // ParserDelegate + void OnHeader(ConstHeaderRef & header) override { mMessageId = header.GetMessageId(); } + void OnResource(ResourceType type, const ResourceData & data) override {} + void OnQuery(const QueryData & data) override; + +private: + /// Sets the query responder to a blank state and frees up any + /// allocated memory. + void Clear(); + + QueryResponderSettings AddAllocatedResponder(Responder * responder) + { + if (responder == nullptr) + { + ChipLogError(Discovery, "Responder memory allocation failed"); + return QueryResponderSettings(); // failed + } + + for (size_t i = 0; i < kMaxAllocatedResponders; i++) + { + if (mAllocatedResponders[i] != nullptr) + { + continue; + } + + mAllocatedResponders[i] = responder; + return mQueryResponder.AddResponder(mAllocatedResponders[i]); + } + + Platform::Delete(responder); + ChipLogError(Discovery, "Failed to find free slot for adding a responder"); + return QueryResponderSettings(); + } + + /// Appends another responder to the internal replies. + template + QueryResponderSettings AddResponder(Args &&... args) + { + return AddAllocatedResponder(chip::Platform::New(std::forward(args)...)); + } + + template + FullQName AllocateQName(Args &&... names) + { + for (size_t i = 0; i < kMaxAllocatedQNameData; i++) + { + if (mAllocatedQNameParts[i] != nullptr) + { + continue; + } + + mAllocatedQNameParts[i] = + chip::Platform::MemoryAlloc(FlatAllocatedQName::RequiredStorageSize(std::forward(names)...)); + + if (mAllocatedQNameParts[i] == nullptr) + { + ChipLogError(Discovery, "QName memory allocation failed"); + return FullQName(); + } + return FlatAllocatedQName::Build(mAllocatedQNameParts[i], std::forward(names)...); + } + + ChipLogError(Discovery, "Failed to find free slot for adding a qname"); + return FullQName(); + } + + FullQName GetCommisioningTextEntries(const CommisioningAdvertisingParameters & params); + FullQName GetCommisionableTextEntries(const CommisionableAdvertisingParameters & params); + + static constexpr size_t kMaxEndPoints = 10; + static constexpr size_t kMaxRecords = 16; + static constexpr size_t kMaxAllocatedResponders = 16; + static constexpr size_t kMaxAllocatedQNameData = 8; + + Server mServer; + QueryResponder mQueryResponder; + ResponseSender mResponseSender; + + // current request handling + const chip::Inet::IPPacketInfo * mCurrentSource = nullptr; + uint32_t mMessageId = 0; + + // dynamically allocated items + Responder * mAllocatedResponders[kMaxAllocatedResponders]; + void * mAllocatedQNameParts[kMaxAllocatedQNameData]; + + const char * mEmptyTextEntries[1] = { + "=", + }; +}; + +void AdvertiserMinMdns::OnQuery(const BytesRange & data, const chip::Inet::IPPacketInfo * info) +{ + ChipLogDetail(Discovery, "MinMdns received a query."); + + mCurrentSource = info; + if (!ParsePacket(data, this)) + { + ChipLogError(Discovery, "Failed to parse mDNS query"); + } + mCurrentSource = nullptr; +} + +void AdvertiserMinMdns::OnQuery(const QueryData & data) +{ + if (mCurrentSource == nullptr) + { + ChipLogError(Discovery, "INTERNAL CONSISTENCY ERROR: missing query source"); + return; + } + + LogQuery(data); + + CHIP_ERROR err = mResponseSender.Respond(mMessageId, data, mCurrentSource); + if (err != CHIP_NO_ERROR) + { + ChipLogError(Discovery, "Failed to reply to query: %s", ErrorStr(err)); + } +} + +CHIP_ERROR AdvertiserMinMdns::Start(chip::Inet::InetLayer * inetLayer, uint16_t port) +{ + mServer.Shutdown(); + + AllInterfaces allInterfaces; + + ReturnErrorOnFailure(mServer.Listen(inetLayer, &allInterfaces, port)); + + ChipLogProgress(Discovery, "CHIP minimal mDNS started advertising."); + return CHIP_NO_ERROR; +} + +void AdvertiserMinMdns::Clear() +{ + // Init clears all responders, so that data can be freed + mQueryResponder.Init(); + + // Free all allocated data + for (size_t i = 0; i < kMaxAllocatedResponders; i++) + { + if (mAllocatedResponders[i] != nullptr) + { + chip::Platform::Delete(mAllocatedResponders[i]); + mAllocatedResponders[i] = nullptr; + } + } + + for (size_t i = 0; i < kMaxAllocatedQNameData; i++) + { + if (mAllocatedQNameParts[i] != nullptr) + { + chip::Platform::MemoryFree(mAllocatedQNameParts[i]); + mAllocatedQNameParts[i] = nullptr; + } + } +} + +CHIP_ERROR AdvertiserMinMdns::Advertise(const OperationalAdvertisingParameters & params) +{ + Clear(); + + char uniqueName[64] = ""; + + /// need to set server name + size_t len = snprintf(uniqueName, sizeof(uniqueName), "%" PRIX64 "-%" PRIX64, params.GetFabricId(), params.GetNodeId()); + if (len >= sizeof(uniqueName)) + { + ChipLogError(Discovery, "Failed to allocate QNames."); + return CHIP_ERROR_NO_MEMORY; + } + + FullQName operationalServiceName = AllocateQName("_chip", "_tcp", "local"); + FullQName operationalServerName = AllocateQName(uniqueName, "_chip", "_tcp", "local"); + FullQName serverName = AllocateQName(uniqueName, "local"); + + if ((operationalServiceName.nameCount == 0) || (operationalServerName.nameCount == 0) || (serverName.nameCount == 0)) + { + ChipLogError(Discovery, "Failed to allocate QNames."); + return CHIP_ERROR_NO_MEMORY; + } + + if (!AddResponder(operationalServiceName, operationalServerName) + .SetReportAdditional(operationalServerName) + .SetReportInServiceListing(true) + .IsValid()) + { + ChipLogError(Discovery, "Failed to add service PTR record mDNS responder"); + return CHIP_ERROR_NO_MEMORY; + } + + if (!AddResponder(SrvResourceRecord(operationalServerName, serverName, params.GetPort())) + .SetReportAdditional(serverName) + .IsValid()) + { + ChipLogError(Discovery, "Failed to add SRV record mDNS responder"); + return CHIP_ERROR_NO_MEMORY; + } + if (!AddResponder(TxtResourceRecord(operationalServerName, mEmptyTextEntries)) + .SetReportAdditional(serverName) + .IsValid()) + { + ChipLogError(Discovery, "Failed to add TXT record mDNS responder"); + return CHIP_ERROR_NO_MEMORY; + } + + if (!AddResponder(serverName).IsValid()) + { + ChipLogError(Discovery, "Failed to add IPv6 mDNS responder"); + return CHIP_ERROR_NO_MEMORY; + } + + if (params.IsIPv4Enabled()) + { + if (!AddResponder(serverName).IsValid()) + { + ChipLogError(Discovery, "Failed to add IPv4 mDNS responder"); + return CHIP_ERROR_NO_MEMORY; + } + } + + ChipLogProgress(Discovery, "CHIP minimal mDNS configured as 'Operational device'."); + + return CHIP_NO_ERROR; +} + +CHIP_ERROR AdvertiserMinMdns::Advertise(const CommisioningAdvertisingParameters & params) +{ + Clear(); + + // TODO: need to detect colisions here + char nameBuffer[64] = ""; + size_t len = snprintf(nameBuffer, sizeof(nameBuffer), "chip-%016" PRIX64, GetRandU64()); + if (len >= sizeof(nameBuffer)) + { + return CHIP_ERROR_NO_MEMORY; + } + + FullQName operationalServiceName = AllocateQName("_chipc", "_udp", "local"); + FullQName operationalServerName = AllocateQName(nameBuffer, "_chipc", "_udp", "local"); + FullQName serverName = AllocateQName(nameBuffer, "local"); + + if ((operationalServiceName.nameCount == 0) || (operationalServerName.nameCount == 0) || (serverName.nameCount == 0)) + { + ChipLogError(Discovery, "Failed to allocate QNames."); + return CHIP_ERROR_NO_MEMORY; + } + + if (!AddResponder(operationalServiceName, operationalServerName) + .SetReportAdditional(operationalServerName) + .SetReportInServiceListing(true) + .IsValid()) + { + ChipLogError(Discovery, "Failed to add service PTR record mDNS responder"); + return CHIP_ERROR_NO_MEMORY; + } + + if (!AddResponder(SrvResourceRecord(operationalServerName, serverName, params.GetPort())) + .SetReportAdditional(serverName) + .IsValid()) + { + ChipLogError(Discovery, "Failed to add SRV record mDNS responder"); + return CHIP_ERROR_NO_MEMORY; + } + if (!AddResponder(serverName).IsValid()) + { + ChipLogError(Discovery, "Failed to add IPv6 mDNS responder"); + return CHIP_ERROR_NO_MEMORY; + } + + if (params.IsIPv4Enabled()) + { + if (!AddResponder(serverName).IsValid()) + { + ChipLogError(Discovery, "Failed to add IPv4 mDNS responder"); + return CHIP_ERROR_NO_MEMORY; + } + } + + { + sprintf(nameBuffer, "S%03d", params.GetShortDiscriminator()); + FullQName shortServiceName = AllocateQName(nameBuffer, "_sub", "_chipc", "_udp", "local"); + ReturnErrorCodeIf(shortServiceName.nameCount == 0, CHIP_ERROR_NO_MEMORY); + + if (!AddResponder(shortServiceName, operationalServerName) + .SetReportAdditional(operationalServerName) + .SetReportInServiceListing(true) + .IsValid()) + { + ChipLogError(Discovery, "Failed to add short discriminator PTR record mDNS responder"); + return CHIP_ERROR_NO_MEMORY; + } + } + + { + sprintf(nameBuffer, "L%04d", params.GetLongDiscriminator()); + FullQName longServiceName = AllocateQName(nameBuffer, "_sub", "_chipc", "_udp", "local"); + ReturnErrorCodeIf(longServiceName.nameCount == 0, CHIP_ERROR_NO_MEMORY); + if (!AddResponder(longServiceName, operationalServerName) + .SetReportAdditional(operationalServerName) + .SetReportInServiceListing(true) + .IsValid()) + { + ChipLogError(Discovery, "Failed to add long discriminator PTR record mDNS responder"); + return CHIP_ERROR_NO_MEMORY; + } + } + + if (params.GetVendorId().HasValue()) + { + sprintf(nameBuffer, "V%d", params.GetVendorId().Value()); + FullQName vendorServiceName = AllocateQName(nameBuffer, "_sub", "_chipc", "_udp", "local"); + ReturnErrorCodeIf(vendorServiceName.nameCount == 0, CHIP_ERROR_NO_MEMORY); + + if (!AddResponder(vendorServiceName, operationalServerName) + .SetReportAdditional(operationalServerName) + .SetReportInServiceListing(true) + .IsValid()) + { + ChipLogError(Discovery, "Failed to add vendor discriminator PTR record mDNS responder"); + return CHIP_ERROR_NO_MEMORY; + } + } + + if (!AddResponder(TxtResourceRecord(operationalServerName, GetCommisioningTextEntries(params))) + .SetReportAdditional(serverName) + .IsValid()) + { + ChipLogError(Discovery, "Failed to add TXT record mDNS responder"); + return CHIP_ERROR_NO_MEMORY; + } + + ChipLogProgress(Discovery, "CHIP minimal mDNS configured as 'Commisioning device'."); + + return CHIP_NO_ERROR; +} + +FullQName AdvertiserMinMdns::GetCommisioningTextEntries(const CommisioningAdvertisingParameters & params) +{ + // a discriminator always exists + char txtDiscriminator[32]; + sprintf(txtDiscriminator, "D=%d", params.GetLongDiscriminator()); + + if (!params.GetVendorId().HasValue()) + { + return AllocateQName(txtDiscriminator); + } + + // Need to also set a vid/pid string + char txtVidPid[64]; + if (params.GetProductId().HasValue()) + { + sprintf(txtVidPid, "V=%d+%d", params.GetVendorId().Value(), params.GetProductId().Value()); + } + else + { + sprintf(txtVidPid, "V=%d", params.GetVendorId().Value()); + } + + return AllocateQName(txtDiscriminator, txtVidPid); +} + +CHIP_ERROR AdvertiserMinMdns::Advertise(const CommisionableAdvertisingParameters & params) +{ + Clear(); + + // TODO: need to detect colisions here + char nameBuffer[64] = ""; + size_t len = snprintf(nameBuffer, sizeof(nameBuffer), "chip-%016" PRIX64, GetRandU64()); + if (len >= sizeof(nameBuffer)) + { + return CHIP_ERROR_NO_MEMORY; + } + + FullQName operationalServiceName = AllocateQName("_chipd", "_udp", "local"); + FullQName operationalServerName = AllocateQName(nameBuffer, "_chipd", "_udp", "local"); + FullQName serverName = AllocateQName(nameBuffer, "local"); + + if ((operationalServiceName.nameCount == 0) || (operationalServerName.nameCount == 0) || (serverName.nameCount == 0)) + { + ChipLogError(Discovery, "Failed to allocate QNames."); + return CHIP_ERROR_NO_MEMORY; + } + + if (!AddResponder(operationalServiceName, operationalServerName) + .SetReportAdditional(operationalServerName) + .SetReportInServiceListing(true) + .IsValid()) + { + ChipLogError(Discovery, "Failed to add service PTR record mDNS responder"); + return CHIP_ERROR_NO_MEMORY; + } + + if (!AddResponder(SrvResourceRecord(operationalServerName, serverName, params.GetPort())) + .SetReportAdditional(serverName) + .IsValid()) + { + ChipLogError(Discovery, "Failed to add SRV record mDNS responder"); + return CHIP_ERROR_NO_MEMORY; + } + if (!AddResponder(serverName).IsValid()) + { + ChipLogError(Discovery, "Failed to add IPv6 mDNS responder"); + return CHIP_ERROR_NO_MEMORY; + } + + if (params.IsIPv4Enabled()) + { + if (!AddResponder(serverName).IsValid()) + { + ChipLogError(Discovery, "Failed to add IPv4 mDNS responder"); + return CHIP_ERROR_NO_MEMORY; + } + } + + { + sprintf(nameBuffer, "S%03d", params.GetShortDiscriminator()); + FullQName shortServiceName = AllocateQName(nameBuffer, "_sub", "_chipd", "_udp", "local"); + ReturnErrorCodeIf(shortServiceName.nameCount == 0, CHIP_ERROR_NO_MEMORY); + + if (!AddResponder(shortServiceName, operationalServerName) + .SetReportAdditional(operationalServerName) + .SetReportInServiceListing(true) + .IsValid()) + { + ChipLogError(Discovery, "Failed to add short discriminator PTR record mDNS responder"); + return CHIP_ERROR_NO_MEMORY; + } + } + + { + sprintf(nameBuffer, "L%04d", params.GetLongDiscriminator()); + FullQName longServiceName = AllocateQName(nameBuffer, "_sub", "_chipd", "_udp", "local"); + ReturnErrorCodeIf(longServiceName.nameCount == 0, CHIP_ERROR_NO_MEMORY); + if (!AddResponder(longServiceName, operationalServerName) + .SetReportAdditional(operationalServerName) + .SetReportInServiceListing(true) + .IsValid()) + { + ChipLogError(Discovery, "Failed to add long discriminator PTR record mDNS responder"); + return CHIP_ERROR_NO_MEMORY; + } + } + + if (params.GetVendorId().HasValue()) + { + sprintf(nameBuffer, "V%d", params.GetVendorId().Value()); + FullQName vendorServiceName = AllocateQName(nameBuffer, "_sub", "_chipd", "_udp", "local"); + ReturnErrorCodeIf(vendorServiceName.nameCount == 0, CHIP_ERROR_NO_MEMORY); + + if (!AddResponder(vendorServiceName, operationalServerName) + .SetReportAdditional(operationalServerName) + .SetReportInServiceListing(true) + .IsValid()) + { + ChipLogError(Discovery, "Failed to add vendor discriminator PTR record mDNS responder"); + return CHIP_ERROR_NO_MEMORY; + } + } + + if (!AddResponder(TxtResourceRecord(operationalServerName, GetCommisionableTextEntries(params))) + .SetReportAdditional(serverName) + .IsValid()) + { + ChipLogError(Discovery, "Failed to add TXT record mDNS responder"); + return CHIP_ERROR_NO_MEMORY; + } + + ChipLogProgress(Discovery, "CHIP minimal mDNS configured as 'Commisionable device'."); + + return CHIP_NO_ERROR; +} + +FullQName AdvertiserMinMdns::GetCommisionableTextEntries(const CommisionableAdvertisingParameters & params) +{ + // a discriminator always exists + char txtDiscriminator[32]; + sprintf(txtDiscriminator, "D=%d", params.GetLongDiscriminator()); + + if (!params.GetVendorId().HasValue()) + { + return AllocateQName(txtDiscriminator); + } + + // Need to also set a vid/pid string + char txtVidPid[64]; + if (params.GetProductId().HasValue()) + { + sprintf(txtVidPid, "V=%d+%d", params.GetVendorId().Value(), params.GetProductId().Value()); + } + else + { + sprintf(txtVidPid, "V=%d", params.GetVendorId().Value()); + } + + char txtPairingInstrHint[128]; + if (params.GetPairingInstr().HasValue() && params.GetPairingHint().HasValue()) + { + sprintf(txtPairingInstrHint, "P=%s+%d", params.GetPairingInstr().Value(), params.GetPairingHint().Value()); + } + + return AllocateQName(txtDiscriminator, txtVidPid, txtPairingInstrHint); +} + +AdvertiserMinMdns gAdvertiser; +} // namespace + +ServiceAdvertiser & ServiceAdvertiser::Instance() +{ + return gAdvertiser; +} + +} // namespace Mdns +} // namespace chip diff --git a/src/lib/mdns/Advertiser_ImplNone.cpp b/src/lib/mdns/Advertiser_ImplNone.cpp new file mode 100644 index 00000000000000..7cee217715452d --- /dev/null +++ b/src/lib/mdns/Advertiser_ImplNone.cpp @@ -0,0 +1,64 @@ +/* + * + * 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 "Advertiser.h" + +#include + +namespace chip { +namespace Mdns { +namespace { + +class NoneAdvertiser : public ServiceAdvertiser +{ +public: + CHIP_ERROR Start(chip::Inet::InetLayer * inetLayet, uint16_t port) override + { + ChipLogError(Discovery, "mDNS advertising not available. mDNS start disabled."); + return CHIP_ERROR_NOT_IMPLEMENTED; + } + + CHIP_ERROR Advertise(const OperationalAdvertisingParameters & params) override + { + ChipLogError(Discovery, "mDNS advertising not available. Operational Advertisement failed."); + return CHIP_ERROR_NOT_IMPLEMENTED; + } + + CHIP_ERROR Advertise(const CommisioningAdvertisingParameters & params) override + { + ChipLogError(Discovery, "mDNS advertising not available. Commisioning Advertisement failed."); + return CHIP_ERROR_NOT_IMPLEMENTED; + } + + CHIP_ERROR Advertise(const CommisionableAdvertisingParameters & params) override + { + ChipLogError(Discovery, "mDNS advertising not available. Commisionable Advertisement failed."); + return CHIP_ERROR_NOT_IMPLEMENTED; + } +}; + +NoneAdvertiser gAdvertiser; + +} // namespace + +ServiceAdvertiser & ServiceAdvertiser::Instance() +{ + return gAdvertiser; +} + +} // namespace Mdns +} // namespace chip diff --git a/src/lib/mdns/BUILD.gn b/src/lib/mdns/BUILD.gn index 0704363be4be50..ded9e327fecb3a 100644 --- a/src/lib/mdns/BUILD.gn +++ b/src/lib/mdns/BUILD.gn @@ -14,6 +14,11 @@ import("//build_overrides/chip.gni") +declare_args() { + # Set up what advertiser to use for mDNS advertisement + chip_mdns_advertiser = "minimal" +} + source_set("platform_header") { sources = [ "platform/Mdns.h" ] } @@ -26,8 +31,19 @@ static_library("mdns") { "${chip_root}/src/platform", ] - sources = [ - "DiscoveryManager.cpp", - "DiscoveryManager.h", - ] + sources = [ "Advertiser.h" ] + + if (chip_mdns_advertiser == "none") { + sources += [ "Advertiser_ImplNone.cpp" ] + } else if (chip_mdns_advertiser == "minimal") { + sources += [ "Advertiser_ImplMinimalMdns.cpp" ] + public_deps += [ "${chip_root}/src/lib/mdns/minimal" ] + } else if (chip_mdns_advertiser == "platform") { + sources += [ + "Discovery_ImplPlatform.cpp", + "Discovery_ImplPlatform.h", + ] + } else { + assert(false, "Unknown mDNS advertiser implementation.") + } } diff --git a/src/lib/mdns/DiscoveryManager.cpp b/src/lib/mdns/Discovery_ImplPlatform.cpp similarity index 51% rename from src/lib/mdns/DiscoveryManager.cpp rename to src/lib/mdns/Discovery_ImplPlatform.cpp index 40c6cf25169a78..2cfb2db37698cc 100644 --- a/src/lib/mdns/DiscoveryManager.cpp +++ b/src/lib/mdns/Discovery_ImplPlatform.cpp @@ -15,7 +15,7 @@ * limitations under the License. */ -#include "DiscoveryManager.h" +#include "Discovery_ImplPlatform.h" #include @@ -27,8 +27,6 @@ #include "support/ErrorStr.h" #include "support/RandUtils.h" -#if CHIP_ENABLE_MDNS - namespace { uint8_t HexToInt(char c) @@ -52,31 +50,31 @@ uint8_t HexToInt(char c) constexpr uint64_t kUndefinedNodeId = 0; } // namespace -#endif namespace chip { namespace Mdns { -DiscoveryManager DiscoveryManager::sManager; +DiscoveryImplPlatform DiscoveryImplPlatform::sManager; -CHIP_ERROR DiscoveryManager::Init() +DiscoveryImplPlatform::DiscoveryImplPlatform() { -#if CHIP_ENABLE_MDNS - CHIP_ERROR error; + mCommissionInstanceName = GetRandU64(); + CHIP_ERROR error = ChipMdnsInit(HandleMdnsInit, HandleMdnsError, this); - mUnprovisionedInstanceName = GetRandU64(); - SuccessOrExit(error = ChipMdnsInit(HandleMdnsInit, HandleMdnsError, this)); -exit: - return error; -#else + if (error != CHIP_NO_ERROR) + { + ChipLogError(Discovery, "Failed to initialize platform mdns: %s", ErrorStr(error)); + } +} + +CHIP_ERROR DiscoveryImplPlatform::Start(Inet::InetLayer * inetLayer, uint16_t port) +{ return CHIP_NO_ERROR; -#endif // CHIP_ENABLE_MDNS } -void DiscoveryManager::HandleMdnsInit(void * context, CHIP_ERROR initError) +void DiscoveryImplPlatform::HandleMdnsInit(void * context, CHIP_ERROR initError) { -#if CHIP_ENABLE_MDNS - DiscoveryManager * publisher = static_cast(context); + DiscoveryImplPlatform * publisher = static_cast(context); if (initError == CHIP_NO_ERROR) { @@ -86,61 +84,30 @@ void DiscoveryManager::HandleMdnsInit(void * context, CHIP_ERROR initError) { ChipLogError(Discovery, "mDNS initialization failed with %s", chip::ErrorStr(initError)); } -#endif // CHIP_ENABLE_MDNS } -void DiscoveryManager::HandleMdnsError(void * context, CHIP_ERROR error) +void DiscoveryImplPlatform::HandleMdnsError(void * context, CHIP_ERROR error) { -#if CHIP_ENABLE_MDNS - DiscoveryManager * publisher = static_cast(context); - if (error == CHIP_ERROR_FORCED_RESET && publisher->mIsPublishing) + DiscoveryImplPlatform * publisher = static_cast(context); + if (error == CHIP_ERROR_FORCED_RESET) { - publisher->StartPublishDevice(); + if (publisher->mIsOperationalPublishing) + { + publisher->Advertise(publisher->mOperationalAdvertisingParams); + } + if (publisher->mIsCommissionalPublishing) + { + publisher->Advertise(publisher->mCommissioningdvertisingParams); + } } else { ChipLogError(Discovery, "mDNS error: %s", chip::ErrorStr(error)); } -#endif // CHIP_ENABLE_MDNS } -CHIP_ERROR DiscoveryManager::StartPublishDevice(chip::Inet::IPAddressType addressType, chip::Inet::InterfaceId interface) +CHIP_ERROR DiscoveryImplPlatform::SetupHostname() { -#if CHIP_ENABLE_MDNS - CHIP_ERROR error; - - // TODO: after multi-admin is decided we may need to publish both _chipc._udp and _chip._tcp service - if (!mIsPublishing) - { - SuccessOrExit(error = SetupHostname()); - } - else if (chip::DeviceLayer::ConfigurationMgr().IsFullyProvisioned() != mIsPublishingProvisionedDevice) - { - SuccessOrExit(error = StopPublishDevice()); - // Set hostname again in case the mac address changes when shifting from soft-AP to station - SuccessOrExit(error = SetupHostname()); - } - mIsPublishingProvisionedDevice = chip::DeviceLayer::ConfigurationMgr().IsFullyProvisioned(); - - if (mIsPublishingProvisionedDevice) - { - error = PublishProvisionedDevice(addressType, interface); - } - else - { - error = PublishUnprovisionedDevice(addressType, interface); - } - mIsPublishing = true; -exit: - return error; -#else - return CHIP_ERROR_NOT_IMPLEMENTED; -#endif // CHIP_ENABLE_MDNS -} - -CHIP_ERROR DiscoveryManager::SetupHostname() -{ -#if CHIP_ENABLE_MDNS uint8_t mac[6]; // 6 byte wifi mac char hostname[13]; // Hostname will be the hex representation of mac. CHIP_ERROR error; @@ -154,94 +121,102 @@ CHIP_ERROR DiscoveryManager::SetupHostname() exit: return error; -#else - return CHIP_ERROR_NOT_IMPLEMENTED; -#endif // CHIP_ENABLE_MDNS } -CHIP_ERROR DiscoveryManager::PublishUnprovisionedDevice(chip::Inet::IPAddressType addressType, chip::Inet::InterfaceId interface) +CHIP_ERROR DiscoveryImplPlatform::Advertise(const CommisioningAdvertisingParameters & params) { -#if CHIP_ENABLE_MDNS CHIP_ERROR error = CHIP_NO_ERROR; MdnsService service; - uint16_t discriminator; - uint16_t vendorID; - uint16_t productID; - char discriminatorBuf[5]; // hex representation of 16-bit discriminator - char vendorProductBuf[10]; // "FFFF+FFFF" - // TODO: The text entry will be updated in the spec, update accordingly. - TextEntry entries[2] = { - { "D", nullptr, 0 }, - { "VP", nullptr, 0 }, - }; - - VerifyOrExit(mMdnsInitialized, error = CHIP_ERROR_INCORRECT_STATE); - ChipLogProgress(Discovery, "setup mdns service"); - SuccessOrExit(error = chip::DeviceLayer::ConfigurationMgr().GetSetupDiscriminator(discriminator)); - snprintf(service.mName, sizeof(service.mName), "%016" PRIX64, mUnprovisionedInstanceName); + char discriminatorBuf[6]; + char vendorProductBuf[12]; + TextEntry textEntries[3]; + size_t textEntrySize = 0; + char shortDiscriminatorSubtype[6]; + char longDiscriminatorSubtype[7]; + char vendorSubType[8]; + const char * subTypes[3]; + size_t subTypeSize = 0; + + if (!mMdnsInitialized) + { + return CHIP_ERROR_INCORRECT_STATE; + } + snprintf(service.mName, sizeof(service.mName), "%016" PRIX64, mCommissionInstanceName); strncpy(service.mType, "_chipc", sizeof(service.mType)); service.mProtocol = MdnsServiceProtocol::kMdnsProtocolUdp; - SuccessOrExit(error = chip::DeviceLayer::ConfigurationMgr().GetVendorId(vendorID)); - SuccessOrExit(error = chip::DeviceLayer::ConfigurationMgr().GetProductId(productID)); - snprintf(discriminatorBuf, sizeof(discriminatorBuf), "%04X", discriminator); - snprintf(vendorProductBuf, sizeof(vendorProductBuf), "%04X+%04X", vendorID, productID); - entries[0].mData = reinterpret_cast(discriminatorBuf); - entries[0].mDataSize = strnlen(discriminatorBuf, sizeof(discriminatorBuf)); - entries[1].mData = reinterpret_cast(vendorProductBuf); - entries[1].mDataSize = strnlen(discriminatorBuf, sizeof(vendorProductBuf)); - service.mTextEntryies = entries; - service.mTextEntrySize = sizeof(entries) / sizeof(TextEntry); + + snprintf(discriminatorBuf, sizeof(discriminatorBuf), "%04u", params.GetLongDiscriminator()); + textEntries[textEntrySize++] = { "D", reinterpret_cast(discriminatorBuf), + strnlen(discriminatorBuf, sizeof(discriminatorBuf)) }; + if (params.GetVendorId().HasValue()) + { + if (params.GetProductId().HasValue()) + { + snprintf(vendorProductBuf, sizeof(vendorProductBuf), "%u+%u", params.GetVendorId().Value(), + params.GetProductId().Value()); + } + else + { + snprintf(vendorProductBuf, sizeof(vendorProductBuf), "%u", params.GetVendorId().Value()); + } + textEntries[textEntrySize++] = { "VP", reinterpret_cast(vendorProductBuf), + strnlen(vendorProductBuf, sizeof(vendorProductBuf)) }; + } +#if CHIP_ENABLE_ADDITIONAL_DATA_ADVERTISING + textEntries[textEntrySize++] = { "RI", reinterpret_cast(CHIP_ROTATING_DEVICE_ID), + strlen(CHIP_ROTATING_DEVICE_ID) }; +#endif + + snprintf(shortDiscriminatorSubtype, sizeof(shortDiscriminatorSubtype), "_S%03u", params.GetShortDiscriminator()); + subTypes[subTypeSize++] = shortDiscriminatorSubtype; + snprintf(longDiscriminatorSubtype, sizeof(longDiscriminatorSubtype), "_L%04u", params.GetLongDiscriminator()); + subTypes[subTypeSize++] = longDiscriminatorSubtype; + if (params.GetVendorId().HasValue()) + { + snprintf(vendorSubType, sizeof(vendorSubType), "_V%u", params.GetVendorId().Value()); + subTypes[subTypeSize++] = vendorSubType; + } + + service.mTextEntryies = textEntries; + service.mTextEntrySize = textEntrySize; service.mPort = CHIP_PORT; - service.mInterface = interface; - service.mAddressType = addressType; + service.mInterface = INET_NULL_INTERFACEID; + service.mSubTypes = subTypes; + service.mSubTypeSize = subTypeSize; + service.mAddressType = Inet::kIPAddressType_Any; error = ChipMdnsPublishService(&service); -exit: return error; -#else - return CHIP_ERROR_NOT_IMPLEMENTED; -#endif // CHIP_ENABLE_MDNS } -CHIP_ERROR DiscoveryManager::PublishProvisionedDevice(chip::Inet::IPAddressType addressType, chip::Inet::InterfaceId interface) +CHIP_ERROR DiscoveryImplPlatform::Advertise(const OperationalAdvertisingParameters & params) { -#if CHIP_ENABLE_MDNS - uint64_t deviceId; - uint64_t fabricId; MdnsService service; CHIP_ERROR error = CHIP_NO_ERROR; + mOperationalAdvertisingParams = params; // TODO: There may be multilple device/fabrid ids after multi-admin. - SuccessOrExit(error = chip::DeviceLayer::ConfigurationMgr().GetFabricId(fabricId)); - SuccessOrExit(error = chip::DeviceLayer::ConfigurationMgr().GetDeviceId(deviceId)); - snprintf(service.mName, sizeof(service.mName), "%" PRIX64 "-%" PRIX64, deviceId, fabricId); + snprintf(service.mName, sizeof(service.mName), "%" PRIX64 "-%" PRIX64, params.GetNodeId(), params.GetFabricId()); strncpy(service.mType, "_chip", sizeof(service.mType)); service.mProtocol = MdnsServiceProtocol::kMdnsProtocolTcp; service.mPort = CHIP_PORT; service.mTextEntryies = nullptr; service.mTextEntrySize = 0; - service.mInterface = interface; - service.mAddressType = addressType; + service.mInterface = INET_NULL_INTERFACEID; + service.mAddressType = Inet::kIPAddressType_Any; error = ChipMdnsPublishService(&service); -exit: return error; -#else - return CHIP_ERROR_NOT_IMPLEMENTED; -#endif // CHIP_ENABLE_MDNS } -CHIP_ERROR DiscoveryManager::StopPublishDevice() +CHIP_ERROR DiscoveryImplPlatform::StopPublishDevice() { -#if CHIP_ENABLE_MDNS - mIsPublishing = false; + mIsOperationalPublishing = false; + mIsCommissionalPublishing = false; return ChipMdnsStopPublish(); -#else - return CHIP_ERROR_NOT_IMPLEMENTED; -#endif // CHIP_ENABLE_MDNS } -CHIP_ERROR DiscoveryManager::RegisterResolveDelegate(ResolveDelegate * delegate) +CHIP_ERROR DiscoveryImplPlatform::RegisterResolveDelegate(ResolveDelegate * delegate) { if (mResolveDelegate != nullptr) { @@ -254,9 +229,8 @@ CHIP_ERROR DiscoveryManager::RegisterResolveDelegate(ResolveDelegate * delegate) } } -CHIP_ERROR DiscoveryManager::ResolveNodeId(uint64_t nodeId, uint64_t fabricId, Inet::IPAddressType type) +CHIP_ERROR DiscoveryImplPlatform::ResolveNodeId(uint64_t nodeId, uint64_t fabricId, Inet::IPAddressType type) { -#if CHIP_ENABLE_MDNS MdnsService service; snprintf(service.mName, sizeof(service.mName), "%" PRIX64 "-%" PRIX64, nodeId, fabricId); @@ -264,15 +238,11 @@ CHIP_ERROR DiscoveryManager::ResolveNodeId(uint64_t nodeId, uint64_t fabricId, I service.mProtocol = MdnsServiceProtocol::kMdnsProtocolTcp; service.mAddressType = type; return ChipMdnsResolve(&service, INET_NULL_INTERFACEID, HandleNodeIdResolve, this); -#else - return CHIP_ERROR_NOT_IMPLEMENTED; -#endif // CHIP_ENABLE_MDNS } -void DiscoveryManager::HandleNodeIdResolve(void * context, MdnsService * result, CHIP_ERROR error) +void DiscoveryImplPlatform::HandleNodeIdResolve(void * context, MdnsService * result, CHIP_ERROR error) { -#if CHIP_ENABLE_MDNS - DiscoveryManager * mgr = static_cast(context); + DiscoveryImplPlatform * mgr = static_cast(context); if (mgr->mResolveDelegate == nullptr) { @@ -327,7 +297,11 @@ void DiscoveryManager::HandleNodeIdResolve(void * context, MdnsService * result, mgr->mResolveDelegate->HandleNodeIdResolve(error, kUndefinedNodeId, *result); } } -#endif // CHIP_ENABLE_MDNS +} + +ServiceAdvertiser & chip::Mdns::ServiceAdvertiser::Instance() +{ + return DiscoveryImplPlatform::GetInstance(); } } // namespace Mdns diff --git a/src/lib/mdns/DiscoveryManager.h b/src/lib/mdns/Discovery_ImplPlatform.h similarity index 65% rename from src/lib/mdns/DiscoveryManager.h rename to src/lib/mdns/Discovery_ImplPlatform.h index 2b83e1438de7a5..de0c8758bbe8f3 100644 --- a/src/lib/mdns/DiscoveryManager.h +++ b/src/lib/mdns/Discovery_ImplPlatform.h @@ -19,6 +19,7 @@ #include "core/CHIPError.h" #include "inet/InetInterface.h" +#include "lib/mdns/Advertiser.h" #include "lib/mdns/platform/Mdns.h" #include "platform/CHIPDeviceConfig.h" @@ -32,7 +33,7 @@ class ResolveDelegate virtual ~ResolveDelegate() {} }; -class DiscoveryManager +class DiscoveryImplPlatform : public ServiceAdvertiser { public: /** @@ -41,19 +42,13 @@ class DiscoveryManager */ CHIP_ERROR Init(); - /** - * This method publishes the device on mDNS. - * - * This function will fetch device name and other information and publish them - * via mDNS. If device meta data has changed, you can call this function again - * to update the information. - * - * @param[in] addressType The protocol version of the IP address. - * @param[in] interface The interface to send mDNS multicast. - * - */ - CHIP_ERROR StartPublishDevice(chip::Inet::IPAddressType addressType = chip::Inet::kIPAddressType_Any, - chip::Inet::InterfaceId interface = INET_NULL_INTERFACEID); + CHIP_ERROR Start(Inet::InetLayer * inetLayer, uint16_t port) override; + + /// Advertises the CHIP node as an operational node + CHIP_ERROR Advertise(const OperationalAdvertisingParameters & params) override; + + /// Advertises the CHIP node as a commisioning node + CHIP_ERROR Advertise(const CommisioningAdvertisingParameters & params) override; /** * This function stops publishing the device on mDNS. @@ -73,13 +68,13 @@ class DiscoveryManager */ CHIP_ERROR ResolveNodeId(uint64_t nodeId, uint64_t fabricId, chip::Inet::IPAddressType type = chip::Inet::kIPAddressType_Any); - static DiscoveryManager & GetInstance() { return sManager; } + static DiscoveryImplPlatform & GetInstance() { return sManager; } private: - DiscoveryManager() = default; + DiscoveryImplPlatform(); - DiscoveryManager(const DiscoveryManager &) = delete; - DiscoveryManager & operator=(const DiscoveryManager &) = delete; + DiscoveryImplPlatform(const DiscoveryImplPlatform &) = delete; + DiscoveryImplPlatform & operator=(const DiscoveryImplPlatform &) = delete; CHIP_ERROR PublishUnprovisionedDevice(chip::Inet::IPAddressType addressType, chip::Inet::InterfaceId interface); CHIP_ERROR PublishProvisionedDevice(chip::Inet::IPAddressType addressType, chip::Inet::InterfaceId interface); @@ -89,15 +84,16 @@ class DiscoveryManager static void HandleMdnsInit(void * context, CHIP_ERROR initError); static void HandleMdnsError(void * context, CHIP_ERROR initError); -#if CHIP_ENABLE_MDNS - uint64_t mUnprovisionedInstanceName; - bool mMdnsInitialized = false; - bool mIsPublishingProvisionedDevice = false; - bool mIsPublishing = false; -#endif // CHIP_ENABLE_MDNS + OperationalAdvertisingParameters mOperationalAdvertisingParams; + bool mIsOperationalPublishing = false; + uint64_t mCommissionInstanceName; + CommisioningAdvertisingParameters mCommissioningdvertisingParams; + bool mIsCommissionalPublishing = false; + + bool mMdnsInitialized = false; ResolveDelegate * mResolveDelegate = nullptr; - static DiscoveryManager sManager; + static DiscoveryImplPlatform sManager; }; } // namespace Mdns diff --git a/src/lib/mdns/minimal/QueryBuilder.h b/src/lib/mdns/minimal/QueryBuilder.h index b269f4d3165399..3abac57cbfc0aa 100644 --- a/src/lib/mdns/minimal/QueryBuilder.h +++ b/src/lib/mdns/minimal/QueryBuilder.h @@ -28,8 +28,13 @@ namespace Minimal { class QueryBuilder { public: - QueryBuilder(chip::System::PacketBuffer * packet) : mPacket(packet), mHeader(mPacket->Start()) + QueryBuilder() : mHeader(nullptr) {} + QueryBuilder(chip::System::PacketBufferHandle && packet) : mHeader(nullptr) { Reset(std::move(packet)); } + + QueryBuilder & Reset(chip::System::PacketBufferHandle && packet) { + mPacket = std::move(packet); + mHeader = HeaderRef(mPacket->Start()); if (mPacket->AvailableDataLength() >= HeaderRef::kSizeBytes) { @@ -38,17 +43,26 @@ class QueryBuilder } else { - mQueryBuidOk = false; + mQueryBuildOk = false; } mHeader.SetFlags(mHeader.GetFlags().SetQuery()); + return *this; + } + + CHECK_RETURN_VALUE + chip::System::PacketBufferHandle && ReleasePacket() + { + mHeader = HeaderRef(nullptr); + mQueryBuildOk = false; + return std::move(mPacket); } HeaderRef & Header() { return mHeader; } QueryBuilder & AddQuery(const Query & query) { - if (!mQueryBuidOk) + if (!mQueryBuildOk) { return *this; } @@ -57,7 +71,7 @@ class QueryBuilder if (!query.Append(mHeader, out)) { - mQueryBuidOk = false; + mQueryBuildOk = false; } else { @@ -66,12 +80,12 @@ class QueryBuilder return *this; } - bool Ok() const { return mQueryBuidOk; } + bool Ok() const { return mQueryBuildOk; } private: - chip::System::PacketBuffer * mPacket; + chip::System::PacketBufferHandle mPacket; HeaderRef mHeader; - bool mQueryBuidOk = true; + bool mQueryBuildOk = true; }; } // namespace Minimal diff --git a/src/lib/mdns/minimal/ResponseBuilder.h b/src/lib/mdns/minimal/ResponseBuilder.h index e583b703e9d862..cfa563c3bcb847 100644 --- a/src/lib/mdns/minimal/ResponseBuilder.h +++ b/src/lib/mdns/minimal/ResponseBuilder.h @@ -53,7 +53,7 @@ class ResponseBuilder } CHECK_RETURN_VALUE - chip::System::PacketBufferHandle && ReleasePacket() + chip::System::PacketBufferHandle ReleasePacket() { mHeader = HeaderRef(nullptr); mBuildOk = false; diff --git a/src/lib/mdns/minimal/Server.cpp b/src/lib/mdns/minimal/Server.cpp index 453a3f1510da03..d0ab63d64138c8 100644 --- a/src/lib/mdns/minimal/Server.cpp +++ b/src/lib/mdns/minimal/Server.cpp @@ -18,6 +18,7 @@ #include "Server.h" #include +#include #include @@ -150,13 +151,13 @@ CHIP_ERROR ServerBase::DirectSend(chip::System::PacketBufferHandle && data, cons continue; } - return info->udp->SendTo(addr, port, data.Release_ForNow()); + return info->udp->SendTo(addr, port, std::move(data)); } return CHIP_ERROR_NOT_CONNECTED; } -CHIP_ERROR ServerBase::BroadcastSend(chip::System::PacketBufferHandle && data, uint16_t port, chip::Inet::InterfaceId interface) +CHIP_ERROR ServerBase::BroadcastSend(chip::System::PacketBufferHandle data, uint16_t port, chip::Inet::InterfaceId interface) { for (size_t i = 0; i < mEndpointCount; i++) { @@ -172,19 +173,23 @@ CHIP_ERROR ServerBase::BroadcastSend(chip::System::PacketBufferHandle && data, u continue; } - // data may be sent over multiple packets. Keep the one ref active all the time - chip::System::PacketBufferHandle extraCopy = data.Retain(); - CHIP_ERROR err; + /// The same packet needs to be sent over potentially multiple interfaces. + /// LWIP does not like having a pbuf sent over serparate interfaces, hence we create a copy + /// TODO: this wastes one copy of the data and that could be optimized away + chip::System::PacketBufferHandle copy = data.CloneData(); + if (info->addressType == chip::Inet::kIPAddressType_IPv6) { - err = info->udp->SendTo(kBroadcastIp.ipv6, port, info->udp->GetBoundInterface(), extraCopy.Release_ForNow()); + err = info->udp->SendTo(kBroadcastIp.ipv6, port, info->udp->GetBoundInterface(), std::move(copy)); } +#if INET_CONFIG_ENABLE_IPV4 else if (info->addressType == chip::Inet::kIPAddressType_IPv4) { - err = info->udp->SendTo(kBroadcastIp.ipv4, port, info->udp->GetBoundInterface(), extraCopy.Release_ForNow()); + err = info->udp->SendTo(kBroadcastIp.ipv4, port, info->udp->GetBoundInterface(), std::move(copy)); } +#endif else { return CHIP_ERROR_INCORRECT_STATE; @@ -199,7 +204,7 @@ CHIP_ERROR ServerBase::BroadcastSend(chip::System::PacketBufferHandle && data, u return CHIP_NO_ERROR; } -CHIP_ERROR ServerBase::BroadcastSend(chip::System::PacketBuffer * data, uint16_t port) +CHIP_ERROR ServerBase::BroadcastSend(chip::System::PacketBufferHandle data, uint16_t port) { for (size_t i = 0; i < mEndpointCount; i++) { @@ -210,24 +215,25 @@ CHIP_ERROR ServerBase::BroadcastSend(chip::System::PacketBuffer * data, uint16_t continue; } - // data may be sent over multiple packets. Keep the one ref active all the time - data->AddRef(); - CHIP_ERROR err; + /// The same packet needs to be sent over potentially multiple interfaces. + /// LWIP does not like having a pbuf sent over serparate interfaces, hence we create a copy + /// TODO: this wastes one copy of the data and that could be optimized away + chip::System::PacketBufferHandle copy = data.CloneData(); + if (info->addressType == chip::Inet::kIPAddressType_IPv6) { - err = info->udp->SendTo(kBroadcastIp.ipv6, port, info->udp->GetBoundInterface(), data); + err = info->udp->SendTo(kBroadcastIp.ipv6, port, info->udp->GetBoundInterface(), std::move(copy)); } +#if INET_CONFIG_ENABLE_IPV4 else if (info->addressType == chip::Inet::kIPAddressType_IPv4) { - err = info->udp->SendTo(kBroadcastIp.ipv4, port, info->udp->GetBoundInterface(), data); + err = info->udp->SendTo(kBroadcastIp.ipv4, port, info->udp->GetBoundInterface(), std::move(copy)); } +#endif else { - // remove extra ref and then also clear it - chip::System::PacketBuffer::Free(data); - chip::System::PacketBuffer::Free(data); return CHIP_ERROR_INCORRECT_STATE; } @@ -240,12 +246,10 @@ CHIP_ERROR ServerBase::BroadcastSend(chip::System::PacketBuffer * data, uint16_t } else if (err != CHIP_NO_ERROR) { - chip::System::PacketBuffer::Free(data); return err; } } - chip::System::PacketBuffer::Free(data); return CHIP_NO_ERROR; } diff --git a/src/lib/mdns/minimal/Server.h b/src/lib/mdns/minimal/Server.h index e5e1dd73e3f07e..e1e66ecce0ddb5 100644 --- a/src/lib/mdns/minimal/Server.h +++ b/src/lib/mdns/minimal/Server.h @@ -95,10 +95,10 @@ class ServerBase chip::Inet::InterfaceId interface); /// Send a specific packet broadcast to all interfaces - CHIP_ERROR BroadcastSend(chip::System::PacketBuffer * data, uint16_t port); + CHIP_ERROR BroadcastSend(chip::System::PacketBufferHandle data, uint16_t port); /// Send a specific packet broadcast to a specific interface - CHIP_ERROR BroadcastSend(chip::System::PacketBufferHandle && data, uint16_t port, chip::Inet::InterfaceId interface); + CHIP_ERROR BroadcastSend(chip::System::PacketBufferHandle data, uint16_t port, chip::Inet::InterfaceId interface); ServerBase & SetDelegate(ServerDelegate * d) { diff --git a/src/lib/mdns/minimal/core/FlatAllocatedQName.h b/src/lib/mdns/minimal/core/FlatAllocatedQName.h new file mode 100644 index 00000000000000..0af2829761683f --- /dev/null +++ b/src/lib/mdns/minimal/core/FlatAllocatedQName.h @@ -0,0 +1,93 @@ +/* + * + * 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. + */ + +#pragma once + +#include "QName.h" + +namespace mdns { +namespace Minimal { + +/// A void* implementation that stores QNames as +/// [ptr array] [name1] #0 [name2] #0 .... [namen] #0 +/// +/// Usage: +/// - RequiredStorageSize("some", "name", "here") provides the memory block +/// - Build(ptr, "some", "name", "here") stores all data in [ptr] +/// +namespace FlatAllocatedQName { + +inline size_t RequiredStorageSize() +{ + return 0; +} + +/// Determines the memory size required to store the given qname parts. +/// +/// Example: +/// malloc(RequiredStorageSize("myhostname", "local")); +template +inline size_t RequiredStorageSize(QNamePart name, Args &&... rest) +{ + static_assert(CHAR_BIT == 8, "Assumption is that names can be stored in 1 byte"); + + // need to store a pointer entry in the array, the name and null terminator plus + // the rest of the data + return sizeof(QNamePart) + strlen(name) + 1 + RequiredStorageSize(std::forward(rest)...); +} + +namespace Internal { + +// nothing left to initialize +inline void Initialize(QNamePart * ptrLocation, char * nameLocation) {} + +template +inline void Initialize(QNamePart * ptrLocation, char * nameLocation, const char * name, Args &&... rest) +{ + *ptrLocation = nameLocation; + strcpy(nameLocation, name); + + Initialize(ptrLocation + 1, nameLocation + strlen(nameLocation) + 1, std::forward(rest)...); +} + +} // namespace Internal + +/// Builds a qname inside the given storage. +/// +/// storage MUST be aligned to hold pointers +/// +/// Example: +/// void * data = malloc(RequiredStorageSize("myhostname", "local")); +/// FullQName value = Build(data, "myhostname", "local"); +template +inline FullQName Build(void * storage, Args &&... args) +{ + QNamePart * names = reinterpret_cast(storage); + char * nameOut = reinterpret_cast(names + sizeof...(args)); + + Internal::Initialize(names, nameOut, std::forward(args)...); + + FullQName result; + result.names = names; + result.nameCount = sizeof...(args); + return result; +} + +} // namespace FlatAllocatedQName + +} // namespace Minimal +} // namespace mdns diff --git a/src/lib/mdns/minimal/core/tests/BUILD.gn b/src/lib/mdns/minimal/core/tests/BUILD.gn index c4ffa3d80dabdf..e1ea787680ae06 100644 --- a/src/lib/mdns/minimal/core/tests/BUILD.gn +++ b/src/lib/mdns/minimal/core/tests/BUILD.gn @@ -20,7 +20,10 @@ import("${chip_root}/build/chip/chip_test_suite.gni") chip_test_suite("tests") { output_name = "libMinimalMdnsCoreTests" - test_sources = [ "TestQName.cpp" ] + test_sources = [ + "TestFlatAllocatedQName.cpp", + "TestQName.cpp", + ] cflags = [ "-Wconversion" ] diff --git a/src/lib/mdns/minimal/core/tests/TestFlatAllocatedQName.cpp b/src/lib/mdns/minimal/core/tests/TestFlatAllocatedQName.cpp new file mode 100644 index 00000000000000..ca2c06b014a537 --- /dev/null +++ b/src/lib/mdns/minimal/core/tests/TestFlatAllocatedQName.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. + */ +#include +#include + +#include + +namespace { + +using namespace mdns::Minimal; + +class AutoFreeBuffer +{ +public: + AutoFreeBuffer(size_t n) { mBuffer = malloc(n); } + ~AutoFreeBuffer() { free(mBuffer); } + + AutoFreeBuffer(const AutoFreeBuffer &) = delete; + AutoFreeBuffer & operator=(const AutoFreeBuffer &) = delete; + + void * Buffer() { return mBuffer; } + +private: + void * mBuffer; +}; + +void TestFlatAllocatedQName(nlTestSuite * inSuite, void * inContext) +{ + AutoFreeBuffer buffer(128); + + NL_TEST_ASSERT(inSuite, FlatAllocatedQName::RequiredStorageSize("some", "test") == (sizeof(char * [2]) + 5 + 5)); + + { + FullQName built = FlatAllocatedQName::Build(buffer.Buffer(), "some", "test"); + const QNamePart expected[] = { "some", "test" }; + + NL_TEST_ASSERT(inSuite, FullQName(expected) == built); + } + + { + FullQName built = FlatAllocatedQName::Build(buffer.Buffer(), "1", "2", "3"); + const QNamePart expected[] = { "1", "2", "3" }; + + NL_TEST_ASSERT(inSuite, FullQName(expected) == built); + } +} + +const nlTest sTests[] = { + NL_TEST_DEF("TestFlatAllocatedQName", TestFlatAllocatedQName), // + NL_TEST_SENTINEL() // +}; + +} // namespace + +int TestFlatAllocatedQName(void) +{ + nlTestSuite theSuite = { "FlatAllocatedQName", sTests, nullptr, nullptr }; + nlTestRunner(&theSuite, nullptr); + return nlTestRunnerStats(&theSuite); +} + +CHIP_REGISTER_TEST_SUITE(TestFlatAllocatedQName) diff --git a/src/lib/mdns/minimal/records/ResourceRecord.h b/src/lib/mdns/minimal/records/ResourceRecord.h index 85d98bba1e449f..74ff2a980d5b28 100644 --- a/src/lib/mdns/minimal/records/ResourceRecord.h +++ b/src/lib/mdns/minimal/records/ResourceRecord.h @@ -35,6 +35,8 @@ class ResourceRecord virtual ~ResourceRecord() {} + ResourceRecord & operator=(const ResourceRecord & other) = default; + const FullQName & GetName() const { return mQName; } QClass GetClass() const { return QClass::IN; } QType GetType() const { return mType; } @@ -57,9 +59,9 @@ class ResourceRecord ResourceRecord(QType type, FullQName name) : mType(type), mQName(name) {} private: - const QType mType; + QType mType; uint64_t mTtl = kDefaultTtl; - const FullQName mQName; + FullQName mQName; }; } // namespace Minimal diff --git a/src/lib/mdns/minimal/records/Srv.h b/src/lib/mdns/minimal/records/Srv.h index 9b1dd51ca6833f..3dc7211cbb5ef3 100644 --- a/src/lib/mdns/minimal/records/Srv.h +++ b/src/lib/mdns/minimal/records/Srv.h @@ -28,6 +28,7 @@ class SrvResourceRecord : public ResourceRecord SrvResourceRecord(const FullQName & qName, const FullQName & serverName, uint16_t port) : ResourceRecord(QType::SRV, qName), mServerName(serverName), mPort(port) {} + SrvResourceRecord & operator=(const SrvResourceRecord & other) = default; FullQName GetServerName() const { return mServerName; } uint16_t GetPort() const { return mPort; } @@ -49,8 +50,8 @@ class SrvResourceRecord : public ResourceRecord } private: - const FullQName mServerName; - const uint16_t mPort; + FullQName mServerName; + uint16_t mPort; uint16_t mPriority = 0; uint16_t mWeight = 0; }; diff --git a/src/lib/mdns/minimal/records/Txt.h b/src/lib/mdns/minimal/records/Txt.h index 0a55cab94e10a5..7820c27a3c0cc3 100644 --- a/src/lib/mdns/minimal/records/Txt.h +++ b/src/lib/mdns/minimal/records/Txt.h @@ -42,6 +42,13 @@ class TxtResourceRecord : public ResourceRecord SetTtl(kDefaultTtl); } + // A FullQName is a holder of a string array. + TxtResourceRecord(const FullQName & qName, FullQName entries) : + ResourceRecord(QType::TXT, qName), mEntries(entries.names), mEntryCount(entries.nameCount) + { + SetTtl(kDefaultTtl); + } + protected: bool WriteData(chip::Encoding::BigEndian::BufferWriter & out) const override { @@ -60,7 +67,7 @@ class TxtResourceRecord : public ResourceRecord } private: - const char ** mEntries; + const char * const * mEntries; const size_t mEntryCount; }; diff --git a/src/lib/mdns/minimal/responders/Srv.h b/src/lib/mdns/minimal/responders/Srv.h index 876c1c62bbae35..3b6c350e955d69 100644 --- a/src/lib/mdns/minimal/responders/Srv.h +++ b/src/lib/mdns/minimal/responders/Srv.h @@ -26,7 +26,7 @@ namespace Minimal { class SrvResponder : public Responder { public: - SrvResponder(const FullQName & qname, const SrvResourceRecord & record) : Responder(QType::SRV, qname), mRecord(record) {} + SrvResponder(const SrvResourceRecord & record) : Responder(QType::SRV, record.GetName()), mRecord(record) {} void AddAllResponses(const chip::Inet::IPPacketInfo * source, ResponderDelegate * delegate) override { diff --git a/src/lib/mdns/platform/Mdns.h b/src/lib/mdns/platform/Mdns.h index 5cc154ed3c76b2..ad9e84c616c504 100644 --- a/src/lib/mdns/platform/Mdns.h +++ b/src/lib/mdns/platform/Mdns.h @@ -63,6 +63,8 @@ struct MdnsService chip::Inet::InterfaceId mInterface; TextEntry * mTextEntryies; size_t mTextEntrySize; + const char ** mSubTypes; + size_t mSubTypeSize; Optional mAddress; }; diff --git a/src/lib/protocols/common/CHIPMessage.h b/src/lib/protocols/common/CHIPMessage.h deleted file mode 100644 index 128a9a09615298..00000000000000 --- a/src/lib/protocols/common/CHIPMessage.h +++ /dev/null @@ -1,350 +0,0 @@ -/* - * - * Copyright (c) 2020 Project CHIP Authors - * Copyright (c) 2013-2017 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 - * This file defines macros and objects commonly used for the - * processing of CHIP messages. - * - */ - -#ifndef _CHIP_MESSAGE_H -#define _CHIP_MESSAGE_H - -#include -#include -#include -#include - -#include - -/* - * these macros are the guts of the packing and parsing stuff and they're used - * everywhere. - * - * here are the writers - * parameters: - * - PTR, a pointer into a buffer of type uint8_t - * - VAL, a value to write - */ -#define WRITEBYTE(PTR, VAL) \ - do \ - { \ - *(PTR)++ = (uint8_t)(VAL); \ - } while (0) - -#define WRITE16(PTR, VAL) \ - do \ - { \ - WRITEBYTE((PTR), ((VAL) >> 0)); \ - WRITEBYTE((PTR), ((VAL) >> 8)); \ - } while (0) - -#define WRITE32(PTR, VAL) \ - do \ - { \ - WRITEBYTE((PTR), ((VAL) >> 0)); \ - WRITEBYTE((PTR), ((VAL) >> 8)); \ - WRITEBYTE((PTR), ((VAL) >> 16)); \ - WRITEBYTE((PTR), ((VAL) >> 24)); \ - } while (0) - -/* - * and the readers - * parameter: PTR, a pointer into a buffer of type uint8_t - * value: the value read form the buffer - */ -#define READBYTE(PTR) (*(uint8_t *) (PTR)++) -/* - * parameters: - * - PTR, a pointer into a buffer of type uint8_t - * - DEST, where to put what's read from *p - */ -#define READ16(PTR, DEST) \ - do \ - { \ - uint16_t __byte0 = (uint16_t) READBYTE(PTR); \ - uint16_t __byte1 = (uint16_t) READBYTE(PTR); \ - DEST = __byte0 + (__byte1 << 8); \ - } while (0) - -#define READ32(PTR, DEST) \ - do \ - { \ - uint16_t __byte0 = (uint16_t) READBYTE(PTR); \ - uint16_t __byte1 = (uint16_t) READBYTE(PTR); \ - uint16_t __byte2 = (uint16_t) READBYTE(PTR); \ - uint16_t __byte3 = (uint16_t) READBYTE(PTR); \ - DEST = __byte0 + (__byte1 << 8) + (__byte2 << 16) + (__byte3 << 24); \ - } while (0) - -/* - * the message iterator class allows packet handling to operate in - * a regular manner, do a bit of work, check the result, get out if - * it's not good and so on. this results in a bunch of boilerplate - * code, which is captured here. - */ -#define TRY(OPERATION) \ - do \ - { \ - CHIP_ERROR e = (OPERATION); \ - if (e != CHIP_NO_ERROR) \ - return e; \ - } while (0) - -#define RESCUE(ERR, OPERATION, OUT) \ - do \ - { \ - ERR = (OPERATION); \ - if (ERR != CHIP_NO_ERROR) \ - goto OUT; \ - } while (0) - -namespace chip { - -namespace Protocols { - -/** - * @class RetainedPacketBuffer - * - * @brief - * This is a base class that serves as a convenience object for - * automatically reference counting a System::PacketBuffer. - * - */ -class DLL_EXPORT RetainedPacketBuffer -{ -public: - // Con/destructors - RetainedPacketBuffer(); - RetainedPacketBuffer(const RetainedPacketBuffer & aRetainedPacketBuffer); - ~RetainedPacketBuffer(); - - RetainedPacketBuffer & operator=(const RetainedPacketBuffer & aRetainedPacketBuffer); - - virtual bool IsRetaining() const; - - void Retain(System::PacketBuffer * aBuffer); - virtual void Release(); - - inline System::PacketBuffer * GetBuffer() { return (mBuffer); } - -protected: - System::PacketBuffer * mBuffer; ///< A pointer to the retained packet buffer. -}; - -/** - * In order to use message buffers sensibly, we define this iterator, - * which can be used to keep track of boundaries and so on. - */ -class DLL_EXPORT MessageIterator : public RetainedPacketBuffer -{ -public: - // constructor - MessageIterator(System::PacketBuffer *); - // reading and writing - CHIP_ERROR readByte(uint8_t *); - CHIP_ERROR read16(uint16_t *); - CHIP_ERROR read32(uint32_t *); - CHIP_ERROR read64(uint64_t *); - CHIP_ERROR readString(uint16_t, char *); - CHIP_ERROR readBytes(uint16_t, uint8_t *); - CHIP_ERROR writeByte(uint8_t); - CHIP_ERROR write16(uint16_t); - CHIP_ERROR write32(uint32_t); - CHIP_ERROR write64(uint64_t); - CHIP_ERROR writeString(uint16_t, char *); - CHIP_ERROR writeBytes(uint16_t, uint8_t *); - // standard iterator operations - MessageIterator & operator++(); - MessageIterator & operator+(uint16_t); - MessageIterator & operator-(uint16_t); - bool operator==(const MessageIterator &); - bool operator!=(const MessageIterator &); - uint8_t & operator*(); - void append(); - // size checking - bool hasData(uint16_t); - bool hasRoom(uint16_t); - // finishing - void finishWriting(); - // data members - uint8_t * thePoint; -}; -/** - * Here's how to handle strings in CHIP. This class has 8-bit - * and 16-bit variants. - */ -class DLL_EXPORT ReferencedString : public RetainedPacketBuffer -{ -public: - // constructor - ReferencedString(); - // initializers - CHIP_ERROR init(uint16_t aLength, char * aString, System::PacketBuffer * aBuffer); - CHIP_ERROR init(uint16_t aLength, char * aString); - CHIP_ERROR init(uint8_t aLength, char * aString, System::PacketBuffer * aBuffer); - CHIP_ERROR init(uint8_t aLength, char * aString); - // pack and parse - CHIP_ERROR pack(MessageIterator &); - static CHIP_ERROR parse(MessageIterator &, ReferencedString &); - // comparison - bool operator==(const ReferencedString &) const; - // print string generation (for testing) - char * printString(); - // data members - uint16_t theLength; - char * theString; - bool isShort; -}; -/** - * Similarly, we need to be able to represent a big old blob - * of TLV data. - */ -class DLL_EXPORT ReferencedTLVData : public RetainedPacketBuffer -{ -public: - /* - * under certain circumstances, e.g. when we don't want to blow out the - * stack by writing some big thing into it in preparation for sending - * a message with a referenced extent in it, we want to only write the - * bits AFTER we've obtained the outgoing buffer. we do that using one - * of these. - * - * NOTE!!! the handler set up below does NOT return an error and, in - * the case where one is supplied, the pack method will not return an - * error either. this means that the NHL-supplied handler MUST handler - * all errors that arise from the formatting of TLV. - * - * parameters: - * - TLVWriter&, a TLV writer to use to write things out - * - void*, a state object known to the application - */ - - typedef void (*TLVWriteCallback)(TLV::TLVWriter & aWriter, void * aAppState); - - // constructor - - ReferencedTLVData(); - - // initializers - - CHIP_ERROR init(System::PacketBuffer * aBuffer); - CHIP_ERROR init(MessageIterator & i); - CHIP_ERROR init(uint16_t aLength, uint16_t aMaxLength, uint8_t * aByteString); - CHIP_ERROR init(TLVWriteCallback aWriteCallback, void * anAppState); - - /* - * ReferencedTLVData needs to override the free() and isFree() - * methods because "freedom", in this case, is more than nothing - * left to lose. - */ - - void free(); - - bool isFree(); - - /** - * Check if a ReferencedTLVData object has anything in it. - * - * There are two possible ways such an object could "have" - * something. Either it could have 0 length OR it could have no - * write callback. - * - * @return true if the data set has 0 length or there's no write - * callback in hand, false otherwise. - */ - - inline bool isEmpty() { return (theLength == 0 && theWriteCallback == nullptr); } - - // packing and parsing - - /** - * @fn CHIP_ERROR ReferencedTLVData::pack(System::PacketBuffer *buff) - * - * @brief Pack a ReferencedTLVData object directly into a PacketBuffer - * - * @param [in] buff the buffer to fill. - * - * @return a CHIP_ERROR reflecting the success of the underlying - * pack call. - */ - - inline CHIP_ERROR pack(System::PacketBuffer * buff) - { - MessageIterator i(buff); - - return pack(i); - } - - CHIP_ERROR pack(MessageIterator & i, uint32_t maxLen = 0xFFFFFFFFUL); - - /** - * Return the data length assuming that the object has been packed - * into a buffer. - * - * @return the integer length of the packed data. - */ - - inline uint16_t packedLength() { return theLength; } - - /** - * @fn CHIP_ERROR parse(System::PacketBuffer *buff, ReferencedTLVData &aTarget) - * - * @brief Parse a ReferencedTLVData object from a supplied PacketBuffer - * - * Parse a ReferencedTLVData object out of an inet buffer - * (assuming it just contains TLV). - * - * @param [in] buff the buffer to read from. - * - * @param [out] aTarget a ReferencedTLVData object to "fill" with the result. - * - * @return a CHIP_ERROR reflecting the success of the underlying - * parse call. - */ - - static inline CHIP_ERROR parse(System::PacketBuffer * buff, ReferencedTLVData & aTarget) - { - MessageIterator i(buff); - - return parse(i, aTarget); - } - - static CHIP_ERROR parse(MessageIterator & i, ReferencedTLVData & aTarget); - - // comparison - - bool operator==(const ReferencedTLVData &) const; - - // data members - - uint16_t theLength; - uint16_t theMaxLength; - uint8_t * theData; - -private: - TLVWriteCallback theWriteCallback; - void * theAppState; -}; - -} // namespace Protocols -} // namespace chip - -#endif // _CHIP_MESSAGE_H diff --git a/src/lib/protocols/common/CommonProtocol.h b/src/lib/protocols/common/CommonProtocol.h deleted file mode 100644 index a81201dd42d312..00000000000000 --- a/src/lib/protocols/common/CommonProtocol.h +++ /dev/null @@ -1,126 +0,0 @@ -/* - * - * Copyright (c) 2020 Project CHIP Authors - * Copyright (c) 2013-2017 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 - * The defines constants for the CHIP Common Protocol, present in - * every CHIP device. - * - */ - -#ifndef _COMMON_PROTOCOL_H -#define _COMMON_PROTOCOL_H - -/** - * @namespace chip::Protocols::Common - * - * @brief - * This namespace includes all interfaces within CHIP for the - * CHIP Common profile. - * - * The interfaces define message types and status codes. - */ - -namespace chip { -namespace Protocols { -namespace Common { - -/** - * Common Profile Message Types - */ -enum -{ - kMsgType_StatusReport = 1, - kMsgType_Null = 2, - - // Reliable Messaging Protocol Message Types - kMsgType_RMP_Delayed_Delivery = 3, - kMsgType_RMP_Throttle_Flow = 4 -}; - -/** - * Common Protocol Status Codes - */ -enum -{ - kStatus_Success = 0, /**< The operation completed without error. */ - kStatus_Canceled = 1, /**< The operation was canceled. */ - kStatus_BadRequest = 0x0010, /**< The request was unrecognized or malformed. */ - kStatus_UnsupportedMessage = 0x0011, /**< An unrecognized or unsupported message was received. */ - kStatus_UnexpectedMessage = 0x0012, /**< A message was received at an unexpected time or in an unexpected context. */ - kStatus_AuthenticationRequired = 0x0013, /**< The request can only be made by an authenticated party. */ - kStatus_AccessDenied = 0x0014, /**< The request can only be made by a party with sufficient access. */ - kStatus_OutOfMemory = - 0x0017, /**< The sender is low on memory resources and cannot perform the requested operation at the current time. */ - kStatus_NotAvailable = 0x0018, /**< The requested operation cannot be performed given the current state of the sender. */ - kStatus_LocalSetupRequired = 0x0019, /**< The requested operation could not be performed because one or more necessary local - configuration steps have not been completed. */ - kStatus_InternalServerProblem = 0x0020, /**< Request could not be completeted because of problems on the server. */ - kStatus_Relocated = 0x0030, /**< Request was made to the wrong endpoint. Client should query its - directory server for an updated endpoint list and try again. */ - kStatus_Busy = 0x0040, /**< The sender is busy and cannot perform the requested operation at the current time. */ - kStatus_Timeout = 0x0041, /**< The operation or protocol interaction failed to complete in the allotted time. */ - kStatus_InternalError = 0x0050, /**< An internal failure prevented an operation from completing. */ - kStatus_Continue = 0x0090, /**< Context-specific signal to proceed. */ -}; - -/** - * Common Protocol MIME file type - */ -enum -{ - kMIMEType_AppOctetStream = 0x0000, /**< The most general unrestricted set of bytes, same as "unspecified." */ - kMIMEType_TextPlain = 0x0001, /**< Plain text, uncompressed. */ - kMIMEType_AppGzip = 0x0002, /**< gzip-compressed data. */ -}; - -/** - * @var kTag_SystemErrorCode - * @brief [uint] System-specific error. - * - * Tag Category: Protocol-specific. Constraints: none - * - * @var kTag_SchemaVersion - * @brief [uint] Schema revision. - * - * Tag Category: Protocol-specific. Constraints: 0-255 - * - * @var kTag_MIMEType - * @brief [uint] MIME type. - * - * Tag Category: Protocol-agnostic. Constraints: none - */ - -/** - * Common Protocol Data Tags - */ -enum -{ - // Value Tag Category Element Type Constraints Description - // ------------------------------------------------------------------------ - kTag_SystemErrorCode = 0x0001, // Protocol-specific Unsigned Integer - System-specific error - kTag_SchemaVersion = 0x0002, // Protocol-specific Unsigned Integer 0-255 Schema revision - kTag_MIMEType = 0x0004, // Protocol-agnostic Unsigned Integer - MIME type -}; - -} // namespace Common -} // namespace Protocols -} // namespace chip - -#endif // _COMMON_PROTOCOL_H diff --git a/src/lib/support/BitFlags.h b/src/lib/support/BitFlags.h index 00409fab730880..4d22b66c952b60 100644 --- a/src/lib/support/BitFlags.h +++ b/src/lib/support/BitFlags.h @@ -49,6 +49,8 @@ class BitFlags explicit BitFlags(FlagsEnum v) { Set(v); } + explicit BitFlags(StorageType value) { SetRaw(value); } + BitFlags & Set(FlagsEnum v) { mValue = static_cast(mValue | static_cast(v)); @@ -65,6 +67,8 @@ class BitFlags bool Has(FlagsEnum v) const { return (mValue & static_cast(v)) != 0; } + bool Has(StorageType other) const { return (mValue & other) == other; } + BitFlags & Set(const BitFlags & other) { mValue |= other.mValue; diff --git a/src/lib/support/CodeUtils.h b/src/lib/support/CodeUtils.h index 425e7d1ec7c830..30b731dc90cd81 100644 --- a/src/lib/support/CodeUtils.h +++ b/src/lib/support/CodeUtils.h @@ -403,7 +403,10 @@ inline void chipDie(void) #endif // defined(__cplusplus) && (__cplusplus >= 201103L) -#if defined(__GNUC__) && (__GNUC__ >= 4) +#if defined(__cplusplus) && \ + ((__cplusplus >= 201703L) || (defined(__GNUC__) && (__GNUC__ >= 7)) || (defined(__clang__)) && (__clang_major__ >= 4)) +#define CHECK_RETURN_VALUE [[nodiscard]] +#elif defined(__GNUC__) && (__GNUC__ >= 4) #define CHECK_RETURN_VALUE __attribute__((warn_unused_result)) #elif defined(_MSC_VER) && (_MSC_VER >= 1700) #define CHECK_RETURN_VALUE _Check_return_ diff --git a/src/lib/support/StringBuilder.h b/src/lib/support/StringBuilder.h new file mode 100644 index 00000000000000..bab9f2de5a300d --- /dev/null +++ b/src/lib/support/StringBuilder.h @@ -0,0 +1,86 @@ +/* + * + * 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. + */ + +#pragma once + +#include + +#include "BufferWriter.h" + +namespace chip { + +/// Build a c-style string out of distinct parts +class StringBuilderBase +{ +public: + StringBuilderBase(char * buffer, size_t size) : mWriter(reinterpret_cast(buffer), size - 1) + { + nlASSERT(size > 0); + buffer[0] = 0; // make c-str work by default + } + + /// Append a null terminated string + StringBuilderBase & Add(const char * s) + { + mWriter.Put(s); + NullTerminate(); + return *this; + } + + /// Append an integer value + StringBuilderBase & Add(int value) + { + char buff[32]; + snprintf(buff, sizeof(buff), "%d", value); + buff[sizeof(buff) - 1] = 0; + return Add(buff); + } + + /// did all the values fit? + bool Fit() const { return mWriter.Fit(); } + + /// access the underlying value + const char * c_str() const { return reinterpret_cast(mWriter.Buffer()); } + +private: + Encoding::LittleEndian::BufferWriter mWriter; + + void NullTerminate() + { + if (mWriter.Fit()) + { + mWriter.Buffer()[mWriter.Needed()] = 0; + } + else + { + mWriter.Buffer()[mWriter.Size()] = 0; + } + } +}; + +/// a preallocated sized string builder +template +class StringBuilder : public StringBuilderBase +{ +public: + StringBuilder() : StringBuilderBase(mBuffer, kSize) {} + +private: + char mBuffer[kSize]; +}; + +} // namespace chip diff --git a/src/lib/support/tests/BUILD.gn b/src/lib/support/tests/BUILD.gn index b644042e0e707b..3f31e469663220 100644 --- a/src/lib/support/tests/BUILD.gn +++ b/src/lib/support/tests/BUILD.gn @@ -32,6 +32,7 @@ chip_test_suite("tests") { "TestSafeInt.cpp", "TestScopedBuffer.cpp", "TestSerializableIntegerSet.cpp", + "TestStringBuilder.cpp", "TestTimeUtils.cpp", ] sources = [] diff --git a/src/lib/support/tests/TestStringBuilder.cpp b/src/lib/support/tests/TestStringBuilder.cpp new file mode 100644 index 00000000000000..5fa0a95492f535 --- /dev/null +++ b/src/lib/support/tests/TestStringBuilder.cpp @@ -0,0 +1,97 @@ +/* + * + * 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 + +namespace { + +using namespace chip; + +void TestStringBuilder(nlTestSuite * inSuite, void * inContext) +{ + + StringBuilder<64> builder; + + NL_TEST_ASSERT(inSuite, builder.Fit()); + NL_TEST_ASSERT(inSuite, strcmp(builder.c_str(), "") == 0); + + builder.Add("foo"); + NL_TEST_ASSERT(inSuite, builder.Fit()); + NL_TEST_ASSERT(inSuite, strcmp(builder.c_str(), "foo") == 0); + + builder.Add("bar"); + NL_TEST_ASSERT(inSuite, builder.Fit()); + NL_TEST_ASSERT(inSuite, strcmp(builder.c_str(), "foobar") == 0); +} + +void TestIntegerAppend(nlTestSuite * inSuite, void * inContext) +{ + + StringBuilder<64> builder; + + builder.Add("nr: ").Add(1234); + NL_TEST_ASSERT(inSuite, builder.Fit()); + NL_TEST_ASSERT(inSuite, strcmp(builder.c_str(), "nr: 1234") == 0); + + builder.Add(", ").Add(-22); + NL_TEST_ASSERT(inSuite, builder.Fit()); + NL_TEST_ASSERT(inSuite, strcmp(builder.c_str(), "nr: 1234, -22") == 0); +} + +void TestOverflow(nlTestSuite * inSuite, void * inContext) +{ + + { + StringBuilder<4> builder; + + builder.Add("foo"); + NL_TEST_ASSERT(inSuite, builder.Fit()); + NL_TEST_ASSERT(inSuite, strcmp(builder.c_str(), "foo") == 0); + + builder.Add("bar"); + NL_TEST_ASSERT(inSuite, !builder.Fit()); + NL_TEST_ASSERT(inSuite, strcmp(builder.c_str(), "foo") == 0); + } + + { + StringBuilder<7> builder; + + builder.Add("x: ").Add(12345); + NL_TEST_ASSERT(inSuite, !builder.Fit()); + NL_TEST_ASSERT(inSuite, strcmp(builder.c_str(), "x: 123") == 0); + } +} + +const nlTest sTests[] = { + NL_TEST_DEF("TestStringBuilder", TestStringBuilder), // + NL_TEST_DEF("TestIntegerAppend", TestIntegerAppend), // + NL_TEST_DEF("TestOverflow", TestOverflow), // + NL_TEST_SENTINEL() // +}; + +} // namespace + +int TestStringBuilder(void) +{ + nlTestSuite theSuite = { "StringBuilder", sTests, nullptr, nullptr }; + nlTestRunner(&theSuite, nullptr); + return nlTestRunnerStats(&theSuite); +} + +CHIP_REGISTER_TEST_SUITE(TestStringBuilder) diff --git a/src/lwip/BUILD.gn b/src/lwip/BUILD.gn index 40fa3eae7712a7..13b97c1c4d553d 100644 --- a/src/lwip/BUILD.gn +++ b/src/lwip/BUILD.gn @@ -28,8 +28,8 @@ if (lwip_platform == "") { } assert(lwip_platform == "external" || lwip_platform == "standalone" || - lwip_platform == "efr32" || lwip_platform == "k32w" || - lwip_platform == "qpg6100", + lwip_platform == "cc13x2_26x2" || lwip_platform == "efr32" || + lwip_platform == "k32w" || lwip_platform == "qpg6100", "Unsupported lwIP platform: ${lwip_platform}") if (lwip_platform != "external") { @@ -39,7 +39,9 @@ if (lwip_platform != "external") { } } -if (lwip_platform == "efr32") { +if (lwip_platform == "cc13x2_26x2") { + import("//build_overrides/ti_simplelink_sdk.gni") +} else if (lwip_platform == "efr32") { import("//build_overrides/efr32_sdk.gni") } else if (lwip_platform == "qpg6100") { import("//build_overrides/qpg6100_sdk.gni") @@ -105,7 +107,9 @@ if (current_os == "zephyr") { } public_deps = [ ":lwip_buildconfig" ] - if (lwip_platform == "efr32") { + if (lwip_platform == "cc13x2_26x2") { + public_deps += [ "${ti_simplelink_sdk_build_root}:ti_simplelink_sdk" ] + } else if (lwip_platform == "efr32") { public_deps += [ "${efr32_sdk_build_root}:efr32_sdk" ] } else if (lwip_platform == "qpg6100") { public_deps += [ "${qpg6100_sdk_build_root}:qpg6100_sdk" ] diff --git a/src/lwip/cc13x2_26x2/arch/cc.h b/src/lwip/cc13x2_26x2/arch/cc.h new file mode 100644 index 00000000000000..2803d6d77e7c94 --- /dev/null +++ b/src/lwip/cc13x2_26x2/arch/cc.h @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2020 Project CHIP Authors + * Copyright (c) 2018-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. + */ + +/* + * + * Description: + * This file defines processor-architecture- and toolchain- + * specific constants and types required for building + * LwIP against FreeRTOS. + * + */ + +#ifndef CHIP_LWIP_FREERTOS_ARCH_CC_H +#define CHIP_LWIP_FREERTOS_ARCH_CC_H + +#include +#include +#include +#include +#include +#include + +#include + +//#include "app_error.h" + +#if __cplusplus +extern "C" { +#endif + +#ifndef LWIP_NOASSERT +#ifdef DEBUG +#define LWIP_PLATFORM_ASSERT(MSG) assert(0) +#else +#define LWIP_PLATFORM_ASSERT(MSG) assert(0) +#endif +#else +#define LWIP_PLATFORM_ASSERT(message) +#endif + +#ifndef BYTE_ORDER +#if defined(__LITTLE_ENDIAN__) +#define BYTE_ORDER LITTLE_ENDIAN +#elif defined(__BIG_ENDIAN__) +#define BYTE_ORDER BIG_ENDIAN +#elif defined(__BYTE_ORDER__) +#define BYTE_ORDER __BYTE_ORDER__ +#endif +#endif // BYTE_ORDER + +#define PACK_STRUCT_STRUCT __attribute__((__packed__)) +#define PACK_STRUCT_FIELD(x) x + +extern void LwIPLog(const char * fmt, ...); +#define LWIP_PLATFORM_DIAG(x) \ + do \ + { \ + LwIPLog x; \ + } while (0) + +// Place LwIP pools into their own subsections of .bss to make it easier to see +// their sizes in the linker map file. +extern uint8_t __attribute__((section(".bss.lwip_ND6_QUEUE"))) memp_memory_ND6_QUEUE_base[]; +extern uint8_t __attribute__((section(".bss.lwip_IP6_REASSDATA"))) memp_memory_IP6_REASSDATA_base[]; +extern uint8_t __attribute__((section(".bss.lwip_RAW_PCB"))) memp_memory_RAW_PCB_base[]; +extern uint8_t __attribute__((section(".bss.lwip_TCP_SEG"))) memp_memory_TCP_SEG_base[]; +extern uint8_t __attribute__((section(".bss.lwip_PBUF_POOL"))) memp_memory_PBUF_POOL_base[]; +extern uint8_t __attribute__((section(".bss.lwip_FRAG_PBUF"))) memp_memory_FRAG_PBUF_base[]; +extern uint8_t __attribute__((section(".bss.lwip_PBUF"))) memp_memory_PBUF_base[]; +extern uint8_t __attribute__((section(".bss.lwip_TCP_PCB_LISTEN"))) memp_memory_TCP_PCB_LISTEN_base[]; +extern uint8_t __attribute__((section(".bss.lwip_REASSDATA"))) memp_memory_REASSDATA_base[]; +extern uint8_t __attribute__((section(".bss.lwip_UDP_PCB"))) memp_memory_UDP_PCB_base[]; +extern uint8_t __attribute__((section(".bss.lwip_MLD6_GROUP"))) memp_memory_MLD6_GROUP_base[]; +extern uint8_t __attribute__((section(".bss.lwip_IGMP_GROUP"))) memp_memory_IGMP_GROUP_base[]; +extern uint8_t __attribute__((section(".bss.lwip_TCP_PCB"))) memp_memory_TCP_PCB_base[]; +extern uint8_t __attribute__((section(".bss.lwip_SYS_TIMEOUT"))) memp_memory_SYS_TIMEOUT_base[]; + +#if __cplusplus +} +#endif + +#endif /* CHIP_LWIP_FREERTOS_ARCH_CC_H */ diff --git a/src/lwip/cc13x2_26x2/arch/perf.h b/src/lwip/cc13x2_26x2/arch/perf.h new file mode 100644 index 00000000000000..5c15942730ca8f --- /dev/null +++ b/src/lwip/cc13x2_26x2/arch/perf.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2020 Project CHIP Authors + * Copyright (c) 2018-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. + */ + +/* + * + * Description: + * This file defines processor-architecture-specific constants, + * interfaces and types required for LwIP performance + * measurement. + * + */ + +#ifndef CHIP_LWIP_FREERTOS_ARCH_PERF_H +#define CHIP_LWIP_FREERTOS_ARCH_PERF_H + +#define PERF_START +#define PERF_STOP(s) + +#endif /* CHIP_LWIP_FREERTOS_ARCH_PERF_H */ diff --git a/src/lwip/cc13x2_26x2/lwipopts.h b/src/lwip/cc13x2_26x2/lwipopts.h new file mode 100644 index 00000000000000..4c0d703603a5b4 --- /dev/null +++ b/src/lwip/cc13x2_26x2/lwipopts.h @@ -0,0 +1,169 @@ +/* + * + * Copyright (c) 2020 Project CHIP Authors + * Copyright (c) 2018 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. + */ + +#ifndef __LWIPOPTS_H__ +#define __LWIPOPTS_H__ + +#if CHIP_HAVE_CONFIG_H +#include +#endif + +#include + +// disable static tasks because the call to `xTaskCreateStatic` in +// `src/lwip/freertos/sys_arch.c` is wrong and passes a NULL for the TCB area +#define LWIP_FREERTOS_USE_STATIC_TCPIP_TASK 0 + +#define NO_SYS 0 +#define MEM_ALIGNMENT (4) +#define MEMP_NUM_TCP_SEG (TCP_SND_QUEUELEN + 1) +#define LWIP_TIMEVAL_PRIVATE (0) +#define MEM_LIBC_MALLOC (0) +#define LWIP_COMPAT_MUTEX (0) +#define SYS_LIGHTWEIGHT_PROT (1) +#define LWIP_AUTOIP (0) +#define LWIP_DHCP_AUTOIP_COOP (0) +#define LWIP_SOCKET_SET_ERRNO 0 +#define IP_REASS_MAX_PBUFS 0 +#define IP_REASSEMBLY 0 +#define MEMP_NUM_REASSDATA 0 +#define LWIP_SO_RCVTIMEO 0 +#define SO_REUSE (1) +#define LWIP_RANDOMIZE_INITIAL_LOCAL_PORTS (1) +#define LWIP_STATS (0) +#define LWIP_TCPIP_CORE_LOCKING 1 +#define TCP_QUEUE_OOSEQ 0 +#define ARP_QUEUEING (0) +#define TCPIP_THREAD_NAME "LWIP" + +#define LWIP_SOCKET 0 + +#define LWIP_RAW 1 +#define MEMP_NUM_RAW_PCB (5) + +#define MEMP_NUM_UDP_PCB (7) + +#define LWIP_HAVE_LOOPIF (0) + +#define LWIP_NETIF_LOOPBACK (0) + +#define MEMP_NUM_NETCONN (0) + +#define LWIP_IPV4 0 +#define LWIP_IPV6 1 +#define LWIP_ARP (0) +#define LWIP_DNS (0) +#define LWIP_ICMP (0) +#define LWIP_IGMP (0) +#define LWIP_DHCP (0) +#define LWIP_IPV6_REASS (0) +#define LWIP_IPV6_DHCP6 0 +#define LWIP_IPV6_AUTOCONFIG (0) +#define LWIP_IPV6_ROUTER_SUPPORT 0 +#define LWIP_ND6_LISTEN_RA 0 + +#define LWIP_ND6_NUM_NEIGHBORS (0) +#define LWIP_ND6_NUM_DESTINATIONS (0) +#define LWIP_ND6_NUM_PREFIXES (0) +#define LWIP_ND6_NUM_ROUTERS (0) +#define LWIP_ND6_MAX_MULTICAST_SOLICIT (0) +#define LWIP_ND6_MAX_UNICAST_SOLICIT (0) +#define LWIP_ND6_MAX_NEIGHBOR_ADVERTISEMENT (0) +#define LWIP_ND6_TCP_REACHABILITY_HINTS (0) + +#define MEMP_SEPARATE_POOLS (1) +#define LWIP_PBUF_FROM_CUSTOM_POOLS (0) +#define MEMP_USE_CUSTOM_POOLS (0) +#define PBUF_POOL_SIZE (4) +#define PBUF_POOL_BUFSIZE (1500) +#define PBUF_POOL_SIZE_LARGE (1) +#define PBUF_POOL_SIZE_MEDIUM (2) +#define PBUF_POOL_SIZE_SMALL (2) +#define PBUF_POOL_BUFSIZE_LARGE (1280) +#define PBUF_POOL_BUFSIZE_MEDIUM (640) +#define PBUF_POOL_BUFSIZE_SMALL (256) +#define PBUF_CUSTOM_POOL_IDX_START (MEMP_PBUF_POOL_SMALL) +#define PBUF_CUSTOM_POOL_IDX_END (MEMP_PBUF_POOL_LARGE) + +#define TCP_MSS (1152) +#define TCP_SND_BUF (2 * TCP_MSS) +#define TCP_LISTEN_BACKLOG (1) + +#define ETH_PAD_SIZE (0) +#define SUB_ETHERNET_HEADER_SPACE (0) +#define PBUF_LINK_HLEN (0) + +// 2 k byte stack +#define TCPIP_THREAD_STACKSIZE (0x800) // uint32_t +#define TCPIP_THREAD_PRIO (2) + +#define NETIF_MAX_HWADDR_LEN 8U + +#define LWIP_IPV6_NUM_ADDRESSES 5 + +#define LWIP_IPV6_ND 0 +#define LWIP_ND6_QUEUEING 0 + +#define LWIP_MULTICAST_PING 0 + +#define TCPIP_MBOX_SIZE 6 +#define DEFAULT_RAW_RECVMBOX_SIZE 6 +#define DEFAULT_UDP_RECVMBOX_SIZE 6 +#define DEFAULT_TCP_RECVMBOX_SIZE 6 + +// TODO: make LWIP_DEBUG conditional on build type + +#ifndef LWIP_DEBUG +#define LWIP_DEBUG 1 +#endif + +#define MEMP_OVERFLOW_CHECK (0) +#define MEMP_SANITY_CHECK (0) +#define MEM_DEBUG (LWIP_DBG_OFF) +#define MEMP_DEBUG (LWIP_DBG_OFF) +#define PBUF_DEBUG (LWIP_DBG_OFF) +#define API_LIB_DEBUG (LWIP_DBG_OFF) +#define API_MSG_DEBUG (LWIP_DBG_OFF) +#define TCPIP_DEBUG (LWIP_DBG_OFF) +#define NETIF_DEBUG (LWIP_DBG_OFF) +#define SOCKETS_DEBUG (LWIP_DBG_OFF) +#define DEMO_DEBUG (LWIP_DBG_OFF) +#define DHCP_DEBUG (LWIP_DBG_OFF) +#define AUTOIP_DEBUG (LWIP_DBG_OFF) +#define ETHARP_DEBUG (LWIP_DBG_OFF) +#define IP_DEBUG (LWIP_DBG_OFF) +#define IP_REASS_DEBUG (LWIP_DBG_OFF) +#define IP6_DEBUG (LWIP_DBG_OFF) +#define RAW_DEBUG (LWIP_DBG_OFF) +#define ICMP_DEBUG (LWIP_DBG_OFF) +#define UDP_DEBUG (LWIP_DBG_OFF) +#define TCP_DEBUG (LWIP_DBG_OFF) +#define TCP_INPUT_DEBUG (LWIP_DBG_OFF) +#define TCP_OUTPUT_DEBUG (LWIP_DBG_OFF) +#define TCP_RTO_DEBUG (LWIP_DBG_OFF) +#define TCP_CWND_DEBUG (LWIP_DBG_OFF) +#define TCP_WND_DEBUG (LWIP_DBG_OFF) +#define TCP_FR_DEBUG (LWIP_DBG_OFF) +#define TCP_QLEN_DEBUG (LWIP_DBG_OFF) +#define TCP_RST_DEBUG (LWIP_DBG_OFF) +#define PPP_DEBUG (LWIP_DBG_OFF) + +#define LWIP_DBG_TYPES_ON \ + (LWIP_DBG_ON | LWIP_DBG_TRACE) /* (LWIP_DBG_ON|LWIP_DBG_TRACE|LWIP_DBG_STATE|LWIP_DBG_FRESH|LWIP_DBG_HALT) */ + +#endif /* __LWIPOPTS_H__ */ diff --git a/src/lwip/cc13x2_26x2/lwippools.h b/src/lwip/cc13x2_26x2/lwippools.h new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/src/lwip/qpg6100/lwipopts.h b/src/lwip/qpg6100/lwipopts.h index 7a3aaaf3f06bb1..a5e6f20b31cca3 100644 --- a/src/lwip/qpg6100/lwipopts.h +++ b/src/lwip/qpg6100/lwipopts.h @@ -47,7 +47,6 @@ #define LWIP_TCPIP_CORE_LOCKING 1 #define TCP_QUEUE_OOSEQ 0 #define ARP_QUEUEING (0) -#define TCPIP_THREAD_NAME "LWIP" #define LWIP_SOCKET 0 diff --git a/src/messaging/ExchangeContext.cpp b/src/messaging/ExchangeContext.cpp index 4390c062cba0ba..c09160635653c8 100644 --- a/src/messaging/ExchangeContext.cpp +++ b/src/messaging/ExchangeContext.cpp @@ -37,6 +37,7 @@ #include #include #include +#include #include #include @@ -69,11 +70,17 @@ void ExchangeContext::SetResponseExpected(bool inResponseExpected) mFlags.Set(ExFlagValues::kFlagResponseExpected, inResponseExpected); } +void ExchangeContext::SetResponseTimeout(Timeout timeout) +{ + mResponseTimeout = timeout; +} + CHIP_ERROR ExchangeContext::SendMessage(uint16_t protocolId, uint8_t msgType, PacketBufferHandle msgBuf, const SendFlags & sendFlags, void * msgCtxt) { CHIP_ERROR err = CHIP_NO_ERROR; PayloadHeader payloadHeader; + Transport::PeerConnectionState * state = nullptr; // Don't let method get called on a freed object. VerifyOrDie(mExchangeMgr != nullptr && GetReferenceCount() > 0); @@ -92,8 +99,34 @@ CHIP_ERROR ExchangeContext::SendMessage(uint16_t protocolId, uint8_t msgType, Pa // Set the message type for this header. payloadHeader.SetMessageType(msgType); + payloadHeader.SetInitiator(IsInitiator()); + + // If sending via UDP and auto-request ACK feature is enabled, automatically request an acknowledgment, + // UNLESS the NoAutoRequestAck send flag has been specified. + state = mExchangeMgr->GetSessionMgr()->GetPeerConnectionState(mSecureSession); + VerifyOrExit(state != nullptr, err = CHIP_ERROR_NOT_CONNECTED); + if ((state->GetPeerAddress().GetTransportType() == Transport::Type::kUdp) && mReliableMessageContext.AutoRequestAck() && + !sendFlags.Has(SendMessageFlags::kNoAutoRequestAck)) + { + payloadHeader.SetNeedsAck(true); + } + + // If there is a pending acknowledgment piggyback it on this message. + if (mReliableMessageContext.HasPeerRequestedAck()) + { + payloadHeader.SetAckId(mReliableMessageContext.mPendingPeerAckId); + + // Set AckPending flag to false since current outgoing message is going to serve as the ack on this exchange. + mReliableMessageContext.SetAckPending(false); + +#if !defined(NDEBUG) + ChipLogProgress(ExchangeManager, "Piggybacking Ack for MsgId:%08" PRIX32 " with msg", + mReliableMessageContext.mPendingPeerAckId); +#endif + } + // If a response message is expected... - if (sendFlags.Has(SendMessageFlags::kSendFlag_ExpectResponse)) + if (sendFlags.Has(SendMessageFlags::kExpectResponse)) { // Only one 'response expected' message can be outstanding at a time. VerifyOrExit(!IsResponseExpected(), err = CHIP_ERROR_INCORRECT_STATE); @@ -108,10 +141,33 @@ CHIP_ERROR ExchangeContext::SendMessage(uint16_t protocolId, uint8_t msgType, Pa } } - payloadHeader.SetInitiator(IsInitiator()); + // Send the message. + if (payloadHeader.IsNeedsAck()) + { + ReliableMessageManager::RetransTableEntry * entry = nullptr; + + // Add to Table for subsequent sending + err = mExchangeMgr->GetReliableMessageMgr()->AddToRetransTable(&mReliableMessageContext, &entry); + SuccessOrExit(err); - err = mExchangeMgr->GetSessionMgr()->SendMessage(payloadHeader, mPeerNodeId, std::move(msgBuf)); - SuccessOrExit(err); + err = mExchangeMgr->GetSessionMgr()->SendMessage(mSecureSession, payloadHeader, std::move(msgBuf), &entry->retainedBuf); + + if (err != CHIP_NO_ERROR) + { + // Remove from table + ChipLogError(ExchangeManager, "Failed to send message with err %ld", long(err)); + mExchangeMgr->GetReliableMessageMgr()->ClearRetransTable(*entry); + } + else + { + mExchangeMgr->GetReliableMessageMgr()->StartRetransmision(entry); + } + } + else + { + err = mExchangeMgr->GetSessionMgr()->SendMessage(mSecureSession, payloadHeader, std::move(msgBuf)); + SuccessOrExit(err); + } exit: if (err != CHIP_NO_ERROR && IsResponseExpected()) @@ -120,13 +176,6 @@ CHIP_ERROR ExchangeContext::SendMessage(uint16_t protocolId, uint8_t msgType, Pa SetResponseExpected(false); } - if (sendFlags.Has(SendMessageFlags::kSendFlag_RetainBuffer)) - { - // Nothing currently calls us with this flag. Ensure it stays that way until kSendFlag_RetainBuffer is removed - // in favour of callers Retain()ing buffers. - err = CHIP_ERROR_NOT_IMPLEMENTED; - } - // Release the reference to the exchange context acquired above. Under normal circumstances // this will merely decrement the reference count, without actually freeing the exchange context. // However if one of the function calls in this method resulted in a callback to the protocol, @@ -146,6 +195,19 @@ void ExchangeContext::DoClose(bool clearRetransTable) } mDelegate = nullptr; + // Closure of an exchange context is based on ref counting. The Protocol, when it calls DoClose(), indicates that + // it is done with the exchange context and the message layer sets all callbacks to NULL and does not send anything + // received on the exchange context up to higher layers. At this point, the message layer needs to handle the + // remaining work to be done on that exchange, (e.g. send all pending acks) before truly cleaning it up. + mReliableMessageContext.FlushAcks(); + + // In case the protocol wants a harder release of the EC right away, such as calling Abort(), exchange + // needs to clear the CRMP retransmission table immediately. + if (clearRetransTable) + { + mExchangeMgr->GetReliableMessageMgr()->ClearRetransTable(&mReliableMessageContext); + } + // Cancel the response timer. CancelResponseTimer(); } @@ -191,21 +253,22 @@ void ExchangeContext::Reset() *this = ExchangeContext(); } -ExchangeContext * ExchangeContext::Alloc(ExchangeManager * em, uint16_t ExchangeId, uint64_t PeerNodeId, bool Initiator, +ExchangeContext * ExchangeContext::Alloc(ExchangeManager * em, uint16_t ExchangeId, SecureSessionHandle session, bool Initiator, ExchangeDelegate * delegate) { - VerifyOrDie(delegate != nullptr); VerifyOrDie(mExchangeMgr == nullptr && GetReferenceCount() == 0); Reset(); Retain(); mExchangeMgr = em; em->IncrementContextsInUse(); - mExchangeId = ExchangeId; - mPeerNodeId = PeerNodeId; + mExchangeId = ExchangeId; + mSecureSession = session; mFlags.Set(ExFlagValues::kFlagInitiator, Initiator); mDelegate = delegate; + mReliableMessageContext.Init(em->GetReliableMessageMgr(), this); + #if defined(CHIP_EXCHANGE_CONTEXT_DETAIL_LOGGING) ChipLogProgress(ExchangeManager, "ec++ id: %d, inUse: %d, addr: 0x%x", (this - em->ContextPool + 1), em->GetContextsInUse(), this); @@ -236,7 +299,8 @@ void ExchangeContext::Free() SYSTEM_STATS_DECREMENT(chip::System::Stats::kExchangeMgr_NumContexts); } -bool ExchangeContext::MatchExchange(const PacketHeader & packetHeader, const PayloadHeader & payloadHeader) +bool ExchangeContext::MatchExchange(SecureSessionHandle session, const PacketHeader & packetHeader, + const PayloadHeader & payloadHeader) { // A given message is part of a particular exchange if... return @@ -244,8 +308,8 @@ bool ExchangeContext::MatchExchange(const PacketHeader & packetHeader, const Pay // The exchange identifier of the message matches the exchange identifier of the context. (mExchangeId == payloadHeader.GetExchangeID()) - // AND The message was received from the peer node associated with the exchange, or the peer node identifier is 'any'. - && ((mPeerNodeId == kAnyNodeId) || (mPeerNodeId == packetHeader.GetSourceNodeId().Value())) + // AND The message was received from the peer node associated with the exchange + && (mSecureSession == session) // AND The message was sent by an initiator and the exchange context is a responder (IsInitiator==false) // OR The message was sent by a responder and the exchange context is an initiator (IsInitiator==true) (for the broadcast @@ -299,6 +363,7 @@ CHIP_ERROR ExchangeContext::HandleMessage(const PacketHeader & packetHeader, con PacketBufferHandle msgBuf) { CHIP_ERROR err = CHIP_NO_ERROR; + uint32_t messageId = 0; uint16_t protocolId = 0; uint8_t messageType = 0; @@ -308,25 +373,57 @@ CHIP_ERROR ExchangeContext::HandleMessage(const PacketHeader & packetHeader, con // layer has completed its work on the ExchangeContext. Retain(); + messageId = packetHeader.GetMessageId(); protocolId = payloadHeader.GetProtocolID(); messageType = payloadHeader.GetMessageType(); - // Since we got the response, cancel the response timer. - CancelResponseTimer(); + if (payloadHeader.IsAckMsg()) + { + err = mReliableMessageContext.HandleRcvdAck(payloadHeader.GetAckId().Value()); + SuccessOrExit(err); + } - // If the context was expecting a response to a previously sent message, this message - // is implicitly that response. - SetResponseExpected(false); + if (payloadHeader.IsNeedsAck()) + { + MessageFlags msgFlags; - if (mDelegate != nullptr) + // An acknowledgment needs to be sent back to the peer for this message on this exchange, + // Set the flag in message header indicating an ack requested by peer; + msgFlags.Set(MessageFlagValues::kPeerRequestedAck); + + // Also set the flag in the exchange context indicating an ack requested; + mReliableMessageContext.SetPeerRequestedAck(true); + + err = mReliableMessageContext.HandleNeedsAck(messageId, msgFlags); + SuccessOrExit(err); + } + + // The SecureChannel::StandaloneAck message type is only used for CRMP; do not pass such messages to the application layer. + if ((protocolId == Protocols::kProtocol_SecureChannel) && + (messageType == static_cast(Protocols::SecureChannel::MsgType::StandaloneAck))) { - mDelegate->OnMessageReceived(this, packetHeader, protocolId, messageType, std::move(msgBuf)); + ExitNow(err = CHIP_NO_ERROR); } else { - DefaultOnMessageReceived(this, packetHeader, protocolId, messageType, std::move(msgBuf)); + // Since we got the response, cancel the response timer. + CancelResponseTimer(); + + // If the context was expecting a response to a previously sent message, this message + // is implicitly that response. + SetResponseExpected(false); + + if (mDelegate != nullptr) + { + mDelegate->OnMessageReceived(this, packetHeader, protocolId, messageType, std::move(msgBuf)); + } + else + { + DefaultOnMessageReceived(this, packetHeader, protocolId, messageType, std::move(msgBuf)); + } } +exit: // Release the reference to the ExchangeContext that was held at the beginning of this function. // This call should also do the needful of closing the ExchangeContext if the protocol has // already made a prior call to Close(). diff --git a/src/messaging/ExchangeContext.h b/src/messaging/ExchangeContext.h index bd85fe28a5fbd6..bfa14079db8d8b 100644 --- a/src/messaging/ExchangeContext.h +++ b/src/messaging/ExchangeContext.h @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -55,6 +56,8 @@ class DLL_EXPORT ExchangeContext : public ReferenceCounted mFlags; // Internal state flags /** * Search for an existing exchange that the message applies to. * + * @param[in] session The secure session of the received message. + * * @param[in] packetHeader A reference to the PacketHeader object. * * @param[in] payloadHeader A reference to the PayloadHeader object. @@ -174,7 +181,7 @@ class DLL_EXPORT ExchangeContext : public ReferenceCounted #include #include +#include #include #include #include @@ -58,7 +59,7 @@ namespace Messaging { * prior to use. * */ -ExchangeManager::ExchangeManager() +ExchangeManager::ExchangeManager() : mReliableMessageMgr(mContextPool) { mState = State::kState_NotInitialized; } @@ -79,6 +80,8 @@ CHIP_ERROR ExchangeManager::Init(SecureSessionMgr * sessionMgr) sessionMgr->SetDelegate(this); + mReliableMessageMgr.Init(sessionMgr->SystemLayer(), sessionMgr); + mState = State::kState_Initialized; return CHIP_NO_ERROR; @@ -99,21 +102,9 @@ CHIP_ERROR ExchangeManager::Shutdown() return CHIP_NO_ERROR; } -ExchangeContext * ExchangeManager::NewContext(const NodeId & peerNodeId, ExchangeDelegate * delegate) +ExchangeContext * ExchangeManager::NewContext(SecureSessionHandle session, ExchangeDelegate * delegate) { - return AllocContext(mNextExchangeId++, peerNodeId, true, delegate); -} - -ExchangeContext * ExchangeManager::FindContext(NodeId peerNodeId, ExchangeDelegate * delegate, bool isInitiator) -{ - for (auto & ec : ContextPool) - { - if (ec.GetReferenceCount() > 0 && ec.GetPeerNodeId() == peerNodeId && ec.GetDelegate() == delegate && - ec.IsInitiator() == isInitiator) - return &ec; - } - - return nullptr; + return AllocContext(mNextExchangeId++, session, true, delegate); } CHIP_ERROR ExchangeManager::RegisterUnsolicitedMessageHandler(uint32_t protocolId, ExchangeDelegate * delegate) @@ -141,16 +132,16 @@ void ExchangeManager::OnReceiveError(CHIP_ERROR error, const Transport::PeerAddr ChipLogError(ExchangeManager, "Accept FAILED, err = %s", ErrorStr(error)); } -ExchangeContext * ExchangeManager::AllocContext(uint16_t ExchangeId, uint64_t PeerNodeId, bool Initiator, +ExchangeContext * ExchangeManager::AllocContext(uint16_t ExchangeId, SecureSessionHandle session, bool Initiator, ExchangeDelegate * delegate) { CHIP_FAULT_INJECT(FaultInjection::kFault_AllocExchangeContext, return nullptr); - for (auto & ec : ContextPool) + for (auto & ec : mContextPool) { if (ec.GetReferenceCount() == 0) { - return ec.Alloc(this, ExchangeId, PeerNodeId, Initiator, delegate); + return ec.Alloc(this, ExchangeId, session, Initiator, delegate); } } @@ -158,18 +149,26 @@ ExchangeContext * ExchangeManager::AllocContext(uint16_t ExchangeId, uint64_t Pe return nullptr; } -void ExchangeManager::DispatchMessage(const PacketHeader & packetHeader, const PayloadHeader & payloadHeader, - System::PacketBufferHandle msgBuf) +void ExchangeManager::DispatchMessage(SecureSessionHandle session, const PacketHeader & packetHeader, + const PayloadHeader & payloadHeader, System::PacketBufferHandle msgBuf) { + CHIP_ERROR err = CHIP_NO_ERROR; UnsolicitedMessageHandler * umh = nullptr; UnsolicitedMessageHandler * matchingUMH = nullptr; - CHIP_ERROR err = CHIP_NO_ERROR; + bool sendAckAndCloseExchange = false; // Search for an existing exchange that the message applies to. If a match is found... - for (auto & ec : ContextPool) + for (auto & ec : mContextPool) { - if (ec.GetReferenceCount() > 0 && ec.MatchExchange(packetHeader, payloadHeader)) + if (ec.GetReferenceCount() > 0 && ec.MatchExchange(session, packetHeader, payloadHeader)) { + // Found a matching exchange. Set flag for correct subsequent CRMP + // retransmission timeout selection. + if (!ec.mReliableMessageContext.HasRcvdMsgFromPeer()) + { + ec.mReliableMessageContext.SetMsgRcvdFromPeer(true); + } + // Matched ExchangeContext; send to message handler. ec.HandleMessage(packetHeader, payloadHeader, std::move(msgBuf)); @@ -203,23 +202,43 @@ void ExchangeManager::DispatchMessage(const PacketHeader & packetHeader, const P } } } - // Discard the message if it isn't marked as being sent by an initiator. - else + // Discard the message if it isn't marked as being sent by an initiator and the message does not need to send + // an ack to the peer. + else if (!payloadHeader.IsNeedsAck()) { ExitNow(err = CHIP_ERROR_UNSOLICITED_MSG_NO_ORIGINATOR); } + // If we didn't find an existing exchange that matches the message, and no unsolicited message handler registered + // to hand this message, we need to create a temporary exchange to send an ack for this message and then close this exchange. + sendAckAndCloseExchange = payloadHeader.IsNeedsAck() && (matchingUMH == nullptr); + // If we found a handler or we need to create a new exchange context (EC). - if (matchingUMH != nullptr) + if (matchingUMH != nullptr || sendAckAndCloseExchange) { - auto * ec = - AllocContext(payloadHeader.GetExchangeID(), packetHeader.GetSourceNodeId().Value(), false, matchingUMH->Delegate); + ExchangeContext * ec = nullptr; + + if (sendAckAndCloseExchange) + { + // If rcvd msg is from initiator then this exchange is created as not Initiator. + // If rcvd msg is not from initiator then this exchange is created as Initiator. + ec = AllocContext(payloadHeader.GetExchangeID(), session, !payloadHeader.IsInitiator(), nullptr); + } + else + { + ec = AllocContext(payloadHeader.GetExchangeID(), session, false, matchingUMH->Delegate); + } + VerifyOrExit(ec != nullptr, err = CHIP_ERROR_NO_MEMORY); - ChipLogProgress(ExchangeManager, "ec pos: %d, id: %d, Delegate: 0x%x", ec - ContextPool.begin(), ec->GetExchangeId(), + ChipLogProgress(ExchangeManager, "ec pos: %d, id: %d, Delegate: 0x%x", ec - mContextPool.begin(), ec->GetExchangeId(), ec->GetDelegate()); ec->HandleMessage(packetHeader, payloadHeader, std::move(msgBuf)); + + // Close exchange if it was created only to send ack for a duplicate message. + if (sendAckAndCloseExchange) + ec->Close(); } exit: @@ -278,17 +297,16 @@ CHIP_ERROR ExchangeManager::UnregisterUMH(uint32_t protocolId, int16_t msgType) } void ExchangeManager::OnMessageReceived(const PacketHeader & packetHeader, const PayloadHeader & payloadHeader, - const Transport::PeerConnectionState * state, System::PacketBufferHandle msgBuf, - SecureSessionMgr * msgLayer) + SecureSessionHandle session, System::PacketBufferHandle msgBuf, SecureSessionMgr * msgLayer) { - DispatchMessage(packetHeader, payloadHeader, std::move(msgBuf)); + DispatchMessage(session, packetHeader, payloadHeader, std::move(msgBuf)); } -void ExchangeManager::OnConnectionExpired(const Transport::PeerConnectionState * state, SecureSessionMgr * mgr) +void ExchangeManager::OnConnectionExpired(SecureSessionHandle session, SecureSessionMgr * mgr) { - for (auto & ec : ContextPool) + for (auto & ec : mContextPool) { - if (ec.GetReferenceCount() > 0 && ec.mPeerNodeId == state->GetPeerNodeId()) + if (ec.GetReferenceCount() > 0 && ec.mSecureSession == session) { ec.Close(); // Continue iterate because there can be multiple contexts associated with the connection. diff --git a/src/messaging/ExchangeMgr.h b/src/messaging/ExchangeMgr.h index d433d592ffabb5..1f7d160f7260a1 100644 --- a/src/messaging/ExchangeMgr.h +++ b/src/messaging/ExchangeMgr.h @@ -27,6 +27,7 @@ #include #include +#include #include #include @@ -90,20 +91,7 @@ class DLL_EXPORT ExchangeManager : public SecureSessionMgrDelegate * @return A pointer to the created ExchangeContext object On success. Otherwise NULL if no object * can be allocated or is available. */ - ExchangeContext * NewContext(const NodeId & peerNodeId, ExchangeDelegate * delegate); - - /** - * Find the ExchangeContext from a pool matching a given set of parameters. - * - * @param[in] peerNodeId The node identifier of the peer with which the ExchangeContext has been set up. - * - * @param[in] delegate A pointer to ExchangeDelegate. - * - * @param[in] isInitiator Boolean indicator of whether the local node is the initiator of the exchange. - * - * @return A pointer to the ExchangeContext object matching the provided parameters On success, NULL on no match. - */ - ExchangeContext * FindContext(NodeId peerNodeId, ExchangeDelegate * delegate, bool isInitiator); + ExchangeContext * NewContext(SecureSessionHandle session, ExchangeDelegate * delegate); /** * Register an unsolicited message handler for a given protocol identifier. This handler would be @@ -165,6 +153,8 @@ class DLL_EXPORT ExchangeManager : public SecureSessionMgrDelegate SecureSessionMgr * GetSessionMgr() const { return mSessionMgr; } + ReliableMessageManager * GetReliableMessageMgr() { return &mReliableMessageMgr; }; + size_t GetContextsInUse() const { return mContextsInUse; } private: @@ -184,27 +174,28 @@ class DLL_EXPORT ExchangeManager : public SecureSessionMgrDelegate uint16_t mNextExchangeId; State mState; SecureSessionMgr * mSessionMgr; + ReliableMessageManager mReliableMessageMgr; - std::array ContextPool; + std::array mContextPool; size_t mContextsInUse; UnsolicitedMessageHandler UMHandlerPool[CHIP_CONFIG_MAX_UNSOLICITED_MESSAGE_HANDLERS]; void (*OnExchangeContextChanged)(size_t numContextsInUse); - ExchangeContext * AllocContext(uint16_t ExchangeId, uint64_t PeerNodeId, bool Initiator, ExchangeDelegate * delegate); + ExchangeContext * AllocContext(uint16_t ExchangeId, SecureSessionHandle session, bool Initiator, ExchangeDelegate * delegate); - void DispatchMessage(const PacketHeader & packetHeader, const PayloadHeader & payloadHeader, System::PacketBufferHandle msgBuf); + void DispatchMessage(SecureSessionHandle session, const PacketHeader & packetHeader, const PayloadHeader & payloadHeader, + System::PacketBufferHandle msgBuf); CHIP_ERROR RegisterUMH(uint32_t protocolId, int16_t msgType, ExchangeDelegate * delegate); CHIP_ERROR UnregisterUMH(uint32_t protocolId, int16_t msgType); void OnReceiveError(CHIP_ERROR error, const Transport::PeerAddress & source, SecureSessionMgr * msgLayer) override; - void OnMessageReceived(const PacketHeader & packetHeader, const PayloadHeader & payloadHeader, - const Transport::PeerConnectionState * state, System::PacketBufferHandle msgBuf, - SecureSessionMgr * msgLayer) override; + void OnMessageReceived(const PacketHeader & packetHeader, const PayloadHeader & payloadHeader, SecureSessionHandle session, + System::PacketBufferHandle msgBuf, SecureSessionMgr * msgLayer) override; - void OnConnectionExpired(const Transport::PeerConnectionState * state, SecureSessionMgr * mgr) override; + void OnConnectionExpired(SecureSessionHandle session, SecureSessionMgr * mgr) override; }; } // namespace Messaging diff --git a/src/messaging/Flags.h b/src/messaging/Flags.h index 40ff6fe53d965b..df28b9a943d644 100644 --- a/src/messaging/Flags.h +++ b/src/messaging/Flags.h @@ -38,52 +38,44 @@ namespace Messaging { enum class MessageFlagValues : uint32_t { /**< Indicates that the existing source node identifier must be reused. */ - kMessageFlag_ReuseSourceId = 0x00000020, - /**< Indicates that the sending of the message needs to be delayed. */ - kMessageFlag_DelaySend = 0x00000040, - /**< Indicates that the message buffer should not be freed after sending. */ - kMessageFlag_RetainBuffer = 0x00000080, + kReuseSourceId = 0x00000020, /**< Indicates that the CHIP message is already encoded. */ - kMessageFlag_MessageEncoded = 0x00001000, + kMessageEncoded = 0x00001000, /**< Indicates that default IPv6 source address selection should be used when sending IPv6 multicast messages. */ - kMessageFlag_DefaultMulticastSourceAddress = 0x00002000, + kDefaultMulticastSourceAddress = 0x00002000, /**< Indicates that the sender of the message requested an acknowledgment. */ - kMessageFlag_PeerRequestedAck = 0x00004000, + kPeerRequestedAck = 0x00004000, /**< Indicates that the message is a duplicate of a previously received message. */ - kMessageFlag_DuplicateMessage = 0x00008000, + kDuplicateMessage = 0x00008000, /**< Indicates that the peer's group key message counter is not synchronized. */ - kMessageFlag_PeerGroupMsgIdNotSynchronized = 0x00010000, + kPeerGroupMsgIdNotSynchronized = 0x00010000, /**< Indicates that the source of the message is the initiator of the CHIP exchange. */ - kMessageFlag_FromInitiator = 0x00020000, + kFromInitiator = 0x00020000, /**< Indicates that message is being sent/received via the local ephemeral UDP port. */ - kMessageFlag_ViaEphemeralUDPPort = 0x00040000, + kViaEphemeralUDPPort = 0x00040000, }; using MessageFlags = BitFlags; enum class SendMessageFlags : uint16_t { - kSendFlag_None = 0x0000, + kNone = 0x0000, /**< Used to indicate that automatic retransmission is enabled. */ - kSendFlag_AutoRetrans = 0x0001, + kAutoRetrans = 0x0001, /**< Used to indicate that a response is expected within a specified timeout. */ - kSendFlag_ExpectResponse = 0x0002, - /**< Used to indicate that the sending of the current message needs to be delayed. */ - kSendFlag_DelaySend = 0x0008, + kExpectResponse = 0x0002, /**< Used to indicate that the source node ID in the message header can be reused. */ - kSendFlag_ReuseSourceId = 0x0020, - /**< Used to indicate that the message buffer should not be freed after sending. */ - kSendFlag_RetainBuffer = 0x0040, + kReuseSourceId = 0x0020, /**< Used to indicate that the message is already encoded. */ - kSendFlag_AlreadyEncoded = 0x0080, + kAlreadyEncoded = 0x0080, /**< Used to indicate that default IPv6 source address selection should be used when sending IPv6 multicast messages. */ - kSendFlag_DefaultMulticastSourceAddress = 0x0100, + kDefaultMulticastSourceAddress = 0x0100, /**< Used to indicate that the current message is the initiator of the exchange. */ - kSendFlag_FromInitiator = 0x0200, + kFromInitiator = 0x0200, /**< Used to send a ReliableMessageProtocol message requesting an acknowledgment. */ - kSendFlag_RequestAck = 0x0400, + kRequestAck = 0x0400, /**< Suppress the auto-request acknowledgment feature when sending a message. */ - kSendFlag_NoAutoRequestAck = 0x0800, + kNoAutoRequestAck = 0x0800, }; using SendFlags = BitFlags; diff --git a/src/messaging/ReliableMessageContext.cpp b/src/messaging/ReliableMessageContext.cpp index d66f9d088a2dca..b811444db3b8df 100644 --- a/src/messaging/ReliableMessageContext.cpp +++ b/src/messaging/ReliableMessageContext.cpp @@ -23,6 +23,7 @@ #include +#include #include #include @@ -30,21 +31,47 @@ #include #include #include -#include +#include #include namespace chip { namespace Messaging { -void ReliableMessageContextDeletor::Release(ReliableMessageContext * obj) +ReliableMessageContext::ReliableMessageContext() : + mManager(nullptr), mExchange(nullptr), mDelegate(nullptr), mConfig(gDefaultReliableMessageProtocolConfig), mNextAckTimeTick(0), + mPendingPeerAckId(0) +{} + +void ReliableMessageContext::Init(ReliableMessageManager * manager, ExchangeContext * exchange) { - obj->mManager->FreeContext(obj); + mManager = manager; + mExchange = exchange; + mDelegate = nullptr; + + SetDropAckDebug(false); + SetAckPending(false); + SetPeerRequestedAck(false); + SetMsgRcvdFromPeer(false); + SetAutoRequestAck(true); } -ReliableMessageContext::ReliableMessageContext() : - mConfig(gDefaultReliableMessageProtocolConfig), mNextAckTimeTick(0), mThrottleTimeoutTick(0), mPendingPeerAckId(0), - mDelegate(nullptr) -{} +void ReliableMessageContext::Retain() +{ + mExchange->Retain(); +} + +void ReliableMessageContext::Release() +{ + mExchange->Release(); +} + +/** + * Returns whether an acknowledgment will be requested whenever a message is sent. + */ +bool ReliableMessageContext::AutoRequestAck() const +{ + return mFlags.Has(Flags::kFlagAutoRequestAck); +} /** * Determine whether there is already an acknowledgment pending to be sent @@ -78,6 +105,18 @@ bool ReliableMessageContext::HasRcvdMsgFromPeer() const return mFlags.Has(Flags::kFlagMsgRcvdFromPeer); } +/** + * Set whether an acknowledgment should be requested whenever a message is sent. + * + * @param[in] autoReqAck A Boolean indicating whether or not an + * acknowledgment should be requested whenever a + * message is sent. + */ +void ReliableMessageContext::SetAutoRequestAck(bool autoReqAck) +{ + mFlags.Set(Flags::kFlagAutoRequestAck, autoReqAck); +} + /** * Set if a message has been received from the peer * on this exchange. @@ -154,8 +193,8 @@ CHIP_ERROR ReliableMessageContext::FlushAcks() if (IsAckPending()) { - // Send the acknowledgment as a Common::Null message - err = SendCommonNullMessage(); + // Send the acknowledgment as a SecureChannel::StandStandaloneAck message + err = SendStandaloneAckMessage(); if (err == CHIP_NO_ERROR) { @@ -180,131 +219,6 @@ uint64_t ReliableMessageContext::GetCurrentRetransmitTimeoutTick() return (HasRcvdMsgFromPeer() ? mConfig.mActiveRetransTimeoutTick : mConfig.mInitialRetransTimeoutTick); } -/** - * Send a Throttle Flow message to the peer node requesting it to throttle its sending of messages. - * - * @note - * This message is part of the CHIP Reliable Messaging protocol. - * - * @param[in] pauseTimeMillis The time (in milliseconds) that the recipient is expected - * to throttle its sending. - * @retval #CHIP_ERROR_INVALID_ARGUMENT If an invalid argument was passed to this SendMessage API. - * @retval #CHIP_ERROR_SEND_THROTTLED If this exchange context has been throttled when using the - * CHIP reliable messaging protocol. - * @retval #CHIP_ERROR_WRONG_MSG_VERSION_FOR_EXCHANGE If there is a mismatch in the specific send operation and the - * CHIP message protocol version that is supported. For example, - * this error would be generated if CHIP Reliable Messaging - * semantics are being attempted when the CHIP message protocol - * version is V1. - * @retval #CHIP_ERROR_NOT_CONNECTED If the context was associated with a connection that is now - * closed. - * @retval #CHIP_ERROR_INCORRECT_STATE If the state of the exchange context is incorrect. - * @retval #CHIP_NO_ERROR If the CHIP layer successfully sent the message down to the - * network layer. - * - */ -CHIP_ERROR ReliableMessageContext::SendThrottleFlow(uint32_t pauseTimeMillis) -{ - CHIP_ERROR err = CHIP_NO_ERROR; - uint8_t * p = nullptr; - uint8_t msgLen = sizeof(pauseTimeMillis); - - System::PacketBufferHandle msgBuf = System::PacketBuffer::NewWithAvailableSize(msgLen); - VerifyOrExit(!msgBuf.IsNull(), err = CHIP_ERROR_NO_MEMORY); - - p = msgBuf->Start(); - - // Encode the fields in the buffer - Encoding::LittleEndian::Write32(p, pauseTimeMillis); - msgBuf->SetDataLength(msgLen); - - // Send a Throttle Flow message to the peer. Throttle Flow messages must never request - // acknowledgment, so suppress the auto-request ACK feature on the exchange in case it has been - // enabled by the application. - err = mManager->SendMessage(this, Protocols::kProtocol_Protocol_Common, Protocols::Common::kMsgType_RMP_Throttle_Flow, - msgBuf.Release_ForNow(), - BitFlags(SendMessageFlags::kSendFlag_NoAutoRequestAck)); - -exit: - return err; -} - -/** - * Send a Delayed Delivery message to notify a sender node that its previously sent message would experience an expected - * delay before being delivered to the recipient. One of the possible causes for messages to be delayed before being - * delivered is when the recipient end node is sleepy. This message is potentially generated by a suitable intermediate - * node in the send path who has enough knowledge of the recipient to infer about the delayed delivery. Upon receiving - * this message, the sender would re-adjust its retransmission timers for messages that seek acknowledgments back. - * - * @note - * This message is part of the CHIP Reliable Messaging protocol. - * - * @param[in] pauseTimeMillis The time (in milliseconds) that the previously sent message is expected - * to be delayed before being delivered. - * - * @param[in] delayedNodeId The node identifier of the peer node to whom the mesage delivery would be delayed. - * - * @retval #CHIP_ERROR_INVALID_ARGUMENT if an invalid argument was passed to this SendMessage API. - * @retval #CHIP_ERROR_WRONG_MSG_VERSION_FOR_EXCHANGE if there is a mismatch in the specific send operation and the - * CHIP message protocol version that is supported. For example, - * this error would be generated if CHIP Reliable Messaging - * semantics are being attempted when the CHIP message protocol - * version is V1. - * @retval #CHIP_ERROR_NOT_CONNECTED if the context was associated with a connection that is now - * closed. - * @retval #CHIP_ERROR_INCORRECT_STATE if the state of the exchange context is incorrect. - * @retval #CHIP_NO_ERROR if the CHIP layer successfully sent the message down to the - * network layer. - * - */ -CHIP_ERROR ReliableMessageContext::SendDelayedDelivery(uint32_t pauseTimeMillis, uint64_t delayedNodeId) -{ - CHIP_ERROR err = CHIP_NO_ERROR; - uint8_t * p = nullptr; - uint8_t msgLen = sizeof(pauseTimeMillis) + sizeof(delayedNodeId); - - System::PacketBufferHandle msgBuf = System::PacketBuffer::NewWithAvailableSize(msgLen); - VerifyOrExit(!msgBuf.IsNull(), err = CHIP_ERROR_NO_MEMORY); - - p = msgBuf->Start(); - // Set back the pointer by the length of the fields - - // Encode the fields in the buffer - Encoding::LittleEndian::Write32(p, pauseTimeMillis); - Encoding::LittleEndian::Write64(p, delayedNodeId); - msgBuf->SetDataLength(msgLen); - - // Send a Delayed Delivery message to the peer. Delayed Delivery messages must never request - // acknowledgment, so suppress the auto-request ACK feature on the exchange in case it has been - // enabled by the application. - err = mManager->SendMessage(this, Protocols::kProtocol_Protocol_Common, Protocols::Common::kMsgType_RMP_Delayed_Delivery, - msgBuf.Release_ForNow(), - BitFlags{ SendMessageFlags::kSendFlag_NoAutoRequestAck }); - -exit: - return err; -} - -/** - * Process received Ack. Remove the corresponding message context from the RetransTable and execute the application - * callback - * - * @note - * This message is part of the CHIP Reliable Messaging protocol. - * - * @param[in] exchHeader CHIP exchange information for incoming Ack message. - * - * @retval #CHIP_ERROR_INVALID_ACK_ID if the msgId of received Ack is not in the RetransTable. - * @retval #CHIP_NO_ERROR if the context was removed. - * - */ -CHIP_ERROR ReliableMessageContext::HandleDelayedDeliveryMessage(uint32_t PauseTimeMillis) -{ - mManager->ProcessDelayedDeliveryMessage(this, PauseTimeMillis); - mDelegate->OnDelayedDeliveryRcvd(PauseTimeMillis); - return CHIP_NO_ERROR; -} - /** * Process received Ack. Remove the corresponding message context from the RetransTable and execute the application * callback @@ -312,7 +226,7 @@ CHIP_ERROR ReliableMessageContext::HandleDelayedDeliveryMessage(uint32_t PauseTi * @note * This message is part of the CHIP Reliable Messaging protocol. * - * @param[in] exchHeader CHIP exchange information for incoming Ack message. + * @param[in] AckMsgId The msgId of incoming Ack message. * * @retval #CHIP_ERROR_INVALID_ACK_ID if the msgId of received Ack is not in the RetransTable. * @retval #CHIP_NO_ERROR if the context was removed. @@ -333,7 +247,11 @@ CHIP_ERROR ReliableMessageContext::HandleRcvdAck(uint32_t AckMsgId) } else { - mDelegate->OnAckRcvd(); + if (mDelegate) + { + mDelegate->OnAckRcvd(); + } + #if !defined(NDEBUG) ChipLogProgress(ExchangeManager, "Removed CHIP MsgId:%08" PRIX32 " from RetransTable", AckMsgId); #endif @@ -347,11 +265,15 @@ CHIP_ERROR ReliableMessageContext::HandleNeedsAck(uint32_t MessageId, BitFlagsExpireTicks(); // If the message IS a duplicate. - if (MsgFlags.Has(MessageFlagValues::kMessageFlag_DuplicateMessage)) + if (MsgFlags.Has(MessageFlagValues::kDuplicateMessage)) { #if !defined(NDEBUG) ChipLogProgress(ExchangeManager, "Forcing tx of solitary ack for duplicate MsgId:%08" PRIX32, MessageId); @@ -365,8 +287,8 @@ CHIP_ERROR ReliableMessageContext::HandleNeedsAck(uint32_t MessageId, BitFlagsExpireTicks(); - - // Flow Control Message Received; Adjust Throttle timeout accordingly. - // A PauseTimeMillis of zero indicates that peer is unthrottling this Exchange. - - if (0 != PauseTimeMillis) - { - mThrottleTimeoutTick = - static_cast(mManager->GetTickCounterFromTimeDelta(System::Timer::GetCurrentEpoch() + PauseTimeMillis)); - mManager->PauseRetransTable(this, PauseTimeMillis); - } - else - { - mThrottleTimeoutTick = 0; - mManager->ResumeRetransTable(this); - } - - // Call OnThrottleRcvd application callback - mDelegate->OnThrottleRcvd(PauseTimeMillis); - - // Schedule next physical wakeup - mManager->StartTimer(); - return CHIP_NO_ERROR; -} - /** - * Send a Common::Null message. + * Send a SecureChannel::StandaloneAck message. * * @note When sent via UDP, the null message is sent *without* requesting an acknowledgment, * even in the case where the auto-request acknowledgment feature has been enabled on the @@ -445,7 +339,7 @@ CHIP_ERROR ReliableMessageContext::HandleThrottleFlow(uint32_t PauseTimeMillis) * @retval other Another critical error returned by SendMessage(). * */ -CHIP_ERROR ReliableMessageContext::SendCommonNullMessage() +CHIP_ERROR ReliableMessageContext::SendStandaloneAckMessage() { CHIP_ERROR err = CHIP_NO_ERROR; @@ -454,9 +348,17 @@ CHIP_ERROR ReliableMessageContext::SendCommonNullMessage() VerifyOrExit(!msgBuf.IsNull(), err = CHIP_ERROR_NO_MEMORY); // Send the null message - err = mManager->SendMessage(this, chip::Protocols::kProtocol_Protocol_Common, chip::Protocols::Common::kMsgType_Null, - msgBuf.Release_ForNow(), - BitFlags{ SendMessageFlags::kSendFlag_NoAutoRequestAck }); + if (mExchange != nullptr) + { + err = mExchange->SendMessage(Protocols::kProtocol_SecureChannel, + static_cast(Protocols::SecureChannel::MsgType::StandaloneAck), std::move(msgBuf), + BitFlags{ SendMessageFlags::kNoAutoRequestAck }); + } + else + { + ChipLogError(ExchangeManager, "ExchangeContext is not initilized in ReliableMessageContext"); + err = CHIP_ERROR_NOT_CONNECTED; + } exit: if (IsSendErrorNonCritical(err)) diff --git a/src/messaging/ReliableMessageContext.h b/src/messaging/ReliableMessageContext.h index 7000cf9b51fdc6..fb6df5718ea2ca 100644 --- a/src/messaging/ReliableMessageContext.h +++ b/src/messaging/ReliableMessageContext.h @@ -39,6 +39,7 @@ namespace chip { namespace Messaging { class ChipMessageInfo; +class ExchangeContext; enum class MessageFlagValues : uint32_t; class ReliableMessageContext; class ReliableMessageManager; @@ -49,36 +50,26 @@ class ReliableMessageDelegate virtual ~ReliableMessageDelegate() {} /* Application callbacks */ - virtual void OnThrottleRcvd(uint32_t pauseTime) = 0; /**< Application callback for received Throttle message. */ - virtual void OnDelayedDeliveryRcvd(uint32_t pauseTime) = 0; /**< Application callback for received Delayed Delivery message. */ - virtual void OnSendError(CHIP_ERROR err) = 0; /**< Application callback for error while sending. */ - virtual void OnAckRcvd() = 0; /**< Application callback for received acknowledgment. */ + virtual void OnSendError(CHIP_ERROR err) = 0; /**< Application callback for error while sending. */ + virtual void OnAckRcvd() = 0; /**< Application callback for received acknowledgment. */ }; -class ReliableMessageContextDeletor +class ReliableMessageContext { public: - static void Release(ReliableMessageContext * obj); -}; - -class ReliableMessageContext : public ReferenceCounted -{ -public: - friend class ReliableMessageContextDeletor; - ReliableMessageContext(); - void Init(ReliableMessageManager * manager) { mManager = manager; } + void Init(ReliableMessageManager * manager, ExchangeContext * exchange); void SetConfig(ReliableMessageProtocolConfig config) { mConfig = config; } void SetDelegate(ReliableMessageDelegate * delegate) { mDelegate = delegate; } CHIP_ERROR FlushAcks(); uint64_t GetCurrentRetransmitTimeoutTick(); - CHIP_ERROR SendThrottleFlow(uint32_t PauseTimeMillis); - CHIP_ERROR SendDelayedDelivery(uint32_t PauseTimeMillis, uint64_t DelayedNodeId); - CHIP_ERROR SendCommonNullMessage(); + CHIP_ERROR SendStandaloneAckMessage(); + bool AutoRequestAck() const; + void SetAutoRequestAck(bool autoReqAck); bool ShouldDropAckDebug() const; void SetDropAckDebug(bool inDropAckDebug); bool IsAckPending() const; @@ -114,21 +105,21 @@ class ReliableMessageContext : public ReferenceCounted mFlags; // Internal state flags - CHIP_ERROR HandleDelayedDeliveryMessage(uint32_t PauseTimeMillis); + void Retain(); + void Release(); CHIP_ERROR HandleRcvdAck(uint32_t AckMsgId); CHIP_ERROR HandleNeedsAck(uint32_t MessageId, BitFlags Flags); - CHIP_ERROR HandleThrottleFlow(uint32_t PauseTimeMillis); private: friend class ReliableMessageManager; + friend class ExchangeContext; ReliableMessageManager * mManager; + ExchangeContext * mExchange; + ReliableMessageDelegate * mDelegate; ReliableMessageProtocolConfig mConfig; - uint16_t mNextAckTimeTick; // Next time for triggering Solo Ack - uint16_t mThrottleTimeoutTick; // Timeout until when Throttle is On when ThrottleEnabled is set + uint16_t mNextAckTimeTick; // Next time for triggering Solo Ack uint32_t mPendingPeerAckId; - - ReliableMessageDelegate * mDelegate; }; } // namespace Messaging diff --git a/src/messaging/ReliableMessageManager.cpp b/src/messaging/ReliableMessageManager.cpp index 9857430e489cf0..2c8304559dd6a5 100644 --- a/src/messaging/ReliableMessageManager.cpp +++ b/src/messaging/ReliableMessageManager.cpp @@ -36,36 +36,36 @@ namespace chip { namespace Messaging { -ReliableMessageManager::RetransTableEntry::RetransTableEntry() : - rc(nullptr), msgBuf(nullptr), msgId(0), msgSendFlags(0), nextRetransTimeTick(0), sendCount(0) -{} +ReliableMessageManager::RetransTableEntry::RetransTableEntry() : rc(nullptr), nextRetransTimeTick(0), sendCount(0) {} -ReliableMessageManager::ReliableMessageManager() : - mTimeStampBase(System::Timer::GetCurrentEpoch()), mCurrentTimerExpiry(0), +ReliableMessageManager::ReliableMessageManager(std::array & contextPool) : + mContextPool(contextPool), mSystemLayer(nullptr), mSessionMgr(nullptr), mCurrentTimerExpiry(0), mTimerIntervalShift(CHIP_CONFIG_RMP_TIMER_DEFAULT_PERIOD_SHIFT) {} ReliableMessageManager::~ReliableMessageManager() {} -void ReliableMessageManager::ProcessDelayedDeliveryMessage(ReliableMessageContext * rc, uint32_t PauseTimeMillis) +void ReliableMessageManager::Init(chip::System::Layer * systemLayer, SecureSessionMgr * sessionMgr) { - // Expire any virtual ticks that have expired so all wakeup sources reflect the current time - ExpireTicks(); + mSystemLayer = systemLayer; + mSessionMgr = sessionMgr; - // Go through the retrans table entries for that node and adjust the timer. - for (int i = 0; i < CHIP_CONFIG_RMP_RETRANS_TABLE_SIZE; i++) - { - // Exchcontext is the sentinel object to ascertain validity of the element - if (RetransTable[i].rc && RetransTable[i].rc == rc) - { - // Paustime is specified in milliseconds; Update retrans values - RetransTable[i].nextRetransTimeTick = - static_cast(RetransTable[i].nextRetransTimeTick + (PauseTimeMillis >> mTimerIntervalShift)); - } // exchContext - } // for loop in table entry + mTimeStampBase = System::Timer::GetCurrentEpoch(); + mCurrentTimerExpiry = 0; +} - // Schedule next physical wakeup - StartTimer(); +void ReliableMessageManager::Shutdown() +{ + mSystemLayer = nullptr; + mSessionMgr = nullptr; + + StopTimer(); + + // Clear the retransmit table + for (RetransTableEntry & rEntry : mRetransTable) + { + ClearRetransTable(rEntry); + } } /** @@ -99,10 +99,10 @@ void ReliableMessageManager::TicklessDebugDumpRetransTable(const char * log) for (int i = 0; i < CHIP_CONFIG_RMP_RETRANS_TABLE_SIZE; i++) { - if (RetransTable[i].rc) + if (mRetransTable[i].rc) { ChipLogProgress(ExchangeManager, "EC:%04" PRIX16 " MsgId:%08" PRIX32 " NextRetransTimeCtr:%04" PRIX16, - RetransTable[i].rc, RetransTable[i].msgId, RetransTable[i].nextRetransTimeTick); + mRetransTable[i].rc, mRetransTable[i].msgId, mRetransTable[i].nextRetransTimeTick); } } } @@ -132,57 +132,57 @@ void ReliableMessageManager::ExecuteActions() #if defined(RMP_TICKLESS_DEBUG) ChipLogProgress(ExchangeManager, "ReliableMessageManager::ExecuteActions sending ACK"); #endif - // Send the Ack in a Common::Null message - rc->SendCommonNullMessage(); + // Send the Ack in a SecureChannel::StandaloneAck message + rc->SendStandaloneAckMessage(); rc->SetAckPending(false); } } }); - TicklessDebugDumpRetransTable("ReliableMessageManager::ExecuteActions Dumping RetransTable entries before processing"); + TicklessDebugDumpRetransTable("ReliableMessageManager::ExecuteActions Dumping mRetransTable entries before processing"); // Retransmit / cancel anything in the retrans table whose retrans timeout // has expired for (int i = 0; i < CHIP_CONFIG_RMP_RETRANS_TABLE_SIZE; i++) { - ReliableMessageContext * rc = RetransTable[i].rc; + ReliableMessageContext * rc = mRetransTable[i].rc; CHIP_ERROR err = CHIP_NO_ERROR; - if (!rc || RetransTable[i].nextRetransTimeTick != 0) + if (!rc || mRetransTable[i].nextRetransTimeTick != 0) continue; - uint8_t sendCount = RetransTable[i].sendCount; + uint8_t sendCount = mRetransTable[i].sendCount; if (sendCount == rc->mConfig.mMaxRetrans) { err = CHIP_ERROR_MESSAGE_NOT_ACKNOWLEDGED; ChipLogError(ExchangeManager, "Failed to Send CHIP MsgId:%08" PRIX32 " sendCount: %" PRIu8 " max retries: %" PRIu8, - RetransTable[i].msgId, sendCount, rc->mConfig.mMaxRetrans); + mRetransTable[i].retainedBuf.GetMsgId(), sendCount, rc->mConfig.mMaxRetrans); // Remove from Table - ClearRetransmitTable(RetransTable[i]); + ClearRetransTable(mRetransTable[i]); } // Resend from Table (if the operation fails, the entry is cleared) if (err == CHIP_NO_ERROR) - err = SendFromRetransTable(&(RetransTable[i])); + err = SendFromRetransTable(&(mRetransTable[i])); if (err == CHIP_NO_ERROR) { // If the retransmission was successful, update the passive timer - RetransTable[i].nextRetransTimeTick = static_cast(rc->GetCurrentRetransmitTimeoutTick()); + mRetransTable[i].nextRetransTimeTick = static_cast(rc->GetCurrentRetransmitTimeoutTick()); #if !defined(NDEBUG) - ChipLogProgress(ExchangeManager, "Retransmit MsgId:%08" PRIX32 " Send Cnt %d", RetransTable[i].msgId, - RetransTable[i].sendCount); + ChipLogProgress(ExchangeManager, "Retransmit MsgId:%08" PRIX32 " Send Cnt %d", mRetransTable[i].retainedBuf.GetMsgId(), + mRetransTable[i].sendCount); #endif } - if (err != CHIP_NO_ERROR) + if (err != CHIP_NO_ERROR && rc->mDelegate) rc->mDelegate->OnSendError(err); } - TicklessDebugDumpRetransTable("ReliableMessageManager::ExecuteActions Dumping RetransTable entries after processing"); + TicklessDebugDumpRetransTable("ReliableMessageManager::ExecuteActions Dumping mRetransTable entries after processing"); } static void TickProceed(uint16_t & time, uint64_t ticks) @@ -233,26 +233,16 @@ void ReliableMessageManager::ExpireTicks() } }); - // Process Throttle Time - // Check Throttle timeout stored in EC to set/unset Throttle flag for (int i = 0; i < CHIP_CONFIG_RMP_RETRANS_TABLE_SIZE; i++) { - ReliableMessageContext * rc = RetransTable[i].rc; + ReliableMessageContext * rc = mRetransTable[i].rc; if (rc) { - // Process Retransmit Table - // Decrement Throttle timeout by elapsed timeticks - TickProceed(rc->mThrottleTimeoutTick, deltaTicks); -#if defined(RMP_TICKLESS_DEBUG) - ChipLogProgress(ExchangeManager, "ReliableMessageManager::ExpireTicks set mThrottleTimeoutTick to %u", - RetransTable[i].nextRetransTimeTick); -#endif - // Decrement Retransmit timeout by elapsed timeticks - TickProceed(RetransTable[i].nextRetransTimeTick, deltaTicks); + TickProceed(mRetransTable[i].nextRetransTimeTick, deltaTicks); #if defined(RMP_TICKLESS_DEBUG) ChipLogProgress(ExchangeManager, "ReliableMessageManager::ExpireTicks set nextRetransTimeTick to %u", - RetransTable[i].nextRetransTimeTick); + mRetransTable[i].nextRetransTimeTick); #endif } // rc entry is allocated } @@ -295,78 +285,81 @@ void ReliableMessageManager::Timeout(System::Layer * aSystemLayer, void * aAppSt * * @param[in] rc A pointer to the ExchangeContext object. * - * @param[in] msgBuf A pointer to the message buffer holding the CHIP message to be retransmitted. - * - * @param[in] messageId The message identifier of the stored CHIP message. - * * @param[out] rEntry A pointer to a pointer of a retransmission table entry added into the table. * * @retval #CHIP_ERROR_RETRANS_TABLE_FULL If there is no empty slot left in the table for addition. * @retval #CHIP_NO_ERROR On success. * */ -CHIP_ERROR ReliableMessageManager::AddToRetransTable(ReliableMessageContext * rc, System::PacketBuffer * msgBuf, uint32_t messageId, - uint16_t msgSendFlags, RetransTableEntry ** rEntry) +CHIP_ERROR ReliableMessageManager::AddToRetransTable(ReliableMessageContext * rc, RetransTableEntry ** rEntry) { bool added = false; CHIP_ERROR err = CHIP_NO_ERROR; + VerifyOrDie(rc != nullptr && rc->mExchange != nullptr); + for (int i = 0; i < CHIP_CONFIG_RMP_RETRANS_TABLE_SIZE; i++) { // Check the exchContext pointer for finding an empty slot in Table - if (!RetransTable[i].rc) + if (!mRetransTable[i].rc) { // Expire any virtual ticks that have expired so all wakeup sources reflect the current time ExpireTicks(); - RetransTable[i].rc = rc; - RetransTable[i].msgId = messageId; - RetransTable[i].msgBuf = msgBuf; - RetransTable[i].msgSendFlags = msgSendFlags; - RetransTable[i].sendCount = 0; - RetransTable[i].nextRetransTimeTick = static_cast( - rc->GetCurrentRetransmitTimeoutTick() + GetTickCounterFromTimeDelta(System::Timer::GetCurrentEpoch())); + mRetransTable[i].rc = rc; + mRetransTable[i].sendCount = 0; + mRetransTable[i].retainedBuf = EncryptedPacketBufferHandle(); + + *rEntry = &mRetransTable[i]; - *rEntry = &RetransTable[i]; // Increment the reference count rc->Retain(); added = true; - // Check if the timer needs to be started and start it. - StartTimer(); break; } } if (!added) { - ChipLogError(ExchangeManager, "RetransTable Already Full"); + ChipLogError(ExchangeManager, "mRetransTable Already Full"); err = CHIP_ERROR_RETRANS_TABLE_FULL; } return err; } -void ReliableMessageManager::PauseRetransTable(ReliableMessageContext * rc, uint32_t PauseTimeMillis) +void ReliableMessageManager::StartRetransmision(RetransTableEntry * entry) +{ + VerifyOrDie(entry != nullptr && entry->rc != nullptr); + + entry->nextRetransTimeTick = static_cast(entry->rc->GetCurrentRetransmitTimeoutTick() + + GetTickCounterFromTimeDelta(System::Timer::GetCurrentEpoch())); + + // Check if the timer needs to be started and start it. + StartTimer(); +} + +void ReliableMessageManager::PauseRetransmision(ReliableMessageContext * rc, uint32_t PauseTimeMillis) { for (int i = 0; i < CHIP_CONFIG_RMP_RETRANS_TABLE_SIZE; i++) { - if (RetransTable[i].rc == rc) + if (mRetransTable[i].rc == rc) { - RetransTable[i].nextRetransTimeTick = - static_cast(RetransTable[i].nextRetransTimeTick + (PauseTimeMillis >> mTimerIntervalShift)); + mRetransTable[i].nextRetransTimeTick = + static_cast(mRetransTable[i].nextRetransTimeTick + (PauseTimeMillis >> mTimerIntervalShift)); break; } } } -void ReliableMessageManager::ResumeRetransTable(ReliableMessageContext * rc) +void ReliableMessageManager::ResumeRetransmision(ReliableMessageContext * rc) { for (int i = 0; i < CHIP_CONFIG_RMP_RETRANS_TABLE_SIZE; i++) { - if (RetransTable[i].rc == rc) + if (mRetransTable[i].rc == rc) { - RetransTable[i].nextRetransTimeTick = 0; + mRetransTable[i].nextRetransTimeTick = 0; break; } } @@ -376,10 +369,10 @@ bool ReliableMessageManager::CheckAndRemRetransTable(ReliableMessageContext * rc { for (int i = 0; i < CHIP_CONFIG_RMP_RETRANS_TABLE_SIZE; i++) { - if ((RetransTable[i].rc == rc) && RetransTable[i].msgId == ackMsgId) + if ((mRetransTable[i].rc == rc) && mRetransTable[i].retainedBuf.GetMsgId() == ackMsgId) { // Clear the entry from the retransmision table. - ClearRetransmitTable(RetransTable[i]); + ClearRetransTable(mRetransTable[i]); #if !defined(NDEBUG) ChipLogProgress(ExchangeManager, "Rxd Ack; Removing MsgId:%08" PRIX32 " from Retrans Table", ackMsgId); @@ -404,57 +397,30 @@ CHIP_ERROR ReliableMessageManager::SendFromRetransTable(RetransTableEntry * entr CHIP_ERROR err = CHIP_NO_ERROR; ReliableMessageContext * rc = entry->rc; - // To trigger a call to OnSendError, set the number of transmissions so - // that the next call to ExecuteActions will abort this entry, - // restart the timer immediately, and ExitNow. - - CHIP_FAULT_INJECT(FaultInjection::kFault_RMPSendError, entry->sendCount = static_cast(rc->mConfig.mMaxRetrans + 1); - entry->nextRetransTimeTick = 0; StartTimer(); ExitNow()); - if (rc) { - // Locally store the start and length; - uint8_t * p = entry->msgBuf->Start(); - uint16_t len = entry->msgBuf->DataLength(); + err = mSessionMgr->SendEncryptedMessage(entry->rc->mExchange->GetSecureSession(), std::move(entry->retainedBuf), + &entry->retainedBuf); - // Send the message through - uint16_t msgSendFlags = entry->msgSendFlags; - SetFlag(msgSendFlags, MessageFlagValues::kMessageFlag_RetainBuffer); - err = SendMessage(rc, entry->msgBuf, msgSendFlags); - - // Reset the msgBuf start pointer and data length after sending - entry->msgBuf->SetStart(p); - entry->msgBuf->SetDataLength(len); + if (err == CHIP_NO_ERROR) + { + // Update the counters + entry->sendCount++; + } + else + { + // Remove from table + ChipLogError(ExchangeManager, "Crit-err %ld when sending CHIP MsgId:%08" PRIX32 ", send tries: %d", long(err), + entry->retainedBuf.GetMsgId(), entry->sendCount); - // Update the counters - entry->sendCount++; + ClearRetransTable(*entry); + } } else { ChipLogError(ExchangeManager, "Table entry invalid"); } - VerifyOrExit(err != CHIP_NO_ERROR, err = CHIP_NO_ERROR); - - // Any error generated during initial sending is evaluated for criticality which would - // qualify it to be reportable back to the caller. If it is non-critical then - // err is set to CHIP_NO_ERROR. - if (IsSendErrorNonCritical(err)) - { - ChipLogError(ExchangeManager, "Non-crit err %ld sending CHIP MsgId:%08" PRIX32 " from retrans table", long(err), - entry->msgId); - err = CHIP_NO_ERROR; - } - else - { - // Remove from table - ChipLogError(ExchangeManager, "Crit-err %ld when sending CHIP MsgId:%08" PRIX32 ", send tries: %d", long(err), entry->msgId, - entry->sendCount); - - ClearRetransmitTable(*entry); - } - -exit: return err; } @@ -464,14 +430,14 @@ CHIP_ERROR ReliableMessageManager::SendFromRetransTable(RetransTableEntry * entr * @param[in] rc A pointer to the ExchangeContext object. * */ -void ReliableMessageManager::ClearRetransmitTable(ReliableMessageContext * rc) +void ReliableMessageManager::ClearRetransTable(ReliableMessageContext * rc) { for (int i = 0; i < CHIP_CONFIG_RMP_RETRANS_TABLE_SIZE; i++) { - if (RetransTable[i].rc == rc) + if (mRetransTable[i].rc == rc) { // Clear the retransmit table entry. - ClearRetransmitTable(RetransTable[i]); + ClearRetransTable(mRetransTable[i]); } } } @@ -482,22 +448,18 @@ void ReliableMessageManager::ClearRetransmitTable(ReliableMessageContext * rc) * @param[in] rEntry A reference to the RetransTableEntry object. * */ -void ReliableMessageManager::ClearRetransmitTable(RetransTableEntry & rEntry) +void ReliableMessageManager::ClearRetransTable(RetransTableEntry & rEntry) { if (rEntry.rc) { + VerifyOrDie(rEntry.rc->mExchange != nullptr); + // Expire any virtual ticks that have expired so all wakeup sources reflect the current time ExpireTicks(); rEntry.rc->Release(); rEntry.rc = nullptr; - if (rEntry.msgBuf) - { - System::PacketBuffer::Free(rEntry.msgBuf); - rEntry.msgBuf = nullptr; - } - // Clear all other fields rEntry = RetransTableEntry(); @@ -514,14 +476,14 @@ void ReliableMessageManager::ClearRetransmitTable(RetransTableEntry & rEntry) * @param[in] err The error for failing table entries. * */ -void ReliableMessageManager::FailRetransmitTableEntries(ReliableMessageContext * rc, CHIP_ERROR err) +void ReliableMessageManager::FailRetransTableEntries(ReliableMessageContext * rc, CHIP_ERROR err) { for (int i = 0; i < CHIP_CONFIG_RMP_RETRANS_TABLE_SIZE; i++) { - if (RetransTable[i].rc == rc) + if (mRetransTable[i].rc == rc) { // Remove the entry from the retransmission table. - ClearRetransmitTable(RetransTable[i]); + ClearRetransTable(mRetransTable[i]); // Application callback OnSendError. rc->mDelegate->OnSendError(err); @@ -556,23 +518,13 @@ void ReliableMessageManager::StartTimer() for (int i = 0; i < CHIP_CONFIG_RMP_RETRANS_TABLE_SIZE; i++) { - ReliableMessageContext * rc = RetransTable[i].rc; + ReliableMessageContext * rc = mRetransTable[i].rc; if (rc) { - // When do we need to next wake up for throttle retransmission? - if (rc->mThrottleTimeoutTick != 0 && rc->mThrottleTimeoutTick < nextWakeTimeTick) - { - nextWakeTimeTick = rc->mThrottleTimeoutTick; - foundWake = true; -#if defined(RMP_TICKLESS_DEBUG) - ChipLogProgress(ExchangeManager, "ReliableMessageManager::StartTimer throttle timeout %u", nextWakeTimeTick); -#endif - } - // When do we need to next wake up for ReliableMessageProtocol retransmit? - if (RetransTable[i].nextRetransTimeTick < nextWakeTimeTick) + if (mRetransTable[i].nextRetransTimeTick < nextWakeTimeTick) { - nextWakeTimeTick = RetransTable[i].nextRetransTimeTick; + nextWakeTimeTick = mRetransTable[i].nextRetransTimeTick; foundWake = true; #if defined(RMP_TICKLESS_DEBUG) ChipLogProgress(ExchangeManager, "ReliableMessageManager::StartTimer RetransTime %u", nextWakeTimeTick); @@ -622,7 +574,7 @@ void ReliableMessageManager::StartTimer() StopTimer(); } - TicklessDebugDumpRetransTable("ReliableMessageManager::StartTimer Dumping RetransTable entries after setting wakeup times"); + TicklessDebugDumpRetransTable("ReliableMessageManager::StartTimer Dumping mRetransTable entries after setting wakeup times"); } void ReliableMessageManager::StopTimer() @@ -635,7 +587,7 @@ int ReliableMessageManager::TestGetCountRetransTable() int count = 0; for (int i = 0; i < CHIP_CONFIG_RMP_RETRANS_TABLE_SIZE; i++) { - ReliableMessageContext * rc = RetransTable[i].rc; + ReliableMessageContext * rc = mRetransTable[i].rc; if (rc) count++; } diff --git a/src/messaging/ReliableMessageManager.h b/src/messaging/ReliableMessageManager.h index 269634817aba5e..6b6178e89c23cb 100644 --- a/src/messaging/ReliableMessageManager.h +++ b/src/messaging/ReliableMessageManager.h @@ -23,8 +23,10 @@ #pragma once +#include #include +#include #include #include @@ -57,39 +59,34 @@ class ReliableMessageManager { RetransTableEntry(); - ReliableMessageContext * rc; /**< The context for the stored CHIP message. */ - System::PacketBuffer * msgBuf; /**< A pointer to the PacketBuffer object holding the CHIP message. */ - uint32_t msgId; /**< The message identifier of the CHIP message awaiting acknowledgment. */ - uint16_t msgSendFlags; - uint16_t nextRetransTimeTick; /**< A counter representing the next retransmission time for the message. */ - uint8_t sendCount; /**< A counter representing the number of times the message has been sent. */ + ReliableMessageContext * rc; /**< The context for the stored CHIP message. */ + EncryptedPacketBufferHandle retainedBuf; /**< The PacketBuffer object holding the CHIP message. */ + uint16_t nextRetransTimeTick; /**< A counter representing the next retransmission time for the message. */ + uint8_t sendCount; /**< A counter representing the number of times the message has been sent. */ }; public: - ReliableMessageManager(); + ReliableMessageManager(std::array & contextPool); ~ReliableMessageManager(); - void Init(chip::System::Layer & system) { mSystemLayer = &system; } - void Shutdown() {} - - void FreeContext(ReliableMessageContext * rc); + void Init(chip::System::Layer * systemLayer, SecureSessionMgr * sessionMgr); + void Shutdown(); uint64_t GetTickCounterFromTimePeriod(uint64_t period); uint64_t GetTickCounterFromTimeDelta(uint64_t newTime); void ExecuteActions(); - void ProcessDelayedDeliveryMessage(ReliableMessageContext * rc, uint32_t PauseTimeMillis); static void Timeout(System::Layer * aSystemLayer, void * aAppState, System::Error aError); - CHIP_ERROR AddToRetransTable(ReliableMessageContext * rc, System::PacketBuffer * msgBuf, uint32_t messageId, - uint16_t msgSendFlags, RetransTableEntry ** rEntry); - void PauseRetransTable(ReliableMessageContext * rc, uint32_t PauseTimeMillis); - void ResumeRetransTable(ReliableMessageContext * rc); + CHIP_ERROR AddToRetransTable(ReliableMessageContext * rc, RetransTableEntry ** rEntry); + void StartRetransmision(RetransTableEntry * entry); + void PauseRetransmision(ReliableMessageContext * rc, uint32_t PauseTimeMillis); + void ResumeRetransmision(ReliableMessageContext * rc); bool CheckAndRemRetransTable(ReliableMessageContext * rc, uint32_t msgId); CHIP_ERROR SendFromRetransTable(RetransTableEntry * entry); - void ClearRetransmitTable(ReliableMessageContext * rc); - void ClearRetransmitTable(RetransTableEntry & rEntry); - void FailRetransmitTableEntries(ReliableMessageContext * rc, CHIP_ERROR err); + void ClearRetransTable(ReliableMessageContext * rc); + void ClearRetransTable(RetransTableEntry & rEntry); + void FailRetransTableEntries(ReliableMessageContext * rc, CHIP_ERROR err); void StartTimer(); void StopTimer(); @@ -99,14 +96,10 @@ class ReliableMessageManager int TestGetCountRetransTable(); void TestSetIntervalShift(uint16_t value) { mTimerIntervalShift = value; } -public: - // public functions for ReliableMessageProtocol internal usage - CHIP_ERROR SendMessage(ReliableMessageContext * context, System::PacketBuffer * msgBuf, uint16_t sendFlags); - CHIP_ERROR SendMessage(ReliableMessageContext * context, uint32_t profileId, uint8_t msgType, System::PacketBuffer * msgBuf, - BitFlags sendFlags); - private: + std::array & mContextPool; chip::System::Layer * mSystemLayer; + SecureSessionMgr * mSessionMgr; uint64_t mTimeStampBase; // ReliableMessageProtocol timer base value to add offsets to evaluate timeouts System::Timer::Epoch mCurrentTimerExpiry; // Tracks when the ReliableMessageProtocol timer will next expire uint16_t mTimerIntervalShift; // ReliableMessageProtocol Timer tick period shift @@ -114,12 +107,17 @@ class ReliableMessageManager /* Placeholder function to run a function for all exchanges */ template void ExecuteForAllContext(Function function) - {} + { + for (auto & ec : mContextPool) + { + function(ec.GetReliableMessageContext()); + } + } void TicklessDebugDumpRetransTable(const char * log); // ReliableMessageProtocol Global tables for timer context - RetransTableEntry RetransTable[CHIP_CONFIG_RMP_RETRANS_TABLE_SIZE]; + RetransTableEntry mRetransTable[CHIP_CONFIG_RMP_RETRANS_TABLE_SIZE]; }; } // namespace Messaging diff --git a/src/messaging/ReliableMessageProtocolConfig.h b/src/messaging/ReliableMessageProtocolConfig.h index f6706d7f9d277f..16b72f0a3c8f6e 100644 --- a/src/messaging/ReliableMessageProtocolConfig.h +++ b/src/messaging/ReliableMessageProtocolConfig.h @@ -35,11 +35,11 @@ namespace Messaging { * * @brief * The default ReliableMessageProtocol timer tick interval shift in - * milliseconds. 8 bit equals 256 milliseconds + * milliseconds. 6 bit equals 64 milliseconds * */ #ifndef CHIP_CONFIG_RMP_TIMER_DEFAULT_PERIOD_SHIFT -#define CHIP_CONFIG_RMP_TIMER_DEFAULT_PERIOD_SHIFT 8 +#define CHIP_CONFIG_RMP_TIMER_DEFAULT_PERIOD_SHIFT 6 #endif // CHIP_CONFIG_RMP_TIMER_DEFAULT_PERIOD_SHIFT /** diff --git a/src/messaging/tests/BUILD.gn b/src/messaging/tests/BUILD.gn index 642ad9a1c07cf9..1a28de8ca3269a 100644 --- a/src/messaging/tests/BUILD.gn +++ b/src/messaging/tests/BUILD.gn @@ -34,6 +34,7 @@ chip_test_suite("tests") { "${chip_root}/src/lib/core", "${chip_root}/src/lib/support", "${chip_root}/src/messaging", + "${chip_root}/src/protocols", "${chip_root}/src/transport", "${chip_root}/src/transport/raw/tests:helpers", "${nlio_root}:nlio", diff --git a/src/messaging/tests/TestExchangeMgr.cpp b/src/messaging/tests/TestExchangeMgr.cpp index 0e50f54a19d524..06179c2929492e 100644 --- a/src/messaging/tests/TestExchangeMgr.cpp +++ b/src/messaging/tests/TestExchangeMgr.cpp @@ -37,6 +37,7 @@ #include #include +#include namespace { @@ -58,11 +59,9 @@ class LoopbackTransport : public Transport::Base /// Transports are required to have a constructor that takes exactly one argument CHIP_ERROR Init(const char * unused) { return CHIP_NO_ERROR; } - CHIP_ERROR SendMessage(const PacketHeader & header, const PeerAddress & address, System::PacketBuffer * msgBuf) override + CHIP_ERROR SendMessage(const PacketHeader & header, const PeerAddress & address, System::PacketBufferHandle msgBuf) override { - System::PacketBufferHandle msg_ForNow; - msg_ForNow.Adopt(msgBuf); - HandleMessageReceived(header, address, std::move(msg_ForNow)); + HandleMessageReceived(header, address, std::move(msgBuf)); return CHIP_NO_ERROR; } @@ -103,6 +102,27 @@ void CheckSimpleInitTest(nlTestSuite * inSuite, void * inContext) NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); } +class TestSessMgrCallback : public SecureSessionMgrDelegate +{ +public: + void OnMessageReceived(const PacketHeader & header, const PayloadHeader & payloadHeader, SecureSessionHandle session, + System::PacketBufferHandle msgBuf, SecureSessionMgr * mgr) override + { + ReceiveHandlerCallCount++; + } + + void OnNewConnection(SecureSessionHandle session, SecureSessionMgr * mgr) override + { + mSecureSession = session; + NewConnectionHandlerCallCount++; + } + void OnConnectionExpired(SecureSessionHandle session, SecureSessionMgr * mgr) override {} + + SecureSessionHandle mSecureSession; + int ReceiveHandlerCallCount = 0; + int NewConnectionHandlerCallCount = 0; +}; + void CheckNewContextTest(nlTestSuite * inSuite, void * inContext) { TestContext & ctx = *reinterpret_cast(inContext); @@ -111,6 +131,23 @@ void CheckNewContextTest(nlTestSuite * inSuite, void * inContext) SecureSessionMgr secureSessionMgr; CHIP_ERROR err; + TestSessMgrCallback callback; + secureSessionMgr.SetDelegate(&callback); + + IPAddress addr; + IPAddress::FromString("127.0.0.1", addr); + SecurePairingUsingTestSecret pairing1(Optional::Value(kSourceNodeId), 1, 2); + Optional peer1(Transport::PeerAddress::UDP(addr, 1)); + err = secureSessionMgr.NewPairing(peer1, kDestinationNodeId, &pairing1); + NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + SecureSessionHandle sessionFromSourceToDestination = callback.mSecureSession; + + SecurePairingUsingTestSecret pairing2(Optional::Value(kDestinationNodeId), 2, 1); + Optional peer2(Transport::PeerAddress::UDP(addr, 2)); + err = secureSessionMgr.NewPairing(peer2, kSourceNodeId, &pairing2); + NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + SecureSessionHandle sessionFromDestinationToSource = callback.mSecureSession; + ctx.GetInetLayer().SystemLayer()->Init(nullptr); err = transportMgr.Init("LOOPBACK"); @@ -124,48 +161,17 @@ void CheckNewContextTest(nlTestSuite * inSuite, void * inContext) MockAppDelegate mockAppDelegate; - ExchangeContext * ec1 = exchangeMgr.NewContext(kSourceNodeId, &mockAppDelegate); + ExchangeContext * ec1 = exchangeMgr.NewContext(sessionFromDestinationToSource, &mockAppDelegate); NL_TEST_ASSERT(inSuite, ec1 != nullptr); NL_TEST_ASSERT(inSuite, ec1->IsInitiator() == true); NL_TEST_ASSERT(inSuite, ec1->GetExchangeId() != 0); - NL_TEST_ASSERT(inSuite, ec1->GetPeerNodeId() == kSourceNodeId); + NL_TEST_ASSERT(inSuite, ec1->GetSecureSession() == sessionFromDestinationToSource); NL_TEST_ASSERT(inSuite, ec1->GetDelegate() == &mockAppDelegate); - ExchangeContext * ec2 = exchangeMgr.NewContext(kDestinationNodeId, &mockAppDelegate); + ExchangeContext * ec2 = exchangeMgr.NewContext(sessionFromSourceToDestination, &mockAppDelegate); NL_TEST_ASSERT(inSuite, ec2 != nullptr); NL_TEST_ASSERT(inSuite, ec2->GetExchangeId() > ec1->GetExchangeId()); - NL_TEST_ASSERT(inSuite, ec2->GetPeerNodeId() == kDestinationNodeId); -} - -void CheckFindContextTest(nlTestSuite * inSuite, void * inContext) -{ - TestContext & ctx = *reinterpret_cast(inContext); - - TransportMgr transportMgr; - SecureSessionMgr secureSessionMgr; - CHIP_ERROR err; - - ctx.GetInetLayer().SystemLayer()->Init(nullptr); - - err = transportMgr.Init("LOOPBACK"); - NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); - err = secureSessionMgr.Init(kSourceNodeId, ctx.GetInetLayer().SystemLayer(), &transportMgr); - NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); - - ExchangeManager exchangeMgr; - err = exchangeMgr.Init(&secureSessionMgr); - NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); - - MockAppDelegate mockAppDelegate; - - ExchangeContext * ec = exchangeMgr.NewContext(kDestinationNodeId, &mockAppDelegate); - NL_TEST_ASSERT(inSuite, ec != nullptr); - - bool result = exchangeMgr.FindContext(kDestinationNodeId, &mockAppDelegate, true); - NL_TEST_ASSERT(inSuite, result == true); - - result = exchangeMgr.FindContext(kDestinationNodeId, nullptr, false); - NL_TEST_ASSERT(inSuite, result == false); + NL_TEST_ASSERT(inSuite, ec2->GetSecureSession() == sessionFromSourceToDestination); } void CheckUmhRegistrationTest(nlTestSuite * inSuite, void * inContext) @@ -211,12 +217,26 @@ void CheckUmhRegistrationTest(nlTestSuite * inSuite, void * inContext) void CheckExchangeMessages(nlTestSuite * inSuite, void * inContext) { TestContext & ctx = *reinterpret_cast(inContext); - CHIP_ERROR err; TransportMgr transportMgr; SecureSessionMgr secureSessionMgr; + CHIP_ERROR err; + + TestSessMgrCallback callback; + secureSessionMgr.SetDelegate(&callback); + IPAddress addr; IPAddress::FromString("127.0.0.1", addr); + SecurePairingUsingTestSecret pairing1(Optional::Value(kSourceNodeId), 1, 2); + Optional peer1(Transport::PeerAddress::UDP(addr, 1)); + err = secureSessionMgr.NewPairing(peer1, kDestinationNodeId, &pairing1); + NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + SecureSessionHandle sessionFromSourceToDestination = callback.mSecureSession; + + SecurePairingUsingTestSecret pairing2(Optional::Value(kDestinationNodeId), 2, 1); + Optional peer2(Transport::PeerAddress::UDP(addr, 2)); + err = secureSessionMgr.NewPairing(peer2, kSourceNodeId, &pairing2); + NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); ctx.GetInetLayer().SystemLayer()->Init(nullptr); @@ -229,29 +249,20 @@ void CheckExchangeMessages(nlTestSuite * inSuite, void * inContext) err = exchangeMgr.Init(&secureSessionMgr); NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); - SecurePairingUsingTestSecret pairing1(Optional::Value(kSourceNodeId), 1, 2); - Optional peer1(Transport::PeerAddress::UDP(addr, 1)); - err = secureSessionMgr.NewPairing(peer1, kSourceNodeId, &pairing1); - NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); - SecurePairingUsingTestSecret pairing2(Optional::Value(kDestinationNodeId), 2, 1); - Optional peer2(Transport::PeerAddress::UDP(addr, 2)); - err = secureSessionMgr.NewPairing(peer2, kDestinationNodeId, &pairing2); - NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); - // create solicited exchange MockAppDelegate mockSolicitedAppDelegate; - ExchangeContext * ec1 = exchangeMgr.NewContext(kDestinationNodeId, &mockSolicitedAppDelegate); + ExchangeContext * ec1 = exchangeMgr.NewContext(sessionFromSourceToDestination, &mockSolicitedAppDelegate); // create unsolicited exchange MockAppDelegate mockUnsolicitedAppDelegate; err = exchangeMgr.RegisterUnsolicitedMessageHandler(0x0001, 0x0001, &mockUnsolicitedAppDelegate); // send a malicious packet - ec1->SendMessage(0x0001, 0x0002, System::PacketBuffer::New(), SendFlags(Messaging::SendMessageFlags::kSendFlag_None)); + ec1->SendMessage(0x0001, 0x0002, System::PacketBuffer::New(), SendFlags(Messaging::SendMessageFlags::kNone)); NL_TEST_ASSERT(inSuite, !mockUnsolicitedAppDelegate.IsOnMessageReceivedCalled); // send a good packet - ec1->SendMessage(0x0001, 0x0001, System::PacketBuffer::New(), SendFlags(Messaging::SendMessageFlags::kSendFlag_None)); + ec1->SendMessage(0x0001, 0x0001, System::PacketBuffer::New(), SendFlags(Messaging::SendMessageFlags::kNone)); NL_TEST_ASSERT(inSuite, mockUnsolicitedAppDelegate.IsOnMessageReceivedCalled); } @@ -265,7 +276,6 @@ const nlTest sTests[] = { NL_TEST_DEF("Test ExchangeMgr::Init", CheckSimpleInitTest), NL_TEST_DEF("Test ExchangeMgr::NewContext", CheckNewContextTest), - NL_TEST_DEF("Test ExchangeMgr::FindContext", CheckFindContextTest), NL_TEST_DEF("Test ExchangeMgr::CheckUmhRegistrationTest", CheckUmhRegistrationTest), NL_TEST_DEF("Test ExchangeMgr::CheckExchangeMessages", CheckExchangeMessages), diff --git a/src/messaging/tests/TestReliableMessageProtocol.cpp b/src/messaging/tests/TestReliableMessageProtocol.cpp index b1644b11857b05..efe4431e41db47 100644 --- a/src/messaging/tests/TestReliableMessageProtocol.cpp +++ b/src/messaging/tests/TestReliableMessageProtocol.cpp @@ -28,7 +28,11 @@ #include #include #include +#include #include +#include +#include +#include #include #include @@ -36,17 +40,66 @@ #include +#include +#include +#include + namespace { using namespace chip; using namespace chip::Inet; +using namespace chip::Transport; using namespace chip::Messaging; +using namespace chip::Protocols; using TestContext = chip::Test::IOContext; TestContext sContext; -ReliableMessageManager manager; +const char PAYLOAD[] = "Hello!"; +constexpr NodeId kSourceNodeId = 123654; +constexpr NodeId kDestinationNodeId = 111222333; + +int gSendMessageCount = 0; + +class OutgoingTransport : public Transport::Base +{ +public: + /// Transports are required to have a constructor that takes exactly one argument + CHIP_ERROR Init(const char * unused) { return CHIP_NO_ERROR; } + + CHIP_ERROR SendMessage(const PacketHeader & header, const PeerAddress & address, System::PacketBufferHandle msgBuf) override + { + const uint16_t headerSize = header.EncodeSizeBytes(); + + VerifyOrReturnError(msgBuf->EnsureReservedSize(headerSize), CHIP_ERROR_NO_MEMORY); + + msgBuf->SetStart(msgBuf->Start() - headerSize); + + uint16_t actualEncodedHeaderSize; + ReturnErrorOnFailure(header.Encode(msgBuf->Start(), msgBuf->DataLength(), &actualEncodedHeaderSize)); + + gSendMessageCount++; + + return CHIP_NO_ERROR; + } + + bool CanSendToPeer(const PeerAddress & address) override { return true; } +}; + +class MockAppDelegate : public ExchangeDelegate +{ +public: + void OnMessageReceived(ExchangeContext * ec, const PacketHeader & packetHeader, uint32_t protocolId, uint8_t msgType, + System::PacketBufferHandle buffer) override + { + IsOnMessageReceivedCalled = true; + } + + void OnResponseTimeout(ExchangeContext * ec) override {} + + bool IsOnMessageReceivedCalled = false; +}; void test_os_sleep_ms(uint64_t millisecs) { @@ -66,8 +119,6 @@ class ReliableMessageDelegateObject : public ReliableMessageDelegate ~ReliableMessageDelegateObject() override {} /* Application callbacks */ - void OnThrottleRcvd(uint32_t pauseTime) override {} - void OnDelayedDeliveryRcvd(uint32_t pauseTime) override {} void OnSendError(CHIP_ERROR err) override { SendErrorCalled = true; } void OnAckRcvd() override {} @@ -77,119 +128,155 @@ class ReliableMessageDelegateObject : public ReliableMessageDelegate void CheckAddClearRetrans(nlTestSuite * inSuite, void * inContext) { TestContext & ctx = *reinterpret_cast(inContext); - auto & m = manager; - m.Init(ctx.GetSystemLayer()); - ReliableMessageContext rc; - rc.Init(&m); + + TransportMgr transportMgr; + SecureSessionMgr secureSessionMgr; + CHIP_ERROR err; + + ctx.GetInetLayer().SystemLayer()->Init(nullptr); + + err = transportMgr.Init("LOOPBACK"); + NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + err = secureSessionMgr.Init(kSourceNodeId, ctx.GetInetLayer().SystemLayer(), &transportMgr); + NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + + ExchangeManager exchangeMgr; + err = exchangeMgr.Init(&secureSessionMgr); + NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + + MockAppDelegate mockAppDelegate; + + // TODO: temprary create a SecureSessionHandle from node id, will be fix in PR 3602 + ExchangeContext * exchange = exchangeMgr.NewContext({ kDestinationNodeId, kAnyKeyId }, &mockAppDelegate); + NL_TEST_ASSERT(inSuite, exchange != nullptr); + + ReliableMessageManager * rm = exchangeMgr.GetReliableMessageMgr(); + ReliableMessageContext * rc = exchange->GetReliableMessageContext(); + NL_TEST_ASSERT(inSuite, rm != nullptr); + NL_TEST_ASSERT(inSuite, rc != nullptr); + ReliableMessageManager::RetransTableEntry * entry; - m.AddToRetransTable(&rc, nullptr, 1, 0, &entry); - NL_TEST_ASSERT(inSuite, m.TestGetCountRetransTable() == 1); - m.ClearRetransmitTable(*entry); - NL_TEST_ASSERT(inSuite, m.TestGetCountRetransTable() == 0); - m.Shutdown(); + + rm->AddToRetransTable(rc, &entry); + NL_TEST_ASSERT(inSuite, rm->TestGetCountRetransTable() == 1); + rm->ClearRetransTable(*entry); + NL_TEST_ASSERT(inSuite, rm->TestGetCountRetransTable() == 0); } void CheckFailRetrans(nlTestSuite * inSuite, void * inContext) { TestContext & ctx = *reinterpret_cast(inContext); - auto & m = manager; - m.Init(ctx.GetSystemLayer()); - ReliableMessageContext rc; - rc.Init(&m); - ReliableMessageDelegateObject delegate; - rc.SetDelegate(&delegate); + + TransportMgr transportMgr; + SecureSessionMgr secureSessionMgr; + CHIP_ERROR err; + + ctx.GetInetLayer().SystemLayer()->Init(nullptr); + + err = transportMgr.Init("LOOPBACK"); + NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + err = secureSessionMgr.Init(kSourceNodeId, ctx.GetInetLayer().SystemLayer(), &transportMgr); + NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + + ExchangeManager exchangeMgr; + err = exchangeMgr.Init(&secureSessionMgr); + NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + + MockAppDelegate mockAppDelegate; + + // TODO: temprary create a SecureSessionHandle from node id, will be fix in PR 3602 + ExchangeContext * exchange = exchangeMgr.NewContext({ kDestinationNodeId, kAnyKeyId }, &mockAppDelegate); + NL_TEST_ASSERT(inSuite, exchange != nullptr); + + ReliableMessageManager * rm = exchangeMgr.GetReliableMessageMgr(); + ReliableMessageContext * rc = exchange->GetReliableMessageContext(); + NL_TEST_ASSERT(inSuite, rm != nullptr); + NL_TEST_ASSERT(inSuite, rc != nullptr); + ReliableMessageManager::RetransTableEntry * entry; - auto buf = System::PacketBuffer::New(); - m.AddToRetransTable(&rc, buf.Release_ForNow(), 1, 0, &entry); - NL_TEST_ASSERT(inSuite, m.TestGetCountRetransTable() == 1); + ReliableMessageDelegateObject delegate; + rc->SetDelegate(&delegate); + rm->AddToRetransTable(rc, &entry); + NL_TEST_ASSERT(inSuite, rm->TestGetCountRetransTable() == 1); NL_TEST_ASSERT(inSuite, !delegate.SendErrorCalled); - m.FailRetransmitTableEntries(&rc, CHIP_NO_ERROR); - NL_TEST_ASSERT(inSuite, m.TestGetCountRetransTable() == 0); + rm->FailRetransTableEntries(rc, CHIP_NO_ERROR); + NL_TEST_ASSERT(inSuite, rm->TestGetCountRetransTable() == 0); NL_TEST_ASSERT(inSuite, delegate.SendErrorCalled); - m.Shutdown(); } -void CheckRetransExpire(nlTestSuite * inSuite, void * inContext) +void CheckResendMessage(nlTestSuite * inSuite, void * inContext) { TestContext & ctx = *reinterpret_cast(inContext); - auto & m = manager; - m.TestSetIntervalShift(4); // 16ms per tick - m.Init(ctx.GetSystemLayer()); - ReliableMessageContext rc; - rc.Init(&m); - ReliableMessageDelegateObject delegate; - rc.SetDelegate(&delegate); - rc.SetConfig({ - 1, // CHIP_CONFIG_RMP_DEFAULT_INITIAL_RETRANS_TIMEOUT_TICK - 1, // CHIP_CONFIG_RMP_DEFAULT_ACTIVE_RETRANS_TIMEOUT_TICK - 1, // CHIP_CONFIG_RMP_DEFAULT_ACK_TIMEOUT_TICK - 2, // CHIP_CONFIG_RMP_DEFAULT_MAX_RETRANS - }); - ReliableMessageManager::RetransTableEntry * entry; - auto buf = System::PacketBuffer::New(); - m.AddToRetransTable(&rc, buf.Release_ForNow(), 1, 0, &entry); - NL_TEST_ASSERT(inSuite, m.TestGetCountRetransTable() == 1); - - test_os_sleep_ms(20); - ReliableMessageManager::Timeout(&ctx.GetSystemLayer(), &m, CHIP_SYSTEM_NO_ERROR); - NL_TEST_ASSERT(inSuite, m.TestGetCountRetransTable() == 1); - // 1st retrans - - test_os_sleep_ms(20); - ReliableMessageManager::Timeout(&ctx.GetSystemLayer(), &m, CHIP_SYSTEM_NO_ERROR); - NL_TEST_ASSERT(inSuite, m.TestGetCountRetransTable() == 1); - NL_TEST_ASSERT(inSuite, !delegate.SendErrorCalled); - // 2nd retrans - test_os_sleep_ms(20); - ReliableMessageManager::Timeout(&ctx.GetSystemLayer(), &m, CHIP_SYSTEM_NO_ERROR); - NL_TEST_ASSERT(inSuite, m.TestGetCountRetransTable() == 0); - NL_TEST_ASSERT(inSuite, delegate.SendErrorCalled); - // send error + uint16_t payload_len = sizeof(PAYLOAD); - m.Shutdown(); -} + ctx.GetInetLayer().SystemLayer()->Init(nullptr); -void CheckDelayDelivery(nlTestSuite * inSuite, void * inContext) -{ - TestContext & ctx = *reinterpret_cast(inContext); - auto & m = manager; - m.TestSetIntervalShift(4); // 16ms per tick - m.Init(ctx.GetSystemLayer()); - ReliableMessageContext rc; - rc.Init(&m); - ReliableMessageDelegateObject delegate; - rc.SetDelegate(&delegate); - rc.SetConfig({ + chip::System::PacketBufferHandle buffer = chip::System::PacketBuffer::NewWithAvailableSize(payload_len); + NL_TEST_ASSERT(inSuite, !buffer.IsNull()); + + memmove(buffer->Start(), PAYLOAD, payload_len); + buffer->SetDataLength(payload_len); + + IPAddress addr; + IPAddress::FromString("127.0.0.1", addr); + CHIP_ERROR err = CHIP_NO_ERROR; + + TransportMgr transportMgr; + SecureSessionMgr secureSessionMgr; + + err = transportMgr.Init("LOOPBACK"); + NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + err = secureSessionMgr.Init(kSourceNodeId, ctx.GetInetLayer().SystemLayer(), &transportMgr); + NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + + ExchangeManager exchangeMgr; + err = exchangeMgr.Init(&secureSessionMgr); + NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + + SecurePairingUsingTestSecret pairing1(Optional::Value(kSourceNodeId), 1, 2); + Optional peer(Transport::PeerAddress::UDP(addr, CHIP_PORT)); + + err = secureSessionMgr.NewPairing(peer, kDestinationNodeId, &pairing1); + NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + + SecurePairingUsingTestSecret pairing2(Optional::Value(kDestinationNodeId), 2, 1); + err = secureSessionMgr.NewPairing(peer, kSourceNodeId, &pairing2); + NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + + MockAppDelegate mockSender; + + // TODO: temprary create a SecureSessionHandle from node id, will be fix in PR 3602 + ExchangeContext * exchange = exchangeMgr.NewContext({ kDestinationNodeId, kAnyKeyId }, &mockSender); + NL_TEST_ASSERT(inSuite, exchange != nullptr); + + ReliableMessageManager * rm = exchangeMgr.GetReliableMessageMgr(); + ReliableMessageContext * rc = exchange->GetReliableMessageContext(); + NL_TEST_ASSERT(inSuite, rm != nullptr); + NL_TEST_ASSERT(inSuite, rc != nullptr); + + rc->SetConfig({ 1, // CHIP_CONFIG_RMP_DEFAULT_INITIAL_RETRANS_TIMEOUT_TICK 1, // CHIP_CONFIG_RMP_DEFAULT_ACTIVE_RETRANS_TIMEOUT_TICK 1, // CHIP_CONFIG_RMP_DEFAULT_ACK_TIMEOUT_TICK - 1, // CHIP_CONFIG_RMP_DEFAULT_MAX_RETRANS + 3, // CHIP_CONFIG_RMP_DEFAULT_MAX_RETRANS }); - ReliableMessageManager::RetransTableEntry * entry; - auto buf = System::PacketBuffer::New(); - m.AddToRetransTable(&rc, buf.Release_ForNow(), 1, 0, &entry); - m.ProcessDelayedDeliveryMessage(&rc, 64); - NL_TEST_ASSERT(inSuite, m.TestGetCountRetransTable() == 1); - - test_os_sleep_ms(50); - ReliableMessageManager::Timeout(&ctx.GetSystemLayer(), &m, CHIP_SYSTEM_NO_ERROR); - NL_TEST_ASSERT(inSuite, m.TestGetCountRetransTable() == 1); - // not send, delayed - - test_os_sleep_ms(50); - ReliableMessageManager::Timeout(&ctx.GetSystemLayer(), &m, CHIP_SYSTEM_NO_ERROR); - NL_TEST_ASSERT(inSuite, m.TestGetCountRetransTable() == 1); - NL_TEST_ASSERT(inSuite, !delegate.SendErrorCalled); - // 1st retrans - test_os_sleep_ms(20); - ReliableMessageManager::Timeout(&ctx.GetSystemLayer(), &m, CHIP_SYSTEM_NO_ERROR); - NL_TEST_ASSERT(inSuite, m.TestGetCountRetransTable() == 0); - NL_TEST_ASSERT(inSuite, delegate.SendErrorCalled); - // send error + gSendMessageCount = 0; - m.Shutdown(); + err = exchange->SendMessage(kProtocol_Echo, kEchoMessageType_EchoRequest, std::move(buffer), + Messaging::SendFlags(Messaging::SendMessageFlags::kNone)); + NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + + // 1 tick is 64 ms, sleep 65 ms to trigger first re-transmit + test_os_sleep_ms(65); + ReliableMessageManager::Timeout(&ctx.GetSystemLayer(), rm, CHIP_SYSTEM_NO_ERROR); + NL_TEST_ASSERT(inSuite, gSendMessageCount == 2); + + // sleep another 65 ms to trigger second re-transmit + test_os_sleep_ms(65); + ReliableMessageManager::Timeout(&ctx.GetSystemLayer(), rm, CHIP_SYSTEM_NO_ERROR); + NL_TEST_ASSERT(inSuite, gSendMessageCount == 3); } // Test Suite @@ -202,8 +289,7 @@ const nlTest sTests[] = { NL_TEST_DEF("Test ReliableMessageManager::CheckAddClearRetrans", CheckAddClearRetrans), NL_TEST_DEF("Test ReliableMessageManager::CheckFailRetrans", CheckFailRetrans), - NL_TEST_DEF("Test ReliableMessageManager::CheckRetransExpire", CheckRetransExpire), - NL_TEST_DEF("Test ReliableMessageManager::CheckDelayDelivery", CheckDelayDelivery), + NL_TEST_DEF("Test ReliableMessageManager::CheckResendMessage", CheckResendMessage), NL_TEST_SENTINEL() }; @@ -242,24 +328,6 @@ int Finalize(void * aContext) } // namespace -namespace chip { -namespace Messaging { - -// Stub implementation -CHIP_ERROR ReliableMessageManager::SendMessage(ReliableMessageContext * context, System::PacketBuffer * msgBuf, uint16_t sendFlags) -{ - return CHIP_NO_ERROR; -} -CHIP_ERROR ReliableMessageManager::SendMessage(ReliableMessageContext * context, uint32_t profileId, uint8_t msgType, - System::PacketBuffer * msgBuf, BitFlags sendFlags) -{ - return CHIP_NO_ERROR; -} -void ReliableMessageManager::FreeContext(ReliableMessageContext *) {} - -} // namespace Messaging -} // namespace chip - /** * Main */ diff --git a/src/messaging/tests/echo/Dockerfile.requester b/src/messaging/tests/echo/Dockerfile.requester new file mode 100644 index 00000000000000..dfd7856850ad1e --- /dev/null +++ b/src/messaging/tests/echo/Dockerfile.requester @@ -0,0 +1,6 @@ +from chip-cirque-device-base + +COPY out/chip-echo-requester /usr/bin/ +COPY entrypoint.sh / + +ENTRYPOINT ["/entrypoint.sh", "requester"] diff --git a/src/messaging/tests/echo/Dockerfile.responder b/src/messaging/tests/echo/Dockerfile.responder new file mode 100644 index 00000000000000..744c831ee1f318 --- /dev/null +++ b/src/messaging/tests/echo/Dockerfile.responder @@ -0,0 +1,6 @@ +from chip-cirque-device-base + +COPY out/chip-echo-responder /usr/bin/ +COPY entrypoint.sh / + +ENTRYPOINT ["/entrypoint.sh", "responder"] diff --git a/src/messaging/tests/echo/README.md b/src/messaging/tests/echo/README.md index 337ffd0afb3051..69a7fd05621ca0 100644 --- a/src/messaging/tests/echo/README.md +++ b/src/messaging/tests/echo/README.md @@ -40,12 +40,12 @@ EchoRequests and sends back EchoResponse messages. To start the Server in echo mode, run the built executable. - $ ./chip-echo-responder + $ ./chip-echo-responder [--tcp] To start the Client in echo mode, run the built executable and pass it the IP address of the server to talk to. - $ ./chip-echo-requester + $ ./chip-echo-requester [--tcp] If valid values are supplied, it will begin to periodically send messages to the server address provided for three times. diff --git a/src/messaging/tests/echo/common.cpp b/src/messaging/tests/echo/common.cpp index fed5640cedb4fb..b98088d233d666 100644 --- a/src/messaging/tests/echo/common.cpp +++ b/src/messaging/tests/echo/common.cpp @@ -68,7 +68,7 @@ void DriveIO(void) int selectRes; sleepTime.tv_sec = 0; - sleepTime.tv_usec = NETWORK_SLEEP_TIME_MSECS; + sleepTime.tv_usec = kNetworkSleepTimeMsecs; FD_ZERO(&readFDs); FD_ZERO(&writeFDs); diff --git a/src/messaging/tests/echo/common.h b/src/messaging/tests/echo/common.h index e3b43698e15ba9..95b8175d823b79 100644 --- a/src/messaging/tests/echo/common.h +++ b/src/messaging/tests/echo/common.h @@ -26,8 +26,9 @@ #include -#define MAX_MESSAGE_SOURCE_STR_LENGTH (100) -#define NETWORK_SLEEP_TIME_MSECS (100 * 1000) +constexpr size_t kMaxTcpActiveConnectionCount = 4; +constexpr size_t kMaxTcpPendingPackets = 4; +constexpr size_t kNetworkSleepTimeMsecs = (100 * 1000); extern chip::Messaging::ExchangeManager gExchangeManager; diff --git a/src/messaging/tests/echo/echo_requester.cpp b/src/messaging/tests/echo/echo_requester.cpp index 96a26376667947..948652d118f720 100644 --- a/src/messaging/tests/echo/echo_requester.cpp +++ b/src/messaging/tests/echo/echo_requester.cpp @@ -36,6 +36,7 @@ #include #include #include +#include #include #define ECHO_CLIENT_PORT (CHIP_PORT + 1) @@ -51,10 +52,9 @@ constexpr int32_t gEchoInterval = 1000; // The EchoClient object. chip::Protocols::EchoClient gEchoClient; -chip::TransportMgr gTransportManager; - +chip::TransportMgr gUDPManager; +chip::TransportMgr> gTCPManager; chip::SecureSessionMgr gSessionManager; - chip::Inet::IPAddress gDestAddr; // The last time a CHIP Echo was attempted to be sent. @@ -70,6 +70,8 @@ uint64_t gEchoCount = 0; // Count of the number of EchoResponses received. uint64_t gEchoRespCount = 0; +bool gUseTCP = false; + bool EchoIntervalExpired(void) { uint64_t now = chip::System::Timer::GetCurrentEpoch(); @@ -101,7 +103,7 @@ CHIP_ERROR SendEchoRequest(void) printf("\nSend echo request message to Node: %" PRIu64 "\n", chip::kTestDeviceNodeId); - err = gEchoClient.SendEchoRequest(chip::kTestDeviceNodeId, std::move(payloadBuf)); + err = gEchoClient.SendEchoRequest(std::move(payloadBuf)); if (err == CHIP_NO_ERROR) { @@ -120,14 +122,23 @@ CHIP_ERROR EstablishSecureSession() { CHIP_ERROR err = CHIP_NO_ERROR; + chip::Optional peerAddr; chip::SecurePairingUsingTestSecret * testSecurePairingSecret = chip::Platform::New( chip::Optional::Value(chip::kTestDeviceNodeId), static_cast(0), static_cast(0)); VerifyOrExit(testSecurePairingSecret != nullptr, err = CHIP_ERROR_NO_MEMORY); + if (gUseTCP) + { + peerAddr = chip::Optional::Value(chip::Transport::PeerAddress::TCP(gDestAddr, CHIP_PORT)); + } + else + { + peerAddr = chip::Optional::Value( + chip::Transport::PeerAddress::UDP(gDestAddr, CHIP_PORT, INET_NULL_INTERFACEID)); + } + // Attempt to connect to the peer. - err = gSessionManager.NewPairing(chip::Optional::Value( - chip::Transport::PeerAddress::UDP(gDestAddr, CHIP_PORT, INET_NULL_INTERFACEID)), - chip::kTestDeviceNodeId, testSecurePairingSecret); + err = gSessionManager.NewPairing(peerAddr, chip::kTestDeviceNodeId, testSecurePairingSecret); exit: if (err != CHIP_NO_ERROR) @@ -143,7 +154,7 @@ CHIP_ERROR EstablishSecureSession() return err; } -void HandleEchoResponseReceived(chip::NodeId nodeId, chip::System::PacketBufferHandle payload) +void HandleEchoResponseReceived(chip::Messaging::ExchangeContext * ec, chip::System::PacketBufferHandle payload) { uint32_t respTime = chip::System::Timer::GetCurrentEpoch(); uint32_t transitTime = respTime - gLastEchoTime; @@ -151,11 +162,18 @@ void HandleEchoResponseReceived(chip::NodeId nodeId, chip::System::PacketBufferH gWaitingForEchoResp = false; gEchoRespCount++; - printf("Echo Response from node %" PRIu64 ": %" PRIu64 "/%" PRIu64 "(%.2f%%) len=%u time=%.3fms\n", nodeId, gEchoRespCount, - gEchoCount, static_cast(gEchoRespCount) * 100 / gEchoCount, payload->DataLength(), - static_cast(transitTime) / 1000); + printf("Echo Response: %" PRIu64 "/%" PRIu64 "(%.2f%%) len=%u time=%.3fms\n", gEchoRespCount, gEchoCount, + static_cast(gEchoRespCount) * 100 / gEchoCount, payload->DataLength(), static_cast(transitTime) / 1000); } +class TestSecureSessionMgrDelegate : public chip::SecureSessionMgrDelegate +{ +public: + void OnNewConnection(chip::SecureSessionHandle session, chip::SecureSessionMgr * mgr) override { mSecureSession = session; } + + chip::SecureSessionHandle mSecureSession; +} gTestSecureSessionMgrDelegate; + } // namespace int main(int argc, char * argv[]) @@ -168,6 +186,17 @@ int main(int argc, char * argv[]) ExitNow(err = CHIP_ERROR_INVALID_ARGUMENT); } + if (argc > 3) + { + printf("Too many arguments specified!\n"); + ExitNow(err = CHIP_ERROR_INVALID_ARGUMENT); + } + + if ((argc == 3) && (strcmp(argv[2], "--tcp") == 0)) + { + gUseTCP = true; + } + if (!chip::Inet::IPAddress::FromString(argv[1], gDestAddr)) { printf("Invalid Echo Server IP address: %s\n", argv[1]); @@ -176,27 +205,42 @@ int main(int argc, char * argv[]) InitializeChip(); - err = gTransportManager.Init(chip::Transport::UdpListenParameters(&chip::DeviceLayer::InetLayer) - .SetAddressType(chip::Inet::kIPAddressType_IPv4) - .SetListenPort(ECHO_CLIENT_PORT)); - SuccessOrExit(err); + if (gUseTCP) + { + err = gTCPManager.Init(chip::Transport::TcpListenParameters(&chip::DeviceLayer::InetLayer) + .SetAddressType(chip::Inet::kIPAddressType_IPv4) + .SetListenPort(ECHO_CLIENT_PORT)); + SuccessOrExit(err); - err = gSessionManager.Init(chip::kTestControllerNodeId, &chip::DeviceLayer::SystemLayer, &gTransportManager); - SuccessOrExit(err); + err = gSessionManager.Init(chip::kTestControllerNodeId, &chip::DeviceLayer::SystemLayer, &gTCPManager); + SuccessOrExit(err); + } + else + { + err = gUDPManager.Init(chip::Transport::UdpListenParameters(&chip::DeviceLayer::InetLayer) + .SetAddressType(chip::Inet::kIPAddressType_IPv4) + .SetListenPort(ECHO_CLIENT_PORT)); + SuccessOrExit(err); + + err = gSessionManager.Init(chip::kTestControllerNodeId, &chip::DeviceLayer::SystemLayer, &gUDPManager); + SuccessOrExit(err); + } + + gSessionManager.SetDelegate(&gTestSecureSessionMgrDelegate); err = gExchangeManager.Init(&gSessionManager); SuccessOrExit(err); - err = gEchoClient.Init(&gExchangeManager); + // Start the CHIP connection to the CHIP echo responder. + err = EstablishSecureSession(); + SuccessOrExit(err); + + err = gEchoClient.Init(&gExchangeManager, gTestSecureSessionMgrDelegate.mSecureSession); SuccessOrExit(err); // Arrange to get a callback whenever an Echo Response is received. gEchoClient.SetEchoResponseReceived(HandleEchoResponseReceived); - // Start the CHIP connection to the CHIP echo responder. - err = EstablishSecureSession(); - SuccessOrExit(err); - // Connection has been established. Now send the EchoRequests. for (unsigned int i = 0; i < kMaxEchoCount; i++) { diff --git a/src/messaging/tests/echo/echo_responder.cpp b/src/messaging/tests/echo/echo_responder.cpp index afc4c4c23263fd..4a644ed270f9d9 100644 --- a/src/messaging/tests/echo/echo_responder.cpp +++ b/src/messaging/tests/echo/echo_responder.cpp @@ -36,20 +36,22 @@ #include #include #include +#include #include namespace { // The EchoServer object. chip::Protocols::EchoServer gEchoServer; -chip::TransportMgr gTransportManager; +chip::TransportMgr gUDPManager; +chip::TransportMgr> gTCPManager; chip::SecureSessionMgr gSessionManager; chip::SecurePairingUsingTestSecret gTestPairing; // Callback handler when a CHIP EchoRequest is received. -void HandleEchoRequestReceived(chip::NodeId nodeId, chip::System::PacketBufferHandle payload) +void HandleEchoRequestReceived(chip::Messaging::ExchangeContext * ec, chip::System::PacketBufferHandle payload) { - printf("Echo Request from node %" PRIu64 ", len=%u ... sending response.\n", nodeId, payload->DataLength()); + printf("Echo Request, len=%u ... sending response.\n", payload->DataLength()); } } // namespace @@ -58,15 +60,39 @@ int main(int argc, char * argv[]) { CHIP_ERROR err = CHIP_NO_ERROR; chip::Optional peer(chip::Transport::Type::kUndefined); + bool useTCP = false; + + if (argc > 2) + { + printf("Too many arguments specified!\n"); + ExitNow(err = CHIP_ERROR_INVALID_ARGUMENT); + } + + if ((argc == 2) && (strcmp(argv[1], "--tcp") == 0)) + { + useTCP = true; + } InitializeChip(); - err = gTransportManager.Init( - chip::Transport::UdpListenParameters(&chip::DeviceLayer::InetLayer).SetAddressType(chip::Inet::kIPAddressType_IPv4)); - SuccessOrExit(err); + if (useTCP) + { + err = gTCPManager.Init( + chip::Transport::TcpListenParameters(&chip::DeviceLayer::InetLayer).SetAddressType(chip::Inet::kIPAddressType_IPv4)); + SuccessOrExit(err); - err = gSessionManager.Init(chip::kTestDeviceNodeId, &chip::DeviceLayer::SystemLayer, &gTransportManager); - SuccessOrExit(err); + err = gSessionManager.Init(chip::kTestDeviceNodeId, &chip::DeviceLayer::SystemLayer, &gTCPManager); + SuccessOrExit(err); + } + else + { + err = gUDPManager.Init( + chip::Transport::UdpListenParameters(&chip::DeviceLayer::InetLayer).SetAddressType(chip::Inet::kIPAddressType_IPv4)); + SuccessOrExit(err); + + err = gSessionManager.Init(chip::kTestDeviceNodeId, &chip::DeviceLayer::SystemLayer, &gUDPManager); + SuccessOrExit(err); + } err = gExchangeManager.Init(&gSessionManager); SuccessOrExit(err); diff --git a/src/messaging/tests/echo/entrypoint.sh b/src/messaging/tests/echo/entrypoint.sh new file mode 100755 index 00000000000000..23c00c0a659a09 --- /dev/null +++ b/src/messaging/tests/echo/entrypoint.sh @@ -0,0 +1,16 @@ +#!/bin/bash + +service dbus start +sleep 1 +service avahi-daemon start +/usr/sbin/otbr-agent -I wpan0 spinel+hdlc+uart:///dev/ttyUSB0 & +sleep 1 +ot-ctl panid 0x1234 +ot-ctl ifconfig up +ot-ctl thread start + +if [ "$1" = "responder" ]; then + chip-echo-responder +else + sleep infinity +fi diff --git a/src/platform/BUILD.gn b/src/platform/BUILD.gn index 313e9d0de82da3..8157c42268d995 100644 --- a/src/platform/BUILD.gn +++ b/src/platform/BUILD.gn @@ -44,6 +44,9 @@ if (chip_device_platform != "none") { # By pass provision and secure session chip_bypass_rendezvous = false + + # Enable including the additional data in the advertisement packets + chip_enable_additional_data_advertising = true } buildconfig_header("platform_buildconfig") { @@ -79,7 +82,18 @@ if (chip_device_platform != "none") { defines += [ "CHIP_BYPASS_RENDEZVOUS=1" ] } - if (chip_device_platform == "darwin") { + if (chip_enable_additional_data_advertising) { + defines += [ "CHIP_ENABLE_ADDITIONAL_DATA_ADVERTISING=1" ] + } else { + defines += [ "CHIP_ENABLE_ADDITIONAL_DATA_ADVERTISING=0" ] + } + + if (chip_device_platform == "cc13x2_26x2") { + defines += [ + "CHIP_DEVICE_LAYER_TARGET_CC13X2_26X2=1", + "CHIP_DEVICE_LAYER_TARGET=cc13x2_26x2", + ] + } else if (chip_device_platform == "darwin") { defines += [ "CHIP_DEVICE_LAYER_TARGET_DARWIN=1", "CHIP_DEVICE_LAYER_TARGET=Darwin", @@ -208,7 +222,39 @@ if (chip_device_platform != "none" && chip_device_platform != "external") { public_deps += [ "${chip_root}/src/lib/mdns:platform_header" ] } - if (chip_device_platform == "darwin") { + if (chip_device_platform == "cc13x2_26x2") { + sources += [ + "FreeRTOS/SystemTimeSupport.cpp", + "cc13x2_26x2/BlePlatformConfig.h", + "cc13x2_26x2/CC13X2_26X2Config.cpp", + "cc13x2_26x2/CC13X2_26X2Config.h", + "cc13x2_26x2/CHIPDevicePlatformConfig.h", + "cc13x2_26x2/CHIPDevicePlatformConfig.h", + "cc13x2_26x2/CHIPDevicePlatformEvent.h", + "cc13x2_26x2/ConfigurationManagerImpl.cpp", + "cc13x2_26x2/ConnectivityManagerImpl.cpp", + "cc13x2_26x2/ConnectivityManagerImpl.h", + "cc13x2_26x2/InetPlatformConfig.h", + "cc13x2_26x2/Logging.cpp", + "cc13x2_26x2/PlatformManagerImpl.cpp", + "cc13x2_26x2/PlatformManagerImpl.h", + "cc13x2_26x2/SystemPlatformConfig.h", + ] + if (chip_enable_openthread) { + public_deps += [ + "${chip_root}/third_party/ti_simplelink_sdk:mbedtls", + "${chip_root}/third_party/ti_simplelink_sdk:ti_simplelink_sdk", + "${chip_root}/third_party/ti_simplelink_sdk:ti_simplelink_sysconfig", + "${openthread_root}:libopenthread-mtd", + ] + + sources += [ + "OpenThread/OpenThreadUtils.cpp", + "cc13x2_26x2/ThreadStackManagerImpl.cpp", + "cc13x2_26x2/ThreadStackManagerImpl.h", + ] + } + } else if (chip_device_platform == "darwin") { sources += [ "Darwin/BLEManagerImpl.cpp", "Darwin/BLEManagerImpl.h", @@ -395,32 +441,32 @@ if (chip_device_platform != "none" && chip_device_platform != "external") { public_deps += [ "${chip_root}/third_party/inipp" ] } else if (chip_device_platform == "nrfconnect") { sources += [ + "Zephyr/BLEManagerImpl.cpp", + "Zephyr/ConfigurationManagerImpl.cpp", + "Zephyr/Logging.cpp", + "Zephyr/PlatformManagerImpl.cpp", "Zephyr/SystemTimeSupport.cpp", - "nrfconnect/BLEManagerImpl.cpp", + "Zephyr/ZephyrConfig.cpp", + "Zephyr/ZephyrConfig.h", "nrfconnect/BLEManagerImpl.h", "nrfconnect/BlePlatformConfig.h", "nrfconnect/CHIPDevicePlatformConfig.h", "nrfconnect/CHIPDevicePlatformEvent.h", "nrfconnect/CHIPPlatformConfig.h", - "nrfconnect/ConfigurationManagerImpl.cpp", "nrfconnect/ConfigurationManagerImpl.h", "nrfconnect/ConnectivityManagerImpl.cpp", "nrfconnect/ConnectivityManagerImpl.h", "nrfconnect/DeviceNetworkProvisioningDelegateImpl.cpp", "nrfconnect/DeviceNetworkProvisioningDelegateImpl.h", "nrfconnect/InetPlatformConfig.h", - "nrfconnect/Logging.cpp", - "nrfconnect/PlatformManagerImpl.cpp", "nrfconnect/PlatformManagerImpl.h", "nrfconnect/SystemPlatformConfig.h", - "nrfconnect/ZephyrConfig.cpp", - "nrfconnect/ZephyrConfig.h", ] if (chip_enable_openthread) { sources += [ "OpenThread/OpenThreadUtils.cpp", - "nrfconnect/ThreadStackManagerImpl.cpp", + "Zephyr/ThreadStackManagerImpl.cpp", "nrfconnect/ThreadStackManagerImpl.h", ] } @@ -437,6 +483,7 @@ if (chip_device_platform != "none" && chip_device_platform != "external") { "qpg6100/ConfigurationManagerImpl.h", "qpg6100/ConnectivityManagerImpl.cpp", "qpg6100/ConnectivityManagerImpl.h", + "qpg6100/DeviceNetworkProvisioningDelegateImpl.cpp", "qpg6100/DeviceNetworkProvisioningDelegateImpl.h", "qpg6100/InetPlatformConfig.h", "qpg6100/Logging.cpp", diff --git a/src/platform/EFR32/BLEManagerImpl.cpp b/src/platform/EFR32/BLEManagerImpl.cpp index c0db6adfc76ce7..da43b4143065af 100644 --- a/src/platform/EFR32/BLEManagerImpl.cpp +++ b/src/platform/EFR32/BLEManagerImpl.cpp @@ -377,7 +377,7 @@ void BLEManagerImpl::_OnPlatformEvent(const ChipDeviceEvent * event) case DeviceEventType::kCHIPoBLEWriteReceived: { ChipLogProgress(DeviceLayer, "_OnPlatformEvent kCHIPoBLEWriteReceived"); HandleWriteReceived(event->CHIPoBLEWriteReceived.ConId, &CHIP_BLE_SVC_ID, &ChipUUID_CHIPoBLEChar_RX, - PacketBufferHandle::Create(event->CHIPoBLEWriteReceived.Data)); + PacketBufferHandle::Adopt(event->CHIPoBLEWriteReceived.Data)); } break; diff --git a/src/platform/ESP32/Logging.cpp b/src/platform/ESP32/Logging.cpp index e05be9eacca4e2..b3e02f51e80f1e 100644 --- a/src/platform/ESP32/Logging.cpp +++ b/src/platform/ESP32/Logging.cpp @@ -27,6 +27,11 @@ #include +#ifdef LOG_LOCAL_LEVEL +#undef LOG_LOCAL_LEVEL +#endif +#define LOG_LOCAL_LEVEL ESP_LOG_VERBOSE + #include "esp_log.h" using namespace ::chip; diff --git a/src/platform/ESP32/NetworkProvisioningServerImpl.cpp b/src/platform/ESP32/NetworkProvisioningServerImpl.cpp index 6de68937732a2b..17d27f9942a784 100644 --- a/src/platform/ESP32/NetworkProvisioningServerImpl.cpp +++ b/src/platform/ESP32/NetworkProvisioningServerImpl.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include "esp_event.h" #include "esp_wifi.h" @@ -232,7 +233,6 @@ void NetworkProvisioningServerImpl::HandleScanDone() wifi_ap_record_t * scanResults = NULL; uint16_t scanResultCount; uint16_t encodedResultCount; - PacketBuffer * respBuf = NULL; // If we receive a SCAN DONE event for a scan that we didn't initiate, simply ignore it. VerifyOrExit(mState == kState_ScanNetworks_InProgress, err = CHIP_NO_ERROR); @@ -263,19 +263,19 @@ void NetworkProvisioningServerImpl::HandleScanDone() // If the ScanNetworks request is still outstanding... if (GetCurrentOp() == kMsgType_ScanNetworks) { - chip::TLV::TLVWriter writer; + System::PacketBufferTLVWriter writer; TLVType outerContainerType; // Sort results by rssi. qsort(scanResults, scanResultCount, sizeof(*scanResults), ESP32Utils::OrderScanResultsByRSSI); // Allocate a packet buffer to hold the encoded scan results. - respBuf = PacketBuffer::New(CHIP_SYSTEM_CONFIG_HEADER_RESERVE_SIZE + 1); - VerifyOrExit(respBuf != NULL, err = CHIP_ERROR_NO_MEMORY); + PacketBufferHandle respBuf = PacketBuffer::New(CHIP_SYSTEM_CONFIG_HEADER_RESERVE_SIZE + 1); + VerifyOrExit(!respBuf.IsNull(), err = CHIP_ERROR_NO_MEMORY); // Encode the list of scan results into the response buffer. If the encoded size of all // the results exceeds the size of the buffer, encode only what will fit. - writer.Init(respBuf, respBuf->AvailableDataLength() - 1); + writer.Init(std::move(respBuf)); err = writer.StartContainer(AnonymousTag, kTLVType_Array, outerContainerType); SuccessOrExit(err); for (encodedResultCount = 0; encodedResultCount < scanResultCount; encodedResultCount++) @@ -306,19 +306,16 @@ void NetworkProvisioningServerImpl::HandleScanDone() } err = writer.EndContainer(outerContainerType); SuccessOrExit(err); - err = writer.Finalize(); + err = writer.Finalize(&respBuf); SuccessOrExit(err); // Send the scan results to the requestor. Note that this method takes ownership of the // buffer, success or fail. - err = SendNetworkScanComplete(encodedResultCount, respBuf); - respBuf = NULL; + err = SendNetworkScanComplete(encodedResultCount, std::move(respBuf)); SuccessOrExit(err); } exit: - PacketBuffer::Free(respBuf); - // If an error occurred and we haven't yet responded, send a Internal Error back to the // requestor. if (err != CHIP_NO_ERROR && GetCurrentOp() == kMsgType_ScanNetworks) diff --git a/src/platform/ESP32/bluedroid/BLEManagerImpl.cpp b/src/platform/ESP32/bluedroid/BLEManagerImpl.cpp index b9561c06037b39..fbc0a51caa6305 100644 --- a/src/platform/ESP32/bluedroid/BLEManagerImpl.cpp +++ b/src/platform/ESP32/bluedroid/BLEManagerImpl.cpp @@ -250,7 +250,7 @@ void BLEManagerImpl::_OnPlatformEvent(const ChipDeviceEvent * event) case DeviceEventType::kCHIPoBLEWriteReceived: HandleWriteReceived(event->CHIPoBLEWriteReceived.ConId, &CHIP_BLE_SVC_ID, &ChipUUID_CHIPoBLEChar_RX, - PacketBufferHandle::Create(event->CHIPoBLEWriteReceived.Data)); + PacketBufferHandle::Adopt(event->CHIPoBLEWriteReceived.Data)); break; case DeviceEventType::kCHIPoBLEIndicateConfirm: diff --git a/src/platform/ESP32/nimble/BLEManagerImpl.cpp b/src/platform/ESP32/nimble/BLEManagerImpl.cpp index bdee4efa422692..086a926edc1585 100644 --- a/src/platform/ESP32/nimble/BLEManagerImpl.cpp +++ b/src/platform/ESP32/nimble/BLEManagerImpl.cpp @@ -243,7 +243,7 @@ void BLEManagerImpl::_OnPlatformEvent(const ChipDeviceEvent * event) case DeviceEventType::kCHIPoBLEWriteReceived: HandleWriteReceived(event->CHIPoBLEWriteReceived.ConId, &CHIP_BLE_SVC_ID, &chipUUID_CHIPoBLEChar_RX, - PacketBufferHandle::Create(event->CHIPoBLEWriteReceived.Data)); + PacketBufferHandle::Adopt(event->CHIPoBLEWriteReceived.Data)); break; case DeviceEventType::kCHIPoBLEIndicateConfirm: @@ -380,6 +380,7 @@ void BLEManagerImpl::NotifyChipConnectionClosed(BLE_CONNECTION_OBJECT conId) {} void BLEManagerImpl::DriveBLEState(void) { + int ret; CHIP_ERROR err = CHIP_NO_ERROR; // Perform any initialization actions that must occur after the Chip task is running. @@ -469,9 +470,10 @@ void BLEManagerImpl::DriveBLEState(void) { if (GetFlag(mFlags, kFlag_Advertising)) { - err = ble_gap_adv_stop(); - if (err != CHIP_NO_ERROR) + ret = ble_gap_adv_stop(); + if (ret != 0) { + err = CHIP_ERROR_INTERNAL; ChipLogError(DeviceLayer, "ble_gap_adv_stop() failed: %s", ErrorStr(err)); ExitNow(); } @@ -1008,7 +1010,8 @@ int BLEManagerImpl::gatt_svr_chr_access(uint16_t conn_handle, uint16_t attr_hand CHIP_ERROR BLEManagerImpl::StartAdvertising(void) { - CHIP_ERROR err; + int ret; + ble_gap_adv_params adv_params; memset(&adv_params, 0, sizeof(adv_params)); uint8_t own_addr_type = BLE_OWN_ADDR_PUBLIC; @@ -1039,34 +1042,33 @@ CHIP_ERROR BLEManagerImpl::StartAdvertising(void) (((uint32_t) adv_params.itvl_min) * 10) / 16, (connectable) ? "" : "non-", mDeviceName); { - err = ble_gap_adv_start(own_addr_type, NULL, BLE_HS_FOREVER, &adv_params, ble_svr_gap_event, NULL); - if (err != CHIP_NO_ERROR) + ret = ble_gap_adv_start(own_addr_type, NULL, BLE_HS_FOREVER, &adv_params, ble_svr_gap_event, NULL); + if (ret == BLE_HS_EALREADY) { - ChipLogError(DeviceLayer, "ble_gap_adv_start() failed: %s", ErrorStr(err)); - ExitNow(); + /* This error code indicates that the advertising is already active. Stop and restart with the new parameters */ + ChipLogProgress(DeviceLayer, "Device already advertising, stop active advertisement and restart"); + ret = ble_gap_adv_stop(); + if (ret != 0) + { + ChipLogError(DeviceLayer, "ble_gap_adv_stop() failed: %d, cannot restart", ret); + return CHIP_ERROR_INTERNAL; + } + else + { + ret = ble_gap_adv_start(own_addr_type, NULL, BLE_HS_FOREVER, &adv_params, ble_svr_gap_event, NULL); + } } - } -exit: - if (err == BLE_HS_EALREADY && connectable) - { - ChipLogProgress(DeviceLayer, - "Connectable advertising failed because device was already advertising , stop active advertisement"); - err = ble_gap_adv_stop(); - if (err != CHIP_NO_ERROR) + if (ret == 0) { - ChipLogError(DeviceLayer, "ble_gap_adv_stop() failed: %s", ErrorStr(err)); + return CHIP_NO_ERROR; } else { - err = ble_gap_adv_start(own_addr_type, NULL, BLE_HS_FOREVER, &adv_params, ble_svr_gap_event, NULL); - if (err != CHIP_NO_ERROR) - { - ChipLogError(DeviceLayer, "Retried adv start; ble_gap_adv_start() failed: %s", ErrorStr(err)); - } + ChipLogError(DeviceLayer, "ble_gap_adv_start() failed: %d", ret); + return CHIP_ERROR_INTERNAL; } } - return err; } void BLEManagerImpl::DriveBLEState(intptr_t arg) diff --git a/src/platform/Linux/BLEManagerImpl.cpp b/src/platform/Linux/BLEManagerImpl.cpp index 2532f3dcee0dde..97bc770f8bf1f6 100644 --- a/src/platform/Linux/BLEManagerImpl.cpp +++ b/src/platform/Linux/BLEManagerImpl.cpp @@ -29,6 +29,7 @@ #include #include +#include #if CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE @@ -63,7 +64,6 @@ CHIP_ERROR BLEManagerImpl::_Init() err = BleLayer::Init(this, this, this, &SystemLayer); SuccessOrExit(err); - // TODO: for chip-tool set mIsCentral = true; mServiceMode = ConnectivityManager::kCHIPoBLEServiceMode_Enabled; mFlags = (CHIP_DEVICE_CONFIG_CHIPOBLE_ENABLE_ADVERTISING_AUTOSTART && !mIsCentral) ? kFlag_AdvertisingEnabled : 0; mAppState = nullptr; @@ -216,7 +216,7 @@ void BLEManagerImpl::_OnPlatformEvent(const ChipDeviceEvent * event) case DeviceEventType::kCHIPoBLEWriteReceived: HandleWriteReceived(event->CHIPoBLEWriteReceived.ConId, &CHIP_BLE_SVC_ID, &ChipUUID_CHIPoBLEChar_RX, - PacketBufferHandle::Create(event->CHIPoBLEWriteReceived.Data)); + PacketBufferHandle::Adopt(event->CHIPoBLEWriteReceived.Data)); break; case DeviceEventType::kCHIPoBLEIndicateConfirm: @@ -247,19 +247,37 @@ void BLEManagerImpl::_OnPlatformEvent(const ChipDeviceEvent * event) DriveBLEState(); break; default: + HandlePlatformSpecificBLEEvent(event); break; } - - HandlePlatformSpecificBLEEvent(event); } void BLEManagerImpl::HandlePlatformSpecificBLEEvent(const ChipDeviceEvent * apEvent) { CHIP_ERROR err = CHIP_NO_ERROR; bool controlOpComplete = false; - ChipLogProgress(DeviceLayer, "HandlePlatformSpecificBLEEvent , %d", apEvent->Type); + ChipLogProgress(DeviceLayer, "HandlePlatformSpecificBLEEvent %d", apEvent->Type); switch (apEvent->Type) { + case DeviceEventType::kPlatformLinuxBLECentralConnected: + if (OnConnectionComplete != nullptr) + OnConnectionComplete(mBLEScanConfig.mAppState, apEvent->Platform.BLECentralConnected.mConnection); + break; + case DeviceEventType::kPlatformLinuxBLEWriteComplete: + HandleWriteConfirmation(apEvent->Platform.BLEWriteComplete.mConnection, &CHIP_BLE_SVC_ID, &ChipUUID_CHIPoBLEChar_RX); + break; + case DeviceEventType::kPlatformLinuxBLESubscribeOpComplete: + if (apEvent->Platform.BLESubscribeOpComplete.mIsSubscribed) + HandleSubscribeComplete(apEvent->Platform.BLESubscribeOpComplete.mConnection, &CHIP_BLE_SVC_ID, + &ChipUUID_CHIPoBLEChar_TX); + else + HandleUnsubscribeComplete(apEvent->Platform.BLESubscribeOpComplete.mConnection, &CHIP_BLE_SVC_ID, + &ChipUUID_CHIPoBLEChar_TX); + break; + case DeviceEventType::kPlatformLinuxBLEIndicationReceived: + HandleIndicationReceived(apEvent->Platform.BLEIndicationReceived.mConnection, &CHIP_BLE_SVC_ID, &ChipUUID_CHIPoBLEChar_TX, + PacketBufferHandle::Adopt(apEvent->Platform.BLEIndicationReceived.mData)); + break; case DeviceEventType::kPlatformLinuxBLEPeripheralAdvConfiguredComplete: VerifyOrExit(apEvent->Platform.BLEPeripheralAdvConfiguredComplete.mIsSuccess, err = CHIP_ERROR_INCORRECT_STATE); SetFlag(sInstance.mFlags, kFlag_AdvertisingConfigured); @@ -323,14 +341,30 @@ uint16_t BLEManagerImpl::GetMTU(BLE_CONNECTION_OBJECT conId) const bool BLEManagerImpl::SubscribeCharacteristic(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const ChipBleUUID * charId) { - ChipLogError(DeviceLayer, "BLEManagerImpl::SubscribeCharacteristic() not supported"); - return true; + bool result = false; + + VerifyOrExit(Ble::UUIDsMatch(svcId, &CHIP_BLE_SVC_ID), + ChipLogError(DeviceLayer, "SubscribeCharacteristic() called with invalid service ID")); + VerifyOrExit(Ble::UUIDsMatch(charId, &ChipUUID_CHIPoBLEChar_TX), + ChipLogError(DeviceLayer, "SubscribeCharacteristic() called with invalid characteristic ID")); + + result = BluezSubscribeCharacteristic(conId); +exit: + return result; } bool BLEManagerImpl::UnsubscribeCharacteristic(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const ChipBleUUID * charId) { - ChipLogError(DeviceLayer, "BLEManagerImpl::UnsubscribeCharacteristic() not supported"); - return true; + bool result = false; + + VerifyOrExit(Ble::UUIDsMatch(svcId, &CHIP_BLE_SVC_ID), + ChipLogError(DeviceLayer, "UnsubscribeCharacteristic() called with invalid service ID")); + VerifyOrExit(Ble::UUIDsMatch(charId, &ChipUUID_CHIPoBLEChar_TX), + ChipLogError(DeviceLayer, "UnsubscribeCharacteristic() called with invalid characteristic ID")); + + result = BluezUnsubscribeCharacteristic(conId); +exit: + return result; } bool BLEManagerImpl::CloseConnection(BLE_CONNECTION_OBJECT conId) @@ -348,8 +382,16 @@ bool BLEManagerImpl::SendIndication(BLE_CONNECTION_OBJECT conId, const ChipBleUU bool BLEManagerImpl::SendWriteRequest(BLE_CONNECTION_OBJECT conId, const Ble::ChipBleUUID * svcId, const Ble::ChipBleUUID * charId, chip::System::PacketBufferHandle pBuf) { - ChipLogError(Ble, "SendWriteRequest: Not implemented"); - return true; + bool result = false; + + VerifyOrExit(Ble::UUIDsMatch(svcId, &CHIP_BLE_SVC_ID), + ChipLogError(DeviceLayer, "SendWriteRequest() called with invalid service ID")); + VerifyOrExit(Ble::UUIDsMatch(charId, &ChipUUID_CHIPoBLEChar_RX), + ChipLogError(DeviceLayer, "SendWriteRequest() called with invalid characteristic ID")); + + result = BluezSendWriteRequest(conId, std::move(pBuf)); +exit: + return result; } bool BLEManagerImpl::SendReadRequest(BLE_CONNECTION_OBJECT conId, const Ble::ChipBleUUID * svcId, const Ble::ChipBleUUID * charId, @@ -366,9 +408,57 @@ bool BLEManagerImpl::SendReadResponse(BLE_CONNECTION_OBJECT conId, BLE_READ_REQU return true; } -void BLEManagerImpl::CHIPoBluez_NewConnection(BLE_CONNECTION_OBJECT conId) +void BLEManagerImpl::HandleNewConnection(BLE_CONNECTION_OBJECT conId) +{ + if (sInstance.mIsCentral) + { + ChipDeviceEvent event; + event.Type = DeviceEventType::kPlatformLinuxBLECentralConnected; + event.Platform.BLECentralConnected.mConnection = conId; + PlatformMgr().PostEvent(&event); + } +} + +void BLEManagerImpl::HandleWriteComplete(BLE_CONNECTION_OBJECT conId) +{ + ChipDeviceEvent event; + event.Type = DeviceEventType::kPlatformLinuxBLEWriteComplete; + event.Platform.BLEWriteComplete.mConnection = conId; + PlatformMgr().PostEvent(&event); +} + +void BLEManagerImpl::HandleSubscribeOpComplete(BLE_CONNECTION_OBJECT conId, bool subscribed) { - ChipLogProgress(Ble, "CHIPoBluez_NewConnection: %p", conId); + ChipDeviceEvent event; + event.Type = DeviceEventType::kPlatformLinuxBLESubscribeOpComplete; + event.Platform.BLESubscribeOpComplete.mConnection = conId; + event.Platform.BLESubscribeOpComplete.mIsSubscribed = subscribed; + PlatformMgr().PostEvent(&event); +} + +void BLEManagerImpl::HandleTXCharChanged(BLE_CONNECTION_OBJECT conId, const uint8_t * value, size_t len) +{ + using DataLength = decltype(std::declval().AvailableDataLength()); + + CHIP_ERROR err = CHIP_NO_ERROR; + System::PacketBufferHandle buf = PacketBuffer::New(); + + ChipLogProgress(DeviceLayer, "Indication received, conn = %p", conId); + + VerifyOrExit(!buf.IsNull(), err = CHIP_ERROR_NO_MEMORY); + VerifyOrExit(buf->AvailableDataLength() >= len, err = CHIP_ERROR_BUFFER_TOO_SMALL); + memcpy(buf->Start(), value, len); + buf->SetDataLength(static_cast(len)); + + ChipDeviceEvent event; + event.Type = DeviceEventType::kPlatformLinuxBLEIndicationReceived; + event.Platform.BLEIndicationReceived.mConnection = conId; + event.Platform.BLEIndicationReceived.mData = buf.Release_ForNow(); + PlatformMgr().PostEvent(&event); + +exit: + if (err != CHIP_NO_ERROR) + ChipLogError(DeviceLayer, "HandleTXCharChanged() failed: %s", ErrorStr(err)); } void BLEManagerImpl::HandleRXCharWrite(BLE_CONNECTION_OBJECT conId, const uint8_t * value, size_t len) @@ -487,7 +577,7 @@ void BLEManagerImpl::DriveBLEState() } // Register the CHIPoBLE application with the Bluez BLE layer if needed. - if (mServiceMode == ConnectivityManager::kCHIPoBLEServiceMode_Enabled && !GetFlag(mFlags, kFlag_AppRegistered)) + if (!mIsCentral && mServiceMode == ConnectivityManager::kCHIPoBLEServiceMode_Enabled && !GetFlag(mFlags, kFlag_AppRegistered)) { err = BluezGattsAppRegister(static_cast(mpAppState)); SetFlag(mFlags, kFlag_ControlOpInProgress); @@ -535,7 +625,7 @@ void BLEManagerImpl::DriveBLEState() // Configure BLE scanning if (mBLEScanConfig.mDiscriminator && !GetFlag(mFlags, kFlag_Scanning)) { - err = StartDiscovery(static_cast(mpAppState), { mBLEScanConfig.mDiscriminator, /* mAutoConnect= */ true }); + err = StartDiscovery(static_cast(mpAppState), { mBLEScanConfig.mDiscriminator }); SuccessOrExit(err); SetFlag(mFlags, kFlag_Scanning); } diff --git a/src/platform/Linux/BLEManagerImpl.h b/src/platform/Linux/BLEManagerImpl.h index 296748fb05648d..dbf1b31a7f836a 100644 --- a/src/platform/Linux/BLEManagerImpl.h +++ b/src/platform/Linux/BLEManagerImpl.h @@ -94,7 +94,10 @@ class BLEManagerImpl final : public BLEManager, CHIP_ERROR ConfigureBle(uint32_t aNodeId, bool aIsCentral); // Driven by BlueZ IO - static void CHIPoBluez_NewConnection(BLE_CONNECTION_OBJECT user_data); + static void HandleNewConnection(BLE_CONNECTION_OBJECT conId); + static void HandleWriteComplete(BLE_CONNECTION_OBJECT conId); + static void HandleSubscribeOpComplete(BLE_CONNECTION_OBJECT conId, bool subscribed); + static void HandleTXCharChanged(BLE_CONNECTION_OBJECT conId, const uint8_t * value, size_t len); static void HandleRXCharWrite(BLE_CONNECTION_OBJECT user_data, const uint8_t * value, size_t len); static void CHIPoBluez_ConnectionClosed(BLE_CONNECTION_OBJECT user_data); static void HandleTXCharCCCDWrite(BLE_CONNECTION_OBJECT user_data); diff --git a/src/platform/Linux/CHIPBluezHelper.cpp b/src/platform/Linux/CHIPBluezHelper.cpp index 8d786e7e83ac10..33cf1290de07df 100644 --- a/src/platform/Linux/CHIPBluezHelper.cpp +++ b/src/platform/Linux/CHIPBluezHelper.cpp @@ -48,9 +48,11 @@ * Provides Bluez dbus implementatioon for BLE */ +#include #include #include #include +#include #if CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE #include @@ -61,20 +63,90 @@ #include #include +#include "BLEManagerImpl.h" #include "CHIPBluezHelper.h" #include +#include +#include using namespace ::nl; +using namespace chip::SetupPayload; +using namespace chip::Protocols; namespace chip { namespace DeviceLayer { namespace Internal { -static int sBluezFD[2]; -static GMainLoop * sBluezMainLoop = nullptr; -static pthread_t sBluezThread; static BluezConnection * GetBluezConnectionViaDevice(BluezEndpoint * apEndpoint); +namespace { +int sBluezFD[2]; +GMainLoop * sBluezMainLoop = nullptr; +pthread_t sBluezThread; + +/** @class BluezObjectIterator + * + * @brief Helper class to iterate over a list of Bluez objects + */ +class BluezObjectIterator +{ +public: + using iterator_category = std::forward_iterator_tag; + using difference_type = std::ptrdiff_t; + using value_type = BluezObject; + using pointer = BluezObject *; + using reference = BluezObject &; + + BluezObjectIterator() = default; + explicit BluezObjectIterator(GList * position) : mPosition(position) {} + + reference operator*() const { return *BLUEZ_OBJECT(mPosition->data); } + pointer operator->() const { return BLUEZ_OBJECT(mPosition->data); } + bool operator==(const BluezObjectIterator & other) const { return mPosition == other.mPosition; } + bool operator!=(const BluezObjectIterator & other) const { return mPosition != other.mPosition; } + + BluezObjectIterator & operator++() + { + mPosition = mPosition->next; + return *this; + } + + BluezObjectIterator operator++(int) + { + const auto currentPosition = mPosition; + mPosition = mPosition->next; + return BluezObjectIterator(currentPosition); + } + +private: + GList * mPosition = nullptr; +}; + +/** @class BluezObjectList + * + * @brief C++ wrapper for a Bluez object list + */ +class BluezObjectList +{ +public: + explicit BluezObjectList(BluezEndpoint * apEndpoint) + { + VerifyOrReturn(apEndpoint != nullptr, ChipLogError(DeviceLayer, "apEndpoint is NULL in %s", __func__)); + VerifyOrReturn(apEndpoint->mpObjMgr != nullptr, ChipLogError(DeviceLayer, "mpObjMgr is NULL in %s", __func__)); + mObjectList = g_dbus_object_manager_get_objects(apEndpoint->mpObjMgr); + } + + ~BluezObjectList() { g_list_free_full(mObjectList, g_object_unref); } + + BluezObjectIterator begin() const { return BluezObjectIterator(mObjectList); } + BluezObjectIterator end() const { return BluezObjectIterator(); } + +private: + GList * mObjectList = nullptr; +}; + +} // namespace + static gboolean BluezAdvertisingRelease(BluezLEAdvertisement1 * aAdv, GDBusMethodInvocation * aInvocation, gpointer apClosure) { bool isSuccess = false; @@ -695,6 +767,11 @@ static void BluezConnectionInit(BluezConnection * apConn) { apConn->mpC2 = char1; } + else if ((BluezIsCharOnService(char1, apConn->mpService) == TRUE) && + (strcmp(bluez_gatt_characteristic1_get_uuid(char1), CHIP_PLAT_BLE_UUID_C3_STRING) == 0)) + { + apConn->mpC3 = char1; + } else { g_object_unref(char1); @@ -715,17 +792,6 @@ static void BluezConnectionInit(BluezConnection * apConn) g_list_free_full(objects, g_object_unref); } -static gboolean BluezConnectionInitIdle(gpointer user_data) -{ - BluezConnection * conn = static_cast(user_data); - - ChipLogDetail(DeviceLayer, "%s", __func__); - - BluezConnectionInit(conn); - - return FALSE; -} - static void BluezOTConnectionDestroy(BluezConnection * aConn) { if (aConn) @@ -821,157 +887,100 @@ gboolean BluezPeripheralRegisterApp(void * apClosure) return G_SOURCE_REMOVE; } -/*********************************************************************** - * GATT Characteristic object - ***********************************************************************/ +/// Retrieve CHIP device identification info from the device advertising data +static bool BluezGetChipDeviceInfo(BluezDevice1 & aDevice, chip::Ble::ChipBLEDeviceIdentificationInfo & aDeviceInfo) +{ + GVariant * serviceData = bluez_device1_get_service_data(&aDevice); + VerifyOrReturnError(serviceData != nullptr, false); + + GVariant * dataValue = g_variant_lookup_value(serviceData, CHIP_BLE_UUID_SERVICE_STRING, nullptr); + VerifyOrReturnError(dataValue != nullptr, false); -static void BluezHandleAdvertisementFromDevice(BluezDevice1 * aDevice, BluezEndpoint * endpoint) + size_t dataLen = 0; + const void * dataBytes = g_variant_get_fixed_array(dataValue, &dataLen, sizeof(uint8_t)); + VerifyOrReturnError(dataBytes != nullptr && dataLen >= sizeof(aDeviceInfo), false); + + memcpy(&aDeviceInfo, dataBytes, sizeof(aDeviceInfo)); + return true; +} + +/// Handle advertisement from a device and connect to it if its discriminator is the requested one. +static void BluezHandleAdvertisementFromDevice(BluezDevice1 * aDevice, BluezEndpoint * aEndpoint) { const char * address = bluez_device1_get_address(aDevice); - const char * flags = bluez_device1_get_advertising_flags(aDevice); GVariant * serviceData = bluez_device1_get_service_data(aDevice); - - GVariantIter serviceIterator; - GVariant * serviceEntry; - chip::Ble::ChipBleUUID uuid; + char * debugStr = nullptr; chip::Ble::ChipBLEDeviceIdentificationInfo deviceInfo; - char * debugStr = nullptr; - size_t dataLen; - // service data is optional and may not be present VerifyOrExit(serviceData != nullptr, ); - ChipLogDetail(DeviceLayer, "TRACE: Device %s Advertising flags: %s", address, flags); debugStr = g_variant_print(serviceData, TRUE); ChipLogDetail(DeviceLayer, "TRACE: Device %s Service data: %s", address, debugStr); - g_variant_iter_init(&serviceIterator, serviceData); - - while ((serviceEntry = g_variant_iter_next_value(&serviceIterator)) != nullptr) - { - GVariant * key = g_variant_get_child_value(serviceEntry, 0); - GVariant * val = g_variant_get_child_value(serviceEntry, 1); - const auto uuidStr = g_variant_get_string(key, &dataLen); - const void * rawData; - - VerifyOrExit(chip::Ble::StringToUUID(uuidStr, uuid), ChipLogError(DeviceLayer, "TRACE: Invalid BLE UUID format")); + VerifyOrExit(BluezGetChipDeviceInfo(*aDevice, deviceInfo), ); + ChipLogDetail(DeviceLayer, "TRACE: Found CHIP BLE Device: %" PRIu16, deviceInfo.GetDeviceDiscriminator()); - if (!UUIDsMatch(&uuid, &Ble::CHIP_BLE_SVC_ID)) - continue; + if (aEndpoint->mDiscoveryRequest.mDiscriminator == deviceInfo.GetDeviceDiscriminator()) + ConnectDevice(aDevice); +exit: + g_free(debugStr); +} - rawData = g_variant_get_fixed_array(g_variant_get_variant(val), &dataLen, sizeof(uint8_t)); - VerifyOrExit(dataLen == sizeof(deviceInfo), ChipLogError(DeviceLayer, "TRACE: Invalid BLE Device info")); +/// Update the table of open BLE connections whevener a new device is spotted or its attributes have changed. +static void UpdateConnectionTable(BluezDevice1 * apDevice, BluezEndpoint & aEndpoint) +{ + const gchar * objectPath = g_dbus_proxy_get_object_path(G_DBUS_PROXY(apDevice)); + BluezConnection * connection = static_cast(g_hash_table_lookup(aEndpoint.mpConnMap, objectPath)); - memcpy(&deviceInfo, rawData, dataLen); - ChipLogDetail(DeviceLayer, "TRACE: Found CHIP BLE Device: %" PRIu16, deviceInfo.GetDeviceDiscriminator()); + if (connection != nullptr && !bluez_device1_get_connected(apDevice)) + { + ChipLogDetail(DeviceLayer, "Bluez disconnected"); + BLEManagerImpl::CHIPoBluez_ConnectionClosed(connection); + // TODO: the connection object should be released after BLEManagerImpl finishes cleaning up its resources + // after the disconnection. Releasing it here doesn't cause any issues, but it's error-prone. + BluezOTConnectionDestroy(connection); + g_hash_table_remove(aEndpoint.mpConnMap, objectPath); + return; + } - if (endpoint->mDiscoveryRequest.mDiscriminator == deviceInfo.GetDeviceDiscriminator() && - endpoint->mDiscoveryRequest.mAutoConnect) - ConnectDevice(aDevice); + if (connection == nullptr && !bluez_device1_get_connected(apDevice) && aEndpoint.mIsCentral) + { + // Check if the new device is the one that the central is trying to connect to. + BluezHandleAdvertisementFromDevice(apDevice, &aEndpoint); + return; } -exit: - g_free(debugStr); + if (connection == nullptr && bluez_device1_get_connected(apDevice) && + (!aEndpoint.mIsCentral || bluez_device1_get_services_resolved(apDevice))) + { + connection = g_new0(BluezConnection, 1); + connection->mpPeerAddress = g_strdup(bluez_device1_get_address(apDevice)); + connection->mpDevice = static_cast(g_object_ref(apDevice)); + connection->mpEndpoint = &aEndpoint; + BluezConnectionInit(connection); + aEndpoint.mpPeerDevicePath = g_strdup(objectPath); + g_hash_table_insert(aEndpoint.mpConnMap, aEndpoint.mpPeerDevicePath, connection); + + ChipLogDetail(DeviceLayer, "New BLE connection %p, device %s, path %s", connection, connection->mpPeerAddress, + aEndpoint.mpPeerDevicePath); + + BLEManagerImpl::HandleNewConnection(connection); + } } static void BluezSignalInterfacePropertiesChanged(GDBusObjectManagerClient * aManager, GDBusObjectProxy * aObject, GDBusProxy * aInterface, GVariant * aChangedProperties, const gchar * const * aInvalidatedProps, gpointer apClosure) { - BluezEndpoint * endpoint = static_cast(apClosure); - VerifyOrExit(endpoint != nullptr, ChipLogError(DeviceLayer, "endpoint is NULL in %s", __func__)); - VerifyOrExit(endpoint->mpAdapter != nullptr, ChipLogError(DeviceLayer, "FAIL: NULL endpoint->mpAdapter in %s", __func__)); - - if (strcmp(g_dbus_proxy_get_interface_name(aInterface), DEVICE_INTERFACE) == 0) - { - BluezDevice1 * device = BLUEZ_DEVICE1(aInterface); - GVariantIter iter; - GVariant * value; - char * key; - - if (BluezIsDeviceOnAdapter(device, endpoint->mpAdapter)) - { - BluezConnection * conn = - static_cast(g_hash_table_lookup(endpoint->mpConnMap, g_dbus_proxy_get_object_path(aInterface))); - g_variant_iter_init(&iter, aChangedProperties); - while (g_variant_iter_next(&iter, "{&sv}", &key, &value)) - { - if (strcmp(key, "Connected") == 0) - { - gboolean connected; - connected = g_variant_get_boolean(value); - - if (connected) - { - ChipLogDetail(DeviceLayer, "Bluez coonnected"); - // for a central, the connection has been already allocated. For a peripheral, it has not. - // todo do we need this ? we could handle all connection the same wa... - if (endpoint->mIsCentral) - SuccessOrExit(conn != nullptr); - - if (!endpoint->mIsCentral) - { - VerifyOrExit(conn == nullptr, - ChipLogError(DeviceLayer, "FAIL: connection already tracked: conn: %x device: %s", conn, - g_dbus_proxy_get_object_path(aInterface))); - conn = g_new0(BluezConnection, 1); - conn->mpPeerAddress = g_strdup(bluez_device1_get_address(device)); - conn->mpDevice = static_cast(g_object_ref(device)); - conn->mpEndpoint = endpoint; - BluezConnectionInit(conn); - endpoint->mpPeerDevicePath = g_strdup(g_dbus_proxy_get_object_path(aInterface)); - ChipLogDetail(DeviceLayer, "Device %s (Path: %s) Connected", conn->mpPeerAddress, - endpoint->mpPeerDevicePath); - g_hash_table_insert(endpoint->mpConnMap, endpoint->mpPeerDevicePath, conn); - } - // for central, we do not call BluezConnectionInit until the services have been resolved - - BLEManagerImpl::CHIPoBluez_NewConnection(conn); - } - else - { - ChipLogDetail(DeviceLayer, "Bluez disconnected"); - BLEManagerImpl::CHIPoBluez_ConnectionClosed(conn); - BluezOTConnectionDestroy(conn); - g_hash_table_remove(endpoint->mpConnMap, g_dbus_proxy_get_object_path(aInterface)); - } - } - else if (strcmp(key, "ServicesResolved") == 0) - { - gboolean resolved; - resolved = g_variant_get_boolean(value); + VerifyOrReturn(endpoint != nullptr, ChipLogError(DeviceLayer, "endpoint is NULL in %s", __func__)); + VerifyOrReturn(endpoint->mpAdapter != nullptr, ChipLogError(DeviceLayer, "FAIL: NULL endpoint->mpAdapter in %s", __func__)); + VerifyOrReturn(strcmp(g_dbus_proxy_get_interface_name(aInterface), DEVICE_INTERFACE) == 0, ); - if (endpoint->mIsCentral && conn != nullptr && resolved == TRUE) - { - /* delay to idle, this is to workaround race in handling - * of interface-added and properites-changed signals - * it looks like we cannot specify order of those - * handlers and currently implementation assumes - * that interfaces-added is called first. - * - * TODO figure out if we can avoid this - */ - g_idle_add(BluezConnectionInitIdle, conn); - } - } - else if (strcmp(key, "RSSI") == 0) - { - /* when discovery starts we will get this one device is - * found even if device object was already present - */ - if (endpoint->mIsCentral) - { - BluezHandleAdvertisementFromDevice(device, endpoint); - } - } + BluezDevice1 * device = BLUEZ_DEVICE1(aInterface); + VerifyOrReturn(BluezIsDeviceOnAdapter(device, endpoint->mpAdapter)); - g_variant_unref(value); - } - } - } -exit: - return; + UpdateConnectionTable(device, *endpoint); } static void BluezHandleNewDevice(BluezDevice1 * device, BluezEndpoint * apEndpoint) @@ -1256,11 +1265,57 @@ void BluezObjectsCleanup(BluezEndpoint * apEndpoint) EndpointCleanup(apEndpoint); } +#if CHIP_ENABLE_ADDITIONAL_DATA_ADVERTISING +static void UpdateAdditionalDataCharacteristic(BluezGattCharacteristic1 * characteristic) +{ + if (characteristic == nullptr) + { + return; + } + + // Construct the TLV for the additional data + GVariant * cValue = nullptr; + CHIP_ERROR err = CHIP_NO_ERROR; + System::PacketBufferTLVWriter writer; + TLVWriter innerWriter; + chip::System::PacketBufferHandle bufferHandle; + + writer.Init(chip::System::PacketBuffer::New()); + + err = writer.OpenContainer(AnonymousTag, kTLVType_Structure, innerWriter); + SuccessOrExit(err); + + // Adding the rotating device id to the TLV data + err = innerWriter.PutString(ContextTag(kRotatingDeviceIdTag), CHIP_ROTATING_DEVICE_ID); + SuccessOrExit(err); + + err = writer.CloseContainer(innerWriter); + SuccessOrExit(err); + + err = writer.Finalize(&bufferHandle); + SuccessOrExit(err); + + cValue = g_variant_new_from_data(G_VARIANT_TYPE("ay"), bufferHandle->Start(), bufferHandle->DataLength(), TRUE, g_free, + g_memdup(bufferHandle->Start(), bufferHandle->DataLength())); + bluez_gatt_characteristic1_set_value(characteristic, cValue); + + return; + +exit: + if (err != CHIP_NO_ERROR) + { + ChipLogError(DeviceLayer, "Failed to generate TLV encoded Additional Data", __func__); + } + return; +} +#endif + static void BluezPeripheralObjectsSetup(gpointer apClosure) { static const char * const c1_flags[] = { "write", nullptr }; static const char * const c2_flags[] = { "read", "indicate", nullptr }; + static const char * const c3_flags[] = { "read", nullptr }; BluezEndpoint * endpoint = static_cast(apClosure); VerifyOrExit(endpoint != nullptr, ChipLogError(DeviceLayer, "endpoint is NULL in %s", __func__)); @@ -1293,6 +1348,27 @@ static void BluezPeripheralObjectsSetup(gpointer apClosure) ChipLogDetail(DeviceLayer, "CHIP BTP C1 %s", bluez_gatt_characteristic1_get_service(endpoint->mpC1)); ChipLogDetail(DeviceLayer, "CHIP BTP C2 %s", bluez_gatt_characteristic1_get_service(endpoint->mpC2)); +#if CHIP_ENABLE_ADDITIONAL_DATA_ADVERTISING + ChipLogDetail(DeviceLayer, "CHIP_ENABLE_ADDITIONAL_DATA_ADVERTISING is TRUE"); + // Additional data characteristics + endpoint->mpC3 = + BluezCharacteristicCreate(endpoint->mpService, g_strdup("c3"), g_strdup(CHIP_PLAT_BLE_UUID_C3_STRING), endpoint->mpRoot); + bluez_gatt_characteristic1_set_flags(endpoint->mpC3, c3_flags); + g_signal_connect(endpoint->mpC3, "handle-read-value", G_CALLBACK(BluezCharacteristicReadValue), apClosure); + g_signal_connect(endpoint->mpC3, "handle-write-value", G_CALLBACK(BluezCharacteristicWriteValueError), NULL); + g_signal_connect(endpoint->mpC3, "handle-acquire-write", G_CALLBACK(BluezCharacteristicAcquireWriteError), NULL); + g_signal_connect(endpoint->mpC3, "handle-acquire-notify", G_CALLBACK(BluezCharacteristicAcquireNotify), apClosure); + g_signal_connect(endpoint->mpC3, "handle-start-notify", G_CALLBACK(BluezCharacteristicStartNotify), apClosure); + g_signal_connect(endpoint->mpC3, "handle-stop-notify", G_CALLBACK(BluezCharacteristicStopNotify), apClosure); + g_signal_connect(endpoint->mpC3, "handle-confirm", G_CALLBACK(BluezCharacteristicConfirm), apClosure); + // update the characteristic value + UpdateAdditionalDataCharacteristic(endpoint->mpC3); + ChipLogDetail(DeviceLayer, "CHIP BTP C3 %s", bluez_gatt_characteristic1_get_service(endpoint->mpC3)); +#else + ChipLogDetail(DeviceLayer, "CHIP_ENABLE_ADDITIONAL_DATA_ADVERTISING is FALSE"); + (void) c3_flags; +#endif + exit: return; } @@ -1304,10 +1380,14 @@ static void BluezOnBusAcquired(GDBusConnection * aConn, const gchar * aName, gpo ChipLogDetail(DeviceLayer, "TRACE: Bus acquired for name %s", aName); - endpoint->mpRootPath = g_strdup_printf("/chipoble/%04x", getpid() & 0xffff); - endpoint->mpRoot = g_dbus_object_manager_server_new(endpoint->mpRootPath); - g_dbus_object_manager_server_set_connection(endpoint->mpRoot, aConn); - BluezPeripheralObjectsSetup(apClosure); + if (!endpoint->mIsCentral) + { + endpoint->mpRootPath = g_strdup_printf("/chipoble/%04x", getpid() & 0xffff); + endpoint->mpRoot = g_dbus_object_manager_server_new(endpoint->mpRootPath); + g_dbus_object_manager_server_set_connection(endpoint->mpRoot, aConn); + + BluezPeripheralObjectsSetup(apClosure); + } exit: return; @@ -1445,31 +1525,24 @@ static gboolean BluezC2Indicate(void * apClosure) return G_SOURCE_REMOVE; } +static ConnectionDataBundle * MakeConnectionDataBundle(BLE_CONNECTION_OBJECT apConn, const chip::System::PacketBufferHandle & apBuf) +{ + ConnectionDataBundle * bundle = g_new(ConnectionDataBundle, 1); + bundle->mpConn = static_cast(apConn); + bundle->mpVal = + g_variant_new_fixed_array(G_VARIANT_TYPE_BYTE, apBuf->Start(), apBuf->DataLength() * sizeof(uint8_t), sizeof(uint8_t)); + return bundle; +} + bool SendBluezIndication(BLE_CONNECTION_OBJECT apConn, chip::System::PacketBufferHandle apBuf) { - ConnectionDataBundle * closure; - const char * msg = nullptr; - bool success = false; - uint8_t * buffer = nullptr; - size_t len = 0; + bool success = false; VerifyOrExit(!apBuf.IsNull(), ChipLogError(DeviceLayer, "apBuf is NULL in %s", __func__)); - buffer = apBuf->Start(); - len = apBuf->DataLength(); - - closure = g_new(ConnectionDataBundle, 1); - closure->mpConn = static_cast(apConn); - closure->mpVal = g_variant_new_fixed_array(G_VARIANT_TYPE_BYTE, buffer, len * sizeof(uint8_t), sizeof(uint8_t)); - - success = BluezRunOnBluezThread(BluezC2Indicate, closure); + success = BluezRunOnBluezThread(BluezC2Indicate, MakeConnectionDataBundle(apConn, apBuf)); exit: - if (nullptr != msg) - { - ChipLogError(Ble, msg); - } - return success; } @@ -1626,6 +1699,144 @@ CHIP_ERROR InitBluezBleLayer(bool aIsCentral, char * apBleAddr, BLEAdvConfig & a return err; } +// BluezSendWriteRequest callbacks + +static void SendWriteRequestDone(GObject * aObject, GAsyncResult * aResult, gpointer apConnection) +{ + BluezGattCharacteristic1 * c1 = BLUEZ_GATT_CHARACTERISTIC1(aObject); + GError * error = nullptr; + gboolean success = bluez_gatt_characteristic1_call_write_value_finish(c1, aResult, &error); + + VerifyOrExit(success == TRUE, ChipLogError(DeviceLayer, "FAIL: BluezSendWriteRequest : %s", error->message)); + BLEManagerImpl::HandleWriteComplete(static_cast(apConnection)); + +exit: + if (error != nullptr) + g_error_free(error); +} + +static gboolean SendWriteRequestImpl(void * apConnectionData) +{ + ConnectionDataBundle * data = static_cast(apConnectionData); + GVariant * options = nullptr; + GVariantBuilder optionsBuilder; + + VerifyOrExit(data != nullptr, ChipLogError(DeviceLayer, "ConnectionDataBundle is NULL in %s", __func__)); + VerifyOrExit(data->mpConn != nullptr, ChipLogError(DeviceLayer, "BluezConnection is NULL in %s", __func__)); + VerifyOrExit(data->mpConn->mpC1 != nullptr, ChipLogError(DeviceLayer, "C1 is NULL in %s", __func__)); + + g_variant_builder_init(&optionsBuilder, G_VARIANT_TYPE_ARRAY); + g_variant_builder_add(&optionsBuilder, "{sv}", "type", g_variant_new_string("request")); + options = g_variant_builder_end(&optionsBuilder); + + bluez_gatt_characteristic1_call_write_value(data->mpConn->mpC1, data->mpVal, options, nullptr, SendWriteRequestDone, + data->mpConn); + +exit: + g_free(data); + return G_SOURCE_REMOVE; +} + +bool BluezSendWriteRequest(BLE_CONNECTION_OBJECT apConn, chip::System::PacketBufferHandle apBuf) +{ + bool success = false; + + VerifyOrExit(!apBuf.IsNull(), ChipLogError(DeviceLayer, "apBuf is NULL in %s", __func__)); + + success = BluezRunOnBluezThread(SendWriteRequestImpl, MakeConnectionDataBundle(apConn, apBuf)); + +exit: + return success; +} + +// BluezSubscribeCharacteristic callbacks + +static void OnCharacteristicChanged(GDBusProxy * aInterface, GVariant * aChangedProperties, const gchar * const * aInvalidatedProps, + gpointer apConnection) +{ + BLE_CONNECTION_OBJECT connection = static_cast(apConnection); + GVariant * value = g_variant_lookup_value(aChangedProperties, "Value", G_VARIANT_TYPE_BYTESTRING); + VerifyOrReturn(value != nullptr); + + size_t bufferLen; + auto buffer = g_variant_get_fixed_array(value, &bufferLen, sizeof(uint8_t)); + VerifyOrReturn(value != nullptr, ChipLogError(DeviceLayer, "Characteristic value has unexpected type")); + + BLEManagerImpl::HandleTXCharChanged(connection, static_cast(buffer), bufferLen); +} + +static void SubscribeCharacteristicDone(GObject * aObject, GAsyncResult * aResult, gpointer apConnection) +{ + BluezGattCharacteristic1 * c2 = BLUEZ_GATT_CHARACTERISTIC1(aObject); + GError * error = nullptr; + gboolean success = bluez_gatt_characteristic1_call_write_value_finish(c2, aResult, &error); + + VerifyOrExit(success == TRUE, ChipLogError(DeviceLayer, "FAIL: BluezSubscribeCharacteristic : %s", error->message)); + + // Get notifications on the TX characteristic change (e.g. indication is received) + g_signal_connect(c2, "g-properties-changed", G_CALLBACK(OnCharacteristicChanged), apConnection); + BLEManagerImpl::HandleSubscribeOpComplete(static_cast(apConnection), true); + +exit: + if (error != nullptr) + g_error_free(error); +} + +static gboolean SubscribeCharacteristicImpl(void * apConnection) +{ + BluezConnection * connection = static_cast(apConnection); + + VerifyOrExit(connection != nullptr, ChipLogError(DeviceLayer, "BluezConnection is NULL in %s", __func__)); + VerifyOrExit(connection->mpC2 != nullptr, ChipLogError(DeviceLayer, "C2 is NULL in %s", __func__)); + + bluez_gatt_characteristic1_call_start_notify(connection->mpC2, nullptr, SubscribeCharacteristicDone, connection); + +exit: + return G_SOURCE_REMOVE; +} + +bool BluezSubscribeCharacteristic(BLE_CONNECTION_OBJECT apConn) +{ + return BluezRunOnBluezThread(SubscribeCharacteristicImpl, apConn); +} + +// BluezUnsubscribeCharacteristic callbacks + +static void UnsubscribeCharacteristicDone(GObject * aObject, GAsyncResult * aResult, gpointer apConnection) +{ + BluezGattCharacteristic1 * c2 = BLUEZ_GATT_CHARACTERISTIC1(aObject); + GError * error = nullptr; + gboolean success = bluez_gatt_characteristic1_call_write_value_finish(c2, aResult, &error); + + VerifyOrExit(success == TRUE, ChipLogError(DeviceLayer, "FAIL: BluezUnsubscribeCharacteristic : %s", error->message)); + + // Stop listening to the TX characteristic changes + g_signal_handlers_disconnect_by_data(c2, apConnection); + BLEManagerImpl::HandleSubscribeOpComplete(static_cast(apConnection), false); + +exit: + if (error != nullptr) + g_error_free(error); +} + +static gboolean UnsubscribeCharacteristicImpl(void * apConnection) +{ + BluezConnection * connection = static_cast(apConnection); + + VerifyOrExit(connection != nullptr, ChipLogError(DeviceLayer, "BluezConnection is NULL in %s", __func__)); + VerifyOrExit(connection->mpC2 != nullptr, ChipLogError(DeviceLayer, "C2 is NULL in %s", __func__)); + + bluez_gatt_characteristic1_call_start_notify(connection->mpC2, nullptr, UnsubscribeCharacteristicDone, connection); + +exit: + return G_SOURCE_REMOVE; +} + +bool BluezUnsubscribeCharacteristic(BLE_CONNECTION_OBJECT apConn) +{ + return BluezRunOnBluezThread(UnsubscribeCharacteristicImpl, apConn); +} + // StartDiscovery callbacks using DiscoveryTaskArg = std::pair; @@ -1644,6 +1855,29 @@ void StartDiscoveryDone(GObject * aObject, GAsyncResult * aResult, gpointer apEn g_error_free(error); } +static bool CheckIfAlreadyDiscovered(BluezEndpoint & aEndpoint) +{ + chip::Ble::ChipBLEDeviceIdentificationInfo deviceInfo; + + for (BluezObject & object : BluezObjectList(&aEndpoint)) + { + BluezDevice1 * device = bluez_object_get_device1(&object); + if (device == nullptr || !BluezIsDeviceOnAdapter(device, aEndpoint.mpAdapter)) + continue; + + if (!BluezGetChipDeviceInfo(*device, deviceInfo)) + continue; + + if (deviceInfo.GetDeviceDiscriminator() != aEndpoint.mDiscoveryRequest.mDiscriminator) + continue; + + UpdateConnectionTable(device, aEndpoint); + return true; + } + + return false; +} + static gboolean StartDiscoveryImpl(void * apDiscoveryTaskArg) { DiscoveryTaskArg * taskArg = static_cast(apDiscoveryTaskArg); @@ -1655,7 +1889,16 @@ static gboolean StartDiscoveryImpl(void * apDiscoveryTaskArg) VerifyOrExit(endpoint != nullptr, ChipLogError(DeviceLayer, "endpoint is NULL in %s", __func__)); VerifyOrExit(endpoint->mpAdapter != nullptr, ChipLogError(DeviceLayer, "mpAdapter is NULL in %s", __func__)); + // Bluez may already know the device in which case there's no need to discover it endpoint->mDiscoveryRequest = taskArg->second; + + if (CheckIfAlreadyDiscovered(*endpoint)) + { + ChipLogProgress(DeviceLayer, "Device already discovered"); + endpoint->mDiscoveryRequest = {}; + ExitNow(); + } + bluez_adapter1_call_start_discovery(endpoint->mpAdapter, nullptr, StartDiscoveryDone, endpoint); exit: diff --git a/src/platform/Linux/CHIPBluezHelper.h b/src/platform/Linux/CHIPBluezHelper.h index 03ab1b2d825e6e..a07c15592f4650 100644 --- a/src/platform/Linux/CHIPBluezHelper.h +++ b/src/platform/Linux/CHIPBluezHelper.h @@ -50,13 +50,13 @@ #pragma once -#include "BLEManagerImpl.h" -#include -#include #if CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE -#include "ble/CHIPBleServiceData.h" -#include "platform/Linux/dbus/bluez/DbusBluez.h" +#include +#include +#include + +#include namespace chip { namespace DeviceLayer { @@ -75,11 +75,12 @@ namespace Internal { #define CHIP_PLAT_BLE_UUID_C1_STRING "18ee2ef5-263d-4559-959f-4f9c429f9d11" #define CHIP_PLAT_BLE_UUID_C2_STRING "18ee2ef5-263d-4559-959f-4f9c429f9d12" +#define CHIP_PLAT_BLE_UUID_C3_STRING "64630238-8772-45F2-B87D-748A83218F04" #define CHIP_BLE_BASE_SERVICE_UUID_STRING "-0000-1000-8000-00805f9b34fb" #define CHIP_BLE_SERVICE_PREFIX_LENGTH 8 #define CHIP_BLE_BASE_SERVICE_PREFIX "0000" -#define CHIP_BLE_UUID_SERVICE_SHORT_STRING "fffb" +#define CHIP_BLE_UUID_SERVICE_SHORT_STRING "feaf" #define CHIP_BLE_UUID_SERVICE_STRING \ CHIP_BLE_BASE_SERVICE_PREFIX CHIP_BLE_UUID_SERVICE_SHORT_STRING CHIP_BLE_BASE_SERVICE_UUID_STRING @@ -93,8 +94,6 @@ namespace Internal { #define BLUEZ_ADV_FLAGS_LE_EDR_CONTROLLER (1 << 3) #define BLUEZ_ADV_FLAGS_LE_EDR_HOST (1 << 4) -#define CHAR_TO_BLUEZ(c) (static_cast(((c) <= '9') ? (c) - '0' : tolower((c)) - 'a' + 10)) - enum BluezAddressType { BLUEZ_ADDRESS_TYPE_PUBLIC = 0, ///< Bluetooth public device address. @@ -115,27 +114,9 @@ struct IOChannel guint mWatch; }; -struct CHIPIdInfo -{ - uint8_t mMajor; - uint8_t mMinor; - uint16_t mVendorId; - uint16_t mProductId; - uint64_t mDeviceId; - uint8_t mPairingStatus; -} __attribute__((packed)); - -struct CHIPServiceData -{ - uint8_t mDataBlock0Len; - uint8_t mDataBlock0Type; - CHIPIdInfo mIdInfo; -} __attribute__((packed)); - struct BluezDiscoveryRequest { uint16_t mDiscriminator; - bool mAutoConnect; }; struct BluezEndpoint @@ -161,11 +142,12 @@ struct BluezEndpoint BluezGattService1 * mpService; BluezGattCharacteristic1 * mpC1; BluezGattCharacteristic1 * mpC2; + // additional data characteristics + BluezGattCharacteristic1 * mpC3; // map device path to the connection GHashTable * mpConnMap; uint32_t mNodeId; - bool mIsNotify; bool mIsCentral; char * mpAdvertisingUUID; chip::Ble::ChipBLEDeviceIdentificationInfo mDeviceIdInfo; @@ -185,6 +167,9 @@ struct BluezConnection BluezGattService1 * mpService; BluezGattCharacteristic1 * mpC1; BluezGattCharacteristic1 * mpC2; + // additional data characteristics + BluezGattCharacteristic1 * mpC3; + bool mIsNotify; uint16_t mMtu; struct IOChannel mC1Channel; @@ -207,7 +192,15 @@ CHIP_ERROR StopBluezAdv(BluezEndpoint * apEndpoint); CHIP_ERROR BluezGattsAppRegister(BluezEndpoint * apEndpoint); CHIP_ERROR BluezAdvertisementSetup(BluezEndpoint * apEndpoint); -CHIP_ERROR StartDiscovery(BluezEndpoint * apEndpoint, BluezDiscoveryRequest aRequest = {}); +/// Write to the CHIP RX characteristic on the remote peripheral device +bool BluezSendWriteRequest(BLE_CONNECTION_OBJECT apConn, chip::System::PacketBufferHandle apBuf); +/// Subscribe to the CHIP TX characteristic on the remote peripheral device +bool BluezSubscribeCharacteristic(BLE_CONNECTION_OBJECT apConn); +/// Unsubscribe from the CHIP TX characteristic on the remote peripheral device +bool BluezUnsubscribeCharacteristic(BLE_CONNECTION_OBJECT apConn); + +CHIP_ERROR +StartDiscovery(BluezEndpoint * apEndpoint, BluezDiscoveryRequest aRequest = {}); CHIP_ERROR StopDiscovery(BluezEndpoint * apEndpoint); CHIP_ERROR ConnectDevice(BluezDevice1 * apDevice); diff --git a/src/platform/Linux/CHIPDevicePlatformEvent.h b/src/platform/Linux/CHIPDevicePlatformEvent.h index 42cc9d503ecc7d..cccd64654aac1a 100644 --- a/src/platform/Linux/CHIPDevicePlatformEvent.h +++ b/src/platform/Linux/CHIPDevicePlatformEvent.h @@ -44,6 +44,10 @@ enum PublicPlatformSpecificEventTypes enum InternalPlatformSpecificEventTypes { kPlatformLinuxEvent = kRange_InternalPlatformSpecific, + kPlatformLinuxBLECentralConnected, + kPlatformLinuxBLEWriteComplete, + kPlatformLinuxBLESubscribeOpComplete, + kPlatformLinuxBLEIndicationReceived, kPlatformLinuxBLEC1WriteEvent, kPlatformLinuxBLEOutOfBuffersEvent, kPlatformLinuxBLEPeripheralRegisterAppComplete, @@ -61,6 +65,24 @@ struct ChipDevicePlatformEvent { union { + struct + { + BLE_CONNECTION_OBJECT mConnection; + } BLECentralConnected; + struct + { + BLE_CONNECTION_OBJECT mConnection; + } BLEWriteComplete; + struct + { + BLE_CONNECTION_OBJECT mConnection; + bool mIsSubscribed; + } BLESubscribeOpComplete; + struct + { + BLE_CONNECTION_OBJECT mConnection; + chip::System::PacketBuffer * mData; + } BLEIndicationReceived; struct { bool mIsSuccess; diff --git a/src/platform/Linux/ConnectivityManagerImpl.cpp b/src/platform/Linux/ConnectivityManagerImpl.cpp index 8b0e82fa6169cb..6b0348c4abae55 100644 --- a/src/platform/Linux/ConnectivityManagerImpl.cpp +++ b/src/platform/Linux/ConnectivityManagerImpl.cpp @@ -239,19 +239,6 @@ CHIP_ERROR ConnectivityManagerImpl::_Init() GenericConnectivityManagerImpl_Thread::_Init(); #endif -#if CHIP_DEVICE_CONFIG_ENABLE_WPA - mConnectivityFlag = 0; - mWpaSupplicant.state = GDBusWpaSupplicant::INIT; - mWpaSupplicant.scanState = GDBusWpaSupplicant::WIFI_SCANNING_IDLE; - mWpaSupplicant.proxy = nullptr; - mWpaSupplicant.iface = nullptr; - mWpaSupplicant.interfacePath = nullptr; - mWpaSupplicant.networkPath = nullptr; - - wpa_fi_w1_wpa_supplicant1_proxy_new_for_bus(G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, kWpaSupplicantServiceName, - kWpaSupplicantObjectPath, nullptr, _OnWpaProxyReady, nullptr); -#endif - SuccessOrExit(err); exit: @@ -630,6 +617,20 @@ void ConnectivityManagerImpl::_OnWpaProxyReady(GObject * source_object, GAsyncRe g_error_free(err); } +void ConnectivityManagerImpl::StartWiFiManagement() +{ + mConnectivityFlag = 0; + mWpaSupplicant.state = GDBusWpaSupplicant::INIT; + mWpaSupplicant.scanState = GDBusWpaSupplicant::WIFI_SCANNING_IDLE; + mWpaSupplicant.proxy = nullptr; + mWpaSupplicant.iface = nullptr; + mWpaSupplicant.interfacePath = nullptr; + mWpaSupplicant.networkPath = nullptr; + + wpa_fi_w1_wpa_supplicant1_proxy_new_for_bus(G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, kWpaSupplicantServiceName, + kWpaSupplicantObjectPath, nullptr, _OnWpaProxyReady, nullptr); +} + void ConnectivityManagerImpl::DriveAPState() { CHIP_ERROR err = CHIP_NO_ERROR; diff --git a/src/platform/Linux/ConnectivityManagerImpl.h b/src/platform/Linux/ConnectivityManagerImpl.h index c59fba16f7b635..fbcd9e052897a2 100644 --- a/src/platform/Linux/ConnectivityManagerImpl.h +++ b/src/platform/Linux/ConnectivityManagerImpl.h @@ -106,6 +106,10 @@ class ConnectivityManagerImpl final : public ConnectivityManager, public: CHIP_ERROR ProvisionWiFiNetwork(const char * ssid, const char * key); +#if CHIP_DEVICE_CONFIG_ENABLE_WPA + void StartWiFiManagement(); +#endif + private: // ===== Members that implement the ConnectivityManager abstract interface. @@ -151,8 +155,8 @@ class ConnectivityManagerImpl final : public ConnectivityManager, // ==================== ConnectivityManager Private Methods ==================== #if CHIP_DEVICE_CONFIG_ENABLE_WPA - void DriveAPState(void); - CHIP_ERROR ConfigureWiFiAP(void); + void DriveAPState(); + CHIP_ERROR ConfigureWiFiAP(); void ChangeWiFiAPState(WiFiAPState newState); static void DriveAPState(::chip::System::Layer * aLayer, void * aAppState, ::chip::System::Error aError); #endif @@ -174,22 +178,23 @@ class ConnectivityManagerImpl final : public ConnectivityManager, uint32_t mWiFiAPIdleTimeoutMS; }; -inline ConnectivityManager::WiFiAPMode ConnectivityManagerImpl::_GetWiFiAPMode(void) +#if CHIP_DEVICE_CONFIG_ENABLE_WPA +inline ConnectivityManager::WiFiAPMode ConnectivityManagerImpl::_GetWiFiAPMode() { return mWiFiAPMode; } -inline bool ConnectivityManagerImpl::_IsWiFiAPActive(void) +inline bool ConnectivityManagerImpl::_IsWiFiAPActive() { return mWiFiAPState == kWiFiAPState_Active; } -inline bool ConnectivityManagerImpl::_IsWiFiAPApplicationControlled(void) +inline bool ConnectivityManagerImpl::_IsWiFiAPApplicationControlled() { return mWiFiAPMode == kWiFiAPMode_ApplicationControlled; } -inline uint32_t ConnectivityManagerImpl::_GetWiFiAPIdleTimeoutMS(void) +inline uint32_t ConnectivityManagerImpl::_GetWiFiAPIdleTimeoutMS() { return mWiFiAPIdleTimeoutMS; } @@ -198,6 +203,7 @@ inline bool ConnectivityManagerImpl::_HaveServiceConnectivity() { return _HaveServiceConnectivityViaThread(); } +#endif /** * Returns the public interface of the ConnectivityManager singleton object. diff --git a/src/platform/Linux/MdnsImpl.cpp b/src/platform/Linux/MdnsImpl.cpp index 472b83075dd6ee..9f8d5e334242ff 100644 --- a/src/platform/Linux/MdnsImpl.cpp +++ b/src/platform/Linux/MdnsImpl.cpp @@ -468,6 +468,17 @@ CHIP_ERROR MdnsAvahi::PublishService(const MdnsService & service) static_cast(0), service.mName, type.c_str(), nullptr, nullptr, service.mPort, text) == 0, error = CHIP_ERROR_INTERNAL); + for (size_t i = 0; i < service.mSubTypeSize; i++) + { + std::ostringstream sstream; + + sstream << service.mSubTypes[i] << "._sub." << type; + + VerifyOrExit(avahi_entry_group_add_service_subtype(mGroup, interface, ToAvahiProtocol(service.mAddressType), + static_cast(0), service.mName, type.c_str(), + nullptr, sstream.str().c_str()) == 0, + error = CHIP_ERROR_INTERNAL); + } } else { @@ -478,6 +489,7 @@ CHIP_ERROR MdnsAvahi::PublishService(const MdnsService & service) nullptr, text) == 0, error = CHIP_ERROR_INTERNAL); } + VerifyOrExit(avahi_entry_group_commit(mGroup) == 0, error = CHIP_ERROR_INTERNAL); exit: diff --git a/src/platform/Zephyr/GenericBLEManagerImpl_Zephyr.cpp b/src/platform/Zephyr/BLEManagerImpl.cpp similarity index 78% rename from src/platform/Zephyr/GenericBLEManagerImpl_Zephyr.cpp rename to src/platform/Zephyr/BLEManagerImpl.cpp index 378081925b444f..2a0e1b79e24805 100644 --- a/src/platform/Zephyr/GenericBLEManagerImpl_Zephyr.cpp +++ b/src/platform/Zephyr/BLEManagerImpl.cpp @@ -21,10 +21,11 @@ * for Zephyr platforms. */ -#ifndef GENERIC_BLE_MANAGER_IMPL_ZEPHYR_IPP -#define GENERIC_BLE_MANAGER_IMPL_ZEPHYR_IPP +#include -#include +#if CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE + +#include #include #include @@ -45,9 +46,6 @@ namespace chip { namespace DeviceLayer { namespace Internal { -// Fully instantiate the generic implementation class in whatever compilation unit includes this file. -template class GenericBLEManagerImpl_Zephyr; - namespace { const bt_uuid_128 UUID128_CHIPoBLEChar_RX = @@ -62,8 +60,7 @@ const ChipBleUUID chipUUID_CHIPoBLEChar_RX = { { 0x18, 0xEE, 0x2E, 0xF5, 0x26, 0 const ChipBleUUID chipUUID_CHIPoBLEChar_TX = { { 0x18, 0xEE, 0x2E, 0xF5, 0x26, 0x3D, 0x45, 0x59, 0x95, 0x9F, 0x4F, 0x9C, 0x42, 0x9F, 0x9D, 0x12 } }; -_bt_gatt_ccc CHIPoBLEChar_TX_CCC = - BT_GATT_CCC_INITIALIZER(nullptr, GenericBLEManagerImpl_Zephyr::HandleTXCCCWrite, nullptr); +_bt_gatt_ccc CHIPoBLEChar_TX_CCC = BT_GATT_CCC_INITIALIZER(nullptr, BLEManagerImpl::HandleTXCCCWrite, nullptr); // clang-format off @@ -72,7 +69,7 @@ BT_GATT_SERVICE_DEFINE(CHIPoBLE_Service, BT_GATT_CHARACTERISTIC(&UUID128_CHIPoBLEChar_RX.uuid, BT_GATT_CHRC_WRITE | BT_GATT_CHRC_WRITE_WITHOUT_RESP, BT_GATT_PERM_READ | BT_GATT_PERM_WRITE, - nullptr, GenericBLEManagerImpl_Zephyr::HandleRXWrite, nullptr), + nullptr, BLEManagerImpl::HandleRXWrite, nullptr), BT_GATT_CHARACTERISTIC(&UUID128_CHIPoBLEChar_TX.uuid, BT_GATT_CHRC_INDICATE, BT_GATT_PERM_NONE, @@ -88,8 +85,9 @@ constexpr int kCHIPoBLE_CCC_AttributeIndex = 3; } // unnamed namespace -template -CHIP_ERROR GenericBLEManagerImpl_Zephyr::_Init() +BLEManagerImpl BLEManagerImpl::sInstance; + +CHIP_ERROR BLEManagerImpl::_Init() { CHIP_ERROR err; @@ -118,14 +116,12 @@ CHIP_ERROR GenericBLEManagerImpl_Zephyr::_Init() return err; } -template -void GenericBLEManagerImpl_Zephyr::DriveBLEState(intptr_t arg) +void BLEManagerImpl::DriveBLEState(intptr_t arg) { BLEMgrImpl().DriveBLEState(); } -template -void GenericBLEManagerImpl_Zephyr::DriveBLEState() +void BLEManagerImpl::DriveBLEState() { CHIP_ERROR err = CHIP_NO_ERROR; @@ -179,15 +175,13 @@ void GenericBLEManagerImpl_Zephyr::DriveBLEState() } } -template -struct GenericBLEManagerImpl_Zephyr::ServiceData +struct BLEManagerImpl::ServiceData { uint8_t uuid[2]; ChipBLEDeviceIdentificationInfo deviceIdInfo; } __attribute__((packed)); -template -CHIP_ERROR GenericBLEManagerImpl_Zephyr::StartAdvertising(void) +CHIP_ERROR BLEManagerImpl::StartAdvertising(void) { CHIP_ERROR err; @@ -253,8 +247,7 @@ CHIP_ERROR GenericBLEManagerImpl_Zephyr::StartAdvertising(void) return err; } -template -CHIP_ERROR GenericBLEManagerImpl_Zephyr::StopAdvertising(void) +CHIP_ERROR BLEManagerImpl::StopAdvertising(void) { CHIP_ERROR err = CHIP_NO_ERROR; @@ -289,8 +282,7 @@ CHIP_ERROR GenericBLEManagerImpl_Zephyr::StopAdvertising(void) return err; } -template -CHIP_ERROR GenericBLEManagerImpl_Zephyr::_SetCHIPoBLEServiceMode(CHIPoBLEServiceMode val) +CHIP_ERROR BLEManagerImpl::_SetCHIPoBLEServiceMode(CHIPoBLEServiceMode val) { CHIP_ERROR err = CHIP_NO_ERROR; @@ -307,8 +299,7 @@ CHIP_ERROR GenericBLEManagerImpl_Zephyr::_SetCHIPoBLEServiceMode(CHIP return err; } -template -CHIP_ERROR GenericBLEManagerImpl_Zephyr::_SetAdvertisingEnabled(bool val) +CHIP_ERROR BLEManagerImpl::_SetAdvertisingEnabled(bool val) { CHIP_ERROR err = CHIP_NO_ERROR; @@ -326,8 +317,7 @@ CHIP_ERROR GenericBLEManagerImpl_Zephyr::_SetAdvertisingEnabled(bool return err; } -template -CHIP_ERROR GenericBLEManagerImpl_Zephyr::_SetFastAdvertisingEnabled(bool val) +CHIP_ERROR BLEManagerImpl::_SetFastAdvertisingEnabled(bool val) { CHIP_ERROR err = CHIP_NO_ERROR; @@ -345,8 +335,7 @@ CHIP_ERROR GenericBLEManagerImpl_Zephyr::_SetFastAdvertisingEnabled(b return err; } -template -CHIP_ERROR GenericBLEManagerImpl_Zephyr::_GetDeviceName(char * buf, size_t bufSize) +CHIP_ERROR BLEManagerImpl::_GetDeviceName(char * buf, size_t bufSize) { size_t len = bufSize - 1; @@ -356,8 +345,7 @@ CHIP_ERROR GenericBLEManagerImpl_Zephyr::_GetDeviceName(char * buf, s return CHIP_NO_ERROR; } -template -CHIP_ERROR GenericBLEManagerImpl_Zephyr::_SetDeviceName(const char * deviceName) +CHIP_ERROR BLEManagerImpl::_SetDeviceName(const char * deviceName) { if (mServiceMode != ConnectivityManager::kCHIPoBLEServiceMode_NotSupported) { @@ -368,8 +356,7 @@ CHIP_ERROR GenericBLEManagerImpl_Zephyr::_SetDeviceName(const char * return MapErrorZephyr(bt_set_name(deviceName)); } -template -CHIP_ERROR GenericBLEManagerImpl_Zephyr::HandleGAPConnect(const ChipDeviceEvent * event) +CHIP_ERROR BLEManagerImpl::HandleGAPConnect(const ChipDeviceEvent * event) { const BleConnEventType * connEvent = &event->Platform.BleConnEvent; @@ -393,8 +380,7 @@ CHIP_ERROR GenericBLEManagerImpl_Zephyr::HandleGAPConnect(const ChipD return CHIP_NO_ERROR; } -template -CHIP_ERROR GenericBLEManagerImpl_Zephyr::HandleGAPDisconnect(const ChipDeviceEvent * event) +CHIP_ERROR BLEManagerImpl::HandleGAPDisconnect(const ChipDeviceEvent * event) { const BleConnEventType * connEvent = &event->Platform.BleConnEvent; @@ -435,8 +421,7 @@ CHIP_ERROR GenericBLEManagerImpl_Zephyr::HandleGAPDisconnect(const Ch return CHIP_NO_ERROR; } -template -CHIP_ERROR GenericBLEManagerImpl_Zephyr::HandleTXCharCCCDWrite(const ChipDeviceEvent * event) +CHIP_ERROR BLEManagerImpl::HandleTXCharCCCDWrite(const ChipDeviceEvent * event) { const BleCCCWriteEventType * writeEvent = &event->Platform.BleCCCWriteEvent; @@ -472,8 +457,7 @@ CHIP_ERROR GenericBLEManagerImpl_Zephyr::HandleTXCharCCCDWrite(const return CHIP_NO_ERROR; } -template -CHIP_ERROR GenericBLEManagerImpl_Zephyr::HandleRXCharWrite(const ChipDeviceEvent * event) +CHIP_ERROR BLEManagerImpl::HandleRXCharWrite(const ChipDeviceEvent * event) { const BleC1WriteEventType * c1WriteEvent = &event->Platform.BleC1WriteEvent; @@ -481,14 +465,13 @@ CHIP_ERROR GenericBLEManagerImpl_Zephyr::HandleRXCharWrite(const Chip bt_conn_index(c1WriteEvent->BtConn)); HandleWriteReceived(c1WriteEvent->BtConn, &CHIP_BLE_SVC_ID, &chipUUID_CHIPoBLEChar_RX, - PacketBufferHandle::Create(c1WriteEvent->Data)); + PacketBufferHandle::Adopt(c1WriteEvent->Data)); bt_conn_unref(c1WriteEvent->BtConn); return CHIP_NO_ERROR; } -template -CHIP_ERROR GenericBLEManagerImpl_Zephyr::HandleTXComplete(const ChipDeviceEvent * event) +CHIP_ERROR BLEManagerImpl::HandleTXComplete(const ChipDeviceEvent * event) { const BleC2IndDoneEventType * c2IndDoneEvent = &event->Platform.BleC2IndDoneEvent; @@ -502,16 +485,13 @@ CHIP_ERROR GenericBLEManagerImpl_Zephyr::HandleTXComplete(const ChipD return CHIP_NO_ERROR; } -template -void GenericBLEManagerImpl_Zephyr::HandleBLEAdvertisementTimeout(System::Layer * layer, void * param, - System::Error error) +void BLEManagerImpl::HandleBLEAdvertisementTimeout(System::Layer * layer, void * param, System::Error error) { BLEMgr().SetAdvertisingEnabled(false); ChipLogProgress(DeviceLayer, "CHIPoBLE advertising disabled because of timeout expired"); } -template -void GenericBLEManagerImpl_Zephyr::_OnPlatformEvent(const ChipDeviceEvent * event) +void BLEManagerImpl::_OnPlatformEvent(const ChipDeviceEvent * event) { CHIP_ERROR err = CHIP_NO_ERROR; @@ -571,44 +551,36 @@ void GenericBLEManagerImpl_Zephyr::_OnPlatformEvent(const ChipDeviceE } } -template -uint16_t GenericBLEManagerImpl_Zephyr::_NumConnections(void) +uint16_t BLEManagerImpl::_NumConnections(void) { return mGAPConns; } -template -bool GenericBLEManagerImpl_Zephyr::CloseConnection(BLE_CONNECTION_OBJECT conId) +bool BLEManagerImpl::CloseConnection(BLE_CONNECTION_OBJECT conId) { ChipLogProgress(DeviceLayer, "Closing BLE GATT connection (ConnId %02" PRIx16 ")", bt_conn_index(conId)); return bt_conn_disconnect(conId, BT_HCI_ERR_REMOTE_USER_TERM_CONN) == CHIP_NO_ERROR; } -template -uint16_t GenericBLEManagerImpl_Zephyr::GetMTU(BLE_CONNECTION_OBJECT conId) const +uint16_t BLEManagerImpl::GetMTU(BLE_CONNECTION_OBJECT conId) const { return bt_gatt_get_mtu(conId); } -template -bool GenericBLEManagerImpl_Zephyr::SubscribeCharacteristic(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, - const ChipBleUUID * charId) +bool BLEManagerImpl::SubscribeCharacteristic(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const ChipBleUUID * charId) { ChipLogError(DeviceLayer, "%s: NOT IMPLEMENTED", __PRETTY_FUNCTION__); return true; } -template -bool GenericBLEManagerImpl_Zephyr::UnsubscribeCharacteristic(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, - const ChipBleUUID * charId) +bool BLEManagerImpl::UnsubscribeCharacteristic(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const ChipBleUUID * charId) { ChipLogError(DeviceLayer, "%s: NOT IMPLEMENTED", __PRETTY_FUNCTION__); return true; } -template -bool GenericBLEManagerImpl_Zephyr::SendIndication(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, - const ChipBleUUID * charId, PacketBufferHandle pBuf) +bool BLEManagerImpl::SendIndication(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const ChipBleUUID * charId, + PacketBufferHandle pBuf) { CHIP_ERROR err = CHIP_NO_ERROR; uint8_t index = bt_conn_index(conId); @@ -630,50 +602,44 @@ bool GenericBLEManagerImpl_Zephyr::SendIndication(BLE_CONNECTION_OBJE exit: if (err != CHIP_NO_ERROR) { - ChipLogError(DeviceLayer, "GenericBLEManagerImpl_Zephyr::SendIndication() failed: %s", ErrorStr(err)); + ChipLogError(DeviceLayer, "BLEManagerImpl::SendIndication() failed: %s", ErrorStr(err)); } return err == CHIP_NO_ERROR; } -template -bool GenericBLEManagerImpl_Zephyr::SendWriteRequest(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, - const ChipBleUUID * charId, PacketBufferHandle pBuf) +bool BLEManagerImpl::SendWriteRequest(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const ChipBleUUID * charId, + PacketBufferHandle pBuf) { ChipLogError(DeviceLayer, "%s: NOT IMPLEMENTED", __PRETTY_FUNCTION__); return true; } -template -bool GenericBLEManagerImpl_Zephyr::SendReadRequest(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, - const ChipBleUUID * charId, PacketBufferHandle pBuf) +bool BLEManagerImpl::SendReadRequest(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const ChipBleUUID * charId, + PacketBufferHandle pBuf) { ChipLogError(DeviceLayer, "%s: NOT IMPLEMENTED", __PRETTY_FUNCTION__); return true; } -template -bool GenericBLEManagerImpl_Zephyr::SendReadResponse(BLE_CONNECTION_OBJECT conId, BLE_READ_REQUEST_CONTEXT requestContext, - const ChipBleUUID * svcId, const ChipBleUUID * charId) +bool BLEManagerImpl::SendReadResponse(BLE_CONNECTION_OBJECT conId, BLE_READ_REQUEST_CONTEXT requestContext, + const ChipBleUUID * svcId, const ChipBleUUID * charId) { ChipLogError(DeviceLayer, "%s: NOT IMPLEMENTED", __PRETTY_FUNCTION__); return true; } -template -void GenericBLEManagerImpl_Zephyr::NotifyChipConnectionClosed(BLE_CONNECTION_OBJECT conId) +void BLEManagerImpl::NotifyChipConnectionClosed(BLE_CONNECTION_OBJECT conId) { // Intentionally empty. } -template -bool GenericBLEManagerImpl_Zephyr::IsSubscribed(bt_conn * conn) +bool BLEManagerImpl::IsSubscribed(bt_conn * conn) { return mSubscribedConns[bt_conn_index(conn)]; } -template -bool GenericBLEManagerImpl_Zephyr::SetSubscribed(bt_conn * conn) +bool BLEManagerImpl::SetSubscribed(bt_conn * conn) { uint8_t index = bt_conn_index(conn); bool isSubscribed = mSubscribedConns[index]; @@ -688,8 +654,7 @@ bool GenericBLEManagerImpl_Zephyr::SetSubscribed(bt_conn * conn) return !isSubscribed; } -template -bool GenericBLEManagerImpl_Zephyr::UnsetSubscribed(bt_conn * conn) +bool BLEManagerImpl::UnsetSubscribed(bt_conn * conn) { uint8_t index = bt_conn_index(conn); bool isSubscribed = mSubscribedConns[index]; @@ -704,17 +669,15 @@ bool GenericBLEManagerImpl_Zephyr::UnsetSubscribed(bt_conn * conn) return isSubscribed; } -template -uint32_t GenericBLEManagerImpl_Zephyr::GetAdvertisingInterval() +uint32_t BLEManagerImpl::GetAdvertisingInterval() { return (NumConnections() == 0 && !ConfigurationMgr().IsFullyProvisioned()) || GetFlag(mFlags, kFlag_FastAdvertisingEnabled) ? CHIP_DEVICE_CONFIG_BLE_FAST_ADVERTISING_INTERVAL : CHIP_DEVICE_CONFIG_BLE_SLOW_ADVERTISING_INTERVAL; } -template -ssize_t GenericBLEManagerImpl_Zephyr::HandleRXWrite(struct bt_conn * conId, const struct bt_gatt_attr * attr, - const void * buf, uint16_t len, uint16_t offset, uint8_t flags) +ssize_t BLEManagerImpl::HandleRXWrite(struct bt_conn * conId, const struct bt_gatt_attr * attr, const void * buf, uint16_t len, + uint16_t offset, uint8_t flags) { ChipDeviceEvent event; PacketBufferHandle packetBuf = PacketBuffer::NewWithAvailableSize(len); @@ -752,9 +715,7 @@ ssize_t GenericBLEManagerImpl_Zephyr::HandleRXWrite(struct bt_conn * return len; } -template -ssize_t GenericBLEManagerImpl_Zephyr::HandleTXCCCWrite(struct bt_conn * conId, const struct bt_gatt_attr * attr, - uint16_t value) +ssize_t BLEManagerImpl::HandleTXCCCWrite(struct bt_conn * conId, const struct bt_gatt_attr * attr, uint16_t value) { ChipDeviceEvent event; @@ -772,9 +733,7 @@ ssize_t GenericBLEManagerImpl_Zephyr::HandleTXCCCWrite(struct bt_conn return sizeof(value); } -template -void GenericBLEManagerImpl_Zephyr::HandleTXIndicated(struct bt_conn * conId, const struct bt_gatt_attr * attr, - uint8_t err) +void BLEManagerImpl::HandleTXIndicated(struct bt_conn * conId, IndicationAttrType, uint8_t err) { ChipDeviceEvent event; @@ -785,8 +744,7 @@ void GenericBLEManagerImpl_Zephyr::HandleTXIndicated(struct bt_conn * PlatformMgr().PostEvent(&event); } -template -void GenericBLEManagerImpl_Zephyr::HandleConnect(struct bt_conn * conId, uint8_t err) +void BLEManagerImpl::HandleConnect(struct bt_conn * conId, uint8_t err) { ChipDeviceEvent event; @@ -797,8 +755,7 @@ void GenericBLEManagerImpl_Zephyr::HandleConnect(struct bt_conn * con PlatformMgr().PostEvent(&event); } -template -void GenericBLEManagerImpl_Zephyr::HandleDisconnect(struct bt_conn * conId, uint8_t reason) +void BLEManagerImpl::HandleDisconnect(struct bt_conn * conId, uint8_t reason) { ChipDeviceEvent event; @@ -813,4 +770,4 @@ void GenericBLEManagerImpl_Zephyr::HandleDisconnect(struct bt_conn * } // namespace DeviceLayer } // namespace chip -#endif // GENERIC_BLE_MANAGER_IMPL_ZEPHYR_IPP +#endif // CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE diff --git a/src/platform/Zephyr/GenericBLEManagerImpl_Zephyr.h b/src/platform/Zephyr/BLEManagerImpl.h similarity index 74% rename from src/platform/Zephyr/GenericBLEManagerImpl_Zephyr.h rename to src/platform/Zephyr/BLEManagerImpl.h index a3cb16fe738129..d7fe37fa9d04b7 100644 --- a/src/platform/Zephyr/GenericBLEManagerImpl_Zephyr.h +++ b/src/platform/Zephyr/BLEManagerImpl.h @@ -23,12 +23,16 @@ #pragma once +#if CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE + #include #include #include #include +#include + namespace chip { namespace DeviceLayer { namespace Internal { @@ -36,19 +40,22 @@ namespace Internal { using namespace chip::Ble; /** - * Template implementation of the GenericBLEManagerImpl_Zephyr singleton object for the Zephyr platforms. + * Concrete implementation of the BLEManager singleton object for the Zephyr platforms. */ -template -class GenericBLEManagerImpl_Zephyr : public BLEManager, - private BleLayer, - private BlePlatformDelegate, - private BleApplicationDelegate +class BLEManagerImpl final : public BLEManager, private BleLayer, private BlePlatformDelegate, private BleApplicationDelegate { // Allow the BLEManager interface class to delegate method calls to // the implementation methods provided by this class. friend BLEManager; private: + // As a result of https://github.com/zephyrproject-rtos/zephyr/issues/29357, BLE indication + // callback parameter type has changed in recent Zephyr revisions. Select the compatible type + // below to support both versions for now. + using IndicationAttrType = + std::conditional_t::value, + bt_gatt_indicate_params *, const bt_gatt_attr *>; + // ===== Members that implement the BLEManager internal interface. CHIP_ERROR _Init(void); @@ -122,11 +129,18 @@ class GenericBLEManagerImpl_Zephyr : public BLEManager, static void DriveBLEState(intptr_t arg); // Below callbacks run from the system workqueue context and have a limited stack capacity. - static void HandleTXIndicated(bt_conn * conn, const bt_gatt_attr * attr, uint8_t err); + static void HandleTXIndicated(bt_conn * conn, IndicationAttrType attr, uint8_t err); static void HandleConnect(bt_conn * conn, uint8_t err); static void HandleDisconnect(bt_conn * conn, uint8_t reason); static void HandleBLEAdvertisementTimeout(System::Layer * layer, void * param, System::Error error); + // ===== Members for internal use by the following friends. + + friend BLEManager & BLEMgr(void); + friend BLEManagerImpl & BLEMgrImpl(void); + + static BLEManagerImpl sInstance; + public: // Below callbacks are public in order to be visible from the global scope. static ssize_t HandleRXWrite(bt_conn * conn, const bt_gatt_attr * attr, const void * buf, uint16_t len, uint16_t offset, @@ -134,32 +148,49 @@ class GenericBLEManagerImpl_Zephyr : public BLEManager, static ssize_t HandleTXCCCWrite(bt_conn * conn, const bt_gatt_attr * attr, uint16_t value); }; -template -inline BleLayer * GenericBLEManagerImpl_Zephyr::_GetBleLayer() +/** + * 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 Zephyr platforms. + */ +inline BLEManagerImpl & BLEMgrImpl(void) +{ + return BLEManagerImpl::sInstance; +} + +inline BleLayer * BLEManagerImpl::_GetBleLayer() { return this; } -template -inline BLEManager::CHIPoBLEServiceMode GenericBLEManagerImpl_Zephyr::_GetCHIPoBLEServiceMode(void) +inline BLEManager::CHIPoBLEServiceMode BLEManagerImpl::_GetCHIPoBLEServiceMode(void) { return mServiceMode; } -template -inline bool GenericBLEManagerImpl_Zephyr::_IsAdvertisingEnabled(void) +inline bool BLEManagerImpl::_IsAdvertisingEnabled(void) { return GetFlag(mFlags, kFlag_AdvertisingEnabled); } -template -inline bool GenericBLEManagerImpl_Zephyr::_IsFastAdvertisingEnabled(void) +inline bool BLEManagerImpl::_IsFastAdvertisingEnabled(void) { return GetFlag(mFlags, kFlag_FastAdvertisingEnabled); } -template -inline bool GenericBLEManagerImpl_Zephyr::_IsAdvertising(void) +inline bool BLEManagerImpl::_IsAdvertising(void) { return GetFlag(mFlags, kFlag_Advertising); } @@ -167,3 +198,5 @@ inline bool GenericBLEManagerImpl_Zephyr::_IsAdvertising(void) } // namespace Internal } // namespace DeviceLayer } // namespace chip + +#endif // CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE diff --git a/src/platform/Zephyr/CHIPDevicePlatformEvent.h b/src/platform/Zephyr/CHIPDevicePlatformEvent.h new file mode 100644 index 00000000000000..47407ab1b5444e --- /dev/null +++ b/src/platform/Zephyr/CHIPDevicePlatformEvent.h @@ -0,0 +1,104 @@ +/* + * + * 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 + * Defines platform-specific event types and data for the chip + * Device Layer on Zephyr platforms. + */ + +#pragma once + +#include + +#include + +namespace chip { +namespace System { +class PacketBuffer; +} // namespace System +} // namespace chip + +namespace chip { +namespace DeviceLayer { + +namespace DeviceEventType { + +/** + * Enumerates Zephyr platform-specific event types that are visible to the application. + */ +enum PublicPlatformSpecificEventTypes +{ + /* None currently defined */ +}; + +/** + * Enumerates Zephyr platform-specific event types that are internal to the chip Device Layer. + */ +enum InternalPlatformSpecificEventTypes +{ + kPlatformZephyrEvent = kRange_InternalPlatformSpecific, + kPlatformZephyrBleConnected, + kPlatformZephyrBleDisconnected, + kPlatformZephyrBleCCCWrite, + kPlatformZephyrBleC1WriteEvent, + kPlatformZephyrBleC2IndDoneEvent, + kPlatformZephyrBleOutOfBuffersEvent, +}; + +} // namespace DeviceEventType + +struct BleConnEventType +{ + bt_conn * BtConn; + uint8_t HciResult; +}; + +struct BleCCCWriteEventType +{ + bt_conn * BtConn; + uint16_t Value; +}; + +struct BleC1WriteEventType +{ + bt_conn * BtConn; + ::chip::System::PacketBuffer * Data; +}; + +struct BleC2IndDoneEventType +{ + bt_conn * BtConn; + uint8_t Result; +}; + +/** + * Represents platform-specific event information for Zephyr platforms. + */ +struct ChipDevicePlatformEvent final +{ + union + { + BleConnEventType BleConnEvent; + BleCCCWriteEventType BleCCCWriteEvent; + BleC1WriteEventType BleC1WriteEvent; + BleC2IndDoneEventType BleC2IndDoneEvent; + }; +}; + +} // namespace DeviceLayer +} // namespace chip diff --git a/src/platform/nrfconnect/ConfigurationManagerImpl.cpp b/src/platform/Zephyr/ConfigurationManagerImpl.cpp similarity index 98% rename from src/platform/nrfconnect/ConfigurationManagerImpl.cpp rename to src/platform/Zephyr/ConfigurationManagerImpl.cpp index bde9059bf89321..c0a0a85ae9d5c7 100644 --- a/src/platform/nrfconnect/ConfigurationManagerImpl.cpp +++ b/src/platform/Zephyr/ConfigurationManagerImpl.cpp @@ -27,7 +27,7 @@ #include #include -#include +#include #if CHIP_DEVICE_CONFIG_ENABLE_FACTORY_PROVISIONING #include diff --git a/src/platform/Zephyr/ConfigurationManagerImpl.h b/src/platform/Zephyr/ConfigurationManagerImpl.h new file mode 100644 index 00000000000000..6626abb9ba6ad3 --- /dev/null +++ b/src/platform/Zephyr/ConfigurationManagerImpl.h @@ -0,0 +1,118 @@ +/* + * + * 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 + * Provides an implementation of the ConfigurationManager object + * for Zephyr platforms. + */ + +#pragma once + +#include + +#include + +namespace chip { +namespace DeviceLayer { + +/** + * Concrete implementation of the ConfigurationManager singleton object for the Zephyr platform. + */ +class ConfigurationManagerImpl final : public ConfigurationManager, + public Internal::GenericConfigurationManagerImpl, + private Internal::ZephyrConfig +{ + // Allow the ConfigurationManager interface class to delegate method calls to + // the implementation methods provided by this class. + friend class ConfigurationManager; + + // Allow the GenericConfigurationManagerImpl base class to access helper methods and types + // defined on this class. +#ifndef DOXYGEN_SHOULD_SKIP_THIS + friend class Internal::GenericConfigurationManagerImpl; +#endif + +private: + // ===== Members that implement the ConfigurationManager public interface. + + CHIP_ERROR _Init(void); + CHIP_ERROR _GetPrimaryWiFiMACAddress(uint8_t * buf); + bool _CanFactoryReset(void); + void _InitiateFactoryReset(void); + CHIP_ERROR _ReadPersistedStorageValue(::chip::Platform::PersistedStorage::Key key, uint32_t & value); + CHIP_ERROR _WritePersistedStorageValue(::chip::Platform::PersistedStorage::Key key, uint32_t value); + + // NOTE: Other public interface methods are implemented by GenericConfigurationManagerImpl<>. + + // ===== Members for internal use by the following friends. + + friend ConfigurationManager & ConfigurationMgr(void); + friend ConfigurationManagerImpl & ConfigurationMgrImpl(void); + + static ConfigurationManagerImpl sInstance; + + // ===== Private members reserved for use by this class only. + + static void DoFactoryReset(intptr_t arg); +}; + +/** + * Returns the public interface of the ConfigurationManager singleton object. + * + * chip applications should use this to access features of the ConfigurationManager object + * that are common to all platforms. + */ +inline ConfigurationManager & ConfigurationMgr(void) +{ + return ConfigurationManagerImpl::sInstance; +} + +/** + * Returns the platform-specific implementation of the ConfigurationManager singleton object. + * + * chip applications can use this to gain access to features of the ConfigurationManager + * that are specific to the nRF Connect SDK platform. + */ +inline ConfigurationManagerImpl & ConfigurationMgrImpl(void) +{ + return ConfigurationManagerImpl::sInstance; +} + +inline bool ConfigurationManagerImpl::_CanFactoryReset() +{ + return true; +} + +inline CHIP_ERROR ConfigurationManagerImpl::_ReadPersistedStorageValue(::chip::Platform::PersistedStorage::Key key, + uint32_t & value) +{ + return ReadConfigValueCounter(key, value); +} + +inline CHIP_ERROR ConfigurationManagerImpl::_WritePersistedStorageValue(::chip::Platform::PersistedStorage::Key key, uint32_t value) +{ + return WriteConfigValueCounter(key, value); +} + +inline CHIP_ERROR ConfigurationManagerImpl::_GetPrimaryWiFiMACAddress(uint8_t * /* buf */) +{ + return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE; +} + +} // namespace DeviceLayer +} // namespace chip diff --git a/src/platform/Zephyr/GenericThreadStackManagerImpl_Zephyr.h b/src/platform/Zephyr/GenericThreadStackManagerImpl_Zephyr.h deleted file mode 100644 index b901299e20191e..00000000000000 --- a/src/platform/Zephyr/GenericThreadStackManagerImpl_Zephyr.h +++ /dev/null @@ -1,131 +0,0 @@ -/* - * - * 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 - * Provides an generic implementation of ThreadStackManager features - * for use on Zephyr platforms. - */ - -#pragma once - -#include -#include - -#include - -namespace chip { -namespace DeviceLayer { - -class ThreadStackManagerImpl; - -namespace Internal { - -/** - * Provides a generic implementation of ThreadStackManager features that works on Zephyr platforms. - * - * This template contains implementations of select features from the ThreadStackManager abstract - * interface that are suitable for use on Zephyr-based platforms. It is intended to be - * inherited, directly or indirectly, by the ThreadStackManagerImpl class, which also appears as - * the template's ImplClass parameter. - * - * Any task using this class must have cooperative scheduling priority. - */ -template -class GenericThreadStackManagerImpl_Zephyr : public GenericThreadStackManagerImpl_OpenThread -{ -public: - // ===== Methods that implement the ThreadStackManager abstract interface. - CHIP_ERROR _InitThreadStack(); - -protected: - // ===== Methods that implement the ThreadStackManager abstract interface. - - CHIP_ERROR _StartThreadTask(); - void _LockThreadStack(); - bool _TryLockThreadStack(); - void _UnlockThreadStack(); - - // ===== Methods that override the GenericThreadStackManagerImpl_OpenThread abstract interface. - - void _ProcessThreadActivity(); - void _OnCHIPoBLEAdvertisingStart(); - void _OnCHIPoBLEAdvertisingStop(); - -private: - // ===== Private members for use by this class only. - - inline ImplClass * Impl() { return static_cast(this); } -}; - -// Instruct the compiler to instantiate the template only when explicitly told to do so. -extern template class GenericThreadStackManagerImpl_Zephyr; - -template -CHIP_ERROR GenericThreadStackManagerImpl_Zephyr::_InitThreadStack() -{ - return GenericThreadStackManagerImpl_OpenThread::DoInit(openthread_get_default_instance()); -} - -template -CHIP_ERROR GenericThreadStackManagerImpl_Zephyr::_StartThreadTask() -{ - // Intentionally empty. - return CHIP_NO_ERROR; -} - -template -void GenericThreadStackManagerImpl_Zephyr::_LockThreadStack() -{ - openthread_api_mutex_lock(openthread_get_default_context()); -} - -template -bool GenericThreadStackManagerImpl_Zephyr::_TryLockThreadStack() -{ - // There's no openthread_api_mutex_try_lock() in Zephyr, so until it's contributed we must use the low-level API - return k_mutex_lock(&openthread_get_default_context()->api_lock, K_NO_WAIT) == 0; -} - -template -void GenericThreadStackManagerImpl_Zephyr::_UnlockThreadStack() -{ - openthread_api_mutex_unlock(openthread_get_default_context()); -} - -template -void GenericThreadStackManagerImpl_Zephyr::_ProcessThreadActivity() -{ - // Intentionally empty. -} - -template -void GenericThreadStackManagerImpl_Zephyr::_OnCHIPoBLEAdvertisingStart() -{ - ChipLogError(DeviceLayer, "%s: NOT IMPLEMENTED", __PRETTY_FUNCTION__); -} - -template -void GenericThreadStackManagerImpl_Zephyr::_OnCHIPoBLEAdvertisingStop() -{ - ChipLogError(DeviceLayer, "%s: NOT IMPLEMENTED", __PRETTY_FUNCTION__); -} - -} // namespace Internal -} // namespace DeviceLayer -} // namespace chip diff --git a/src/platform/nrfconnect/Logging.cpp b/src/platform/Zephyr/Logging.cpp similarity index 98% rename from src/platform/nrfconnect/Logging.cpp rename to src/platform/Zephyr/Logging.cpp index 526fe4b1805833..ad61fed982d880 100644 --- a/src/platform/nrfconnect/Logging.cpp +++ b/src/platform/Zephyr/Logging.cpp @@ -18,7 +18,7 @@ /** * @file * Provides implementations for the CHIP logging functions - * on Nordic nRF Connect SDK platforms. + * on Zephyr platforms. */ #include diff --git a/src/platform/nrfconnect/PlatformManagerImpl.cpp b/src/platform/Zephyr/PlatformManagerImpl.cpp similarity index 97% rename from src/platform/nrfconnect/PlatformManagerImpl.cpp rename to src/platform/Zephyr/PlatformManagerImpl.cpp index 488af60737cc37..4cf92444cd14e9 100644 --- a/src/platform/nrfconnect/PlatformManagerImpl.cpp +++ b/src/platform/Zephyr/PlatformManagerImpl.cpp @@ -18,7 +18,7 @@ /** * @file * Provides an implementation of the PlatformManager object - * for nRF Connect SDK platforms. + * for Zephyr platforms. */ #include diff --git a/src/platform/Zephyr/PlatformManagerImpl.h b/src/platform/Zephyr/PlatformManagerImpl.h new file mode 100644 index 00000000000000..37160c89d6c49c --- /dev/null +++ b/src/platform/Zephyr/PlatformManagerImpl.h @@ -0,0 +1,78 @@ +/* + * + * 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 + * Provides an implementation of the PlatformManager object. + */ + +#pragma once + +#include +#include + +namespace chip { +namespace DeviceLayer { + +/** + * Concrete implementation of the PlatformManager singleton object for the nRF Connect SDK platforms. + */ +class PlatformManagerImpl final : public PlatformManager, public Internal::GenericPlatformManagerImpl_Zephyr +{ + // Allow the PlatformManager interface class to delegate method calls to + // the implementation methods provided by this class. + friend PlatformManager; + + // Allow the generic implementation base class to call helper methods on + // this class. +#ifndef DOXYGEN_SHOULD_SKIP_THIS + friend Internal::GenericPlatformManagerImpl_Zephyr; +#endif + +public: + // ===== Platform-specific members that may be accessed directly by the application. + + /* none so far */ + +private: + // ===== Methods that implement the PlatformManager abstract interface. + + CHIP_ERROR _InitChipStack(void); + + // ===== Members for internal use by the following friends. + + friend PlatformManager & PlatformMgr(void); + friend PlatformManagerImpl & PlatformMgrImpl(void); + friend class Internal::BLEManagerImpl; + + explicit PlatformManagerImpl(ThreadStack & stack) : Internal::GenericPlatformManagerImpl_Zephyr(stack) {} + + static PlatformManagerImpl sInstance; +}; + +/** + * 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; +} +} // namespace DeviceLayer +} // namespace chip diff --git a/src/platform/Zephyr/README.md b/src/platform/Zephyr/README.md new file mode 100644 index 00000000000000..c5acee50033579 --- /dev/null +++ b/src/platform/Zephyr/README.md @@ -0,0 +1,51 @@ +# Overview of Zephyr Adaption + +The following is a quick overview of the Zephyr adaptation of CHIP. Most of this +code will have parallels in any new adaptation. + +(All file names are relative to `connectedhomeip/src/...`). + +`include/platform/Zephyr/PlatformManagerImpl.h`
`Zephyr/PlatformManagerImpl.cpp` + +- Concrete implementation of PlatformManager interface +- Provides initialization of the CHIP stack and core event loop for the chip + task +- Relies on GenericPlatformManagerImpl_POSIX<> class to provide most of the + implementation + +`include/platform/Zephyr/ConfigurationManagerImpl.h`
`Zephyr/ConfigurationManagerImpl.cpp` + +- Concrete implementation of ConfigurationManager interface +- Manages storage and retrieval of persistent configuration data +- Relies on GenericConfigurationManagerImpl<> classes to implement most API + functionality +- Delegates low-level reading and writing of persistent values to ZephyrConfig + class + +`include/platform/Zephyr/ThreadStackManagerImpl.h`
`Zephyr/ThreadStackManagerImpl.cpp` + +- Concrete implementation of ThreadStackManager interface +- Supports Thread stack initialization and core event loop processing +- Relies on GenericThreadStackManagerImpl_OpenThread/POSIX<> classes to + implement most API functionaltiy + +`include/platform/Zephyr/BLEManagerImpl.h`
`Zephyr/BLEManagerImpl.cpp` + +- Concrete implementation of the BLEManager interface +- Maps CHIP's BLE interface abstractions (BleLayer, BlePlatformDelegate, + BleApplicationDelegate) onto the platform's native BLE services +- Implements chip-compatible BLE advertising. + +`platform/Zephyr/Logging.cpp` + +- Adaption of chip debug logging to platform logging facility. + +`platform/Zephyr/ZephyrConfig.cpp` + +- Implements low-level read/write of persistent configuration values +- Class API specifically designed to work in conjunction with the + GenericConfigurationManagerImpl<> class. + +`platform/Zephyr/CHIPDevicePlatformEvent.h` + +- Defines platform-specific event types and data for the chip Device Layer. diff --git a/src/platform/Zephyr/ThreadStackManagerImpl.cpp b/src/platform/Zephyr/ThreadStackManagerImpl.cpp new file mode 100644 index 00000000000000..08424f617ea002 --- /dev/null +++ b/src/platform/Zephyr/ThreadStackManagerImpl.cpp @@ -0,0 +1,83 @@ +/* + * + * 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 + * Provides an implementation of the ThreadStackManager object for + * Zephyr platforms. + * + */ +/* this file behaves like a config.h, comes first */ +#include + +#include +#include + +#include +#include + +namespace chip { +namespace DeviceLayer { + +using namespace ::chip::DeviceLayer::Internal; + +ThreadStackManagerImpl ThreadStackManagerImpl::sInstance; + +CHIP_ERROR ThreadStackManagerImpl::_InitThreadStack() +{ + return GenericThreadStackManagerImpl_OpenThread::DoInit(openthread_get_default_instance()); +} + +CHIP_ERROR ThreadStackManagerImpl::_StartThreadTask() +{ + // Intentionally empty. + return CHIP_NO_ERROR; +} + +void ThreadStackManagerImpl::_LockThreadStack() +{ + openthread_api_mutex_lock(openthread_get_default_context()); +} + +bool ThreadStackManagerImpl::_TryLockThreadStack() +{ + // There's no openthread_api_mutex_try_lock() in Zephyr, so until it's contributed we must use the low-level API + return k_mutex_lock(&openthread_get_default_context()->api_lock, K_NO_WAIT) == 0; +} + +void ThreadStackManagerImpl::_UnlockThreadStack() +{ + openthread_api_mutex_unlock(openthread_get_default_context()); +} + +void ThreadStackManagerImpl::_ProcessThreadActivity() +{ + // Intentionally empty. +} + +void ThreadStackManagerImpl::_OnCHIPoBLEAdvertisingStart() +{ + // Intentionally empty. +} + +void ThreadStackManagerImpl::_OnCHIPoBLEAdvertisingStop() +{ + // Intentionally empty. +} + +} // namespace DeviceLayer +} // namespace chip diff --git a/src/platform/Zephyr/ThreadStackManagerImpl.h b/src/platform/Zephyr/ThreadStackManagerImpl.h new file mode 100644 index 00000000000000..7d2c17e0f92d8c --- /dev/null +++ b/src/platform/Zephyr/ThreadStackManagerImpl.h @@ -0,0 +1,116 @@ +/* + * + * 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 + * Provides an implementation of the ThreadStackManager object for + * Zephyr platforms. + */ + +#pragma once + +#include + +#include +#include + +#include +#include + +#include + +namespace chip { +namespace DeviceLayer { + +class ThreadStackManager; +class ThreadStackManagerImpl; + +/** + * Concrete implementation of the ThreadStackManager singleton object for nRF Connect platforms. + */ +class ThreadStackManagerImpl final : public ThreadStackManager, + public Internal::GenericThreadStackManagerImpl_OpenThread +{ + // Allow the ThreadStackManager interface class to delegate method calls to + // the implementation methods provided by this class. + friend class ThreadStackManager; + + // namespace Internal { + + // Allow the generic implementation base classes to call helper methods on + // this class. +#ifndef DOXYGEN_SHOULD_SKIP_THIS + friend Internal::GenericThreadStackManagerImpl_OpenThread; +#endif + +public: + // ===== Methods that implement the ThreadStackManager abstract interface. + CHIP_ERROR _InitThreadStack(); + +protected: + // ===== Methods that implement the ThreadStackManager abstract interface. + + CHIP_ERROR _StartThreadTask(); + void _LockThreadStack(); + bool _TryLockThreadStack(); + void _UnlockThreadStack(); + + // ===== Methods that override the GenericThreadStackManagerImpl_OpenThread abstract interface. + + void _ProcessThreadActivity(); + void _OnCHIPoBLEAdvertisingStart(); + void _OnCHIPoBLEAdvertisingStop(); + + //} // namespace Internal + +private: + // ===== Members for internal use by the following friends. + + friend ThreadStackManager & ::chip::DeviceLayer::ThreadStackMgr(void); + friend ThreadStackManagerImpl & ::chip::DeviceLayer::ThreadStackMgrImpl(void); + + static ThreadStackManagerImpl sInstance; + + // ===== Private members for use by this class only. + + ThreadStackManagerImpl() = default; +}; + +/** + * Returns the public interface of the ThreadStackManager singleton object. + * + * chip applications should use this to access features of the ThreadStackManager object + * that are common to all platforms. + */ +inline ThreadStackManager & ThreadStackMgr(void) +{ + return ThreadStackManagerImpl::sInstance; +} + +/** + * Returns the platform-specific implementation of the ThreadStackManager singleton object. + * + * chip applications can use this to gain access to features of the ThreadStackManager + * that are specific to nRF Connect platforms. + */ +inline ThreadStackManagerImpl & ThreadStackMgrImpl(void) +{ + return ThreadStackManagerImpl::sInstance; +} + +} // namespace DeviceLayer +} // namespace chip diff --git a/src/platform/nrfconnect/ZephyrConfig.cpp b/src/platform/Zephyr/ZephyrConfig.cpp similarity index 99% rename from src/platform/nrfconnect/ZephyrConfig.cpp rename to src/platform/Zephyr/ZephyrConfig.cpp index 9a3acc086c6b69..6ac82ba05176c3 100644 --- a/src/platform/nrfconnect/ZephyrConfig.cpp +++ b/src/platform/Zephyr/ZephyrConfig.cpp @@ -22,7 +22,8 @@ */ #include -#include + +#include #include #include diff --git a/src/platform/nrfconnect/ZephyrConfig.h b/src/platform/Zephyr/ZephyrConfig.h similarity index 100% rename from src/platform/nrfconnect/ZephyrConfig.h rename to src/platform/Zephyr/ZephyrConfig.h diff --git a/src/platform/cc13x2_26x2/BlePlatformConfig.h b/src/platform/cc13x2_26x2/BlePlatformConfig.h new file mode 100644 index 00000000000000..7a5d17b5ed39e9 --- /dev/null +++ b/src/platform/cc13x2_26x2/BlePlatformConfig.h @@ -0,0 +1,30 @@ +/* + * + * Copyright (c) 2020 Project CHIP Authors + * Copyright (c) 2020 Texas Instruments Incorporated + * + * 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 the CHIP BLE + * Layer for the Texas Instruments CC1352 platform. + * + * NOTE: Empty because BLE is not enabled, but build defines this file + * to be included by the build configuration. + */ + +#pragma once + +#define BLE_CONFIG_ERROR_TYPE int32_t diff --git a/src/platform/cc13x2_26x2/CC13X2_26X2Config.cpp b/src/platform/cc13x2_26x2/CC13X2_26X2Config.cpp new file mode 100644 index 00000000000000..f228677bef87a0 --- /dev/null +++ b/src/platform/cc13x2_26x2/CC13X2_26X2Config.cpp @@ -0,0 +1,255 @@ +/* + * + * Copyright (c) 2020 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 multiple file partitions and maps + * key-value config calls to the correct partition. + */ + +#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. + +// Keys stored in the Chip-factory namespace +const CC13X2_26X2Config::Key CC13X2_26X2Config::kConfigKey_SerialNum = { { kCC13X2_26X2ChipConfig_Sysid, 0x0001 } }; +const CC13X2_26X2Config::Key CC13X2_26X2Config::kConfigKey_MfrDeviceId = { { kCC13X2_26X2ChipConfig_Sysid, 0x0002 } }; +const CC13X2_26X2Config::Key CC13X2_26X2Config::kConfigKey_MfrDeviceCert = { { kCC13X2_26X2ChipConfig_Sysid, 0x0003 } }; +const CC13X2_26X2Config::Key CC13X2_26X2Config::kConfigKey_MfrDeviceICACerts = { { kCC13X2_26X2ChipConfig_Sysid, 0x0004 } }; +const CC13X2_26X2Config::Key CC13X2_26X2Config::kConfigKey_MfrDevicePrivateKey = { { kCC13X2_26X2ChipConfig_Sysid, 0x0005 } }; +const CC13X2_26X2Config::Key CC13X2_26X2Config::kConfigKey_ProductRevision = { { kCC13X2_26X2ChipConfig_Sysid, 0x0006 } }; +const CC13X2_26X2Config::Key CC13X2_26X2Config::kConfigKey_ManufacturingDate = { { kCC13X2_26X2ChipConfig_Sysid, 0x0007 } }; +const CC13X2_26X2Config::Key CC13X2_26X2Config::kConfigKey_SetupPinCode = { { kCC13X2_26X2ChipConfig_Sysid, 0x0008 } }; +const CC13X2_26X2Config::Key CC13X2_26X2Config::kConfigKey_SetupDiscriminator = { { kCC13X2_26X2ChipConfig_Sysid, 0x0009 } }; + +// Keys stored in the Chip-config namespace +const CC13X2_26X2Config::Key CC13X2_26X2Config::kConfigKey_FabricId = { { kCC13X2_26X2ChipFactory_Sysid, 0x0011 } }; +const CC13X2_26X2Config::Key CC13X2_26X2Config::kConfigKey_ServiceConfig = { { kCC13X2_26X2ChipFactory_Sysid, 0x0012 } }; +const CC13X2_26X2Config::Key CC13X2_26X2Config::kConfigKey_PairedAccountId = { { kCC13X2_26X2ChipFactory_Sysid, 0x0013 } }; +const CC13X2_26X2Config::Key CC13X2_26X2Config::kConfigKey_ServiceId = { { kCC13X2_26X2ChipFactory_Sysid, 0x0014 } }; +const CC13X2_26X2Config::Key CC13X2_26X2Config::kConfigKey_FabricSecret = { { kCC13X2_26X2ChipFactory_Sysid, 0x0015 } }; +const CC13X2_26X2Config::Key CC13X2_26X2Config::kConfigKey_GroupKeyIndex = { { kCC13X2_26X2ChipFactory_Sysid, 0x0016 } }; +const CC13X2_26X2Config::Key CC13X2_26X2Config::kConfigKey_LastUsedEpochKeyId = { { kCC13X2_26X2ChipFactory_Sysid, 0x0017 } }; +const CC13X2_26X2Config::Key CC13X2_26X2Config::kConfigKey_FailSafeArmed = { { kCC13X2_26X2ChipFactory_Sysid, 0x0018 } }; +const CC13X2_26X2Config::Key CC13X2_26X2Config::kConfigKey_WiFiStationSecType = { { kCC13X2_26X2ChipFactory_Sysid, 0x0019 } }; +const CC13X2_26X2Config::Key CC13X2_26X2Config::kConfigKey_OperationalDeviceId = { { kCC13X2_26X2ChipFactory_Sysid, 0x001a } }; +const CC13X2_26X2Config::Key CC13X2_26X2Config::kConfigKey_OperationalDeviceCert = { { kCC13X2_26X2ChipFactory_Sysid, 0x001b } }; +const CC13X2_26X2Config::Key CC13X2_26X2Config::kConfigKey_OperationalDeviceICACerts = { { kCC13X2_26X2ChipFactory_Sysid, + 0x001c } }; +const CC13X2_26X2Config::Key CC13X2_26X2Config::kConfigKey_OperationalDevicePrivateKey = { { kCC13X2_26X2ChipFactory_Sysid, + 0x001d } }; + +/* Static local variables */ +static NVINTF_nvFuncts_t sNvoctpFps = { 0 }; + +CHIP_ERROR CC13X2_26X2Config::Init() +{ + CHIP_ERROR err = CHIP_NO_ERROR; + + /* Load NVOCMP function pointers, extended API */ + NVOCMP_loadApiPtrsExt(&sNvoctpFps); + + /* Initialize NVOCMP */ + sNvoctpFps.initNV(NULL); + + return err; +} + +CHIP_ERROR CC13X2_26X2Config::ReadConfigValue(Key key, bool & val) +{ + CHIP_ERROR ret; + size_t ignore; + uint8_t localVal; + + ret = ReadConfigValueBin(key, &localVal, sizeof(localVal), ignore); + + // reference CC13X2_26X2Config::WriteConfigValue(Key key, bool val) for storage of boolean values + val = (localVal != 0); + + return ret; +} + +CHIP_ERROR CC13X2_26X2Config::ReadConfigValue(Key key, uint32_t & val) +{ + size_t ignore; + + return ReadConfigValueBin(key, (uint8_t *) &val, sizeof(val), ignore); +} + +CHIP_ERROR CC13X2_26X2Config::ReadConfigValue(Key key, uint64_t & val) +{ + size_t ignore; + + return ReadConfigValueBin(key, (uint8_t *) &val, sizeof(val), ignore); +} + +CHIP_ERROR CC13X2_26X2Config::ReadConfigValueStr(Key key, char * buf, size_t bufSize, size_t & outLen) +{ + return ReadConfigValueBin(key, (uint8_t *) buf, bufSize, outLen); +} + +CHIP_ERROR CC13X2_26X2Config::ReadConfigValueBin(Key key, uint8_t * buf, size_t bufSize, size_t & outLen) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + size_t len; + + len = sNvoctpFps.getItemLen(key.nvID); + VerifyOrExit(len > 0, err = CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND); // key not found + VerifyOrExit(len <= bufSize, err = CHIP_ERROR_BUFFER_TOO_SMALL); + + VerifyOrExit(sNvoctpFps.readItem(key.nvID, 0, (uint16_t) len, buf) == NVINTF_SUCCESS, + err = CHIP_ERROR_PERSISTED_STORAGE_FAILED); + + if (outLen) + { + outLen = len; + } + +exit: + return err; +} + +CHIP_ERROR CC13X2_26X2Config::WriteConfigValue(Key key, bool val) +{ + uint8_t localVal = val ? 1 : 0; + return WriteConfigValueBin(key, (const uint8_t *) &localVal, sizeof(localVal)); +} + +CHIP_ERROR CC13X2_26X2Config::WriteConfigValue(Key key, uint32_t val) +{ + return WriteConfigValueBin(key, (const uint8_t *) &val, sizeof(val)); +} + +CHIP_ERROR CC13X2_26X2Config::WriteConfigValue(Key key, uint64_t val) +{ + return WriteConfigValueBin(key, (const uint8_t *) &val, sizeof(val)); +} + +CHIP_ERROR CC13X2_26X2Config::WriteConfigValueStr(Key key, const char * str) +{ + size_t strLen = strlen(str); + return WriteConfigValueBin(key, (const uint8_t *) str, strLen); +} +CHIP_ERROR CC13X2_26X2Config::WriteConfigValueStr(Key key, const char * str, size_t strLen) +{ + return WriteConfigValueBin(key, (const uint8_t *) str, strLen); +} + +CHIP_ERROR CC13X2_26X2Config::WriteConfigValueBin(Key key, const uint8_t * data, size_t dataLen) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + + VerifyOrExit(sNvoctpFps.writeItem(key.nvID, (uint16_t) dataLen, (void *) data) == NVINTF_SUCCESS, + err = CHIP_ERROR_PERSISTED_STORAGE_FAILED); +exit: + return err; +} + +CHIP_ERROR CC13X2_26X2Config::ClearConfigValue(Key key) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + + VerifyOrExit(sNvoctpFps.deleteItem(key.nvID) == NVINTF_SUCCESS, err = CHIP_ERROR_PERSISTED_STORAGE_FAILED); +exit: + return err; +} + +bool CC13X2_26X2Config::ConfigValueExists(Key key) +{ + /* 0 is an invalid length for an item, getting a length of 0 means there is no item */ + return (0 != sNvoctpFps.getItemLen(key.nvID)); +} + +CHIP_ERROR CC13X2_26X2Config::FactoryResetConfig(void) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + NVINTF_nvProxy_t nvProxy = { 0 }; + uint8_t status = NVINTF_SUCCESS; + + intptr_t key = sNvoctpFps.lockNV(); + + /* Setup doNext call */ + nvProxy.sysid = kCC13X2_26X2ChipConfig_Sysid; + nvProxy.flag = NVINTF_DOSTART | NVINTF_DOSYSID | NVINTF_DODELETE; + + /* Lock and wipe all items with sysid TIOP */ + do + { + status = sNvoctpFps.doNext(&nvProxy); + } while (NVINTF_SUCCESS == status); + /* check we ran out of elements */ + VerifyOrExit(status != NVINTF_NOTFOUND, err = CHIP_ERROR_PERSISTED_STORAGE_FAILED); + + /* Setup doNext call. Sysid is the same here, but it doesn't necessarily have to be. Matching POSIX impl */ + nvProxy.sysid = kCC13X2_26X2ChipFactory_Sysid; + nvProxy.flag = NVINTF_DOSTART | NVINTF_DOSYSID | NVINTF_DODELETE; + + /* Lock and wipe all items with sysid TIOP */ + do + { + status = sNvoctpFps.doNext(&nvProxy); + } while (NVINTF_SUCCESS == status); + /* check we ran out of elements */ + VerifyOrExit(status != NVINTF_NOTFOUND, err = CHIP_ERROR_PERSISTED_STORAGE_FAILED); + + /* Setup doNext call. Sysid is the same here, but it doesn't necessarily have to be. Matching POSIX impl */ + nvProxy.sysid = kCC13X2_26X2ChipCounters_Sysid; + nvProxy.flag = NVINTF_DOSTART | NVINTF_DOSYSID | NVINTF_DODELETE; + + /* Lock and wipe all items with sysid TIOP */ + do + { + status = sNvoctpFps.doNext(&nvProxy); + } while (NVINTF_SUCCESS == status); + /* check we ran out of elements */ + VerifyOrExit(status != NVINTF_NOTFOUND, err = CHIP_ERROR_PERSISTED_STORAGE_FAILED); + +exit: + sNvoctpFps.unlockNV(key); + + if (err == CHIP_NO_ERROR) + { + /* force compaction */ + sNvoctpFps.compactNV(0); + } + return err; +} + +void CC13X2_26X2Config::RunConfigUnitTest() +{ + // Run common unit test. + ::chip::DeviceLayer::Internal::RunConfigUnitTest(); +} + +} // namespace Internal +} // namespace DeviceLayer +} // namespace chip diff --git a/src/platform/cc13x2_26x2/CC13X2_26X2Config.h b/src/platform/cc13x2_26x2/CC13X2_26X2Config.h new file mode 100644 index 00000000000000..78387921221c07 --- /dev/null +++ b/src/platform/cc13x2_26x2/CC13X2_26X2Config.h @@ -0,0 +1,106 @@ +/* + * + * Copyright (c) 2020 Project CHIP Authors + * Copyright (c) 2020 Texas Instruments Incorporated + * + * 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 accessing persisted device configuration on + * Texas Instruments cc13x2_26x2 SoCs. + */ + +#pragma once + +#include + +#include + +namespace chip { +namespace DeviceLayer { +namespace Internal { + +class CC13X2_26X2Config +{ +public: + struct Key; + + // TODO: Define a proper system ID in upstream driver + static constexpr uint16_t kNvinf_sysid_chip = (13); + + static const uint16_t kCC13X2_26X2ChipConfig_Sysid = kNvinf_sysid_chip; + static const uint16_t kCC13X2_26X2ChipFactory_Sysid = kNvinf_sysid_chip; + static const uint16_t kCC13X2_26X2ChipCounters_Sysid = kNvinf_sysid_chip; + + // Key definitions for well-known keys. + static const Key kConfigKey_SerialNum; + static const Key kConfigKey_MfrDeviceId; + static const Key kConfigKey_MfrDeviceCert; + static const Key kConfigKey_MfrDeviceICACerts; + static const Key kConfigKey_MfrDevicePrivateKey; + static const Key kConfigKey_ProductRevision; + static const Key kConfigKey_ManufacturingDate; + static const Key kConfigKey_SetupPinCode; + static const Key kConfigKey_SetupDiscriminator; + static const Key kConfigKey_FabricId; + static const Key kConfigKey_ServiceConfig; + static const Key kConfigKey_PairedAccountId; + static const Key kConfigKey_ServiceId; + static const Key kConfigKey_FabricSecret; + static const Key kConfigKey_GroupKeyIndex; + static const Key kConfigKey_LastUsedEpochKeyId; + static const Key kConfigKey_FailSafeArmed; + static const Key kConfigKey_WiFiStationSecType; + static const Key kConfigKey_OperationalDeviceId; + static const Key kConfigKey_OperationalDeviceCert; + static const Key kConfigKey_OperationalDeviceICACerts; + static const Key kConfigKey_OperationalDevicePrivateKey; + + static CHIP_ERROR Init(void); + + // 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); + static CHIP_ERROR FactoryResetConfig(void); + + static void RunConfigUnitTest(void); +}; + +struct CC13X2_26X2Config::Key +{ + NVINTF_itemID_t nvID; + + bool operator==(const Key & other) const; +}; + +inline bool CC13X2_26X2Config::Key::operator==(const Key & other) const +{ + return (nvID.systemID == other.nvID.systemID && nvID.itemID == other.nvID.itemID && nvID.subID == other.nvID.subID); +} + +} // namespace Internal +} // namespace DeviceLayer +} // namespace chip diff --git a/src/platform/cc13x2_26x2/CHIPDevicePlatformConfig.h b/src/platform/cc13x2_26x2/CHIPDevicePlatformConfig.h new file mode 100644 index 00000000000000..42141b76166476 --- /dev/null +++ b/src/platform/cc13x2_26x2/CHIPDevicePlatformConfig.h @@ -0,0 +1,44 @@ +/* + * + * Copyright (c) 2020 Project CHIP Authors + * Copyright (c) 2020 Texas Instruments Incorporated + * + * 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 the chip Device Layer + * for the Texas Instruments CC1352 platform. + * + * NOTE: currently a bare-bones implementation to allow for building. + */ + +#pragma once + +// ==================== Platform Adaptations ==================== + +#define CHIP_DEVICE_CONFIG_ENABLE_WIFI_STATION 0 +#define CHIP_DEVICE_CONFIG_ENABLE_WIFI_AP 0 + +// ========== Platform-specific Configuration ========= + +#define CHIP_DEVICE_CONFIG_ENABLE_WIFI_TELEMETRY 0 +#define CHIP_DEVICE_CONFIG_ENABLE_THREAD_TELEMETRY 0 +#define CHIP_DEVICE_CONFIG_ENABLE_THREAD_TELEMETRY_FULL 0 +#define CHIP_DEVICE_CONFIG_ENABLE_TUNNEL_TELEMETRY 0 +#define CHIP_DEVICE_CONFIG_LOG_PROVISIONING_HASH 0 + +// ========== CHIP Platform Configuration ========= + +#define CHIP_DEVICE_CONFIG_ENABLE_THREAD 1 diff --git a/src/platform/nrfconnect/BLEManagerImpl.cpp b/src/platform/cc13x2_26x2/CHIPDevicePlatformEvent.h similarity index 64% rename from src/platform/nrfconnect/BLEManagerImpl.cpp rename to src/platform/cc13x2_26x2/CHIPDevicePlatformEvent.h index 9d89e49cced948..ea5b2f05b78324 100644 --- a/src/platform/nrfconnect/BLEManagerImpl.cpp +++ b/src/platform/cc13x2_26x2/CHIPDevicePlatformEvent.h @@ -1,6 +1,7 @@ /* * * Copyright (c) 2020 Project CHIP Authors + * Copyright (c) 2020 Texas Instruments Incorporated * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,24 +18,25 @@ /** * @file - * Provides an implementation of the BLEManager singleton object - * for Zephyr platforms. + * Defines platform-specific event types and data for the chip + * for the Texas Instruments CC1352 platform. + * + * NOTE: currently a bare-bones implementation to allow for building. */ -#include - -#if CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE +#pragma once -#include +#include namespace chip { namespace DeviceLayer { -namespace Internal { -BLEManagerImpl BLEManagerImpl::sInstance; +/** + * Represents platform-specific event information + */ +struct ChipDevicePlatformEvent final +{ +}; -} // namespace Internal } // namespace DeviceLayer } // namespace chip - -#endif // CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE diff --git a/src/platform/cc13x2_26x2/CHIPPlatformConfig.h b/src/platform/cc13x2_26x2/CHIPPlatformConfig.h new file mode 100644 index 00000000000000..944e89c580fc90 --- /dev/null +++ b/src/platform/cc13x2_26x2/CHIPPlatformConfig.h @@ -0,0 +1,80 @@ +/* + * + * Copyright (c) 2020 Project CHIP Authors + * Copyright (c) 2020 Texas Instruments Incorporated + * + * 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 Texas Instruments CC1352 platform. + * + * NOTE: currently a bare-bones implementation to allow for building. + */ + +#pragma once + +#include + +// ==================== General Platform Adaptations ==================== + +#define CHIP_CONFIG_ERROR_TYPE uint32_t +#define CHIP_CONFIG_NO_ERROR (0) + +#define ASN1_CONFIG_ERROR_TYPE uint32_t +#define ASN1_CONFIG_NO_ERROR (0) + +#define ChipDie() assert() + +#define CHIP_CONFIG_PERSISTED_STORAGE_KEY_TYPE uint16_t +#define CHIP_CONFIG_PERSISTED_STORAGE_ENC_MSG_CNTR_ID 1 +#define CHIP_CONFIG_PERSISTED_STORAGE_MAX_KEY_LENGTH 2 + +// ==================== Security Adaptations ==================== + +#define CHIP_CONFIG_USE_OPENSSL_ECC 0 +#define CHIP_CONFIG_USE_MICRO_ECC 1 + +#define CHIP_CONFIG_HASH_IMPLEMENTATION_OPENSSL 0 +#define CHIP_CONFIG_HASH_IMPLEMENTATION_MINCRYPT 1 +#define CHIP_CONFIG_HASH_IMPLEMENTATION_MBEDTLS 0 +#define CHIP_CONFIG_HASH_IMPLEMENTATION_PLATFORM 0 + +#define CHIP_CONFIG_AES_IMPLEMENTATION_OPENSSL 0 +#define CHIP_CONFIG_AES_IMPLEMENTATION_AESNI 0 +#define CHIP_CONFIG_AES_IMPLEMENTATION_MBEDTLS 1 +#define CHIP_CONFIG_AES_IMPLEMENTATION_PLATFORM 0 + +#define CHIP_CONFIG_RNG_IMPLEMENTATION_OPENSSL 0 +#define CHIP_CONFIG_RNG_IMPLEMENTATION_CHIPDRBG 1 +#define CHIP_CONFIG_RNG_IMPLEMENTATION_PLATFORM 0 + +#define CHIP_CONFIG_ENABLE_PASE_INITIATOR 0 +#define CHIP_CONFIG_ENABLE_PASE_RESPONDER 1 +#define CHIP_CONFIG_ENABLE_CASE_INITIATOR 1 + +#define CHIP_CONFIG_SUPPORT_PASE_CONFIG0 0 +#define CHIP_CONFIG_SUPPORT_PASE_CONFIG1 0 +#define CHIP_CONFIG_SUPPORT_PASE_CONFIG2 0 +#define CHIP_CONFIG_SUPPORT_PASE_CONFIG3 0 +#define CHIP_CONFIG_SUPPORT_PASE_CONFIG4 1 + +#define CHIP_CONFIG_ENABLE_KEY_EXPORT_INITIATOR 0 + +#define CHIP_CONFIG_ENABLE_PROVISIONING_BUNDLE_SUPPORT 0 + +// ==================== General Configuration Overrides ==================== + +/* none yet */ diff --git a/src/platform/cc13x2_26x2/ConfigurationManagerImpl.cpp b/src/platform/cc13x2_26x2/ConfigurationManagerImpl.cpp new file mode 100644 index 00000000000000..c630c1f4bbcf3a --- /dev/null +++ b/src/platform/cc13x2_26x2/ConfigurationManagerImpl.cpp @@ -0,0 +1,132 @@ +/* + * + * Copyright (c) 2020 Project CHIP Authors + * Copyright (c) 2020 Texas Instruments Incorporated + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @file + * Provides the implementation of the Device Layer ConfigurationManager object + * for the Texas Instruments CC1352 platform. + * + */ + +/* this file behaves like a config.h, comes first */ +#include + +#include +#include + +#include +#include + +#include +#include + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wconversion" +// BSP header cannot handle conversions + +// clang-format off +// `/` is a path delimiter, not the division operation + +#include +#include DeviceFamily_constructPath(driverlib/sys_ctrl.h) + +// clang-format on + +#pragma GCC diagnostic pop + +namespace chip { +namespace DeviceLayer { + +using namespace ::chip::DeviceLayer::Internal; + +/** Singleton instance of the ConfigurationManager implementation object. + */ +ConfigurationManagerImpl ConfigurationManagerImpl::sInstance; + +CHIP_ERROR ConfigurationManagerImpl::_Init() +{ + CHIP_ERROR err; + bool failSafeArmed; + + // If the fail-safe was armed when the device last shutdown, initiate a factory reset. + if (_GetFailSafeArmed(failSafeArmed) == CHIP_NO_ERROR && failSafeArmed) + { + ChipLogProgress(DeviceLayer, "Detected fail-safe armed on reboot; initiating factory reset"); + _InitiateFactoryReset(); + } + err = CHIP_NO_ERROR; + + return err; +} + +bool ConfigurationManagerImpl::_CanFactoryReset() +{ + // TODO: query the application to determine if factory reset is allowed. + return true; +} + +void ConfigurationManagerImpl::_InitiateFactoryReset() +{ + PlatformMgr().ScheduleWork(DoFactoryReset); +} + +CHIP_ERROR ConfigurationManagerImpl::_ReadPersistedStorageValue(::chip::Platform::PersistedStorage::Key key, uint32_t & value) +{ + CC13X2_26X2Config::Key configKey{ { kCC13X2_26X2ChipCounters_Sysid, key } }; + + CHIP_ERROR err = ReadConfigValue(configKey, value); + if (err == CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND) + { + err = CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND; + } + return err; +} + +CHIP_ERROR ConfigurationManagerImpl::_WritePersistedStorageValue(::chip::Platform::PersistedStorage::Key key, uint32_t value) +{ + CC13X2_26X2Config::Key configKey{ { kCC13X2_26X2ChipCounters_Sysid, key } }; + return WriteConfigValue(configKey, value); +} + +void ConfigurationManagerImpl::DoFactoryReset(intptr_t arg) +{ + CHIP_ERROR err; + + ChipLogProgress(DeviceLayer, "Performing factory reset"); + + err = FactoryResetConfig(); + if (err != CHIP_NO_ERROR) + { + ChipLogError(DeviceLayer, "FactoryResetConfig() failed: %s", ErrorStr(err)); + } + +#if CHIP_DEVICE_CONFIG_ENABLE_THREAD + + ChipLogProgress(DeviceLayer, "Clearing Thread provision"); + ThreadStackMgr().ErasePersistentInfo(); + +#endif // CHIP_DEVICE_CONFIG_ENABLE_THREAD + + // Restart the system. + ChipLogProgress(DeviceLayer, "System restarting"); + // There should probably be an OS API for this + SysCtrlSystemReset(); +} + +} // namespace DeviceLayer +} // namespace chip diff --git a/src/platform/cc13x2_26x2/ConfigurationManagerImpl.h b/src/platform/cc13x2_26x2/ConfigurationManagerImpl.h new file mode 100644 index 00000000000000..b2cbbd27ea4243 --- /dev/null +++ b/src/platform/cc13x2_26x2/ConfigurationManagerImpl.h @@ -0,0 +1,100 @@ +/* + * + * Copyright (c) 2020 Project CHIP Authors + * Copyright (c) 2020 Texas Instruments Incorporated + * + * 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 ConfigurationManager object + * for the Texas Instruments CC1352 platform. + */ + +#pragma once + +#include +#include + +namespace chip { +namespace DeviceLayer { + +/** + * Concrete implementation of the ConfigurationManager singleton object for the CC13X2_26X2 platform. + */ +class ConfigurationManagerImpl final : public ConfigurationManager, + public Internal::GenericConfigurationManagerImpl, + private Internal::CC13X2_26X2Config +{ + // Allow the ConfigurationManager interface class to delegate method calls to + // the implementation methods provided by this class. + friend class ConfigurationManager; + + // Allow the GenericConfigurationManagerImpl base class to access helper methods and types + // defined on this class. + friend class Internal::GenericConfigurationManagerImpl; + +private: + // ===== Members that implement the ConfigurationManager public interface. + + CHIP_ERROR _Init(void); + CHIP_ERROR _GetPrimaryWiFiMACAddress(uint8_t * buf); + bool _CanFactoryReset(void); + void _InitiateFactoryReset(void); + CHIP_ERROR _ReadPersistedStorageValue(::chip::Platform::PersistedStorage::Key key, uint32_t & value); + CHIP_ERROR _WritePersistedStorageValue(::chip::Platform::PersistedStorage::Key key, uint32_t value); + + // NOTE: Other public interface methods are implemented by GenericConfigurationManagerImpl<>. + + // ===== Members for internal use by the following friends. + + friend ConfigurationManager & ConfigurationMgr(void); + friend ConfigurationManagerImpl & ConfigurationMgrImpl(void); + + static ConfigurationManagerImpl sInstance; + + // ===== Private members reserved for use by this class only. + + static void DoFactoryReset(intptr_t arg); +}; + +/** + * Returns the public interface of the ConfigurationManager singleton object. + * + * chip applications should use this to access features of the ConfigurationManager object + * that are common to all platforms. + */ +inline ConfigurationManager & ConfigurationMgr(void) +{ + return ConfigurationManagerImpl::sInstance; +} + +/** + * Returns the platform-specific implementation of the ConfigurationManager singleton object. + * + * chip applications can use this to gain access to features of the ConfigurationManager + * that are specific to the CC1352 SoC + */ +inline ConfigurationManagerImpl & ConfigurationMgrImpl(void) +{ + return ConfigurationManagerImpl::sInstance; +} + +inline CHIP_ERROR ConfigurationManagerImpl::_GetPrimaryWiFiMACAddress(uint8_t * buf) +{ + return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE; +} + +} // namespace DeviceLayer +} // namespace chip diff --git a/src/platform/cc13x2_26x2/ConnectivityManagerImpl.cpp b/src/platform/cc13x2_26x2/ConnectivityManagerImpl.cpp new file mode 100644 index 00000000000000..118030090c05d5 --- /dev/null +++ b/src/platform/cc13x2_26x2/ConnectivityManagerImpl.cpp @@ -0,0 +1,73 @@ +/* + * + * Copyright (c) 2020 Project CHIP Authors + * Copyright (c) 2020 Texas Instruments Incorporated + * + * 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 connectivity manager impl class + * for the Texas Instruments CC1352 platform. + */ + +/* this file behaves like a config.h, comes first */ +#include + +#if CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE +#include +#endif + +#if CHIP_DEVICE_CONFIG_ENABLE_THREAD +#include +#endif + +#include +#include +#include +#include + +#include +#include +#include +#include + +using namespace ::chip; +using namespace ::chip::TLV; +using namespace ::chip::DeviceLayer::Internal; + +namespace chip { +namespace DeviceLayer { + +ConnectivityManagerImpl ConnectivityManagerImpl::sInstance; + +CHIP_ERROR ConnectivityManagerImpl::_Init() +{ + // Initialize the generic base classes that require it. +#if CHIP_DEVICE_CONFIG_ENABLE_THREAD + GenericConnectivityManagerImpl_Thread::_Init(); +#endif + + return CHIP_NO_ERROR; +} + +void ConnectivityManagerImpl::_OnPlatformEvent(const ChipDeviceEvent * event) +{ + // Forward the event to the generic base classes as needed. +#if CHIP_DEVICE_CONFIG_ENABLE_THREAD + GenericConnectivityManagerImpl_Thread::_OnPlatformEvent(event); +#endif +} + +} // namespace DeviceLayer +} // namespace chip diff --git a/src/platform/cc13x2_26x2/ConnectivityManagerImpl.h b/src/platform/cc13x2_26x2/ConnectivityManagerImpl.h new file mode 100644 index 00000000000000..467d16ccad5d3e --- /dev/null +++ b/src/platform/cc13x2_26x2/ConnectivityManagerImpl.h @@ -0,0 +1,119 @@ +/* + * + * Copyright (c) 2020 Project CHIP Authors + * Copyright (c) 2020 Texas Instruments Incorporated + * + * 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 connectivity manager class for the Texas + * Instruments CC1352 platform. + */ + +#pragma once + +#include +#include +#if CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE +#include +#else +#include +#endif +#if CHIP_DEVICE_CONFIG_ENABLE_THREAD +#include +#else +#include +#endif +#include + +namespace chip { +namespace DeviceLayer { + +/** + * Concrete implementation of the ConnectivityManager singleton object for the CC13X2_26X2 platforms. + */ +class ConnectivityManagerImpl final : public ConnectivityManager, + public Internal::GenericConnectivityManagerImpl, +#if CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE + public Internal::GenericConnectivityManagerImpl_BLE, +#else + public Internal::GenericConnectivityManagerImpl_NoBLE, +#endif +#if CHIP_DEVICE_CONFIG_ENABLE_THREAD + public Internal::GenericConnectivityManagerImpl_Thread, +#else + public Internal::GenericConnectivityManagerImpl_NoThread, +#endif + public Internal::GenericConnectivityManagerImpl_NoWiFi +{ + // Allow the ConnectivityManager interface class to delegate method calls to + // the implementation methods provided by this class. + friend class ConnectivityManager; + +private: + // ===== Members that implement the ConnectivityManager abstract interface. + + bool _HaveIPv4InternetConnectivity(void); + bool _HaveIPv6InternetConnectivity(void); + bool _HaveServiceConnectivity(void); + CHIP_ERROR _Init(void); + void _OnPlatformEvent(const ChipDeviceEvent * event); + + // ===== Members for internal use by the following friends. + + friend ConnectivityManager & ConnectivityMgr(void); + friend ConnectivityManagerImpl & ConnectivityMgrImpl(void); + + static ConnectivityManagerImpl sInstance; +}; + +inline bool ConnectivityManagerImpl::_HaveIPv4InternetConnectivity(void) +{ + return false; +} + +inline bool ConnectivityManagerImpl::_HaveIPv6InternetConnectivity(void) +{ + return false; +} + +inline bool ConnectivityManagerImpl::_HaveServiceConnectivity(void) +{ + return _HaveServiceConnectivityViaThread(); +} + +/** + * 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 CC1352 platform + */ +inline ConnectivityManagerImpl & ConnectivityMgrImpl(void) +{ + return ConnectivityManagerImpl::sInstance; +} + +} // namespace DeviceLayer +} // namespace chip diff --git a/src/platform/Zephyr/GenericThreadStackManagerImpl_Zephyr.cpp b/src/platform/cc13x2_26x2/DeviceNetworkProvisioningDelegateImpl.h similarity index 52% rename from src/platform/Zephyr/GenericThreadStackManagerImpl_Zephyr.cpp rename to src/platform/cc13x2_26x2/DeviceNetworkProvisioningDelegateImpl.h index d660c38463565d..e3ba66ca9db3f4 100644 --- a/src/platform/Zephyr/GenericThreadStackManagerImpl_Zephyr.cpp +++ b/src/platform/cc13x2_26x2/DeviceNetworkProvisioningDelegateImpl.h @@ -1,7 +1,6 @@ /* * * 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. @@ -16,28 +15,29 @@ * limitations under the License. */ -/** - * @file - * Contains non-inline method definitions for the - * GenericThreadStackManagerImpl_Zephyr<> template. - */ - -#ifndef GENERIC_THREAD_STACK_MANAGER_IMPL_ZEPHYR_IPP -#define GENERIC_THREAD_STACK_MANAGER_IMPL_ZEPHYR_IPP +#pragma once -#include -#include -#include +#include namespace chip { namespace DeviceLayer { + namespace Internal { -// Fully instantiate the generic implementation class in whatever compilation unit includes this file. -template class GenericThreadStackManagerImpl_Zephyr; +template +class GenericDeviceNetworkProvisioningDelegateImpl; } // namespace Internal + +class DeviceNetworkProvisioningDelegateImpl final + : public Internal::GenericDeviceNetworkProvisioningDelegateImpl +{ + friend class GenericDeviceNetworkProvisioningDelegateImpl; + +private: + CHIP_ERROR _ProvisionWiFiNetwork(const char * ssid, const char * passwd) { return CHIP_ERROR_NOT_IMPLEMENTED; } + CHIP_ERROR _ProvisionThreadNetwork(DeviceLayer::Internal::DeviceNetworkInfo & threadData) { return CHIP_ERROR_NOT_IMPLEMENTED; } +}; + } // namespace DeviceLayer } // namespace chip - -#endif // GENERIC_THREAD_STACK_MANAGER_IMPL_ZEPHYR_IPP diff --git a/src/platform/cc13x2_26x2/FreeRTOSConfig.h b/src/platform/cc13x2_26x2/FreeRTOSConfig.h new file mode 100644 index 00000000000000..b4138ef1d7d59b --- /dev/null +++ b/src/platform/cc13x2_26x2/FreeRTOSConfig.h @@ -0,0 +1,222 @@ +/* + * FreeRTOS Kernel V10.0.0 + * Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. If you wish to use our + * Amazon FreeRTOS name, please do so in a fair use way that does not cause + * confusion. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * http://www.FreeRTOS.org + * http://aws.amazon.com/freertos + * + * 1 tab == 4 spaces! + */ + +/****************************************************************************** + See http://www.freertos.org/a00110.html for an explanation of the + definitions contained in this file. +******************************************************************************/ + +#ifndef FREERTOS_CONFIG_H +#define FREERTOS_CONFIG_H + +/*----------------------------------------------------------- + * Application specific definitions. + * + * These definitions should be adjusted for your particular hardware and + * application requirements. + * + * THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE + * FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE. + * http://www.freertos.org/a00110.html + *----------------------------------------------------------*/ + +/* Constants related to the behaviour or the scheduler. */ +#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1 +#define configTICK_RATE_HZ ((TickType_t) 1000) +#define configUSE_PREEMPTION 1 +#define configUSE_TIME_SLICING 0 +#define configMAX_PRIORITIES (10UL) +#define configIDLE_SHOULD_YIELD 0 +#define configUSE_16_BIT_TICKS 0 /* Only for 8 and 16-bit hardware. */ + +/* Constants that describe the hardware and memory usage. */ +#define configCPU_CLOCK_HZ ((unsigned long) 48000000) +#define configMINIMAL_STACK_SIZE ((unsigned short) 256) +#define configMAX_TASK_NAME_LEN (12) + +#define configTOTAL_HEAP_SIZE ((size_t)(0x8000)) +#define configSUPPORT_STATIC_ALLOCATION 1 + +/* Default stack size for TI-POSIX threads (in words) */ +#define configPOSIX_STACK_SIZE ((unsigned short) 512) + +/* Constants that build features in or out. */ +#define configUSE_MUTEXES 1 +#define configUSE_TICKLESS_IDLE 1 +#define configUSE_APPLICATION_TASK_TAG 1 /* Need by POSIX/pthread */ +#define configUSE_CO_ROUTINES 0 +#define configUSE_COUNTING_SEMAPHORES 1 +#define configUSE_RECURSIVE_MUTEXES 1 +#define configUSE_QUEUE_SETS 0 +#define configUSE_TASK_NOTIFICATIONS 1 + +/* Constants that define which hook (callback) functions should be used. */ +#define configUSE_IDLE_HOOK 0 +#define configUSE_TICK_HOOK 0 +#define configUSE_MALLOC_FAILED_HOOK 0 + +/* Constants provided for debugging and optimisation assistance. */ +#define configCHECK_FOR_STACK_OVERFLOW 2 +#define configASSERT(x) \ + if ((x) == 0) \ + { \ + taskDISABLE_INTERRUPTS(); \ + for (;;) \ + ; \ + } +#define configQUEUE_REGISTRY_SIZE 0 + +/* Minimum FreeRTOS tick periods of idle before invoking Power policy */ +/* TODO: find way to reduce this; FreeRTOS requires it to be 2 or more */ +#define configEXPECTED_IDLE_TIME_BEFORE_SLEEP 2 + +/* Software timer definitions. */ +#define configUSE_TIMERS 1 +#define configTIMER_TASK_PRIORITY (5) +#define configTIMER_QUEUE_LENGTH (20) +#define configTIMER_TASK_STACK_DEPTH (configMINIMAL_STACK_SIZE * 2) + +#define configENABLE_BACKWARD_COMPATIBILITY 1 + +#if defined(__TI_COMPILER_VERSION__) || defined(__ti_version__) +#include +#define traceTASK_DELETE(pxTCB) PTLS_taskDeleteHook(pxTCB) +#elif defined(__IAR_SYSTEMS_ICC__) +#ifndef __IAR_SYSTEMS_ASM__ +#include +#define traceTASK_DELETE(pxTCB) Mtx_taskDeleteHook(pxTCB) +#endif +#endif + +/* + * Enable thread local storage + * + * Assign TLS array index ownership here to avoid collisions. + * TLS storage is needed to implement thread-safe errno with + * TI and IAR compilers. With GNU compiler, we enable newlib. + */ +#if defined(__TI_COMPILER_VERSION__) || defined(__ti_version__) || defined(__IAR_SYSTEMS_ICC__) + +#define configNUM_THREAD_LOCAL_STORAGE_POINTERS 2 + +#if defined(__TI_COMPILER_VERSION__) || defined(__ti_version__) +#define PTLS_TLS_INDEX 0 /* ti.posix.freertos.PTLS */ +#elif defined(__IAR_SYSTEMS_ICC__) +#define MTX_TLS_INDEX 0 /* ti.posix.freertos.Mtx */ +#endif + +#define NDK_TLS_INDEX 1 /* Reserve an index for NDK TLS */ + +#elif defined(__GNUC__) + +#define configNUM_THREAD_LOCAL_STORAGE_POINTERS 1 + +#define NDK_TLS_INDEX 0 /* Reserve an index for NDK TLS */ + +/* note: system locks required by newlib are not implemented */ +#define configUSE_NEWLIB_REENTRANT 1 +#endif + +/* + * Set the following definitions to 1 to include the API function, or zero + * to exclude the API function. NOTE: Setting an INCLUDE_ parameter to 0 is + * only necessary if the linker does not automatically remove functions that + * are not referenced anyway. + */ +#define INCLUDE_vTaskPrioritySet 1 +#define INCLUDE_uxTaskPriorityGet 1 +#define INCLUDE_vTaskDelete 1 +#define INCLUDE_vTaskCleanUpResources 0 +#define INCLUDE_vTaskSuspend 1 +#define INCLUDE_vTaskDelayUntil 1 +#define INCLUDE_vTaskDelay 1 +#define INCLUDE_uxTaskGetStackHighWaterMark 0 +#define INCLUDE_xTaskGetIdleTaskHandle 0 +#define INCLUDE_eTaskGetState 1 +#define INCLUDE_xTaskResumeFromISR 0 +#define INCLUDE_xTaskGetCurrentTaskHandle 1 +#define INCLUDE_xTaskGetSchedulerState 1 +#define INCLUDE_xSemaphoreGetMutexHolder 0 +#define INCLUDE_xTimerPendFunctionCall 0 + +/* Cortex-M3/4 interrupt priority configuration follows...................... */ + +/* Use the system definition, if there is one. */ +#ifdef __NVIC_PRIO_BITS +#define configPRIO_BITS __NVIC_PRIO_BITS +#else +#define configPRIO_BITS 3 /* 8 priority levels */ +#endif + +/* + * The lowest interrupt priority that can be used in a call to a "set priority" + * function. + */ +#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY 0x07 + +/* + * The highest interrupt priority that can be used by any interrupt service + * routine that makes calls to interrupt safe FreeRTOS API functions. DO NOT + * CALL INTERRUPT SAFE FREERTOS API FUNCTIONS FROM ANY INTERRUPT THAT HAS A + * HIGHER PRIORITY THAN THIS! (higher priorities are lower numeric values. + */ +#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 1 + +/* + * Interrupt priorities used by the kernel port layer itself. These are generic + * to all Cortex-M ports, and do not rely on any particular library functions. + */ +#define configKERNEL_INTERRUPT_PRIORITY (configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS)) + +/* + * !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!! + * See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. + * + * Priority 1 (shifted 5 since only the top 3 bits are implemented). + * Priority 1 is the second highest priority. + * Priority 0 is the highest priority. + */ +#define configMAX_SYSCALL_INTERRUPT_PRIORITY (configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS)) + +/* + * The trace facility is turned on to make some functions available for use in + * CLI commands. + */ +#define configUSE_TRACE_FACILITY 1 + +/* + * Runtime Object View is a Texas Instrument host tool that helps visualize + * the application. When enabled, the ISR stack will be initialized in the + * startup__.c file to 0xa5a5a5a5. The stack peak can then + * be displayed in Runtime Object View. + */ +#define configENABLE_ISR_STACK_INIT 1 + +#endif /* FREERTOS_CONFIG_H */ diff --git a/src/platform/cc13x2_26x2/InetPlatformConfig.h b/src/platform/cc13x2_26x2/InetPlatformConfig.h new file mode 100644 index 00000000000000..a90834c76aa046 --- /dev/null +++ b/src/platform/cc13x2_26x2/InetPlatformConfig.h @@ -0,0 +1,46 @@ +/* + * + * 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. + */ + +/** + * @file + * Platform-specific configuration overrides for the Openchip Inet + * Layer on nRF52 platforms using the Nordic nRF5 SDK. + * + */ + +#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 + +#define INET_CONFIG_ENABLE_IPV4 0 + +// ========== Platform-specific Configuration Overrides ========= + +#ifndef INET_CONFIG_NUM_TCP_ENDPOINTS +#define INET_CONFIG_NUM_TCP_ENDPOINTS 4 +#endif // INET_CONFIG_NUM_TCP_ENDPOINTS + +#ifndef INET_CONFIG_NUM_UDP_ENDPOINTS +#define INET_CONFIG_NUM_UDP_ENDPOINTS 4 +#endif // INET_CONFIG_NUM_UDP_ENDPOINTS diff --git a/src/platform/cc13x2_26x2/Logging.cpp b/src/platform/cc13x2_26x2/Logging.cpp new file mode 100644 index 00000000000000..e3225084a68a33 --- /dev/null +++ b/src/platform/cc13x2_26x2/Logging.cpp @@ -0,0 +1,151 @@ +/* + * + * Copyright (c) 2020 Project CHIP Authors + * Copyright (c) 2020 Texas Instruments Incorporated + * + * 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 implementations for the CHIP and LwIP logging functions + * for the Texas Instruments CC1352 platform. This uses one of the + * UARTs configured with SysConfig. Future implementations may use + * ITM. + * + */ + +#include "ti_drivers_config.h" +#include +#include + +#include + +#include + +using namespace ::chip; +using namespace ::chip::DeviceLayer; +using namespace ::chip::DeviceLayer::Internal; + +#define DEVICE_LAYER_LOG_BUFFER_SIZE (256) +UART_Handle sDebugUartHandle; +char sDebugUartBuffer[DEVICE_LAYER_LOG_BUFFER_SIZE]; + +extern "C" int cc13x2_26x2LogInit(void) +{ + UART_Params uartParams; + + UART_init(); + + UART_Params_init(&uartParams); + // Most params can be default because we only send data, we don't receive + uartParams.baudRate = 115200; + // unclear why the UART driver sticks in writing sometimes + uartParams.writeTimeout = 10000; // ticks + + sDebugUartHandle = UART_open(CONFIG_UART_DEBUG, &uartParams); + return 0; +} + +extern "C" void cc13x2_26x2VLog(const char * msg, va_list v) +{ + int ret; + + ret = vsnprintf(sDebugUartBuffer, sizeof(sDebugUartBuffer), msg, v); + if (0 < ret) + { + // PuTTY likes \r\n + size_t len = (ret + 2U) < sizeof(sDebugUartBuffer) ? (ret + 2) : sizeof(sDebugUartBuffer); + sDebugUartBuffer[len - 2] = '\r'; + sDebugUartBuffer[len - 1] = '\n'; + sDebugUartBuffer[len] = '\0'; + + UART_write(sDebugUartHandle, sDebugUartBuffer, len); + } +} + +namespace chip { +namespace DeviceLayer { + +/** + * Called whenever a log message is emitted. + * + * Can be overriden by the device logging file + */ +void __attribute__((weak)) OnLogOutput(void) {} + +} // namespace DeviceLayer +} // namespace chip + +namespace chip { +namespace Logging { + +void LogV(uint8_t module, uint8_t category, const char * msg, va_list v) +{ + (void) module; + (void) category; + + cc13x2_26x2VLog(msg, v); + + DeviceLayer::OnLogOutput(); +} + +} // namespace Logging +} // namespace chip + +/** + * LwIP log output function. + */ +extern "C" void LwIPLog(const char * msg, ...) +{ + va_list v; + + va_start(v, msg); + + cc13x2_26x2VLog(msg, v); + + DeviceLayer::OnLogOutput(); + va_end(v); +} + +/** + * Platform log output function. + */ +extern "C" void cc13x2_26x2Log(const char * msg, ...) +{ + va_list v; + + va_start(v, msg); + + cc13x2_26x2VLog(msg, v); + + DeviceLayer::OnLogOutput(); + va_end(v); +} + +#if CHIP_DEVICE_CONFIG_ENABLE_THREAD +extern "C" void otPlatLog(otLogLevel aLogLevel, otLogRegion aLogRegion, const char * aFormat, ...) +{ + va_list v; + + (void) aLogLevel; + (void) aLogRegion; + + va_start(v, aFormat); + + cc13x2_26x2VLog(aFormat, v); + + DeviceLayer::OnLogOutput(); + va_end(v); +} +#endif diff --git a/src/platform/cc13x2_26x2/PlatformManagerImpl.cpp b/src/platform/cc13x2_26x2/PlatformManagerImpl.cpp new file mode 100644 index 00000000000000..b8b7010275011c --- /dev/null +++ b/src/platform/cc13x2_26x2/PlatformManagerImpl.cpp @@ -0,0 +1,59 @@ +/* + * + * Copyright (c) 2020 Project CHIP Authors + * Copyright (c) 2020 Texas Instruments Incorporated + * + * 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 Texas Instruments CC1352 platform. + */ + +/* this file behaves like a config.h, comes first */ +#include + +#include +#include + +#include + +namespace chip { +namespace DeviceLayer { + +PlatformManagerImpl PlatformManagerImpl::sInstance; + +CHIP_ERROR PlatformManagerImpl::_InitChipStack(void) +{ + CHIP_ERROR err; + + // Initialize the configuration system. + err = Internal::CC13X2_26X2Config::Init(); + SuccessOrExit(err); + + // Initialize LwIP. + tcpip_init(NULL, NULL); + + // Call _InitChipStack() on the generic implementation base class + // to finish the initialization process. + err = Internal::GenericPlatformManagerImpl_FreeRTOS::_InitChipStack(); + SuccessOrExit(err); + +exit: + return err; +} + +} // namespace DeviceLayer +} // namespace chip diff --git a/src/platform/cc13x2_26x2/PlatformManagerImpl.h b/src/platform/cc13x2_26x2/PlatformManagerImpl.h new file mode 100644 index 00000000000000..735d34c903346e --- /dev/null +++ b/src/platform/cc13x2_26x2/PlatformManagerImpl.h @@ -0,0 +1,92 @@ +/* + * + * Copyright (c) 2020 Project CHIP Authors + * Copyright (c) 2020 Texas Instruments Incorporated + * + * 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. + */ + +#pragma once + +#include + +namespace chip { +namespace DeviceLayer { + +/** + * Concrete implementation of the PlatformManager singleton object for the + * CC13X2_26X2 platform. + */ +class PlatformManagerImpl final : public PlatformManager, public Internal::GenericPlatformManagerImpl_FreeRTOS +{ + // Allow the PlatformManager interface class to delegate method calls to + // the implementation methods provided by this class. + friend PlatformManager; + + // 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. + + /* none so far */ + +private: + // ===== Methods that implement the PlatformManager abstract interface. + + CHIP_ERROR _InitChipStack(void); + + // ===== Members for internal use by the following friends. + + friend PlatformManager & PlatformMgr(void); + friend PlatformManagerImpl & PlatformMgrImpl(void); + friend class Internal::BLEManagerImpl; + + static PlatformManagerImpl sInstance; + + using Internal::GenericPlatformManagerImpl_FreeRTOS::PostEventFromISR; +}; + +/** + * 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 CC1352 SoC. + */ +inline PlatformManagerImpl & PlatformMgrImpl(void) +{ + return PlatformManagerImpl::sInstance; +} + +} // namespace DeviceLayer +} // namespace chip diff --git a/src/platform/cc13x2_26x2/SystemPlatformConfig.h b/src/platform/cc13x2_26x2/SystemPlatformConfig.h new file mode 100644 index 00000000000000..ff6c4212dfec25 --- /dev/null +++ b/src/platform/cc13x2_26x2/SystemPlatformConfig.h @@ -0,0 +1,55 @@ +/* + * + * 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. + */ + +/** + * @file + * Platform-specific configuration overrides for the CHIP System + * Layer + * + */ + +#pragma once + +#include + +namespace chip { +namespace DeviceLayer { +struct ChipDeviceEvent; +} // namespace DeviceLayer +} // namespace chip + +// ==================== Platform Adaptations ==================== + +#define CHIP_SYSTEM_CONFIG_POSIX_LOCKING 0 +#define CHIP_SYSTEM_CONFIG_FREERTOS_LOCKING 0 +#define CHIP_SYSTEM_CONFIG_NO_LOCKING 1 +#define CHIP_SYSTEM_CONFIG_PLATFORM_PROVIDES_EVENT_FUNCTIONS 1 +#define CHIP_SYSTEM_CONFIG_PLATFORM_PROVIDES_TIME 1 +#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_ERROR_TYPE uint32_t +#define CHIP_SYSTEM_CONFIG_NO_ERROR (0) + +#define CHIP_SYSTEM_CONFIG_ERROR_MIN 0 +#define CHIP_SYSTEM_CONFIG_ERROR_MAX 999 +#define _CHIP_SYSTEM_CONFIG_ERROR(e) (CHIP_SYSTEM_CONFIG_ERROR_MIN + (e)) + +// ========== Platform-specific Configuration Overrides ========= + +/* none yet */ diff --git a/src/platform/cc13x2_26x2/ThreadStackManagerImpl.cpp b/src/platform/cc13x2_26x2/ThreadStackManagerImpl.cpp new file mode 100644 index 00000000000000..688649ecbf713c --- /dev/null +++ b/src/platform/cc13x2_26x2/ThreadStackManagerImpl.cpp @@ -0,0 +1,239 @@ +/* + * + * Copyright (c) 2020 Project CHIP Authors + * Copyright (c) 2019 Nest Labs, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @file + * Provides an implementation of the ThreadStackManager object for + * CC13X2_26X2 platforms using the Texas Instruments SDK and the + * OpenThread stack. + * + */ + +/* this file behaves like a config.h, comes first */ +#include + +#include +#include + +#include +#include +#include +#include + +// platform folder in the TI SDK example application +#include + +namespace chip { +namespace DeviceLayer { + +using namespace ::chip::DeviceLayer::Internal; + +ThreadStackManagerImpl ThreadStackManagerImpl::sInstance; + +static void * ot_calloc(size_t n, size_t size) +{ + void * p_ptr = NULL; + + p_ptr = pvPortMalloc(n * size); + + memset(p_ptr, 0, n * size); + + return p_ptr; +} + +static void ot_free(void * p_ptr) +{ + vPortFree(p_ptr); +} + +CHIP_ERROR ThreadStackManagerImpl::_InitThreadStack(void) +{ + return InitThreadStack(NULL); +} + +CHIP_ERROR ThreadStackManagerImpl::InitThreadStack(otInstance * otInst) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + + // Create FreeRTOS queue for platform driver messages + procQueue = xQueueCreate(16U, sizeof(ThreadStackManagerImpl::procQueueMsg)); + + mbedtls_platform_set_calloc_free(ot_calloc, ot_free); + otHeapSetCAllocFree(ot_calloc, ot_free); + + // Initialize the OpenThread platform layer + otSysInit(0, NULL); + + // Initialize the generic implementation base classes. + err = GenericThreadStackManagerImpl_FreeRTOS::DoInit(); + SuccessOrExit(err); + err = GenericThreadStackManagerImpl_OpenThread_LwIP::DoInit(otInst); + SuccessOrExit(err); + +exit: + return err; +} + +bool ThreadStackManagerImpl::IsInitialized() +{ + return sInstance.mThreadStackLock != NULL; +} + +void ThreadStackManagerImpl::_OnCHIPoBLEAdvertisingStart(void) +{ + // If Thread-over-BLE is enabled, ensure that ToBLE advertising is stopped before + // starting CHIPoBLE advertising. This is accomplished by disabling the OpenThread + // IPv6 interface via a call to otIp6SetEnabled(false). + // +#if OPENTHREAD_CONFIG_ENABLE_TOBLE + LockThreadStack(); + otIp6SetEnabled(OTInstance(), false); + UnlockThreadStack(); +#endif +} + +void ThreadStackManagerImpl::_OnCHIPoBLEAdvertisingStop(void) +{ + // If Thread-over-BLE is enabled, and a Thread provision exists, ensure that ToBLE + // advertising is re-activated once CHIPoBLE advertising stops. + // +#if OPENTHREAD_CONFIG_ENABLE_TOBLE + LockThreadStack(); + if (otThreadGetDeviceRole(OTInstance()) != OT_DEVICE_ROLE_DISABLED && otDatasetIsCommissioned(OTInstance())) + { + otIp6SetEnabled(OTInstance(), true); + } + UnlockThreadStack(); +#endif +} + +void ThreadStackManagerImpl::_SendProcMessage(ThreadStackManagerImpl::procQueueMsg & procMsg) +{ + xQueueSendFromISR(procQueue, &procMsg, NULL); + + // signal processing loop + SignalThreadActivityPendingFromISR(); +} + +void ThreadStackManagerImpl::_ProcMessage(otInstance * aInstance) +{ + procQueueMsg procMsg; + while (pdTRUE == xQueueReceive(procQueue, &procMsg, 0U)) + { + switch (procMsg.cmd) + { + case procQueueCmd_alarm: { + platformAlarmProcess(aInstance); + break; + } + + case procQueueCmd_radio: { + platformRadioProcess(aInstance, procMsg.arg); + break; + } + + case procQueueCmd_tasklets: { + otTaskletsProcess(aInstance); + break; + } + + case procQueueCmd_uart: { + platformUartProcess(procMsg.arg); + break; + } + + case procQueueCmd_random: { + platformRandomProcess(); + break; + } + + case procQueueCmd_alarmu: { + platformAlarmMicroProcess(aInstance); + break; + } + + default: { + break; + } + } + } +} + +} // namespace DeviceLayer +} // namespace chip + +using namespace ::chip::DeviceLayer; + +/** + * Glue function called by alarm processing layer to notify OpenThread the driver needs processing. + */ +extern "C" void platformAlarmSignal() +{ + ThreadStackManagerImpl::procQueueMsg msg; + msg.cmd = ThreadStackManagerImpl::procQueueCmd_alarm; + ThreadStackMgrImpl()._SendProcMessage(msg); +} + +/** + * Glue function called by alarm processing layer to notify OpenThread the driver needs processing. + */ +extern "C" void platformAlarmMicroSignal() +{ + ThreadStackManagerImpl::procQueueMsg msg; + msg.cmd = ThreadStackManagerImpl::procQueueCmd_alarmu; + ThreadStackMgrImpl()._SendProcMessage(msg); +} + +/** + * Glue function called by radio processing layer to notify OpenThread the driver needs processing. + */ +extern "C" void platformRadioSignal(uintptr_t arg) +{ + ThreadStackManagerImpl::procQueueMsg msg; + msg.cmd = ThreadStackManagerImpl::procQueueCmd_radio; + msg.arg = arg; + ThreadStackMgrImpl()._SendProcMessage(msg); +} + +/** + * Glue function called by UART processing layer to notify OpenThread the driver needs processing. + */ +extern "C" void platformUartSignal(uintptr_t arg) +{ + ThreadStackManagerImpl::procQueueMsg msg; + msg.cmd = ThreadStackManagerImpl::procQueueCmd_uart; + msg.arg = arg; + ThreadStackMgrImpl()._SendProcMessage(msg); +} + +/** + * Glue function called directly by the OpenThread stack when tasklet processing work + * is pending. + */ +extern "C" void otTaskletsSignalPending(otInstance * p_instance) +{ + ThreadStackMgrImpl().SignalThreadActivityPending(); +} + +/** + * Process events from the drivers + */ +extern "C" void otSysProcessDrivers(otInstance * aInstance) +{ + ThreadStackMgrImpl()._ProcMessage(aInstance); +} diff --git a/src/platform/cc13x2_26x2/ThreadStackManagerImpl.h b/src/platform/cc13x2_26x2/ThreadStackManagerImpl.h new file mode 100644 index 00000000000000..aa5b70e4fb1a77 --- /dev/null +++ b/src/platform/cc13x2_26x2/ThreadStackManagerImpl.h @@ -0,0 +1,144 @@ +/* + * + * Copyright (c) 2020 Project CHIP Authors + * Copyright (c) 2020 Texas Instruments Incorporated + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @file + * Provides an implementation of the ThreadStackManager object + * for the Texas Instruments CC1352 platform. + * + * NOTE: currently a bare-bones implementation to allow for building. + */ + +#pragma once + +#include +#include + +#include +#include + +#include + +extern "C" void platformAlarmSignal(); +extern "C" void platformAlarmMicroSignal(); +extern "C" void platformRadioSignal(uintptr_t arg); +extern "C" void platformUartSignal(uintptr_t arg); + +namespace chip { +namespace DeviceLayer { + +class ThreadStackManager; +class ThreadStackManagerImpl; + +/** + * Concrete implementation of the ThreadStackManager singleton object for CC1352. + */ +class ThreadStackManagerImpl final : public ThreadStackManager, + public Internal::GenericThreadStackManagerImpl_OpenThread_LwIP, + public Internal::GenericThreadStackManagerImpl_FreeRTOS +{ + // Allow the ThreadStackManager interface class to delegate method calls to + // the implementation methods provided by this class. + friend class ThreadStackManager; + + // Allow the generic implementation base classes to call helper methods on + // this class. +#ifndef DOXYGEN_SHOULD_SKIP_THIS + friend Internal::GenericThreadStackManagerImpl_OpenThread; + friend Internal::GenericThreadStackManagerImpl_OpenThread_LwIP; + friend Internal::GenericThreadStackManagerImpl_FreeRTOS; +#endif + + // Allow glue functions called by OpenThread to call helper methods on this + // class. + friend void ::platformAlarmSignal(); + friend void ::platformAlarmMicroSignal(); + friend void ::platformRadioSignal(uintptr_t arg); + friend void ::platformUartSignal(uintptr_t arg); + friend void ::otTaskletsSignalPending(otInstance * otInst); + + enum procQueueCmd + { + procQueueCmd_alarm, + procQueueCmd_radio, + procQueueCmd_tasklets, + procQueueCmd_uart, + procQueueCmd_random, + procQueueCmd_alarmu, + }; + + struct procQueueMsg + { + enum procQueueCmd cmd; + uintptr_t arg; + }; + +public: + // ===== Platform-specific members that may be accessed directly by the application. + + using ThreadStackManager::InitThreadStack; + CHIP_ERROR InitThreadStack(otInstance * otInst); + void _OnCHIPoBLEAdvertisingStart(void); + void _OnCHIPoBLEAdvertisingStop(void); + void _SendProcMessage(procQueueMsg & procMsg); + void _ProcMessage(otInstance * aInstance); + +private: + // ===== Methods that implement the ThreadStackManager abstract interface. + + CHIP_ERROR _InitThreadStack(void); + + // ===== Members for internal use by the following friends. + + friend ThreadStackManager & ::chip::DeviceLayer::ThreadStackMgr(void); + friend ThreadStackManagerImpl & ::chip::DeviceLayer::ThreadStackMgrImpl(void); + + static ThreadStackManagerImpl sInstance; + + static bool IsInitialized(); + + // ===== Private members for use by this class only. + + ThreadStackManagerImpl() = default; + QueueHandle_t procQueue; +}; + +/** + * Returns the public interface of the ThreadStackManager singleton object. + * + * chip applications should use this to access features of the ThreadStackManager object + * that are common to all platforms. + */ +inline ThreadStackManager & ThreadStackMgr(void) +{ + return ThreadStackManagerImpl::sInstance; +} + +/** + * Returns the platform-specific implementation of the ThreadStackManager singleton object. + * + * chip applications can use this to gain access to features of the ThreadStackManager + * that are specific to CC1352 SoC. + */ +inline ThreadStackManagerImpl & ThreadStackMgrImpl(void) +{ + return ThreadStackManagerImpl::sInstance; +} + +} // namespace DeviceLayer +} // namespace chip diff --git a/src/platform/cc13x2_26x2/args.gni b/src/platform/cc13x2_26x2/args.gni new file mode 100644 index 00000000000000..8b2a11137dff18 --- /dev/null +++ b/src/platform/cc13x2_26x2/args.gni @@ -0,0 +1,43 @@ +# Copyright (c) 2020 Project CHIP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build_overrides/chip.gni") +import("//build_overrides/ti_simplelink_sdk.gni") + +# ARM architecture flags will be set based on Device Family +arm_platform_config = + "${ti_simplelink_sdk_build_root}/ti_simplelink_arm_platform_config.gni" + +chip_device_platform = "cc13x2_26x2" + +freertos_target = "${chip_root}/third_party/ti_simplelink_sdk:freertos" + +mbedtls_target = "${chip_root}/third_party/ti_simplelink_sdk:mbedtls" +openthread_external_mbedtls = mbedtls_target +openthread_external_platform = + "${ti_simplelink_sdk_build_root}:ti_simplelink_sdk" + +lwip_platform = "cc13x2_26x2" +lwip_ipv6 = true +lwip_ipv4 = false +lwip_api = true + +chip_inet_config_enable_ipv4 = false +chip_inet_config_enable_dns_resolver = false + +chip_build_tests = false + +openthread_project_core_config_file = "openthread-core-cc13x2_26x2-config.h" +openthread_core_config_platform_check_file = + "openthread-core-cc13x2_26x2-config-check.h" diff --git a/src/platform/cc13x2_26x2/cc13x2_26x2-mbedtls-config.h b/src/platform/cc13x2_26x2/cc13x2_26x2-mbedtls-config.h new file mode 100644 index 00000000000000..d4fd3f2f6a8917 --- /dev/null +++ b/src/platform/cc13x2_26x2/cc13x2_26x2-mbedtls-config.h @@ -0,0 +1,129 @@ +/* + * + * Copyright (c) 2020 Project CHIP Authors + * Copyright (c) 2020 Texas Instruments Incorporated + * + * 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 cc13x2_26x2-mbedtls-config.h.h + * + * @brief MbedTLS configuration header for CHIP + * + */ + +#ifndef CC13X2_26X2_MBEDTLS_CONFIG_H +#define CC13X2_26X2_MBEDTLS_CONFIG_H + +#include +#include + +/** + * Enable FreeRTOS threading support + */ +//#define MBEDTLS_FREERTOS +//#define MBEDTLS_THREADING_C +//#define MBEDTLS_THREADING_ALT + +/* Enable Hardware Acceleration */ + +#define MBEDTLS_ECJPAKE_ALT +#define MBEDTLS_AES_ALT +#define MBEDTLS_SHA256_ALT +//#define MBEDTLS_ENTROPY_HARDWARE_ALT + +/** + * Enable Crypto and Entropy modules + */ +//#define MBEDTLS_SHA1_C +//#define MBEDTLS_TRNG_C +//#define MBEDTLS_CIPHER_MODE_CTR + +#define MBEDTLS_PLATFORM_SNPRINTF_MACRO snprintf + +#define MBEDTLS_AES_C +#define MBEDTLS_AES_ROM_TABLES +#define MBEDTLS_ASN1_PARSE_C +#define MBEDTLS_ASN1_WRITE_C +#define MBEDTLS_BIGNUM_C +#define MBEDTLS_CCM_C +#define MBEDTLS_CIPHER_C +#define MBEDTLS_CMAC_C +#define MBEDTLS_CTR_DRBG_C +#define MBEDTLS_ECJPAKE_C +#define MBEDTLS_ECP_C +#define MBEDTLS_ECP_DP_SECP256R1_ENABLED +#define MBEDTLS_ECP_NIST_OPTIM +#define MBEDTLS_ENTROPY_C +#define MBEDTLS_HAVE_ASM +#define MBEDTLS_HMAC_DRBG_C +#define MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED +#define MBEDTLS_MD_C +#define MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES +#define MBEDTLS_NO_PLATFORM_ENTROPY +#define MBEDTLS_PK_C +#define MBEDTLS_PK_PARSE_C +#define MBEDTLS_PK_WRITE_C +#define MBEDTLS_PLATFORM_C +#define MBEDTLS_PLATFORM_MEMORY +#define MBEDTLS_PLATFORM_NO_STD_FUNCTIONS +#define MBEDTLS_SHA256_C +#define MBEDTLS_SHA256_SMALLER +#define MBEDTLS_SSL_CLI_C +#define MBEDTLS_SSL_DTLS_ANTI_REPLAY +#define MBEDTLS_SSL_DTLS_HELLO_VERIFY +#define MBEDTLS_SSL_EXPORT_KEYS +#define MBEDTLS_SSL_MAX_FRAGMENT_LENGTH +#define MBEDTLS_SSL_PROTO_TLS1_2 +#define MBEDTLS_SSL_PROTO_DTLS +#define MBEDTLS_SSL_TLS_C +#define MBEDTLS_ERROR_STRERROR_DUMMY +#define MBEDTLS_HKDF_C +#define MBEDTLS_X509_CREATE_C +#define MBEDTLS_X509_CSR_WRITE_C +#define MBEDTLS_BASE64_C +#define MBEDTLS_PEM_WRITE_C + +#define MBEDTLS_SSL_COOKIE_C +#define MBEDTLS_SSL_SRV_C + +#define MBEDTLS_KEY_EXCHANGE_PSK_ENABLED +#define MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED + +#define MBEDTLS_BASE64_C +#define MBEDTLS_ECDH_C +#define MBEDTLS_ECDSA_C +#define MBEDTLS_OID_C +#define MBEDTLS_PEM_PARSE_C +#define MBEDTLS_X509_USE_C +#define MBEDTLS_X509_CRT_PARSE_C +#define MBEDTLS_PKCS5_C + +#define MBEDTLS_MPI_WINDOW_SIZE 1 /**< Maximum windows size used. */ +#define MBEDTLS_MPI_MAX_SIZE 32 /**< Maximum number of bytes for usable MPIs. */ +#define MBEDTLS_ECP_MAX_BITS 256 /**< Maximum bit size of groups */ +#define MBEDTLS_ECP_WINDOW_SIZE 2 /**< Maximum window size used */ +#define MBEDTLS_ECP_FIXED_POINT_OPTIM 0 /**< Enable fixed-point speed-up */ +#define MBEDTLS_ENTROPY_MAX_SOURCES 1 /**< Maximum number of sources supported */ + +#define MBEDTLS_MEMORY_BUFFER_ALLOC_C + +#define MBEDTLS_SSL_MAX_CONTENT_LEN 900 /**< Maxium fragment length in bytes */ + +#define MBEDTLS_SSL_CIPHERSUITES MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8 + +#include "mbedtls/check_config.h" + +#endif // CC13X2_26X2_MBEDTLS_CONFIG_H diff --git a/src/platform/cc13x2_26x2/openthread-core-cc13x2_26x2-config-check.h b/src/platform/cc13x2_26x2/openthread-core-cc13x2_26x2-config-check.h new file mode 100644 index 00000000000000..a5fcac9459b6c4 --- /dev/null +++ b/src/platform/cc13x2_26x2/openthread-core-cc13x2_26x2-config-check.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2019, The OpenThread Authors. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#if OPENTHREAD_CONFIG_RADIO_915MHZ_OQPSK_SUPPORT +#error "Platform cc1352 doesn't support configuration option: OPENTHREAD_CONFIG_RADIO_915MHZ_OQPSK_SUPPORT" +#endif diff --git a/src/platform/cc13x2_26x2/openthread-core-cc13x2_26x2-config.h b/src/platform/cc13x2_26x2/openthread-core-cc13x2_26x2-config.h new file mode 100644 index 00000000000000..4bb968c3142893 --- /dev/null +++ b/src/platform/cc13x2_26x2/openthread-core-cc13x2_26x2-config.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2018, The OpenThread Authors. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +/** + * @def OPENTHREAD_CONFIG_PLATFORM_INFO + * + * The platform-specific string to insert into the OpenThread version string. + * + */ +#define OPENTHREAD_CONFIG_PLATFORM_INFO "CC1352" + +/** + * @def OPENTHREAD_CONFIG_PLATFORM_FLASH_API_ENABLE + * + * Define to 1 to enable otPlatFlash* APIs to support non-volatile storage. + * + * When defined to 1, the platform MUST implement the otPlatFlash* APIs instead of the otPlatSettings* APIs. + * + */ +#define OPENTHREAD_CONFIG_PLATFORM_FLASH_API_ENABLE 0 + +/** + * @def OPENTHREAD_CONFIG_NCP_UART_ENABLE + * + * Define to 1 to enable NCP UART support. + * + */ +#define OPENTHREAD_CONFIG_NCP_UART_ENABLE 0 + +/* reduced to fit in SRAM */ +#define OPENTHREAD_CONFIG_NUM_MESSAGE_BUFFERS 22 diff --git a/src/platform/device.gni b/src/platform/device.gni index 9237b06ce6ae13..c0639e1f86f586 100644 --- a/src/platform/device.gni +++ b/src/platform/device.gni @@ -15,7 +15,7 @@ import("//build_overrides/chip.gni") declare_args() { - # Device platform layer: darwin, efr32, esp32, external, freertos, linux, nrfconnect, k32w, qpg6100, none. + # Device platform layer: cc13x2_26x2, darwin, efr32, esp32, external, freertos, linux, nrfconnect, k32w, qpg6100, none. chip_device_platform = "auto" chip_platform_target = "" } @@ -33,8 +33,9 @@ if (chip_device_platform == "auto") { declare_args() { # Enable openthread support. chip_enable_openthread = - chip_device_platform == "linux" || chip_device_platform == "efr32" || - chip_device_platform == "k32w" + chip_device_platform == "linux" || + chip_device_platform == "cc13x2_26x2" || + chip_device_platform == "efr32" || chip_device_platform == "k32w" # Enable wifi support. chip_enable_wifi = chip_device_platform == "linux" @@ -48,7 +49,9 @@ declare_args() { } _chip_device_layer = "none" -if (chip_device_platform == "darwin") { +if (chip_device_platform == "cc13x2_26x2") { + _chip_device_layer = "cc13x2_26x2" +} else if (chip_device_platform == "darwin") { _chip_device_layer = "Darwin" } else if (chip_device_platform == "efr32") { _chip_device_layer = "EFR32" @@ -95,6 +98,7 @@ if (_chip_device_layer != "none" && chip_device_platform != "external") { assert( (current_os != "freertos" && chip_device_platform == "none") || + chip_device_platform == "cc13x2_26x2" || chip_device_platform == "darwin" || chip_device_platform == "efr32" || chip_device_platform == "esp32" || chip_device_platform == "external" || chip_device_platform == "linux" || diff --git a/src/platform/nrfconnect/BLEManagerImpl.h b/src/platform/nrfconnect/BLEManagerImpl.h index bc5264c03cae2a..af5512431848d2 100644 --- a/src/platform/nrfconnect/BLEManagerImpl.h +++ b/src/platform/nrfconnect/BLEManagerImpl.h @@ -17,68 +17,11 @@ /** * @file - * Provides an implementation of the BLEManager singleton object - * for the Zephyr platforms. + * Provides an implementation of the BLEManager object + * for nRF Connect SDK platforms, by including Zephyr platform + * implementation. */ #pragma once -#if CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE - -#include - -namespace chip { -namespace DeviceLayer { -namespace Internal { - -using namespace chip::Ble; - -/** - * Concrete implementation of the NetworkProvisioningServer singleton object for the Zephyr platforms. - */ -class BLEManagerImpl final : public GenericBLEManagerImpl_Zephyr -{ - // Allow the BLEManager interface class to delegate method calls to - // the implementation methods provided by this class. - friend BLEManager; - -private: - // ===== Members that implement the GenericBLEManagerImpl_Zephyr internal interface. - - // None so far. - - // ===== Members for internal use by the following friends. - - friend BLEManager & BLEMgr(void); - friend BLEManagerImpl & BLEMgrImpl(void); - - static BLEManagerImpl sInstance; -}; - -/** - * 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 Zephyr platforms. - */ -inline BLEManagerImpl & BLEMgrImpl(void) -{ - return BLEManagerImpl::sInstance; -} - -} // namespace Internal -} // namespace DeviceLayer -} // namespace chip - -#endif // CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE +#include diff --git a/src/platform/nrfconnect/BlePlatformConfig.h b/src/platform/nrfconnect/BlePlatformConfig.h index c0ae7b3acc7671..b9827ee268017d 100644 --- a/src/platform/nrfconnect/BlePlatformConfig.h +++ b/src/platform/nrfconnect/BlePlatformConfig.h @@ -18,16 +18,15 @@ /** * @file * Platform-specific configuration overrides for the CHIP BLE - * Layer on Zephyr platforms. + * Layer on nRF Connect SDK platform. * */ #pragma once -#include - // ==================== Platform Adaptations ==================== +struct bt_conn; #define BLE_CONNECTION_OBJECT bt_conn * #define BLE_CONNECTION_UNINITIALIZED nullptr #define BLE_MAX_RECEIVE_WINDOW_SIZE 5 diff --git a/src/platform/nrfconnect/CHIPDevicePlatformConfig.h b/src/platform/nrfconnect/CHIPDevicePlatformConfig.h index d03734ddca882e..b5b06cafe2760c 100644 --- a/src/platform/nrfconnect/CHIPDevicePlatformConfig.h +++ b/src/platform/nrfconnect/CHIPDevicePlatformConfig.h @@ -18,7 +18,7 @@ /** * @file * Platform-specific configuration overrides for the chip Device Layer - * on Zephyr platforms. + * on nRF Connect SDK platform. */ #pragma once diff --git a/src/platform/nrfconnect/CHIPDevicePlatformEvent.h b/src/platform/nrfconnect/CHIPDevicePlatformEvent.h index e3f6766746cd5a..660124da31b774 100644 --- a/src/platform/nrfconnect/CHIPDevicePlatformEvent.h +++ b/src/platform/nrfconnect/CHIPDevicePlatformEvent.h @@ -17,88 +17,11 @@ /** * @file - * Defines platform-specific event types and data for the chip - * Device Layer on Zephyr platforms. + * Provides platform-specific event types and data for the chip + * Device Layer on nRF Connect SDK platforms, by including Zephyr + * platform definitions. */ #pragma once -#include - -#include - -namespace chip { -namespace System { -class PacketBuffer; -} -} // namespace chip - -namespace chip { -namespace DeviceLayer { - -namespace DeviceEventType { - -/** - * Enumerates Zephyr platform-specific event types that are visible to the application. - */ -enum PublicPlatformSpecificEventTypes -{ - /* None currently defined */ -}; - -/** - * Enumerates Zephyr platform-specific event types that are internal to the chip Device Layer. - */ -enum InternalPlatformSpecificEventTypes -{ - kPlatformZephyrEvent = kRange_InternalPlatformSpecific, - kPlatformZephyrBleConnected, - kPlatformZephyrBleDisconnected, - kPlatformZephyrBleCCCWrite, - kPlatformZephyrBleC1WriteEvent, - kPlatformZephyrBleC2IndDoneEvent, - kPlatformZephyrBleOutOfBuffersEvent, -}; - -} // namespace DeviceEventType - -struct BleConnEventType -{ - bt_conn * BtConn; - uint8_t HciResult; -}; - -struct BleCCCWriteEventType -{ - bt_conn * BtConn; - uint16_t Value; -}; - -struct BleC1WriteEventType -{ - bt_conn * BtConn; - ::chip::System::PacketBuffer * Data; -}; - -struct BleC2IndDoneEventType -{ - bt_conn * BtConn; - uint8_t Result; -}; - -/** - * Represents platform-specific event information for Zephyr platforms. - */ -struct ChipDevicePlatformEvent final -{ - union - { - BleConnEventType BleConnEvent; - BleCCCWriteEventType BleCCCWriteEvent; - BleC1WriteEventType BleC1WriteEvent; - BleC2IndDoneEventType BleC2IndDoneEvent; - }; -}; - -} // namespace DeviceLayer -} // namespace chip +#include diff --git a/src/platform/nrfconnect/CHIPPlatformConfig.h b/src/platform/nrfconnect/CHIPPlatformConfig.h index 916a08f8dd043a..ec6101c4b53ec7 100644 --- a/src/platform/nrfconnect/CHIPPlatformConfig.h +++ b/src/platform/nrfconnect/CHIPPlatformConfig.h @@ -18,7 +18,7 @@ /** * @file * Platform-specific configuration overrides for CHIP on - * Zephyr platforms. + * nRF Connect SDK platform. */ #pragma once diff --git a/src/platform/nrfconnect/ConfigurationManagerImpl.h b/src/platform/nrfconnect/ConfigurationManagerImpl.h index 38a82931296933..eac5816df62ee2 100644 --- a/src/platform/nrfconnect/ConfigurationManagerImpl.h +++ b/src/platform/nrfconnect/ConfigurationManagerImpl.h @@ -18,101 +18,10 @@ /** * @file * Provides an implementation of the ConfigurationManager object - * for Zephyr platforms. + * for nRF Connect SDK platforms, by including Zephyr platform + * implementation. */ #pragma once -#include - -#include - -namespace chip { -namespace DeviceLayer { - -/** - * Concrete implementation of the ConfigurationManager singleton object for the Zephyr platform. - */ -class ConfigurationManagerImpl final : public ConfigurationManager, - public Internal::GenericConfigurationManagerImpl, - private Internal::ZephyrConfig -{ - // Allow the ConfigurationManager interface class to delegate method calls to - // the implementation methods provided by this class. - friend class ConfigurationManager; - - // Allow the GenericConfigurationManagerImpl base class to access helper methods and types - // defined on this class. -#ifndef DOXYGEN_SHOULD_SKIP_THIS - friend class Internal::GenericConfigurationManagerImpl; -#endif - -private: - // ===== Members that implement the ConfigurationManager public interface. - - CHIP_ERROR _Init(void); - CHIP_ERROR _GetPrimaryWiFiMACAddress(uint8_t * buf); - bool _CanFactoryReset(void); - void _InitiateFactoryReset(void); - CHIP_ERROR _ReadPersistedStorageValue(::chip::Platform::PersistedStorage::Key key, uint32_t & value); - CHIP_ERROR _WritePersistedStorageValue(::chip::Platform::PersistedStorage::Key key, uint32_t value); - - // NOTE: Other public interface methods are implemented by GenericConfigurationManagerImpl<>. - - // ===== Members for internal use by the following friends. - - friend ConfigurationManager & ConfigurationMgr(void); - friend ConfigurationManagerImpl & ConfigurationMgrImpl(void); - - static ConfigurationManagerImpl sInstance; - - // ===== Private members reserved for use by this class only. - - static void DoFactoryReset(intptr_t arg); -}; - -/** - * Returns the public interface of the ConfigurationManager singleton object. - * - * chip applications should use this to access features of the ConfigurationManager object - * that are common to all platforms. - */ -inline ConfigurationManager & ConfigurationMgr(void) -{ - return ConfigurationManagerImpl::sInstance; -} - -/** - * Returns the platform-specific implementation of the ConfigurationManager singleton object. - * - * chip applications can use this to gain access to features of the ConfigurationManager - * that are specific to the nRF Connect SDK platform. - */ -inline ConfigurationManagerImpl & ConfigurationMgrImpl(void) -{ - return ConfigurationManagerImpl::sInstance; -} - -inline bool ConfigurationManagerImpl::_CanFactoryReset() -{ - return true; -} - -inline CHIP_ERROR ConfigurationManagerImpl::_ReadPersistedStorageValue(::chip::Platform::PersistedStorage::Key key, - uint32_t & value) -{ - return ReadConfigValueCounter(key, value); -} - -inline CHIP_ERROR ConfigurationManagerImpl::_WritePersistedStorageValue(::chip::Platform::PersistedStorage::Key key, uint32_t value) -{ - return WriteConfigValueCounter(key, value); -} - -inline CHIP_ERROR ConfigurationManagerImpl::_GetPrimaryWiFiMACAddress(uint8_t * /* buf */) -{ - return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE; -} - -} // namespace DeviceLayer -} // namespace chip +#include diff --git a/src/platform/nrfconnect/InetPlatformConfig.h b/src/platform/nrfconnect/InetPlatformConfig.h index 305744450eabee..8f18e63cddbee3 100644 --- a/src/platform/nrfconnect/InetPlatformConfig.h +++ b/src/platform/nrfconnect/InetPlatformConfig.h @@ -18,7 +18,7 @@ /** * @file * Platform-specific configuration overrides for the CHIP Inet - * Layer on Zephyr platforms. + * Layer on nRF Connect SDK platform. * */ diff --git a/src/platform/nrfconnect/PlatformManagerImpl.h b/src/platform/nrfconnect/PlatformManagerImpl.h index 37160c89d6c49c..146391e3ab085e 100644 --- a/src/platform/nrfconnect/PlatformManagerImpl.h +++ b/src/platform/nrfconnect/PlatformManagerImpl.h @@ -17,62 +17,11 @@ /** * @file - * Provides an implementation of the PlatformManager object. + * Provides an implementation of the PlatformManager object + * for nRF Connect SDK platforms, by including Zephyr platform + * implementation. */ #pragma once -#include -#include - -namespace chip { -namespace DeviceLayer { - -/** - * Concrete implementation of the PlatformManager singleton object for the nRF Connect SDK platforms. - */ -class PlatformManagerImpl final : public PlatformManager, public Internal::GenericPlatformManagerImpl_Zephyr -{ - // Allow the PlatformManager interface class to delegate method calls to - // the implementation methods provided by this class. - friend PlatformManager; - - // Allow the generic implementation base class to call helper methods on - // this class. -#ifndef DOXYGEN_SHOULD_SKIP_THIS - friend Internal::GenericPlatformManagerImpl_Zephyr; -#endif - -public: - // ===== Platform-specific members that may be accessed directly by the application. - - /* none so far */ - -private: - // ===== Methods that implement the PlatformManager abstract interface. - - CHIP_ERROR _InitChipStack(void); - - // ===== Members for internal use by the following friends. - - friend PlatformManager & PlatformMgr(void); - friend PlatformManagerImpl & PlatformMgrImpl(void); - friend class Internal::BLEManagerImpl; - - explicit PlatformManagerImpl(ThreadStack & stack) : Internal::GenericPlatformManagerImpl_Zephyr(stack) {} - - static PlatformManagerImpl sInstance; -}; - -/** - * 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; -} -} // namespace DeviceLayer -} // namespace chip +#include diff --git a/src/platform/nrfconnect/README.md b/src/platform/nrfconnect/README.md index 1ab76bb4f860ff..06f3de0fa5e2b6 100644 --- a/src/platform/nrfconnect/README.md +++ b/src/platform/nrfconnect/README.md @@ -5,22 +5,13 @@ this code will have parallels in any new adaptation. (All file names are relative to `connectedhomeip/src/...`). -`include/platform/nrfconnect/PlatformManagerImpl.h`
`nrfconnect/PlatformManagerImpl.cpp` +`include/platform/nrfconnect/PlatformManagerImpl.h` -- Concrete implementation of PlatformManager interface -- Provides initialization of the CHIP stack and core event loop for the chip - task -- Relies on GenericPlatformManagerImpl_POSIX<> class to provide most of the - implementation +- Uses Zephyr platform implementation of PlatformManager interface. -`include/platform/nrfconnect/ConfigurationManagerImpl.h`
`nrfconnect/ConfigurationManagerImpl.cpp` +`include/platform/nrfconnect/ConfigurationManagerImpl.h` -- Concrete implementation of ConfigurationManager interface -- Manages storage and retrieval of persistent configuration data -- Relies on GenericConfigurationManagerImpl<> classes to implement most API - functionality -- Delegates low-level reading and writing of persistent values to ZephyrConfig - class +- Uses Zephyr platform implementation of ConfigurationManager interface. `include/platform/nrfconnect/ConnectivityManagerImpl.h`
`nrfconnect/ConnectivityManagerImpl.cpp` @@ -30,30 +21,20 @@ this code will have parallels in any new adaptation. functionality - Very much a work-in-progress in the nrfconnect branch -`include/platform/nrfconnect/ThreadStackManagerImpl.h`
`nrfconnect/ThreadStackManagerImpl.cpp` - -- Concrete implementation of ThreadStackManager interface -- Supports Thread stack initialization and core event loop processing -- Relies on GenericThreadStackManagerImpl_OpenThread/POSIX<> classes to - implement most API functionaltiy - -`include/platform/nrfconnect/BLEManagerImpl.h`
`nrfconnect/BLEManagerImpl.cpp` +`include/platform/nrfconnect/DeviceNetworkProvisioningDelegateImpl.h`
`nrfconnect/DeviceNetworkProvisioningDelegateImpl.cpp` -- Concrete implementation of the BLEManager interface -- Maps CHIP's BLE interface abstractions (BleLayer, BlePlatformDelegate, - BleApplicationDelegate) onto the platform's native BLE services -- Implements chip-compatible BLE advertising. +- Concrete implementation of DeviceNetworkProvisioningDelegate interface +- Provides high-level APIs for managing network provisioning -`platform/nrfconnect/Entropy.cpp` +`include/platform/nrfconnect/ThreadStackManagerImpl.h` -- Implements interface to platform entropy source +- Uses Zephyr platform implementation of ThreadStackManager interface. -`platform/nrfconnect/Logging.cpp` +`include/platform/nrfconnect/BLEManagerImpl.h` -- Adaption of chip debug logging to platform logging facility. +- Uses Zephyr platform implementation of BLEManager interface. -`platform/nrfconnect/ZephyrConfig.cpp` +`include/platform/nrfconnect/CHIPDevicePlatformEvent.h` -- Implements low-level read/write of persistent configuration values -- Class API specifically designed to work in conjunction with the - GenericConfigurationManagerImpl<> class. +- Uses Zephyr platform definitions of platform-specific event types and data + for the chip Device Layer. diff --git a/src/platform/nrfconnect/SystemPlatformConfig.h b/src/platform/nrfconnect/SystemPlatformConfig.h index 0e58ba4d5dc80e..785e429bb8c8f5 100644 --- a/src/platform/nrfconnect/SystemPlatformConfig.h +++ b/src/platform/nrfconnect/SystemPlatformConfig.h @@ -18,7 +18,7 @@ /** * @file * Platform-specific configuration overrides for the CHIP System - * Layer on Zephyr platforms. + * Layer on nRF Connect SDK platform. * */ diff --git a/src/platform/nrfconnect/ThreadStackManagerImpl.h b/src/platform/nrfconnect/ThreadStackManagerImpl.h index d46c92ff9179e5..e4055ffca5f9c7 100644 --- a/src/platform/nrfconnect/ThreadStackManagerImpl.h +++ b/src/platform/nrfconnect/ThreadStackManagerImpl.h @@ -17,75 +17,11 @@ /** * @file - * Provides an implementation of the ThreadStackManager object for - * nRF Connect SDK platforms. + * Provides an implementation of the ThreadStackManager object + * for nRF Connect SDK platforms, by including Zephyr platform + * implementation. */ #pragma once -#include -#include - -#include -#include - -namespace chip { -namespace DeviceLayer { - -class ThreadStackManager; -class ThreadStackManagerImpl; - -/** - * Concrete implementation of the ThreadStackManager singleton object for nRF Connect platforms. - */ -class ThreadStackManagerImpl final : public ThreadStackManager, - public Internal::GenericThreadStackManagerImpl_Zephyr -{ - // Allow the ThreadStackManager interface class to delegate method calls to - // the implementation methods provided by this class. - friend class ThreadStackManager; - - // Allow the generic implementation base classes to call helper methods on - // this class. -#ifndef DOXYGEN_SHOULD_SKIP_THIS - friend Internal::GenericThreadStackManagerImpl_OpenThread; - friend Internal::GenericThreadStackManagerImpl_Zephyr; -#endif - -private: - // ===== Members for internal use by the following friends. - - friend ThreadStackManager & ::chip::DeviceLayer::ThreadStackMgr(void); - friend ThreadStackManagerImpl & ::chip::DeviceLayer::ThreadStackMgrImpl(void); - - static ThreadStackManagerImpl sInstance; - - // ===== Private members for use by this class only. - - ThreadStackManagerImpl() = default; -}; - -/** - * Returns the public interface of the ThreadStackManager singleton object. - * - * chip applications should use this to access features of the ThreadStackManager object - * that are common to all platforms. - */ -inline ThreadStackManager & ThreadStackMgr(void) -{ - return ThreadStackManagerImpl::sInstance; -} - -/** - * Returns the platform-specific implementation of the ThreadStackManager singleton object. - * - * chip applications can use this to gain access to features of the ThreadStackManager - * that are specific to nRF Connect platforms. - */ -inline ThreadStackManagerImpl & ThreadStackMgrImpl(void) -{ - return ThreadStackManagerImpl::sInstance; -} - -} // namespace DeviceLayer -} // namespace chip +#include diff --git a/src/platform/qpg6100/BLEManagerImpl.cpp b/src/platform/qpg6100/BLEManagerImpl.cpp index c1e9cd2911996b..a8da4f9a8aa9d6 100644 --- a/src/platform/qpg6100/BLEManagerImpl.cpp +++ b/src/platform/qpg6100/BLEManagerImpl.cpp @@ -25,13 +25,16 @@ #if CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE +#include #include #include #include #include -using namespace chip::Ble; +using namespace ::chip; +using namespace ::chip::Ble; +using namespace ::chip::System; namespace chip { namespace DeviceLayer { @@ -39,8 +42,17 @@ namespace Internal { namespace { -const uint16_t UUID16_CHIPoBLEService = 0xFEAF; +// Advertising data content definitions +#define CHIP_ADV_DATA_TYPE_FLAGS 0x01 +#define CHIP_ADV_DATA_TYPE_UUID 0x03 +#define CHIP_ADV_DATA_FLAGS 0x06 +#define CHIP_ADV_DATA_TYPE_NAME 0x09 +#define CHIP_ADV_DATA_TYPE_SERVICE_DATA 0x16 +#define CHIP_ADV_SHORT_UUID_LEN 2 +#define CHIP_ADV_CHIP_OVER_BLE_SERVICE_UUID16 0xFEAF + +// Full service UUID - CHIP_BLE_SVC_ID - taken from BleUUID.h header const ChipBleUUID chipUUID_CHIPoBLEChar_RX = { { 0x18, 0xEE, 0x2E, 0xF5, 0x26, 0x3D, 0x45, 0x59, 0x95, 0x9F, 0x4F, 0x9C, 0x42, 0x9F, 0x9D, 0x11 } }; @@ -70,7 +82,7 @@ CHIP_ERROR BLEManagerImpl::_Init() appCbacks.stackCback = ExternalCbHandler; appCbacks.chrReadCback = HandleTXCharRead; appCbacks.chrWriteCback = HandleRXCharWrite; - appCbacks.cccCback = HandleTXCharCCCDWrite; + appCbacks.cccCback = _handleTXCharCCCDWrite; qvCHIP_BleInit(&appCbacks); PlatformMgr().ScheduleWork(DriveBLEState, 0); @@ -158,10 +170,37 @@ void BLEManagerImpl::_OnPlatformEvent(const ChipDeviceEvent * event) switch (event->Type) { // Platform specific events + case DeviceEventType::kCHIPoBLESubscribe: { + ChipDeviceEvent connEstEvent; + + ChipLogProgress(DeviceLayer, "_OnPlatformEvent kCHIPoBLESubscribe"); + HandleSubscribeReceived(event->CHIPoBLESubscribe.ConId, &CHIP_BLE_SVC_ID, &chipUUID_CHIPoBLEChar_TX); + connEstEvent.Type = DeviceEventType::kCHIPoBLEConnectionEstablished; + PlatformMgr().PostEvent(&connEstEvent); + } + break; + + case DeviceEventType::kCHIPoBLEUnsubscribe: { + ChipLogProgress(DeviceLayer, "_OnPlatformEvent kCHIPoBLEUnsubscribe"); + HandleUnsubscribeReceived(event->CHIPoBLEUnsubscribe.ConId, &CHIP_BLE_SVC_ID, &chipUUID_CHIPoBLEChar_TX); + } + break; + + case DeviceEventType::kCHIPoBLEWriteReceived: { + ChipLogProgress(DeviceLayer, "_OnPlatformEvent kCHIPoBLEWriteReceived"); + HandleWriteReceived(event->CHIPoBLEWriteReceived.ConId, &CHIP_BLE_SVC_ID, &chipUUID_CHIPoBLEChar_RX, + PacketBufferHandle::Adopt(event->CHIPoBLEWriteReceived.Data)); + } + break; case DeviceEventType::kCHIPoBLETXCharWriteEvent: HandleTXComplete(event); break; + case DeviceEventType::kCHIPoBLEConnectionError: { + ChipLogProgress(DeviceLayer, "_OnPlatformEvent kCHIPoBLEConnectionError"); + HandleConnectionError(event->CHIPoBLEConnectionError.ConId, event->CHIPoBLEConnectionError.Reason); + } + break; // Generic CHIP events case DeviceEventType::kFabricMembershipChange: case DeviceEventType::kServiceProvisioningChange: @@ -226,18 +265,18 @@ uint16_t BLEManagerImpl::GetMTU(BLE_CONNECTION_OBJECT conId) const bool BLEManagerImpl::SendIndication(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const ChipBleUUID * charId, PacketBufferHandle data) { - CHIP_ERROR err = CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE; + CHIP_ERROR err = CHIP_NO_ERROR; bool isRxHandle; uint16_t cId; uint16_t dataLen = data->DataLength(); VerifyOrExit(IsSubscribed(conId), err = CHIP_ERROR_INVALID_ARGUMENT); - ChipLogDetail(DeviceLayer, "Sending indication for CHIPoBLE TX characteristic (con %u, len %u)", conId, dataLen); + ChipLogDetail(DeviceLayer, "Sending indication for CHIPoBLE Client RX characteristic (con %u, len %u)", conId, dataLen); - isRxHandle = UUIDsMatch(&chipUUID_CHIPoBLEChar_RX, charId); + isRxHandle = UUIDsMatch(&chipUUID_CHIPoBLEChar_TX, charId); cId = qvCHIP_BleGetHandle(isRxHandle); - qvCHIP_TxData(conId, cId, dataLen, data->Start()); + qvCHIP_BleSendIndication(conId, cId, dataLen, data->Start()); exit: if (err != CHIP_NO_ERROR) @@ -327,11 +366,92 @@ void BLEManagerImpl::DriveBLEState(void) } } +CHIP_ERROR BLEManagerImpl::ConfigureAdvertisingData(void) +{ + ChipBLEDeviceIdentificationInfo mDeviceIdInfo; + CHIP_ERROR err; + uint8_t index = 0; + uint8_t mDeviceNameLength = 0; + uint8_t mDeviceIdInfoLength = 0; + + memset(mAdvDataBuf, 0, kMaxAdvertisementDataSetSize); + memset(mScanRespDataBuf, 0, kMaxAdvertisementDataSetSize); + + err = ConfigurationMgr().GetBLEDeviceIdentificationInfo(mDeviceIdInfo); + SuccessOrExit(err); + + if (!GetFlag(mFlags, kFlag_DeviceNameSet)) + { + snprintf(mDeviceName, sizeof(mDeviceName), "%s%04" PRIX32, CHIP_DEVICE_CONFIG_BLE_DEVICE_NAME_PREFIX, (uint32_t) 0); + + mDeviceName[kMaxDeviceNameLength] = 0; + qvCHIP_BleSetDeviceName(mDeviceName); + } + + mDeviceNameLength = static_cast(strlen(mDeviceName)); + mDeviceIdInfoLength = sizeof(mDeviceIdInfo); + + // Check sizes + static_assert(sizeof(mDeviceIdInfo) + CHIP_ADV_SHORT_UUID_LEN + 1 <= UINT8_MAX, "Our length won't fit in a uint8_t"); + static_assert(2 + CHIP_ADV_SHORT_UUID_LEN + sizeof(mDeviceIdInfo) + 1 <= kMaxAdvertisementDataSetSize, + "Advertisement data buffer is not big enough"); + + // Fill in advertising data + index = 0; + mAdvDataBuf[index++] = 0x02; // length + mAdvDataBuf[index++] = CHIP_ADV_DATA_TYPE_FLAGS; // AD type : flags + mAdvDataBuf[index++] = CHIP_ADV_DATA_FLAGS; // AD value + + mAdvDataBuf[index++] = static_cast(mDeviceIdInfoLength + CHIP_ADV_SHORT_UUID_LEN + 1); // AD length + mAdvDataBuf[index++] = CHIP_ADV_DATA_TYPE_SERVICE_DATA; // AD type : Service Data + mAdvDataBuf[index++] = CHIP_ADV_CHIP_OVER_BLE_SERVICE_UUID16 & 0xFF; // AD value + mAdvDataBuf[index++] = (CHIP_ADV_CHIP_OVER_BLE_SERVICE_UUID16 >> 8) & 0xFF; + memcpy(&mAdvDataBuf[index], (void *) &mDeviceIdInfo, mDeviceIdInfoLength); // AD value + index = static_cast(index + mDeviceIdInfoLength); + + mAdvDataBuf[index++] = static_cast(mDeviceNameLength + 1); // length + mAdvDataBuf[index++] = CHIP_ADV_DATA_TYPE_NAME; // AD type : name + memcpy(&mAdvDataBuf[index], mDeviceName, mDeviceNameLength); // AD value + index = static_cast(index + mDeviceNameLength); + + qvCHIP_BleSetAdvData(QV_ADV_DATA_LOC_ADV, index, mAdvDataBuf); + + // Fill in scan response data + index = 0; + mScanRespDataBuf[index++] = CHIP_ADV_SHORT_UUID_LEN + 1; // AD length + mScanRespDataBuf[index++] = CHIP_ADV_DATA_TYPE_UUID; // AD type : uuid + mScanRespDataBuf[index++] = CHIP_ADV_CHIP_OVER_BLE_SERVICE_UUID16 & 0xFF; // AD value + mScanRespDataBuf[index++] = (CHIP_ADV_CHIP_OVER_BLE_SERVICE_UUID16 >> 8) & 0xFF; + + qvCHIP_BleSetAdvData(QV_ADV_DATA_LOC_SCAN, index, mScanRespDataBuf); + +exit: + return err; +} + CHIP_ERROR BLEManagerImpl::StartAdvertising(void) { + CHIP_ERROR err; + uint16_t interval; ChipLogProgress(DeviceLayer, "CHIPoBLE start advertising"); - return qvCHIP_BleStartAdvertising(); + err = ConfigureAdvertisingData(); + SuccessOrExit(err); + + SetFlag(mFlags, kFlag_Advertising, true); + + interval = ((mNumGAPCons == 0 && !ConfigurationMgr().IsPairedToAccount()) || GetFlag(mFlags, kFlag_FastAdvertisingEnabled)) + ? CHIP_DEVICE_CONFIG_BLE_FAST_ADVERTISING_INTERVAL + : CHIP_DEVICE_CONFIG_BLE_SLOW_ADVERTISING_INTERVAL; + + // Minimum and maximum interval are the same + qvCHIP_BleSetAdvInterval(interval, interval); + + err = qvCHIP_BleStartAdvertising(); + // TODO: translate from qvStatus_t to CHIP_ERROR + +exit: + return err; } CHIP_ERROR BLEManagerImpl::StopAdvertising(void) @@ -389,10 +509,10 @@ void BLEManagerImpl::HandleTXCharRead(uint16_t connId, uint16_t handle, uint8_t { uint8_t rsp = 0; - ChipLogProgress(DeviceLayer, "Read request received for CHIPoBLE TX characteristic (con %u)", connId); + ChipLogProgress(DeviceLayer, "Read request received for CHIPoBLE Client RX characteristic (con %u)", connId); // Send a zero-length response. - qvCHIP_TxData(connId, handle, 0, &rsp); + qvCHIP_BleWriteAttr(connId, handle, 0, &rsp); } void BLEManagerImpl::HandleRXCharWrite(uint16_t connId, uint16_t handle, uint8_t operation, uint16_t offset, uint16_t len, @@ -400,7 +520,7 @@ void BLEManagerImpl::HandleRXCharWrite(uint16_t connId, uint16_t handle, uint8_t { CHIP_ERROR err = CHIP_NO_ERROR; - ChipLogProgress(DeviceLayer, "Write request received for CHIPoBLE RX characteristic (con %u, len %u)", connId, len); + ChipLogProgress(DeviceLayer, "Write request received for CHIPoBLE Client TX characteristic (con %u, len %u)", connId, len); // Copy the data to a PacketBuffer. PacketBufferHandle buf = PacketBuffer::New(0); @@ -435,6 +555,26 @@ void BLEManagerImpl::HandleTXCharCCCDWrite(qvCHIP_Ble_AttsCccEvt_t * pEvt) // Determine if the client is enabling or disabling indications. indicationsEnabled = (pEvt->value != 0); + // If the client has requested to enabled indications + if (indicationsEnabled) + { + // Set subcription only the first time + if (!IsSubscribed(pEvt->hdr.param)) + { + // Record that indications have been enabled for this connection. + err = SetSubscribed(pEvt->hdr.param); + VerifyOrExit(err != CHIP_ERROR_NO_MEMORY, err = CHIP_NO_ERROR); + SuccessOrExit(err); + } + } + + else + { + // If indications had previously been enabled for this connection, record that they are no longer + // enabled. + UnsetSubscribed(pEvt->hdr.param); + } + // 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. { @@ -446,6 +586,7 @@ void BLEManagerImpl::HandleTXCharCCCDWrite(qvCHIP_Ble_AttsCccEvt_t * pEvt) ChipLogProgress(DeviceLayer, "CHIPoBLE %s received", indicationsEnabled ? "subscribe" : "unsubscribe"); +exit: if (err != CHIP_NO_ERROR) { ChipLogError(DeviceLayer, "HandleTXCharCCCDWrite() failed: %s", ErrorStr(err)); @@ -565,6 +706,10 @@ void BLEManagerImpl::HandleDmMsg(qvCHIP_Ble_DmEvt_t * pDmEvt) PlatformMgr().PostEvent(&event); // Force a refresh of the advertising state. + if (mNumGAPCons > 0) + { + mNumGAPCons--; + } SetFlag(mFlags, kFlag_AdvertisingRefreshNeeded); PlatformMgr().ScheduleWork(DriveBLEState, 0); break; @@ -693,6 +838,11 @@ bool BLEManagerImpl::IsSubscribed(uint16_t conId) return false; } +void BLEManagerImpl::_handleTXCharCCCDWrite(qvCHIP_Ble_AttsCccEvt_t * event) +{ + sInstance.HandleTXCharCCCDWrite(event); +} + } // namespace Internal } // namespace DeviceLayer } // namespace chip diff --git a/src/platform/qpg6100/BLEManagerImpl.h b/src/platform/qpg6100/BLEManagerImpl.h index f24875e3561368..9bdeb4661b1df7 100644 --- a/src/platform/qpg6100/BLEManagerImpl.h +++ b/src/platform/qpg6100/BLEManagerImpl.h @@ -95,17 +95,19 @@ class BLEManagerImpl final : public BLEManager, private BleLayer, private BlePla kFlag_Advertising = 0x0008, /**< The system is currently CHIPoBLE advertising. */ kFlag_AdvertisingRefreshNeeded = 0x0010, /**< The advertising state/configuration state in the BLE layer needs to be updated. */ + kFlag_DeviceNameSet = 0x0020, }; enum { - kMaxConnections = 5, // TODO - link to qvCHIP define + kMaxConnections = BLE_LAYER_NUM_BLE_ENDPOINTS, kMaxDeviceNameLength = 20, // TODO: right-size this - kMaxAdvertisementDataSetSize = 31 // TODO: verify this + kMaxAdvertisementDataSetSize = 31 }; CHIPoBLEServiceMode mServiceMode; uint16_t mFlags; + char mDeviceName[kMaxDeviceNameLength + 1]; uint16_t mNumGAPCons; uint16_t mSubscribedConIds[kMaxConnections]; uint8_t mAdvDataBuf[kMaxAdvertisementDataSetSize]; @@ -113,7 +115,7 @@ class BLEManagerImpl final : public BLEManager, private BleLayer, private BlePla qvCHIP_Ble_Callbacks_t appCbacks; void DriveBLEState(void); - CHIP_ERROR ConfigureAdvertising(void); + CHIP_ERROR ConfigureAdvertisingData(void); CHIP_ERROR StartAdvertising(void); CHIP_ERROR StopAdvertising(void); CHIP_ERROR SetSubscribed(uint16_t conId); @@ -129,9 +131,12 @@ class BLEManagerImpl final : public BLEManager, private BleLayer, private BlePla static void HandleTXCharRead(uint16_t connId, uint16_t handle, uint8_t operation, uint16_t offset, qvCHIP_Ble_Attr_t * pAttr); static void HandleRXCharWrite(uint16_t connId, uint16_t handle, uint8_t operation, uint16_t offset, uint16_t len, uint8_t * pValue, qvCHIP_Ble_Attr_t * pAttr); - static void HandleTXCharCCCDWrite(qvCHIP_Ble_AttsCccEvt_t * event); + void HandleTXCharCCCDWrite(qvCHIP_Ble_AttsCccEvt_t * event); static void DriveBLEState(intptr_t arg); + + /* Handlers for stack events */ + static void _handleTXCharCCCDWrite(qvCHIP_Ble_AttsCccEvt_t * event); }; /** diff --git a/src/platform/qpg6100/ConfigurationManagerImpl.cpp b/src/platform/qpg6100/ConfigurationManagerImpl.cpp index a4e48e648dbfd4..c4b68b1bc96370 100644 --- a/src/platform/qpg6100/ConfigurationManagerImpl.cpp +++ b/src/platform/qpg6100/ConfigurationManagerImpl.cpp @@ -54,8 +54,6 @@ CHIP_ERROR ConfigurationManagerImpl::_Init() err = Internal::GenericConfigurationManagerImpl::_Init(); SuccessOrExit(err); - // TODO: initialize NVM component - // If the fail-safe was armed when the device last shutdown, initiate a factory reset. if (_GetFailSafeArmed(failSafeArmed) == CHIP_NO_ERROR && failSafeArmed) { @@ -135,7 +133,7 @@ void ConfigurationManagerImpl::DoFactoryReset(intptr_t arg) // Restart the system. ChipLogProgress(DeviceLayer, "System restarting"); - // NVIC_SystemReset(); - FIXME + // TODO - Add CHIP library de-init } } // namespace DeviceLayer diff --git a/src/platform/qpg6100/ConfigurationManagerImpl.h b/src/platform/qpg6100/ConfigurationManagerImpl.h index 12f322c8ffb235..95ae6ce6c96007 100644 --- a/src/platform/qpg6100/ConfigurationManagerImpl.h +++ b/src/platform/qpg6100/ConfigurationManagerImpl.h @@ -42,7 +42,9 @@ class ConfigurationManagerImpl final : public ConfigurationManager, // Allow the GenericConfigurationManagerImpl base class to access helper methods and types // defined on this class. +#ifndef DOXYGEN_SHOULD_SKIP_THIS friend class Internal::GenericConfigurationManagerImpl; +#endif private: // ===== Members that implement the ConfigurationManager public interface. diff --git a/src/platform/nrfconnect/ThreadStackManagerImpl.cpp b/src/platform/qpg6100/DeviceNetworkProvisioningDelegateImpl.cpp similarity index 56% rename from src/platform/nrfconnect/ThreadStackManagerImpl.cpp rename to src/platform/qpg6100/DeviceNetworkProvisioningDelegateImpl.cpp index 120da81df78e29..4a756405871e6b 100644 --- a/src/platform/nrfconnect/ThreadStackManagerImpl.cpp +++ b/src/platform/qpg6100/DeviceNetworkProvisioningDelegateImpl.cpp @@ -15,26 +15,29 @@ * limitations under the License. */ -/** - * @file - * Provides an implementation of the ThreadStackManager object for - * nRF Connect SDK platforms. - * - */ -/* this file behaves like a config.h, comes first */ -#include - -#include +#include "DeviceNetworkProvisioningDelegateImpl.h" -#include +#if CHIP_ENABLE_OPENTHREAD #include +#endif namespace chip { namespace DeviceLayer { -using namespace ::chip::DeviceLayer::Internal; +CHIP_ERROR DeviceNetworkProvisioningDelegateImpl::_ProvisionThreadNetwork(DeviceLayer::Internal::DeviceNetworkInfo & threadData) +{ +#if CHIP_ENABLE_OPENTHREAD + CHIP_ERROR error = CHIP_NO_ERROR; -ThreadStackManagerImpl ThreadStackManagerImpl::sInstance; + SuccessOrExit(error = ThreadStackMgr().SetThreadEnabled(false)); + SuccessOrExit(error = ThreadStackMgr().SetThreadProvision(threadData)); + SuccessOrExit(error = ThreadStackMgr().SetThreadEnabled(true)); +exit: + return error; +#else + return CHIP_ERROR_NOT_IMPLEMENTED; +#endif // CHIP_ENABLE_OPENTHREAD +} } // namespace DeviceLayer } // namespace chip diff --git a/src/platform/qpg6100/DeviceNetworkProvisioningDelegateImpl.h b/src/platform/qpg6100/DeviceNetworkProvisioningDelegateImpl.h index e3ba66ca9db3f4..05a642417934d4 100644 --- a/src/platform/qpg6100/DeviceNetworkProvisioningDelegateImpl.h +++ b/src/platform/qpg6100/DeviceNetworkProvisioningDelegateImpl.h @@ -36,7 +36,7 @@ class DeviceNetworkProvisioningDelegateImpl final private: CHIP_ERROR _ProvisionWiFiNetwork(const char * ssid, const char * passwd) { return CHIP_ERROR_NOT_IMPLEMENTED; } - CHIP_ERROR _ProvisionThreadNetwork(DeviceLayer::Internal::DeviceNetworkInfo & threadData) { return CHIP_ERROR_NOT_IMPLEMENTED; } + CHIP_ERROR _ProvisionThreadNetwork(DeviceLayer::Internal::DeviceNetworkInfo & threadData); }; } // namespace DeviceLayer diff --git a/src/platform/qpg6100/PlatformManagerImpl.h b/src/platform/qpg6100/PlatformManagerImpl.h index 98e3d35c4c3487..ae47d3402d700c 100644 --- a/src/platform/qpg6100/PlatformManagerImpl.h +++ b/src/platform/qpg6100/PlatformManagerImpl.h @@ -38,7 +38,9 @@ class PlatformManagerImpl final : public PlatformManager, public Internal::Gener // 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. diff --git a/src/platform/qpg6100/ThreadStackManagerImpl.cpp b/src/platform/qpg6100/ThreadStackManagerImpl.cpp index 15cc5d75444081..d7dff6dfda6f31 100644 --- a/src/platform/qpg6100/ThreadStackManagerImpl.cpp +++ b/src/platform/qpg6100/ThreadStackManagerImpl.cpp @@ -18,7 +18,7 @@ /** * @file * Provides an implementation of the ThreadStackManager object for the - * QPG6100 platform using the Nordic QPG6100 library and the OpenThread + * QPG6100 platform using the Qorvo QPG6100 library and the OpenThread * stack. * */ diff --git a/src/platform/qpg6100/ThreadStackManagerImpl.h b/src/platform/qpg6100/ThreadStackManagerImpl.h index ec148f2a4e16ab..b5429c2e70e5cf 100644 --- a/src/platform/qpg6100/ThreadStackManagerImpl.h +++ b/src/platform/qpg6100/ThreadStackManagerImpl.h @@ -55,9 +55,11 @@ class ThreadStackManagerImpl final : public ThreadStackManager, // Allow the generic implementation base classes to call helper methods on // this class. +#ifndef DOXYGEN_SHOULD_SKIP_THIS friend Internal::GenericThreadStackManagerImpl_OpenThread; friend Internal::GenericThreadStackManagerImpl_OpenThread_LwIP; friend Internal::GenericThreadStackManagerImpl_FreeRTOS; +#endif // Allow glue functions called by OpenThread to call helper methods on this // class. diff --git a/src/platform/qpg6100/args.gni b/src/platform/qpg6100/args.gni index c14cbd01769d36..e7c8493b9904ca 100644 --- a/src/platform/qpg6100/args.gni +++ b/src/platform/qpg6100/args.gni @@ -19,7 +19,6 @@ import("//build_overrides/qpg6100_sdk.gni") arm_platform_config = "${qpg6100_sdk_build_root}/qpg6100_arm.gni" mbedtls_target = "${qpg6100_sdk_build_root}:qpg6100_sdk" -openthread_external_mbedtls = mbedtls_target chip_device_platform = "qpg6100" diff --git a/src/platform/qpg6100/qpg6100Config.cpp b/src/platform/qpg6100/qpg6100Config.cpp index 7c2496941e3914..6fc4f08c5d9599 100644 --- a/src/platform/qpg6100/qpg6100Config.cpp +++ b/src/platform/qpg6100/qpg6100Config.cpp @@ -52,19 +52,13 @@ uint16_t QPG6100Config::GetSettingsMaxValueLength(Key key) CHIP_ERROR QPG6100Config::ReadConfigValue(Key key, bool & val) { CHIP_ERROR err = CHIP_NO_ERROR; - uint8_t buffer[255]; uint16_t length; bool res; length = sizeof(bool); - res = qvCHIP_Nvm_Restore(key, buffer, &length); - if (res == true) - { - val = (buffer[0] != 0); - ChipLogDetail(DeviceLayer, "ReadConfigValue: %d", val); - } - else + res = qvCHIP_Nvm_Restore(key, (uint8_t *) (&val), &length); + if (res == false) { err = CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND; } @@ -75,19 +69,13 @@ CHIP_ERROR QPG6100Config::ReadConfigValue(Key key, bool & val) CHIP_ERROR QPG6100Config::ReadConfigValue(Key key, uint32_t & val) { CHIP_ERROR err = CHIP_NO_ERROR; - uint8_t buffer[255]; uint16_t length; bool res; length = sizeof(uint32_t); - res = qvCHIP_Nvm_Restore(key, buffer, &length); - if (res == true) - { - val = *((uint32_t *) buffer); - ChipLogDetail(DeviceLayer, "ReadConfigValue: %d", val); - } - else + res = qvCHIP_Nvm_Restore(key, (uint8_t *) (&val), &length); + if (res == false) { err = CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND; } @@ -98,19 +86,13 @@ CHIP_ERROR QPG6100Config::ReadConfigValue(Key key, uint32_t & val) CHIP_ERROR QPG6100Config::ReadConfigValue(Key key, uint64_t & val) { CHIP_ERROR err = CHIP_NO_ERROR; - uint8_t buffer[255]; uint16_t length; bool res; length = sizeof(uint64_t); - res = qvCHIP_Nvm_Restore(key, buffer, &length); - if (res == true) - { - val = *((uint64_t *) buffer); - ChipLogDetail(DeviceLayer, "ReadConfigValue: %d", val); - } - else + res = qvCHIP_Nvm_Restore(key, (uint8_t *) (&val), &length); + if (res == false) { err = CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND; } @@ -129,7 +111,7 @@ CHIP_ERROR QPG6100Config::ReadConfigValueStr(Key key, char * buf, size_t bufSize return CHIP_ERROR_INVALID_ARGUMENT; } - outLen = bufSize; + length = (uint16_t) bufSize; res = qvCHIP_Nvm_Restore(key, (uint8_t *) buf, &length); if (length > bufSize) { @@ -184,42 +166,33 @@ CHIP_ERROR QPG6100Config::ReadConfigValueBin(Key key, uint8_t * buf, size_t bufS CHIP_ERROR QPG6100Config::WriteConfigValue(Key key, bool val) { - uint8_t buffer[255]; uint16_t length; - buffer[0] = (val) ? 1 : 0; - length = sizeof(bool); + length = sizeof(bool); - qvCHIP_Nvm_Backup(key, buffer, length); - ChipLogDetail(DeviceLayer, "WriteConfigValue: %d", val); + qvCHIP_Nvm_Backup(key, (uint8_t *) (&val), length); return CHIP_NO_ERROR; } CHIP_ERROR QPG6100Config::WriteConfigValue(Key key, uint32_t val) { - uint8_t buffer[255]; uint16_t length; - memcpy(&buffer, (uint8_t *) &val, sizeof(uint32_t)); length = sizeof(uint32_t); - qvCHIP_Nvm_Backup(key, buffer, length); - ChipLogDetail(DeviceLayer, "WriteConfigValue: %d", val); + qvCHIP_Nvm_Backup(key, (uint8_t *) (&val), length); return CHIP_NO_ERROR; } CHIP_ERROR QPG6100Config::WriteConfigValue(Key key, uint64_t val) { - uint8_t buffer[255]; uint16_t length; - memcpy(&buffer, (uint8_t *) &val, sizeof(uint64_t)); length = sizeof(uint64_t); - qvCHIP_Nvm_Backup(key, buffer, length); - ChipLogDetail(DeviceLayer, "WriteConfigValue: %d", val); + qvCHIP_Nvm_Backup(key, (uint8_t *) (&val), length); return CHIP_NO_ERROR; } @@ -237,11 +210,7 @@ CHIP_ERROR QPG6100Config::WriteConfigValueStr(Key key, const char * str, size_t } else { - uint8_t buffer[255]; - memcpy(buffer, str, strLen); - buffer[strLen] = 0; - - qvCHIP_Nvm_Backup(key, buffer, (uint16_t) strLen); + qvCHIP_Nvm_Backup(key, (uint8_t *) str, (uint16_t) strLen); } return CHIP_NO_ERROR; diff --git a/src/platform/tests/TestMdns.cpp b/src/platform/tests/TestMdns.cpp index e35ca6918b06b5..9c968eeebc9a0c 100644 --- a/src/platform/tests/TestMdns.cpp +++ b/src/platform/tests/TestMdns.cpp @@ -63,6 +63,8 @@ static void InitCallback(void * context, CHIP_ERROR error) entry.mDataSize = strlen(reinterpret_cast(entry.mData)); service.mTextEntryies = &entry; service.mTextEntrySize = 1; + service.mSubTypes = nullptr; + service.mSubTypeSize = 0; NL_TEST_ASSERT(suite, ChipMdnsPublishService(&service) == CHIP_NO_ERROR); ChipMdnsBrowse("_mock", MdnsServiceProtocol::kMdnsProtocolTcp, chip::Inet::kIPAddressType_Any, INET_NULL_INTERFACEID, diff --git a/src/protocols/Protocols.h b/src/protocols/Protocols.h index 4cef05cb20f33d..a6285ff7cbce46 100644 --- a/src/protocols/Protocols.h +++ b/src/protocols/Protocols.h @@ -47,6 +47,7 @@ enum CHIPProtocolId kProtocol_InteractionModel = (kChipVendor_Common << 16) | 0x0005, // Interaction Model Protocol kProtocol_FabricProvisioning = (kChipVendor_Common << 16) | 0x0006, // Fabric Provisioning Protocol kProtocol_ServiceProvisioning = (kChipVendor_Common << 16) | 0x0007, // Service Provisioning Protocol + kProtocol_OpCredentials = (kChipVendor_Common << 16) | 0x0008, // Operational Credentials // Protocols reserved for internal protocol use diff --git a/src/protocols/common/Constants.h b/src/protocols/common/Constants.h new file mode 100644 index 00000000000000..659de8e180fe35 --- /dev/null +++ b/src/protocols/common/Constants.h @@ -0,0 +1,77 @@ +/* + * + * 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 + * The defines constants for the CHIP Common Protocol, present in + * every CHIP device. + * + */ + +#pragma once + +/** + * @namespace chip::Protocols::Common + * + * @brief + * This namespace includes all interfaces within CHIP for the + * CHIP Common profile. + * + * The interfaces define message types and status codes. + */ + +namespace chip { +namespace Protocols { +namespace Common { + +/** + * Common Profile Message Types + */ +enum class MsgType +{ + // Status Report contians operation results that a responder sends as a reply for requests sent from an initiator. + StatusReport = 1 +}; + +/** + * Common Protocol Status Codes + */ +enum class StatusCode +{ + Success = 0, /**< Operation completed successfully. */ + Failure = 1, /**< Generic failure, additional details may be included in the protocol specific status. */ + BadPrecondition = 2, /**< Operation was rejected by the system because the system is in an invalid state. */ + OutOfRange = 3, /**< A value was out of a required range. */ + BadRequest = 4, /**< A request was unrecognized or malformed. */ + Unsupported = 5, /**< An unrecognized or unsupported request was received. */ + Unexpected = 6, /**< A request was not expected at this time. */ + ResourceExhausted = 7, /**< Insufficient resources to process the given request. */ + Busy = 8, /**< Device is busy and cannot handle this request at this time. */ + Timeout = 9, /**< A timeout occurred. */ + Continue = 10, /**< Context-specific signal to proceed. */ + Aborted = 11, /**< Failure, often due to a concurrency error. */ + InvalidArgument = 12, /**< An invalid/unsupported argument was provided. */ + NotFound = 13, /**< Some requested entity was not found. */ + AlreadyExists = 14, /**< The caller attempted to create something that already exists. */ + PermissionDenied = 15, /**< Caller does not have sufficient permissions to execute the requested operations. */ + DataLoss = 16, /**< Unrecoverable data loss or corruption has occurred. */ +}; + +} // namespace Common +} // namespace Protocols +} // namespace chip diff --git a/src/protocols/echo/Echo.h b/src/protocols/echo/Echo.h index fa6d41b61abb54..695c1d9ebe0f7d 100644 --- a/src/protocols/echo/Echo.h +++ b/src/protocols/echo/Echo.h @@ -43,11 +43,12 @@ enum kEchoMessageType_EchoResponse = 2 }; -typedef void (*EchoFunct)(NodeId nodeId, System::PacketBufferHandle payload); +using EchoFunct = void (*)(Messaging::ExchangeContext * ec, System::PacketBufferHandle payload); class DLL_EXPORT EchoClient : public Messaging::ExchangeDelegate { public: + // TODO: Init function will take a Channel instead a SecureSessionHandle, when Channel API is ready /** * Initialize the EchoClient object. Within the lifetime * of this instance, this method is invoked once after object @@ -55,13 +56,14 @@ class DLL_EXPORT EchoClient : public Messaging::ExchangeDelegate * instance. * * @param[in] exchangeMgr A pointer to the ExchangeManager object. + * @param[in] sessoin A handle to the session. * * @retval #CHIP_ERROR_INCORRECT_STATE If the state is not equal to * kState_NotInitialized. * @retval #CHIP_NO_ERROR On success. * */ - CHIP_ERROR Init(Messaging::ExchangeManager * exchangeMgr); + CHIP_ERROR Init(Messaging::ExchangeManager * exchangeMgr, SecureSessionHandle session); /** * Shutdown the EchoClient. This terminates this instance @@ -88,14 +90,14 @@ class DLL_EXPORT EchoClient : public Messaging::ExchangeDelegate * Other CHIP_ERROR codes as returned by the lower layers. * */ - CHIP_ERROR SendEchoRequest(NodeId nodeId, System::PacketBufferHandle payload); + CHIP_ERROR SendEchoRequest(System::PacketBufferHandle payload); private: Messaging::ExchangeManager * mExchangeMgr = nullptr; Messaging::ExchangeContext * mExchangeCtx = nullptr; EchoFunct OnEchoResponseReceived = nullptr; + SecureSessionHandle mSecureSession; - CHIP_ERROR SendEchoRequest(System::PacketBufferHandle payload); void OnMessageReceived(Messaging::ExchangeContext * ec, const PacketHeader & packetHeader, uint32_t protocolId, uint8_t msgType, System::PacketBufferHandle payload) override; void OnResponseTimeout(Messaging::ExchangeContext * ec) override; diff --git a/src/protocols/echo/EchoClient.cpp b/src/protocols/echo/EchoClient.cpp index a6389f41699139..c005611d14b2c1 100644 --- a/src/protocols/echo/EchoClient.cpp +++ b/src/protocols/echo/EchoClient.cpp @@ -28,13 +28,14 @@ namespace chip { namespace Protocols { -CHIP_ERROR EchoClient::Init(Messaging::ExchangeManager * exchangeMgr) +CHIP_ERROR EchoClient::Init(Messaging::ExchangeManager * exchangeMgr, SecureSessionHandle session) { // Error if already initialized. if (mExchangeMgr != nullptr) return CHIP_ERROR_INCORRECT_STATE; mExchangeMgr = exchangeMgr; + mSecureSession = session; OnEchoResponseReceived = nullptr; mExchangeCtx = nullptr; @@ -50,8 +51,10 @@ void EchoClient::Shutdown() } } -CHIP_ERROR EchoClient::SendEchoRequest(NodeId nodeId, System::PacketBufferHandle payload) +CHIP_ERROR EchoClient::SendEchoRequest(System::PacketBufferHandle payload) { + CHIP_ERROR err = CHIP_NO_ERROR; + // Discard any existing exchange context. Effectively we can only have one Echo exchange with // a single node at any one time. if (mExchangeCtx != nullptr) @@ -61,22 +64,15 @@ CHIP_ERROR EchoClient::SendEchoRequest(NodeId nodeId, System::PacketBufferHandle } // Create a new exchange context. - mExchangeCtx = mExchangeMgr->NewContext(nodeId, this); + mExchangeCtx = mExchangeMgr->NewContext(mSecureSession, this); if (mExchangeCtx == nullptr) { return CHIP_ERROR_NO_MEMORY; } - return SendEchoRequest(std::move(payload)); -} - -CHIP_ERROR EchoClient::SendEchoRequest(System::PacketBufferHandle payload) -{ - CHIP_ERROR err = CHIP_NO_ERROR; - // Send an Echo Request message. Discard the exchange context if the send fails. err = mExchangeCtx->SendMessage(kProtocol_Echo, kEchoMessageType_EchoRequest, std::move(payload), - Messaging::SendFlags(Messaging::SendMessageFlags::kSendFlag_None)); + Messaging::SendFlags(Messaging::SendMessageFlags::kNone)); if (err != CHIP_NO_ERROR) { @@ -115,13 +111,13 @@ void EchoClient::OnMessageReceived(Messaging::ExchangeContext * ec, const Packet // Call the registered OnEchoResponseReceived handler, if any. if (OnEchoResponseReceived != nullptr) { - OnEchoResponseReceived(packetHeader.GetSourceNodeId().ValueOr(0), std::move(payload)); + OnEchoResponseReceived(ec, std::move(payload)); } } void EchoClient::OnResponseTimeout(Messaging::ExchangeContext * ec) { - ChipLogProgress(Echo, "Time out! failed to receive echo response from Node: %llu", ec->GetPeerNodeId()); + ChipLogProgress(Echo, "Time out! failed to receive echo response from Exchange: %p", ec); } } // namespace Protocols diff --git a/src/protocols/echo/EchoServer.cpp b/src/protocols/echo/EchoServer.cpp index dedc22b9d1981a..8fc389d3de5dc6 100644 --- a/src/protocols/echo/EchoServer.cpp +++ b/src/protocols/echo/EchoServer.cpp @@ -64,7 +64,7 @@ void EchoServer::OnMessageReceived(Messaging::ExchangeContext * ec, const Packet if (OnEchoRequestReceived != nullptr) { response = payload.Retain(); - OnEchoRequestReceived(ec->GetPeerNodeId(), std::move(payload)); + OnEchoRequestReceived(ec, std::move(payload)); } else { @@ -79,7 +79,7 @@ void EchoServer::OnMessageReceived(Messaging::ExchangeContext * ec, const Packet // Send an Echo Response back to the sender. ec->SendMessage(kProtocol_Echo, kEchoMessageType_EchoResponse, std::move(response), - Messaging::SendFlags(Messaging::SendMessageFlags::kSendFlag_None)); + Messaging::SendFlags(Messaging::SendMessageFlags::kNone)); // Discard the exchange context. ec->Close(); diff --git a/src/protocols/secure_channel/SecureChannelProtocol.h b/src/protocols/secure_channel/Constants.h similarity index 69% rename from src/protocols/secure_channel/SecureChannelProtocol.h rename to src/protocols/secure_channel/Constants.h index daf5d887061272..0dd20ec0a60d08 100644 --- a/src/protocols/secure_channel/SecureChannelProtocol.h +++ b/src/protocols/secure_channel/Constants.h @@ -42,35 +42,38 @@ namespace SecureChannel { /** * SecureChannel Protocol Message Types */ -enum +enum class MsgType { // Message Counter Synchronization Protocol Message Types - kMsgType_MsgCounterSyncReq = 0x00, - kMsgType_MsgCounterSyncRsp = 0x01, + MsgCounterSyncReq = 0x00, + MsgCounterSyncRsp = 0x01, // Reliable Messaging Protocol Message Types - kMsgType_StandaloneAck = 0x10, + StandaloneAck = 0x10, // Password-based session establishment Message Types - kMsgType_PASE_Spake2pA = 0x20, - kMsgType_PASE_Spake2pB = 0x21, - kMsgType_PASE_Spake2cA = 0x22, + PBKDFParamRequest = 0x20, + PBKDFParamResponse = 0x21, + PASE_Spake2p1 = 0x22, + PASE_Spake2p2 = 0x23, + PASE_Spake2p3 = 0x24, + PASE_Spake2pError = 0x2F, // Certificate-based session establishment Message Types - kMsgType_CASE_SigmaR1 = 0x30, - kMsgType_CASE_SigmaR2 = 0x31, - kMsgType_CASE_SigmaR3 = 0x32, - kMsgType_CASE_SigmaErr = 0x3F, + CASE_SigmaR1 = 0x30, + CASE_SigmaR2 = 0x31, + CASE_SigmaR3 = 0x32, + CASE_SigmaErr = 0x3F, }; /** * SecureChannel Protocol Status Codes */ -enum +enum class StatusCode { - kStatusCode_AlreadyMemberOfFabric = 1, /**< The recipient is already a member of a fabric. */ - kStatusCode_NotMemberOfFabric = 2, /**< The recipient is not a member of a fabric. */ - kStatusCode_InvalidFabricConfig = 3 /**< The specified fabric configuration was invalid. */ + AlreadyMemberOfFabric = 1, /**< The recipient is already a member of a fabric. */ + NotMemberOfFabric = 2, /**< The recipient is not a member of a fabric. */ + InvalidFabricConfig = 3 /**< The specified fabric configuration was invalid. */ }; } // namespace SecureChannel diff --git a/src/setup_payload/AdditionalDataPayload.h b/src/setup_payload/AdditionalDataPayload.h new file mode 100644 index 00000000000000..80a2c5dec0a0e6 --- /dev/null +++ b/src/setup_payload/AdditionalDataPayload.h @@ -0,0 +1,52 @@ +/* + * + * 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 describes a Additional Data Payload class to hold + * data enumerated from a byte stream. + * Additional data may be conveyed during the provisioning phase via multiple + * protocols (BLE, DNS-SD and SoftAP). It contains Rotating Device Id which + * is an optional feature for a Node to implement and an optional feature for + * a Commissioner to utilize. + * The Rotating Device Identifier provides a per-device unique non-trackable + * identifier that could be used in one or more of the following ways: + * 1) Provided to the vendor’s customer support for help in pairing or + * establishing Node provenance + * 2) Used programmatically to obtain a Node’s Setup PIN or other information + * in order to provide a simplified setup flow. Note that the mechanism(s) by + * which the PIN may be obtained is outside of this specification. + */ + +#pragma once + +#include + +namespace chip { +namespace SetupPayload { + +constexpr uint8_t kRotatingDeviceIdLength = 18; +constexpr uint8_t kRotatingDeviceIdTag = 0x00; + +struct AdditionalDataPayload +{ +public: + std::string rotatingDeviceId; +}; + +} // namespace SetupPayload +} // namespace chip diff --git a/src/setup_payload/AdditionalDataPayloadParser.cpp b/src/setup_payload/AdditionalDataPayloadParser.cpp new file mode 100644 index 00000000000000..ed600cb3f4fc64 --- /dev/null +++ b/src/setup_payload/AdditionalDataPayloadParser.cpp @@ -0,0 +1,72 @@ +/** + * + * 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 describes a AdditionalData Payload parser based on the + * CHIP specification. + */ + +#include "AdditionalDataPayloadParser.h" + +#include +#include +#include + +#include +#include +#include +#include +#include + +using namespace chip; +using namespace std; +using namespace chip::SetupPayload; +using namespace chip::TLV; +using namespace chip::TLV::Utilities; +using namespace chip::Protocols; + +CHIP_ERROR AdditionalDataPayloadParser::populatePayload(AdditionalDataPayload & outPayload) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + TLVReader reader; + TLVReader innerReader; + + reader.Init(mPayloadBufferData, mPayloadBufferLength); + err = reader.Next(kTLVType_Structure, AnonymousTag); + SuccessOrExit(err); + + // Open the container + err = reader.OpenContainer(innerReader); + SuccessOrExit(err); + + err = innerReader.Next(kTLVType_UTF8String, ContextTag(kRotatingDeviceIdTag)); + SuccessOrExit(err); + + // Get the value of the rotating device id + char rotatingDeviceId[kRotatingDeviceIdLength]; + err = innerReader.GetString(rotatingDeviceId, sizeof(rotatingDeviceId)); + SuccessOrExit(err); + outPayload.rotatingDeviceId = std::string(rotatingDeviceId); + + // Verify the end of the container + err = reader.VerifyEndOfContainer(); + SuccessOrExit(err); + +exit: + return err; +} diff --git a/src/setup_payload/AdditionalDataPayloadParser.h b/src/setup_payload/AdditionalDataPayloadParser.h new file mode 100644 index 00000000000000..ef2c1fa9d47230 --- /dev/null +++ b/src/setup_payload/AdditionalDataPayloadParser.h @@ -0,0 +1,80 @@ +/** + * + * 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 describes a AdditionalData Payload parser based on the + * CHIP specification. + */ + +#pragma once + +#include "AdditionalDataPayload.h" + +#include +#include + +namespace chip { + +/** + * @class AdditionalDataPayloadParser + * A class that can be used to convert a HEX encoded payload to a AdditionalDataPayload object + * */ +class AdditionalDataPayloadParser +{ +private: + const uint8_t * mPayloadBufferData; + const uint32_t mPayloadBufferLength; + +public: + /** + * Constructs the Additional Data payload parser with payload buffer data + * and the buffer size + * + * @param[in] payloadBufferData The buffer data for the additional data payload, + * it needs to outlive the lifetime of this parse. + * @param[in] payloadBufferLength The buffer data length for the additional data payload. + */ + AdditionalDataPayloadParser(const uint8_t * payloadBufferData, const uint32_t payloadBufferLength) : + mPayloadBufferData(payloadBufferData), mPayloadBufferLength(payloadBufferLength) + {} + + /** + * Parses the Additional Data payload buffer and constructs all the fields + * of the Additional Data structure. + * + * @param[out] outPayload Additional data payload stucture. + * + * + * @retval #CHIP_NO_ERROR If the reader was successfully positioned on a new element. + * @retval #CHIP_END_OF_TLV If no further elements are available. + * @retval #CHIP_ERROR_TLV_UNDERRUN If the underlying TLV encoding ended prematurely. + * @retval #CHIP_ERROR_INVALID_TLV_ELEMENT + * If the reader encountered an invalid or unsupported TLV element + * type. + * @retval #CHIP_ERROR_INVALID_TLV_TAG If the reader encountered a TLV tag in an invalid context. + * @retval #CHIP_ERROR_UNKNOWN_IMPLICIT_TLV_TAG + * If the reader encountered a implicitly-encoded TLV tag for which + * the corresponding profile id is unknown. + * @retval other Other CHIP or platform error codes returned by the configured + * GetNextBuffer() function. Only possible when GetNextBuffer is + * non-NULL. + */ + CHIP_ERROR populatePayload(SetupPayload::AdditionalDataPayload & outPayload); +}; + +} // namespace chip diff --git a/src/setup_payload/BUILD.gn b/src/setup_payload/BUILD.gn index 63c9bb1d828df6..d83933e42dc6fc 100644 --- a/src/setup_payload/BUILD.gn +++ b/src/setup_payload/BUILD.gn @@ -22,6 +22,9 @@ static_library("setup_payload") { output_name = "libSetupPayload" sources = [ + "AdditionalDataPayload.h", + "AdditionalDataPayloadParser.cpp", + "AdditionalDataPayloadParser.h", "Base41.cpp", "Base41.h", "ManualSetupPayloadGenerator.cpp", diff --git a/src/setup_payload/QRCodeSetupPayloadParser.cpp b/src/setup_payload/QRCodeSetupPayloadParser.cpp index 29e98a9e525f02..2713aded71d35f 100644 --- a/src/setup_payload/QRCodeSetupPayloadParser.cpp +++ b/src/setup_payload/QRCodeSetupPayloadParser.cpp @@ -36,6 +36,7 @@ #include #include #include +#include #include #include @@ -297,14 +298,14 @@ CHIP_ERROR QRCodeSetupPayloadParser::parseTLVFields(SetupPayload & outPayload, u CHIP_ERROR QRCodeSetupPayloadParser::populateTLV(SetupPayload & outPayload, const vector & buf, size_t & index) { - CHIP_ERROR err = CHIP_NO_ERROR; size_t bitsLeftToRead = (buf.size() * 8) - index; size_t tlvBytesLength = (bitsLeftToRead + 7) / 8; // ceil(bitsLeftToRead/8) chip::Platform::ScopedMemoryBuffer tlvArray; - SuccessOrExit(tlvBytesLength == 0); + ReturnErrorCodeIf(tlvBytesLength == 0, CHIP_NO_ERROR); + tlvArray.Alloc(tlvBytesLength); - VerifyOrExit(tlvArray, err = CHIP_ERROR_NO_MEMORY); + ReturnErrorCodeIf(!tlvArray, CHIP_ERROR_NO_MEMORY); for (size_t i = 0; i < tlvBytesLength; i++) { @@ -313,11 +314,7 @@ CHIP_ERROR QRCodeSetupPayloadParser::populateTLV(SetupPayload & outPayload, cons tlvArray[i] = static_cast(dest); } - err = parseTLVFields(outPayload, tlvArray.Get(), tlvBytesLength); - SuccessOrExit(err); - -exit: - return err; + return parseTLVFields(outPayload, tlvArray.Get(), tlvBytesLength); } static string extractPayload(string inString) diff --git a/src/setup_payload/java/SetupPayloadParser-JNI.cpp b/src/setup_payload/java/SetupPayloadParser-JNI.cpp index f8155d7d229d12..b1a22175a14cf0 100644 --- a/src/setup_payload/java/SetupPayloadParser-JNI.cpp +++ b/src/setup_payload/java/SetupPayloadParser-JNI.cpp @@ -1,6 +1,9 @@ #include "ManualSetupPayloadParser.h" #include "QRCodeSetupPayloadParser.h" +#include +#include + #include #include @@ -11,6 +14,13 @@ using namespace chip; static jobject TransformSetupPayload(JNIEnv * env, SetupPayload & payload); +jint JNI_OnLoad(JavaVM * jvm, void * reserved) +{ + ChipLogProgress(SetupPayload, "JNI_OnLoad() called"); + chip::Platform::MemoryInit(); + return JNI_VERSION_1_6; +} + JNI_METHOD(jobject, fetchPayloadFromQrCode)(JNIEnv * env, jobject self, jstring qrCodeObj) { CHIP_ERROR err; diff --git a/src/system/BUILD.gn b/src/system/BUILD.gn index d0dc4ef5e95399..044aa744d1418d 100644 --- a/src/system/BUILD.gn +++ b/src/system/BUILD.gn @@ -1,4 +1,4 @@ -# Copyright (c) 2020 Project CHIP Authors +# Copyright (c) 2020-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. @@ -140,6 +140,8 @@ static_library("system") { "SystemTimer.h", "SystemWakeEvent.cpp", "SystemWakeEvent.h", + "TLVPacketBufferBackingStore.cpp", + "TLVPacketBufferBackingStore.h", "TimeSource.h", ] diff --git a/src/system/SystemPacketBuffer.cpp b/src/system/SystemPacketBuffer.cpp index 0a21dc7dbd5c65..24ba9621d1c238 100644 --- a/src/system/SystemPacketBuffer.cpp +++ b/src/system/SystemPacketBuffer.cpp @@ -1,6 +1,6 @@ /* * - * Copyright (c) 2020 Project CHIP Authors + * Copyright (c) 2020-2021 Project CHIP Authors * Copyright (c) 2016-2017 Nest Labs, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -158,8 +158,11 @@ uint16_t PacketBuffer::ReservedSize() const return static_cast(kDelta - CHIP_SYSTEM_PACKETBUFFER_HEADER_SIZE); } -void PacketBuffer::AddToEnd_ForNow(PacketBuffer * aPacket) +void PacketBuffer::AddToEnd(PacketBufferHandle aPacketHandle) { + PacketBuffer * aPacket = aPacketHandle.mBuffer; + aPacketHandle.mBuffer = nullptr; + #if CHIP_SYSTEM_CONFIG_USE_LWIP pbuf_cat(this, aPacket); #else // !CHIP_SYSTEM_CONFIG_USE_LWIP @@ -179,11 +182,6 @@ void PacketBuffer::AddToEnd_ForNow(PacketBuffer * aPacket) #endif // !CHIP_SYSTEM_CONFIG_USE_LWIP } -void PacketBuffer::AddToEnd(PacketBufferHandle aPacketHandle) -{ - AddToEnd_ForNow(aPacketHandle.Release_ForNow()); -} - void PacketBuffer::CompactHead() { uint8_t * const kStart = reinterpret_cast(this) + CHIP_SYSTEM_PACKETBUFFER_HEADER_SIZE; @@ -536,5 +534,31 @@ PacketBufferHandle PacketBufferHandle::PopHead() return PacketBufferHandle(head); } +PacketBufferHandle PacketBufferHandle::CloneData() +{ + if (!mBuffer->Next().IsNull()) + { + // We do not clone an entire chain. + return PacketBufferHandle(); + } + + PacketBufferHandle other = PacketBuffer::New(); + if (other.IsNull()) + { + return other; + } + + if (other->AvailableDataLength() < mBuffer->DataLength()) + { + other = nullptr; + return other; + } + + memcpy(other->Start(), mBuffer->Start(), mBuffer->DataLength()); + other->SetDataLength(mBuffer->DataLength()); + + return other; +} + } // namespace System } // namespace chip diff --git a/src/system/SystemPacketBuffer.h b/src/system/SystemPacketBuffer.h index efdaf6436df09b..5b4dd5d523339e 100644 --- a/src/system/SystemPacketBuffer.h +++ b/src/system/SystemPacketBuffer.h @@ -1,6 +1,6 @@ /* * - * Copyright (c) 2020 Project CHIP Authors + * Copyright (c) 2020-2021 Project CHIP Authors * Copyright (c) 2016-2017 Nest Labs, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -185,7 +185,7 @@ class DLL_EXPORT PacketBuffer : private pbuf * * @return \c true if there is a chained buffer. */ - bool HasChainedBuffer() const { return this->next != nullptr; } + bool HasChainedBuffer() const { return ChainedBuffer() != nullptr; } /** * Add the given packet buffer to the end of the buffer chain, adjusting the total length of each buffer in the chain @@ -254,7 +254,7 @@ class DLL_EXPORT PacketBuffer : private pbuf /** * Return the last buffer in a buffer chain. * - * @return a handle to the next buffer in the buffer chain. + * @return a handle to the last buffer in the buffer chain. */ CHECK_RETURN_VALUE PacketBufferHandle Last(); @@ -308,13 +308,8 @@ class DLL_EXPORT PacketBuffer : private pbuf */ static PacketBufferHandle New(); - // The following will shortly be removed or made private; do not use in new code. - PacketBuffer * Next_ForNow() const { return static_cast(this->next); } - void AddToEnd_ForNow(PacketBuffer * aPacket); + // DO NOT USE. Will be made private after #4094 merges. void AddRef(); - static void Free(PacketBuffer * aPacket); - static PacketBuffer * FreeHead_ForNow(PacketBuffer * aPacket) { return FreeHead(aPacket); } - PacketBuffer * Consume(uint16_t aConsumeLength); private: #if !CHIP_SYSTEM_CONFIG_USE_LWIP && CHIP_SYSTEM_CONFIG_PACKETBUFFER_MAXALLOC @@ -327,8 +322,11 @@ class DLL_EXPORT PacketBuffer : private pbuf static PacketBuffer * RightSize(PacketBuffer * aPacket); #endif + static void Free(PacketBuffer * aPacket); static PacketBuffer * FreeHead(PacketBuffer * aPacket); + PacketBuffer * ChainedBuffer() const { return static_cast(this->next); } + PacketBuffer * Consume(uint16_t aConsumeLength); void Clear(); friend class PacketBufferHandle; @@ -449,7 +447,7 @@ class DLL_EXPORT PacketBufferHandle aOther.mBuffer = nullptr; } - ~PacketBufferHandle() { Adopt(nullptr); } + ~PacketBufferHandle() { *this = nullptr; } /** * Take ownership of a PacketBuffer from another PacketBufferHandle, freeing any existing owned buffer. @@ -470,7 +468,11 @@ class DLL_EXPORT PacketBufferHandle */ PacketBufferHandle & operator=(decltype(nullptr)) { - Adopt(nullptr); + if (mBuffer != nullptr) + { + PacketBuffer::Free(mBuffer); + } + mBuffer = nullptr; return *this; } @@ -489,7 +491,6 @@ class DLL_EXPORT PacketBufferHandle * Access a PackerBuffer's public methods. */ PacketBuffer * operator->() const { return mBuffer; } - PacketBuffer & operator*() const { return *mBuffer; } /** * Test whether this PacketBufferHandle is empty, or owns a PacketBuffer. @@ -547,22 +548,6 @@ class DLL_EXPORT PacketBufferHandle #endif } - /** - * Take ownership of a raw PacketBuffer pointer. - * - * @brief The caller's ownership is transferred to this. An existing owned buffer is freed. - * - * @note This should only be used in low-level code, e.g. to import buffers from LwIP or a similar stack. - */ - void Adopt(PacketBuffer * buffer) - { - if (mBuffer != nullptr) - { - PacketBuffer::Free(mBuffer); - } - mBuffer = buffer; - } - /** * Get a new handle to a raw PacketBuffer pointer. * @@ -570,7 +555,10 @@ class DLL_EXPORT PacketBufferHandle * * @note This should only be used in low-level code, e.g. to import buffers from LwIP or a similar stack. */ - static PacketBufferHandle Create(PacketBuffer * buffer) { return PacketBufferHandle(buffer); } + static PacketBufferHandle Adopt(PacketBuffer * buffer) { return PacketBufferHandle(buffer); } +#if CHIP_SYSTEM_CONFIG_USE_LWIP + static PacketBufferHandle Adopt(pbuf * buffer) { return Adopt(reinterpret_cast(buffer)); } +#endif // CHIP_SYSTEM_CONFIG_USE_LWIP /** * Export a raw PacketBuffer pointer. @@ -591,10 +579,10 @@ class DLL_EXPORT PacketBufferHandle * * @note This differs from `FreeHead()` in that it does not touch any content in the currently referenced packet buffer; * it only changes which buffer this handle owns. (Note that this could result in the previous buffer being freed, - * if there is no other.) `Advance()` is designed to be used with an addition handle to traverse a buffer chain, + * if there is no other owner.) `Advance()` is designed to be used with an additional handle to traverse a buffer chain, * whereas `FreeHead()` modifies a chain. */ - void Advance() { *this = Hold(mBuffer->Next_ForNow()); } + void Advance() { *this = Hold(mBuffer->ChainedBuffer()); } #if CHIP_SYSTEM_CONFIG_USE_LWIP /** @@ -607,10 +595,14 @@ class DLL_EXPORT PacketBufferHandle struct pbuf * GetLwIPpbuf() { return static_cast(mBuffer); } #endif // CHIP_SYSTEM_CONFIG_USE_LWIP - // DO NOT USE. This is intended to be used only to call existing TLV::Init() functions that have not yet been converted - // to take a PacketBufferHandle, and will be removed soon. - // The caller has access but no ownership. - PacketBuffer * Get_ForNow() const { return mBuffer; } + /** + * Creates a copy of the data in this packet. + * + * Does NOT support chained buffers. + * + * @returns empty handle on allocation failure. + */ + PacketBufferHandle CloneData(); private: PacketBufferHandle(const PacketBufferHandle &) = delete; @@ -630,6 +622,8 @@ class DLL_EXPORT PacketBufferHandle PacketBuffer * Get() const { return mBuffer; } + bool operator==(const PacketBufferHandle & aOther) { return mBuffer == aOther.mBuffer; } + PacketBuffer * mBuffer; friend class PacketBuffer; @@ -643,14 +637,14 @@ inline void PacketBuffer::SetDataLength(uint16_t aNewLen, const PacketBufferHand inline PacketBufferHandle PacketBuffer::Next() { - return PacketBufferHandle::Hold(Next_ForNow()); + return PacketBufferHandle::Hold(ChainedBuffer()); } inline PacketBufferHandle PacketBuffer::Last() { PacketBuffer * p = this; - while (p->Next_ForNow() != nullptr) - p = p->Next_ForNow(); + while (p->HasChainedBuffer()) + p = p->ChainedBuffer(); return PacketBufferHandle::Hold(p); } diff --git a/src/system/TLVPacketBufferBackingStore.cpp b/src/system/TLVPacketBufferBackingStore.cpp new file mode 100644 index 00000000000000..2c5cf05f98af60 --- /dev/null +++ b/src/system/TLVPacketBufferBackingStore.cpp @@ -0,0 +1,117 @@ +/* + * + * Copyright (c) 2021 Project CHIP Authors + * Copyright (c) 2013-2017 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 + * This file contains an implementation of TLVBackingStore using PacketBuffers. + */ + +#include + +#include + +namespace chip { +namespace System { + +CHIP_ERROR TLVPacketBufferBackingStore::OnInit(chip::TLV::TLVReader & reader, const uint8_t *& bufStart, uint32_t & bufLen) +{ + bufStart = mHeadBuffer->Start(); + bufLen = mHeadBuffer->DataLength(); + return CHIP_NO_ERROR; +} + +CHIP_ERROR TLVPacketBufferBackingStore::GetNextBuffer(chip::TLV::TLVReader & reader, const uint8_t *& bufStart, uint32_t & bufLen) +{ + if (mUseChainedBuffers) + { + mCurrentBuffer.Advance(); + } + else + { + mCurrentBuffer = nullptr; + } + + if (mCurrentBuffer.IsNull()) + { + bufStart = nullptr; + bufLen = 0; + } + else + { + bufStart = mCurrentBuffer->Start(); + bufLen = mCurrentBuffer->DataLength(); + } + + return CHIP_NO_ERROR; +} + +CHIP_ERROR TLVPacketBufferBackingStore::OnInit(chip::TLV::TLVWriter & writer, uint8_t *& bufStart, uint32_t & bufLen) +{ + bufStart = mHeadBuffer->Start() + mHeadBuffer->DataLength(); + bufLen = mHeadBuffer->AvailableDataLength(); + return CHIP_NO_ERROR; +} + +CHIP_ERROR TLVPacketBufferBackingStore::FinalizeBuffer(chip::TLV::TLVWriter & writer, uint8_t * bufStart, uint32_t dataLen) +{ + uint8_t * endPtr = bufStart + dataLen; + + intptr_t length = endPtr - mCurrentBuffer->Start(); + if (!CanCastTo(length)) + { + return CHIP_ERROR_INVALID_ARGUMENT; + } + mCurrentBuffer->SetDataLength(static_cast(length)); + + return CHIP_NO_ERROR; +} + +CHIP_ERROR TLVPacketBufferBackingStore::GetNewBuffer(chip::TLV::TLVWriter & writer, uint8_t *& bufStart, uint32_t & bufLen) +{ + if (!mUseChainedBuffers) + { + return CHIP_ERROR_NO_MEMORY; + } + + mCurrentBuffer.Advance(); + if (mCurrentBuffer.IsNull()) + { + mCurrentBuffer = PacketBuffer::New(0); + if (mCurrentBuffer.IsNull()) + { + return CHIP_ERROR_NO_MEMORY; + } + mHeadBuffer->AddToEnd(mCurrentBuffer.Retain()); + } + + if (mCurrentBuffer.IsNull()) + { + bufStart = nullptr; + bufLen = 0; + } + else + { + bufStart = mCurrentBuffer->Start(); + bufLen = mCurrentBuffer->MaxDataLength(); + } + + return CHIP_NO_ERROR; +} + +} // namespace System +} // namespace chip diff --git a/src/system/TLVPacketBufferBackingStore.h b/src/system/TLVPacketBufferBackingStore.h new file mode 100644 index 00000000000000..3e6ec0335ab550 --- /dev/null +++ b/src/system/TLVPacketBufferBackingStore.h @@ -0,0 +1,161 @@ +/* + * + * Copyright (c) 2021 Project CHIP Authors + * Copyright (c) 2013-2017 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 + * This file contains an implementation of TLVBackingStore using PacketBuffers. + */ + +#pragma once + +#include +#include + +#include + +namespace chip { +namespace System { + +/** + * An implementation of TLVBackingStore using PacketBuffers. + */ +class TLVPacketBufferBackingStore : public chip::TLV::TLVBackingStore +{ +public: + TLVPacketBufferBackingStore() : mHeadBuffer(nullptr), mCurrentBuffer(nullptr), mUseChainedBuffers(false) {} + TLVPacketBufferBackingStore(chip::System::PacketBufferHandle buffer, bool useChainedBuffers = false) + { + Init(std::move(buffer), useChainedBuffers); + } + virtual ~TLVPacketBufferBackingStore() {} + + /** + * Take ownership of a backing packet buffer. + * + * @param[in] buffer A handle to PacketBuffer, to be used as backing store for a TLV class. + * @param[in] useChainedBuffers + * If true, advance to the next buffer in the chain once all data or space + * in the current buffer has been consumed; a write will allocate new + * PacketBuffers if necessary. + * + * @note This must take place before initializing a TLV class with this backing store. + */ + void Init(chip::System::PacketBufferHandle buffer, bool useChainedBuffers = false) + { + mHeadBuffer = std::move(buffer); + mCurrentBuffer = mHeadBuffer.Retain(); + mUseChainedBuffers = useChainedBuffers; + } + void Adopt(chip::System::PacketBufferHandle buffer) { Init(std::move(buffer), mUseChainedBuffers); } + + /** + * Release ownership of the backing packet buffer. + * + * @note TLV operations must no longer be performed on this store. + */ + CHECK_RETURN_VALUE chip::System::PacketBufferHandle Release() + { + mCurrentBuffer = nullptr; + return std::move(mHeadBuffer); + } + + // TLVBackingStore overrides: + CHIP_ERROR OnInit(chip::TLV::TLVReader & reader, const uint8_t *& bufStart, uint32_t & bufLen) override; + CHIP_ERROR GetNextBuffer(chip::TLV::TLVReader & reader, const uint8_t *& bufStart, uint32_t & bufLen) override; + CHIP_ERROR OnInit(chip::TLV::TLVWriter & writer, uint8_t *& bufStart, uint32_t & bufLen) override; + CHIP_ERROR GetNewBuffer(chip::TLV::TLVWriter & writer, uint8_t *& bufStart, uint32_t & bufLen) override; + CHIP_ERROR FinalizeBuffer(chip::TLV::TLVWriter & writer, uint8_t * bufStart, uint32_t bufLen) override; + +protected: + chip::System::PacketBufferHandle mHeadBuffer; + chip::System::PacketBufferHandle mCurrentBuffer; + bool mUseChainedBuffers; +}; + +class DLL_EXPORT PacketBufferTLVReader : public chip::TLV::TLVReader +{ +public: + /** + * Initializes a TLVReader object to read from a PacketBuffer. + * + * @param[in] buffer A handle to PacketBuffer, to be used as backing store for a TLV class. + * @param[in] useChainedBuffers + * If true, advance to the next buffer in the chain once all data + * in the current buffer has been consumed. + */ + void Init(chip::System::PacketBufferHandle buffer, bool useChainedBuffers = false) + { + mBackingStore.Init(std::move(buffer), useChainedBuffers); + chip::TLV::TLVReader::Init(mBackingStore); + } + +private: + TLVPacketBufferBackingStore mBackingStore; +}; + +class DLL_EXPORT PacketBufferTLVWriter : public chip::TLV::TLVWriter +{ +public: + /** + * Initializes a TLVWriter object to write to a PacketBuffer. + * + * @param[in] buffer A handle to PacketBuffer, to be used as backing store for a TLV class. + * @param[in] useChainedBuffers + * If true, advance to the next buffer in the chain once all space + * in the current buffer has been consumed. Once all existing buffers + * have been used, new PacketBuffers will be allocated as necessary. + */ + void Init(chip::System::PacketBufferHandle buffer, bool useChainedBuffers = false) + { + mBackingStore.Init(std::move(buffer), useChainedBuffers); + chip::TLV::TLVWriter::Init(mBackingStore); + } + /** + * Finish the writing of a TLV encoding and release ownership of the underlying PacketBuffer. + * + * @param[in,out] outBuffer The backing packet buffer. + * + * @retval #CHIP_NO_ERROR If the encoding was finalized successfully. + * @retval #CHIP_ERROR_TLV_CONTAINER_OPEN + * If a container writer has been opened on the current writer and not + * yet closed. + * @retval #CHIP_ERROR_INVALID_ARGUMENT + * If the apparent data length does not fit in uint16_t. + * + * @note No further TLV operations may be performed, unless or until this PacketBufferTLVWriter is re-initialized. + */ + CHIP_ERROR Finalize(chip::System::PacketBufferHandle * outBuffer) + { + CHIP_ERROR err = Finalize(); + *outBuffer = mBackingStore.Release(); + return err; + } + /** + * Free the underlying PacketBuffer. + * + * @note No further TLV operations may be performed, unless or until this PacketBufferTLVWriter is re-initialized. + */ + void Reset() { static_cast(mBackingStore.Release()); } + +private: + CHIP_ERROR Finalize() { return chip::TLV::TLVWriter::Finalize(); } + TLVPacketBufferBackingStore mBackingStore; +}; + +} // namespace System +} // namespace chip diff --git a/src/system/tests/TestSystemPacketBuffer.cpp b/src/system/tests/TestSystemPacketBuffer.cpp index fdd2add0aa48fa..fce564e12412b6 100644 --- a/src/system/tests/TestSystemPacketBuffer.cpp +++ b/src/system/tests/TestSystemPacketBuffer.cpp @@ -1,6 +1,6 @@ /* * - * Copyright (c) 2020 Project CHIP Authors + * Copyright (c) 2020-2021 Project CHIP Authors * Copyright (c) 2016-2017 Nest Labs, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -31,6 +31,8 @@ #include #include #include +#include +#include #include #include @@ -63,9 +65,28 @@ using ::chip::System::pbuf; #define TO_LWIP_PBUF(x) (reinterpret_cast(reinterpret_cast(x))) #define OF_LWIP_PBUF(x) (reinterpret_cast(reinterpret_cast(x))) +/* + * An instance of this class created for the test suite. + * It is a friend class of `PacketBuffer` and `PacketBufferHandle` because some tests + * use or check private methods or properties. + */ class PacketBufferTest { public: + struct TestContext + { + const uint16_t * const reserved_sizes; + size_t reserved_size_count; + const uint16_t * const lengths; + size_t length_count; + PacketBufferTest * test; + }; + + static int TestSetup(void * inContext); + static int TestTeardown(void * inContext); + static int TestInitialize(void * inContext); + static int TestTerminate(void * inContext); + static void CheckNewWithAvailableSizeAndFree(nlTestSuite * inSuite, void * inContext); static void CheckStart(nlTestSuite * inSuite, void * inContext); static void CheckSetStart(nlTestSuite * inSuite, void * inContext); @@ -75,243 +96,310 @@ class PacketBufferTest static void CheckMaxDataLength(nlTestSuite * inSuite, void * inContext); static void CheckAvailableDataLength(nlTestSuite * inSuite, void * inContext); static void CheckReservedSize(nlTestSuite * inSuite, void * inContext); + static void CheckHasChainedBuffer(nlTestSuite * inSuite, void * inContext); static void CheckAddToEnd(nlTestSuite * inSuite, void * inContext); - static void CheckDetachTail(nlTestSuite * inSuite, void * inContext); + static void CheckPopHead(nlTestSuite * inSuite, void * inContext); static void CheckCompactHead(nlTestSuite * inSuite, void * inContext); static void CheckConsumeHead(nlTestSuite * inSuite, void * inContext); static void CheckConsume(nlTestSuite * inSuite, void * inContext); static void CheckEnsureReservedSize(nlTestSuite * inSuite, void * inContext); static void CheckAlignPayload(nlTestSuite * inSuite, void * inContext); static void CheckNext(nlTestSuite * inSuite, void * inContext); + static void CheckLast(nlTestSuite * inSuite, void * inContext); static void CheckAddRef(nlTestSuite * inSuite, void * inContext); static void CheckFree(nlTestSuite * inSuite, void * inContext); static void CheckFreeHead(nlTestSuite * inSuite, void * inContext); + static void CheckHandleConstruct(nlTestSuite * inSuite, void * inContext); + static void CheckHandleMove(nlTestSuite * inSuite, void * inContext); + static void CheckHandleFree(nlTestSuite * inSuite, void * inContext); + static void CheckHandleRetain(nlTestSuite * inSuite, void * inContext); + static void CheckHandleAdopt(nlTestSuite * inSuite, void * inContext); + static void CheckHandleHold(nlTestSuite * inSuite, void * inContext); + static void CheckHandleAdvance(nlTestSuite * inSuite, void * inContext); static void CheckBuildFreeList(nlTestSuite * inSuite, void * inContext); - static void BufferFree(struct TestContext * theContext); + static void PrintHandle(const char * tag, const PacketBuffer * buffer) + { + printf("%s %p ref=%u len=%-4u next=%p\n", tag, buffer, buffer ? buffer->ref : 0, buffer ? buffer->len : 0, + buffer ? buffer->next : 0); + } + static void PrintHandle(const char * tag, const PacketBufferHandle & handle) { PrintHandle(tag, handle.mBuffer); } + +private: + struct BufferConfiguration + { + BufferConfiguration(uint16_t aReservedSize = 0) : + init_len(0), reserved_size(aReservedSize), start_buffer(nullptr), end_buffer(nullptr), payload_ptr(nullptr), + handle(nullptr) + {} + + uint16_t init_len; + uint16_t reserved_size; + uint8_t * start_buffer; + uint8_t * end_buffer; + uint8_t * payload_ptr; + PacketBufferHandle handle; + }; + + static void PrintHandle(const char * tag, const BufferConfiguration & config) { PrintHandle(tag, config.handle); } + static void PrintConfig(const char * tag, const BufferConfiguration & config) + { + printf("%s pay=%-4zu len=%-4u res=%-4u:", tag, config.payload_ptr - config.start_buffer, config.init_len, + config.reserved_size); + PrintHandle("", config.handle); + } + + PacketBufferTest(TestContext * context); + ~PacketBufferTest(); + + int InitializeTest(TestContext * context); + int TerminateTest(TestContext * context); + + /* + * Buffers allocated through PrepareTestBuffer with kRecordHandle set will be recorded in `handles` so that their + * reference counts can be verified by ResetHandles(). Initially they have two refs: the recorded one and the returned one. + */ + static constexpr int kRecordHandle = 0x01; + static constexpr int kAllowHandleReuse = 0x02; + void PrepareTestBuffer(BufferConfiguration * config, int flags = 0); + + /* + * Checks and clears the recorded handles. Returns true if it detects no leaks or double frees. + * Called from `TerminateTest()`, but tests may choose to call it more often to verify reference counts. + */ + bool ResetHandles(); + + TestContext * mContext; + std::vector configurations; + std::vector handles; }; -namespace { +const uint16_t sTestReservedSizes[] = { 0, 10, 128, 1536, CHIP_SYSTEM_PACKETBUFFER_SIZE }; +const uint16_t sTestLengths[] = { 0, 1, 10, 128, CHIP_SYSTEM_PACKETBUFFER_SIZE, UINT16_MAX }; -void CheckNewWithAvailableSizeAndFree(nlTestSuite * inSuite, void * inContext) -{ - PacketBufferTest::CheckNewWithAvailableSizeAndFree(inSuite, inContext); -} -void CheckStart(nlTestSuite * inSuite, void * inContext) -{ - PacketBufferTest::CheckStart(inSuite, inContext); -} -void CheckSetStart(nlTestSuite * inSuite, void * inContext) -{ - PacketBufferTest::CheckSetStart(inSuite, inContext); -} -void CheckDataLength(nlTestSuite * inSuite, void * inContext) -{ - PacketBufferTest::CheckDataLength(inSuite, inContext); -} -void CheckSetDataLength(nlTestSuite * inSuite, void * inContext) -{ - PacketBufferTest::CheckSetDataLength(inSuite, inContext); -} -void CheckTotalLength(nlTestSuite * inSuite, void * inContext) -{ - PacketBufferTest::CheckTotalLength(inSuite, inContext); -} -void CheckMaxDataLength(nlTestSuite * inSuite, void * inContext) -{ - PacketBufferTest::CheckMaxDataLength(inSuite, inContext); -} -void CheckAvailableDataLength(nlTestSuite * inSuite, void * inContext) -{ - PacketBufferTest::CheckAvailableDataLength(inSuite, inContext); -} -void CheckReservedSize(nlTestSuite * inSuite, void * inContext) -{ - PacketBufferTest::CheckReservedSize(inSuite, inContext); -} -void CheckAddToEnd(nlTestSuite * inSuite, void * inContext) -{ - PacketBufferTest::CheckAddToEnd(inSuite, inContext); -} -void CheckDetachTail(nlTestSuite * inSuite, void * inContext) -{ - PacketBufferTest::CheckDetachTail(inSuite, inContext); -} -void CheckCompactHead(nlTestSuite * inSuite, void * inContext) -{ - PacketBufferTest::CheckCompactHead(inSuite, inContext); -} -void CheckConsumeHead(nlTestSuite * inSuite, void * inContext) -{ - PacketBufferTest::CheckConsumeHead(inSuite, inContext); -} -void CheckConsume(nlTestSuite * inSuite, void * inContext) -{ - PacketBufferTest::CheckConsume(inSuite, inContext); -} -void CheckEnsureReservedSize(nlTestSuite * inSuite, void * inContext) -{ - PacketBufferTest::CheckEnsureReservedSize(inSuite, inContext); -} -void CheckAlignPayload(nlTestSuite * inSuite, void * inContext) -{ - PacketBufferTest::CheckAlignPayload(inSuite, inContext); -} -void CheckNext(nlTestSuite * inSuite, void * inContext) -{ - PacketBufferTest::CheckNext(inSuite, inContext); -} -void CheckAddRef(nlTestSuite * inSuite, void * inContext) +PacketBufferTest::TestContext sContext = { + sTestReservedSizes, + sizeof(sTestReservedSizes) / sizeof(uint16_t), + sTestLengths, + sizeof(sTestLengths) / sizeof(uint16_t), +}; + +PacketBufferTest::PacketBufferTest(TestContext * context) : mContext(context) { - PacketBufferTest::CheckAddRef(inSuite, inContext); + // Set up the buffer configuration vector for this suite. + configurations.resize(0); + for (size_t i = 0; i < mContext->reserved_size_count; ++i) + { + configurations.emplace_back(mContext->reserved_sizes[i]); + } } -void CheckFree(nlTestSuite * inSuite, void * inContext) + +int PacketBufferTest::TestSetup(void * inContext) { - PacketBufferTest::CheckFree(inSuite, inContext); + TestContext * const theContext = reinterpret_cast(inContext); + theContext->test = new PacketBufferTest(theContext); + if (theContext->test == nullptr) + { + return FAILURE; + } + return SUCCESS; } -void CheckFreeHead(nlTestSuite * inSuite, void * inContext) + +int PacketBufferTest::TestTeardown(void * inContext) { - PacketBufferTest::CheckFreeHead(inSuite, inContext); + return SUCCESS; } -void CheckBuildFreeList(nlTestSuite * inSuite, void * inContext) + +int PacketBufferTest::TestInitialize(void * inContext) { - PacketBufferTest::CheckBuildFreeList(inSuite, inContext); + TestContext * const theContext = reinterpret_cast(inContext); + if (theContext->test == nullptr) + { + return FAILURE; + } + return theContext->test->InitializeTest(theContext); } -} // namespace - -// Test input vector format. - -struct TestContext +int PacketBufferTest::InitializeTest(TestContext * context) { - uint16_t init_len; - uint16_t reserved_size; - uint8_t * start_buffer; - uint8_t * end_buffer; - uint8_t * payload_ptr; - struct pbuf * buf; -}; - -// Test input data. + if (context != mContext) + { + return FAILURE; + } + return SUCCESS; +} -// clang-format off -struct TestContext sContext[] = +int PacketBufferTest::TestTerminate(void * inContext) { - { 0, 0, nullptr, nullptr, nullptr, nullptr }, - { 0, 10, nullptr, nullptr, nullptr, nullptr }, - { 0, 128, nullptr, nullptr, nullptr, nullptr }, - { 0, 1536, nullptr, nullptr, nullptr, nullptr }, - { 0, CHIP_SYSTEM_PACKETBUFFER_SIZE, nullptr, nullptr, nullptr, nullptr } -}; -// clang-format on - -const uint16_t sLengths[] = { 0, 1, 10, 128, CHIP_SYSTEM_PACKETBUFFER_SIZE, UINT16_MAX }; - -// Number of test context examples. -const size_t kTestElements = sizeof(sContext) / sizeof(struct TestContext); -const size_t kTestLengths = sizeof(sLengths) / sizeof(uint16_t); + TestContext * const theContext = reinterpret_cast(inContext); + if (theContext->test == nullptr) + { + return FAILURE; + } + return theContext->test->TerminateTest(theContext); +} -/** - * Free allocated test buffer memory. - */ -void PacketBufferTest::BufferFree(struct TestContext * theContext) +int PacketBufferTest::TerminateTest(TestContext * context) { - if (theContext->buf != nullptr) + const bool context_ok = (context == mContext); + // Clear the configurations' bufffer handles. + for (size_t i = 0; i < configurations.size(); ++i) { - PacketBuffer::Free(OF_LWIP_PBUF(theContext->buf)); - theContext->buf = nullptr; + configurations[i].handle = nullptr; } + const bool handles_ok = ResetHandles(); + return (context_ok && handles_ok) ? SUCCESS : FAILURE; } /** - * Allocate memory for a test buffer and configure according to test context. + * Allocate memory for a test buffer and configure according to test buffer configuration. */ -void BufferAlloc(struct TestContext * theContext) +void PacketBufferTest::PrepareTestBuffer(BufferConfiguration * config, int flags) { - const size_t lInitialSize = CHIP_SYSTEM_PACKETBUFFER_HEADER_SIZE + theContext->reserved_size; - const size_t lAllocSize = CHIP_SYSTEM_PACKETBUFFER_SIZE; - -#if CHIP_SYSTEM_CONFIG_USE_LWIP - u8_t lType, lFlags; -#if LWIP_PBUF_FROM_CUSTOM_POOLS - u16_t lPool; -#endif // LWIP_PBUF_FROM_CUSTOM_POOLS -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP - - if (theContext->buf == nullptr) + if (config->handle.IsNull()) { - theContext->buf = TO_LWIP_PBUF(PacketBuffer::New(0).Release_ForNow()); + config->handle = PacketBuffer::New(0); + if (config->handle.IsNull()) + { + printf("NewPacketBuffer: Failed to allocate packet buffer (%zu retained): %s\n", handles.size(), strerror(errno)); + exit(EXIT_FAILURE); + } + if (flags & kRecordHandle) + { + handles.push_back(config->handle.Retain()); + } } - - if (theContext->buf == nullptr) + else if ((flags & kAllowHandleReuse) == 0) { - fprintf(stderr, "Failed to allocate %zuB memory: %s\n", lAllocSize, strerror(errno)); + printf("Dirty test configuration\n"); exit(EXIT_FAILURE); } -#if CHIP_SYSTEM_CONFIG_USE_LWIP - lType = PBUF_TYPE(theContext->buf); - lFlags = theContext->buf->flags; -#if LWIP_PBUF_FROM_CUSTOM_POOLS - lPool = theContext->buf->pool; -#endif // LWIP_PBUF_FROM_CUSTOM_POOLS - memset(theContext->buf, 0, lAllocSize); - PBUF_TYPE(theContext->buf) = lType; - theContext->buf->flags = lFlags; -#if LWIP_PBUF_FROM_CUSTOM_POOLS - theContext->buf->pool = lPool; -#endif // LWIP_PBUF_FROM_CUSTOM_POOLS -#else // !CHIP_SYSTEM_CONFIG_USE_LWIP - memset(theContext->buf, 0, lAllocSize); -#if CHIP_SYSTEM_CONFIG_PACKETBUFFER_MAXALLOC == 0 - theContext->buf->alloc_size = lAllocSize; -#endif // CHIP_SYSTEM_CONFIG_PACKETBUFFER_MAXALLOC == 0 -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP + const size_t lInitialSize = CHIP_SYSTEM_PACKETBUFFER_HEADER_SIZE + config->reserved_size; + const size_t lAllocSize = CHIP_SYSTEM_PACKETBUFFER_SIZE; + + uint8_t * const raw = reinterpret_cast(config->handle.Get()); + memset(raw + CHIP_SYSTEM_PACKETBUFFER_HEADER_SIZE, 0, lAllocSize - CHIP_SYSTEM_PACKETBUFFER_HEADER_SIZE); - theContext->start_buffer = reinterpret_cast(theContext->buf); - theContext->end_buffer = reinterpret_cast(theContext->buf) + lAllocSize; + config->start_buffer = raw; + config->end_buffer = raw + lAllocSize; if (lInitialSize > lAllocSize) { - theContext->payload_ptr = theContext->end_buffer; + config->payload_ptr = config->end_buffer; } else { - theContext->payload_ptr = theContext->start_buffer + lInitialSize; + config->payload_ptr = config->start_buffer + lInitialSize; + } + + if (config->handle->HasChainedBuffer()) + { + // This should not happen. + PacketBuffer::Free(config->handle->ChainedBuffer()); + config->handle->next = nullptr; + } + config->handle->payload = config->payload_ptr; + config->handle->len = config->init_len; + config->handle->tot_len = config->init_len; +} + +bool PacketBufferTest::ResetHandles() +{ + // Check against leaks or double-frees in tests: every handle obtained through + // PacketBufferTest::NewPacketBuffer should have a reference count of 1. + bool handles_ok = true; + for (size_t i = 0; i < handles.size(); ++i) + { + const PacketBufferHandle & handle = handles[i]; + if (handle.Get() == nullptr) + { + printf("TestTerminate: handle %zu null\n", i); + handles_ok = false; + } + else if (handle->ref != 1) + { + printf("TestTerminate: handle %zu buffer=%p ref=%u\n", i, handle.Get(), handle->ref); + handles_ok = false; + while (handle->ref > 1) + { + PacketBuffer::Free(handle.Get()); + } + } } + handles.resize(0); + return handles_ok; } +// Test functions invoked from the suite. + /** - * Setup buffer layout as it is used by PacketBuffer class. + * Test PacketBuffer::NewWithAvailableSize() and PacketBuffer::Free() functions. + * + * Description: For every buffer-configuration from inContext, create a + * buffer's instance using NewWithAvailableSize() method. Then, verify that + * when the size of the reserved space passed to NewWithAvailableSize() is + * greater than #CHIP_SYSTEM_CONFIG_PACKETBUFFER_CAPACITY_MAX, the method + * returns NULL. Otherwise, check for correctness of initializing + * the new buffer's internal state. Finally, free the buffer. */ -PacketBuffer * PrepareTestBuffer(struct TestContext * theContext) +void PacketBufferTest::CheckNewWithAvailableSizeAndFree(nlTestSuite * inSuite, void * inContext) { - BufferAlloc(theContext); + TestContext * const theContext = static_cast(inContext); + PacketBufferTest * const test = theContext->test; + NL_TEST_ASSERT(inSuite, test->mContext == theContext); + + for (const auto & config : test->configurations) + { + const PacketBufferHandle buffer = PacketBuffer::NewWithAvailableSize(config.reserved_size, 0); - theContext->buf->next = nullptr; - theContext->buf->payload = theContext->payload_ptr; - theContext->buf->ref = 1; - theContext->buf->len = theContext->init_len; - theContext->buf->tot_len = theContext->init_len; + if (config.reserved_size > CHIP_SYSTEM_CONFIG_PACKETBUFFER_CAPACITY_MAX) + { + NL_TEST_ASSERT(inSuite, buffer.IsNull()); + continue; + } + + NL_TEST_ASSERT(inSuite, config.reserved_size <= buffer->AllocSize()); + NL_TEST_ASSERT(inSuite, !buffer.IsNull()); + + if (!buffer.IsNull()) + { + const pbuf * const pb = TO_LWIP_PBUF(buffer.Get()); + + NL_TEST_ASSERT(inSuite, pb->len == 0); + NL_TEST_ASSERT(inSuite, pb->tot_len == 0); + NL_TEST_ASSERT(inSuite, pb->next == nullptr); + NL_TEST_ASSERT(inSuite, pb->ref == 1); + } + } - return reinterpret_cast(theContext->buf); + // Use the rest of the buffer space + std::vector allocate_all_the_things; + for (;;) + { + PacketBufferHandle buffer = PacketBuffer::NewWithAvailableSize(0, 0); + if (buffer.IsNull()) + { + break; + } + // Hold on to the buffer, to use up all the buffer space. + allocate_all_the_things.push_back(std::move(buffer)); + } } -// Test functions invoked from the suite. /** * Test PacketBuffer::Start() function. */ void PacketBufferTest::CheckStart(nlTestSuite * inSuite, void * inContext) { - struct TestContext * theContext = static_cast(inContext); + struct TestContext * const theContext = static_cast(inContext); + PacketBufferTest * const test = theContext->test; + NL_TEST_ASSERT(inSuite, test->mContext == theContext); - for (size_t ith = 0; ith < kTestElements; ith++) + for (auto & config : test->configurations) { - PacketBuffer * buffer = PrepareTestBuffer(theContext); - - NL_TEST_ASSERT(inSuite, buffer->Start() == theContext->payload_ptr); - - theContext++; + test->PrepareTestBuffer(&config, kRecordHandle); + NL_TEST_ASSERT(inSuite, config.handle->Start() == config.payload_ptr); } } @@ -328,13 +416,16 @@ void PacketBufferTest::CheckStart(nlTestSuite * inSuite, void * inContext) */ void PacketBufferTest::CheckSetStart(nlTestSuite * inSuite, void * inContext) { - struct TestContext * theContext = static_cast(inContext); - static const ptrdiff_t sSizePacketBuffer = CHIP_SYSTEM_PACKETBUFFER_SIZE; + struct TestContext * const theContext = static_cast(inContext); + PacketBufferTest * const test = theContext->test; + NL_TEST_ASSERT(inSuite, test->mContext == theContext); - for (size_t ith = 0; ith < kTestElements; ith++) + static constexpr ptrdiff_t sSizePacketBuffer = CHIP_SYSTEM_PACKETBUFFER_SIZE; + + for (auto & config : test->configurations) { // clang-format off - static const ptrdiff_t start_offset[] = + static constexpr ptrdiff_t start_offset[] = { -sSizePacketBuffer, -128, @@ -348,39 +439,38 @@ void PacketBufferTest::CheckSetStart(nlTestSuite * inSuite, void * inContext) for (ptrdiff_t offset : start_offset) { - PacketBuffer * buffer = PrepareTestBuffer(theContext); - uint8_t * test_start = theContext->payload_ptr + offset; - uint8_t * verify_start = test_start; + test->PrepareTestBuffer(&config, kRecordHandle | kAllowHandleReuse); + uint8_t * const test_start = config.payload_ptr + offset; + uint8_t * verify_start = test_start; - buffer->SetStart(test_start); + config.handle->SetStart(test_start); - if (verify_start < theContext->start_buffer + CHIP_SYSTEM_PACKETBUFFER_HEADER_SIZE) + if (verify_start < config.start_buffer + CHIP_SYSTEM_PACKETBUFFER_HEADER_SIZE) { // Set start before valid payload beginning. - verify_start = theContext->start_buffer + CHIP_SYSTEM_PACKETBUFFER_HEADER_SIZE; + verify_start = config.start_buffer + CHIP_SYSTEM_PACKETBUFFER_HEADER_SIZE; } - if (verify_start > theContext->end_buffer) + if (verify_start > config.end_buffer) { // Set start after valid payload beginning. - verify_start = theContext->end_buffer; + verify_start = config.end_buffer; } - NL_TEST_ASSERT(inSuite, theContext->buf->payload == verify_start); + NL_TEST_ASSERT(inSuite, config.handle->payload == verify_start); - if ((verify_start - theContext->payload_ptr) > theContext->init_len) + if ((verify_start - config.payload_ptr) > config.init_len) { - // Set start to the beginning of payload, right after buffer's header. - NL_TEST_ASSERT(inSuite, theContext->buf->len == 0); + // Set start to the beginning of payload, right after handle's header. + NL_TEST_ASSERT(inSuite, config.handle->len == 0); } else { - // Set start to somewhere between the end of the buffer's + // Set start to somewhere between the end of the handle's // header and the end of payload. - NL_TEST_ASSERT(inSuite, theContext->buf->len == (theContext->init_len - (verify_start - theContext->payload_ptr))); + NL_TEST_ASSERT(inSuite, config.handle->len == (config.init_len - (verify_start - config.payload_ptr))); } } - theContext++; } } @@ -389,15 +479,15 @@ void PacketBufferTest::CheckSetStart(nlTestSuite * inSuite, void * inContext) */ void PacketBufferTest::CheckDataLength(nlTestSuite * inSuite, void * inContext) { - struct TestContext * theContext = static_cast(inContext); + struct TestContext * const theContext = static_cast(inContext); + PacketBufferTest * const test = theContext->test; + NL_TEST_ASSERT(inSuite, test->mContext == theContext); - for (size_t ith = 0; ith < kTestElements; ith++) + for (auto & config : test->configurations) { - PacketBuffer * buffer = PrepareTestBuffer(theContext); - - NL_TEST_ASSERT(inSuite, buffer->DataLength() == theContext->buf->len); + test->PrepareTestBuffer(&config, kRecordHandle); - theContext++; + NL_TEST_ASSERT(inSuite, config.handle->DataLength() == config.handle->len); } } @@ -416,78 +506,68 @@ void PacketBufferTest::CheckDataLength(nlTestSuite * inSuite, void * inContext) */ void PacketBufferTest::CheckSetDataLength(nlTestSuite * inSuite, void * inContext) { - struct TestContext * theFirstContext = static_cast(inContext); + struct TestContext * const theContext = static_cast(inContext); + PacketBufferTest * const test = theContext->test; + NL_TEST_ASSERT(inSuite, test->mContext == theContext); - for (size_t ith = 0; ith < kTestElements; ith++) + for (auto & config_1 : test->configurations) { - struct TestContext * theSecondContext = static_cast(inContext); - - for (size_t jth = 0; jth < kTestElements; jth++) + for (auto & config_2 : test->configurations) { - for (uint16_t length : sLengths) + for (size_t i = 0; i < theContext->length_count; ++i) { - PacketBuffer * buffer_1 = PrepareTestBuffer(theFirstContext); - PacketBuffer * buffer_2 = PrepareTestBuffer(theSecondContext); + const uint16_t length = theContext->lengths[i]; + test->PrepareTestBuffer(&config_1, kRecordHandle | kAllowHandleReuse); + test->PrepareTestBuffer(&config_2, kRecordHandle | kAllowHandleReuse); - if (theFirstContext == theSecondContext) + if (&config_1 == &config_2) { // headOfChain (the second arg) is NULL - buffer_2->SetDataLength(length, nullptr); + config_2.handle->SetDataLength(length, nullptr); - if (length > (theSecondContext->end_buffer - theSecondContext->payload_ptr)) + if (length > (config_2.end_buffer - config_2.payload_ptr)) { - NL_TEST_ASSERT( - inSuite, theSecondContext->buf->len == (theSecondContext->end_buffer - theSecondContext->payload_ptr)); - NL_TEST_ASSERT(inSuite, - theSecondContext->buf->tot_len == - (theSecondContext->end_buffer - theSecondContext->payload_ptr)); - NL_TEST_ASSERT(inSuite, theSecondContext->buf->next == nullptr); + NL_TEST_ASSERT(inSuite, config_2.handle->len == (config_2.end_buffer - config_2.payload_ptr)); + NL_TEST_ASSERT(inSuite, config_2.handle->tot_len == (config_2.end_buffer - config_2.payload_ptr)); + NL_TEST_ASSERT(inSuite, config_2.handle->next == nullptr); } else { - NL_TEST_ASSERT(inSuite, theSecondContext->buf->len == length); - NL_TEST_ASSERT(inSuite, theSecondContext->buf->tot_len == length); - NL_TEST_ASSERT(inSuite, theSecondContext->buf->next == nullptr); + NL_TEST_ASSERT(inSuite, config_2.handle->len == length); + NL_TEST_ASSERT(inSuite, config_2.handle->tot_len == length); + NL_TEST_ASSERT(inSuite, config_2.handle->next == nullptr); } } else { - // headOfChain (the second arg) is buffer_1 - buffer_2->SetDataLength(length, buffer_1); + // headOfChain (the second arg) is config_1.handle + config_2.handle->SetDataLength(length, config_1.handle); - if (length > (theSecondContext->end_buffer - theSecondContext->payload_ptr)) + if (length > (config_2.end_buffer - config_2.payload_ptr)) { - NL_TEST_ASSERT( - inSuite, theSecondContext->buf->len == (theSecondContext->end_buffer - theSecondContext->payload_ptr)); - NL_TEST_ASSERT(inSuite, - theSecondContext->buf->tot_len == - (theSecondContext->end_buffer - theSecondContext->payload_ptr)); - NL_TEST_ASSERT(inSuite, theSecondContext->buf->next == nullptr); + NL_TEST_ASSERT(inSuite, config_2.handle->len == (config_2.end_buffer - config_2.payload_ptr)); + NL_TEST_ASSERT(inSuite, config_2.handle->tot_len == (config_2.end_buffer - config_2.payload_ptr)); + NL_TEST_ASSERT(inSuite, config_2.handle->next == nullptr); NL_TEST_ASSERT(inSuite, - theFirstContext->buf->tot_len == - (theFirstContext->init_len + - static_cast(theSecondContext->end_buffer - theSecondContext->payload_ptr) - - static_cast(theSecondContext->init_len))); + config_1.handle->tot_len == + (config_1.init_len + static_cast(config_2.end_buffer - config_2.payload_ptr) - + static_cast(config_2.init_len))); } else { - NL_TEST_ASSERT(inSuite, theSecondContext->buf->len == length); - NL_TEST_ASSERT(inSuite, theSecondContext->buf->tot_len == length); - NL_TEST_ASSERT(inSuite, theSecondContext->buf->next == nullptr); + NL_TEST_ASSERT(inSuite, config_2.handle->len == length); + NL_TEST_ASSERT(inSuite, config_2.handle->tot_len == length); + NL_TEST_ASSERT(inSuite, config_2.handle->next == nullptr); - NL_TEST_ASSERT(inSuite, - theFirstContext->buf->tot_len == - (theFirstContext->init_len + static_cast(length) - - static_cast(theSecondContext->init_len))); + NL_TEST_ASSERT( + inSuite, + config_1.handle->tot_len == + (config_1.init_len + static_cast(length) - static_cast(config_2.init_len))); } } } - - theSecondContext++; } - - theFirstContext++; } } @@ -496,15 +576,14 @@ void PacketBufferTest::CheckSetDataLength(nlTestSuite * inSuite, void * inContex */ void PacketBufferTest::CheckTotalLength(nlTestSuite * inSuite, void * inContext) { - struct TestContext * theContext = static_cast(inContext); + struct TestContext * const theContext = static_cast(inContext); + PacketBufferTest * const test = theContext->test; + NL_TEST_ASSERT(inSuite, test->mContext == theContext); - for (size_t ith = 0; ith < kTestElements; ith++) + for (auto & config : test->configurations) { - PacketBuffer * buffer = PrepareTestBuffer(theContext); - - NL_TEST_ASSERT(inSuite, buffer->TotalLength() == theContext->init_len); - - theContext++; + test->PrepareTestBuffer(&config, kRecordHandle); + NL_TEST_ASSERT(inSuite, config.handle->TotalLength() == config.init_len); } } @@ -513,15 +592,15 @@ void PacketBufferTest::CheckTotalLength(nlTestSuite * inSuite, void * inContext) */ void PacketBufferTest::CheckMaxDataLength(nlTestSuite * inSuite, void * inContext) { - struct TestContext * theContext = static_cast(inContext); + struct TestContext * const theContext = static_cast(inContext); + PacketBufferTest * const test = theContext->test; + NL_TEST_ASSERT(inSuite, test->mContext == theContext); - for (size_t ith = 0; ith < kTestElements; ith++) + for (auto & config : test->configurations) { - PacketBuffer * buffer = PrepareTestBuffer(theContext); + test->PrepareTestBuffer(&config, kRecordHandle); - NL_TEST_ASSERT(inSuite, buffer->MaxDataLength() == (theContext->end_buffer - theContext->payload_ptr)); - - theContext++; + NL_TEST_ASSERT(inSuite, config.handle->MaxDataLength() == (config.end_buffer - config.payload_ptr)); } } @@ -530,16 +609,16 @@ void PacketBufferTest::CheckMaxDataLength(nlTestSuite * inSuite, void * inContex */ void PacketBufferTest::CheckAvailableDataLength(nlTestSuite * inSuite, void * inContext) { - struct TestContext * theContext = static_cast(inContext); + struct TestContext * const theContext = static_cast(inContext); + PacketBufferTest * const test = theContext->test; + NL_TEST_ASSERT(inSuite, test->mContext == theContext); - for (size_t ith = 0; ith < kTestElements; ith++) + for (auto & config : test->configurations) { - PacketBuffer * buffer = PrepareTestBuffer(theContext); - - NL_TEST_ASSERT( - inSuite, buffer->AvailableDataLength() == ((theContext->end_buffer - theContext->payload_ptr) - theContext->init_len)); + test->PrepareTestBuffer(&config, kRecordHandle); - theContext++; + NL_TEST_ASSERT(inSuite, + config.handle->AvailableDataLength() == ((config.end_buffer - config.payload_ptr) - config.init_len)); } } @@ -548,23 +627,57 @@ void PacketBufferTest::CheckAvailableDataLength(nlTestSuite * inSuite, void * in */ void PacketBufferTest::CheckReservedSize(nlTestSuite * inSuite, void * inContext) { - struct TestContext * theContext = static_cast(inContext); + struct TestContext * const theContext = static_cast(inContext); + PacketBufferTest * const test = theContext->test; + NL_TEST_ASSERT(inSuite, test->mContext == theContext); - for (size_t ith = 0; ith < kTestElements; ith++) + for (auto & config : test->configurations) { - PacketBuffer & lBuffer = *PrepareTestBuffer(theContext); - const size_t kAllocSize = lBuffer.AllocSize(); + test->PrepareTestBuffer(&config, kRecordHandle); + const size_t kAllocSize = config.handle->AllocSize(); - if (theContext->reserved_size > kAllocSize) + if (config.reserved_size > kAllocSize) { - NL_TEST_ASSERT(inSuite, lBuffer.ReservedSize() == kAllocSize); + NL_TEST_ASSERT(inSuite, config.handle->ReservedSize() == kAllocSize); } else { - NL_TEST_ASSERT(inSuite, lBuffer.ReservedSize() == theContext->reserved_size); + NL_TEST_ASSERT(inSuite, config.handle->ReservedSize() == config.reserved_size); } + } +} + +/** + * Test PacketBuffer::HasChainedBuffer() function. + */ +void PacketBufferTest::CheckHasChainedBuffer(nlTestSuite * inSuite, void * inContext) +{ + struct TestContext * const theContext = static_cast(inContext); + PacketBufferTest * const test = theContext->test; + NL_TEST_ASSERT(inSuite, test->mContext == theContext); + + for (auto & config_1 : test->configurations) + { + for (auto & config_2 : test->configurations) + { + if (&config_1 == &config_2) + { + continue; + } + + test->PrepareTestBuffer(&config_1); + test->PrepareTestBuffer(&config_2); - theContext++; + NL_TEST_ASSERT(inSuite, config_1.handle->HasChainedBuffer() == false); + NL_TEST_ASSERT(inSuite, config_2.handle->HasChainedBuffer() == false); + + config_1.handle->AddToEnd(config_2.handle.Retain()); + NL_TEST_ASSERT(inSuite, config_1.handle->HasChainedBuffer() == true); + NL_TEST_ASSERT(inSuite, config_2.handle->HasChainedBuffer() == false); + + config_1.handle = nullptr; + config_2.handle = nullptr; + } } } @@ -581,107 +694,111 @@ void PacketBufferTest::CheckReservedSize(nlTestSuite * inSuite, void * inContext */ void PacketBufferTest::CheckAddToEnd(nlTestSuite * inSuite, void * inContext) { - struct TestContext * theFirstContext = static_cast(inContext); + struct TestContext * const theContext = static_cast(inContext); + PacketBufferTest * const test = theContext->test; + NL_TEST_ASSERT(inSuite, test->mContext == theContext); - for (size_t ith = 0; ith < kTestElements; ith++) + for (auto & config_1 : test->configurations) { - struct TestContext * theSecondContext = static_cast(inContext); - - for (size_t jth = 0; jth < kTestElements; jth++) + for (auto & config_2 : test->configurations) { - struct TestContext * theThirdContext = static_cast(inContext); - - for (size_t kth = 0; kth < kTestElements; kth++) + for (auto & config_3 : test->configurations) { - PacketBuffer * buffer_1 = nullptr; - PacketBuffer * buffer_2 = nullptr; - PacketBuffer * buffer_3 = nullptr; - - if (theFirstContext == theSecondContext || theFirstContext == theThirdContext || - theSecondContext == theThirdContext) + if (&config_1 == &config_2 || &config_1 == &config_3 || &config_2 == &config_3) { - theThirdContext++; continue; } - buffer_1 = PrepareTestBuffer(theFirstContext); - buffer_2 = PrepareTestBuffer(theSecondContext); - buffer_3 = PrepareTestBuffer(theThirdContext); - - buffer_1->AddToEnd_ForNow(buffer_2); - - NL_TEST_ASSERT(inSuite, theFirstContext->buf->tot_len == (theFirstContext->init_len + theSecondContext->init_len)); - NL_TEST_ASSERT(inSuite, theFirstContext->buf->next == theSecondContext->buf); - NL_TEST_ASSERT(inSuite, theSecondContext->buf->next == nullptr); - - NL_TEST_ASSERT(inSuite, theThirdContext->buf->next == nullptr); - - buffer_1->AddToEnd_ForNow(buffer_3); - - NL_TEST_ASSERT(inSuite, - theFirstContext->buf->tot_len == - (theFirstContext->init_len + theSecondContext->init_len + theThirdContext->init_len)); - NL_TEST_ASSERT(inSuite, theFirstContext->buf->next == theSecondContext->buf); - NL_TEST_ASSERT(inSuite, theSecondContext->buf->next == theThirdContext->buf); - NL_TEST_ASSERT(inSuite, theThirdContext->buf->next == nullptr); - - theThirdContext++; + test->PrepareTestBuffer(&config_1); + test->PrepareTestBuffer(&config_2); + test->PrepareTestBuffer(&config_3); + NL_TEST_ASSERT(inSuite, config_1.handle->ref == 1); + NL_TEST_ASSERT(inSuite, config_2.handle->ref == 1); + NL_TEST_ASSERT(inSuite, config_3.handle->ref == 1); + + config_1.handle->AddToEnd(config_2.handle.Retain()); + NL_TEST_ASSERT(inSuite, config_1.handle->ref == 1); // config_1.handle + NL_TEST_ASSERT(inSuite, config_2.handle->ref == 2); // config_2.handle and config_1.handle->next + NL_TEST_ASSERT(inSuite, config_3.handle->ref == 1); // config_3.handle + + NL_TEST_ASSERT(inSuite, config_1.handle->tot_len == (config_1.init_len + config_2.init_len)); + NL_TEST_ASSERT(inSuite, config_1.handle->next == config_2.handle.Get()); + NL_TEST_ASSERT(inSuite, config_2.handle->next == nullptr); + NL_TEST_ASSERT(inSuite, config_3.handle->next == nullptr); + + config_1.handle->AddToEnd(config_3.handle.Retain()); + NL_TEST_ASSERT(inSuite, config_1.handle->ref == 1); // config_1.handle + NL_TEST_ASSERT(inSuite, config_2.handle->ref == 2); // config_2.handle and config_1.handle->next + NL_TEST_ASSERT(inSuite, config_3.handle->ref == 2); // config_3.handle and config_2.handle->next + + NL_TEST_ASSERT(inSuite, config_1.handle->tot_len == (config_1.init_len + config_2.init_len + config_3.init_len)); + NL_TEST_ASSERT(inSuite, config_1.handle->next == config_2.handle.Get()); + NL_TEST_ASSERT(inSuite, config_2.handle->next == config_3.handle.Get()); + NL_TEST_ASSERT(inSuite, config_3.handle->next == nullptr); + + config_1.handle = nullptr; + config_2.handle = nullptr; + config_3.handle = nullptr; } - - theSecondContext++; } - - theFirstContext++; } } /** - * Test PacketBuffer::DetachTail() function. + * Test PacketBuffer::PopHead() function. * * Description: Take two initial configurations of PacketBuffer from * inContext and create two PacketBuffer instances based on those * configurations. Next, link those buffers together, with the first - * buffer instance pointing to the second one. Then, call DetachTail() + * buffer instance pointing to the second one. Then, call PopHead() * on the first buffer to unlink the second buffer. After the call, * verify correct internal state of the first buffer. */ -void PacketBufferTest::CheckDetachTail(nlTestSuite * inSuite, void * inContext) +void PacketBufferTest::CheckPopHead(nlTestSuite * inSuite, void * inContext) { - struct TestContext * theFirstContext = static_cast(inContext); + struct TestContext * const theContext = static_cast(inContext); + PacketBufferTest * const test = theContext->test; + NL_TEST_ASSERT(inSuite, test->mContext == theContext); - for (size_t ith = 0; ith < kTestElements; ith++) + // Single buffer test. + for (auto & config_1 : test->configurations) { - struct TestContext * theSecondContext = static_cast(inContext); + test->PrepareTestBuffer(&config_1, kRecordHandle | kAllowHandleReuse); + NL_TEST_ASSERT(inSuite, config_1.handle->ref == 2); - for (size_t jth = 0; jth < kTestElements; jth++) - { - PacketBuffer * buffer_1 = PrepareTestBuffer(theFirstContext); - PacketBuffer * buffer_2 = PrepareTestBuffer(theSecondContext); - PacketBuffer * returned = nullptr; - buffer_1->AddRef(); // The test still holds ownership via buffer_1. - PacketBufferHandle buffer_handle = PacketBufferHandle::Create(buffer_1); + const PacketBuffer * const buffer_1 = config_1.handle.mBuffer; + + const PacketBufferHandle popped = config_1.handle.PopHead(); - if (theFirstContext != theSecondContext) + NL_TEST_ASSERT(inSuite, config_1.handle.IsNull()); + NL_TEST_ASSERT(inSuite, popped.mBuffer == buffer_1); + NL_TEST_ASSERT(inSuite, popped->next == nullptr); + NL_TEST_ASSERT(inSuite, popped->tot_len == config_1.init_len); + NL_TEST_ASSERT(inSuite, popped->ref == 2); + } + test->ResetHandles(); + + // Chained buffers test. + for (auto & config_1 : test->configurations) + { + for (auto & config_2 : test->configurations) + { + if (&config_1 == &config_2) { - theFirstContext->buf->next = theSecondContext->buf; - theFirstContext->buf->tot_len = static_cast(theFirstContext->buf->tot_len + theSecondContext->init_len); + continue; } - PacketBufferHandle popped = buffer_handle.PopHead(); - returned = buffer_handle.Release_ForNow(); + test->PrepareTestBuffer(&config_1, kRecordHandle | kAllowHandleReuse); + test->PrepareTestBuffer(&config_2, kRecordHandle | kAllowHandleReuse); - NL_TEST_ASSERT(inSuite, theFirstContext->buf->next == nullptr); - NL_TEST_ASSERT(inSuite, theFirstContext->buf->tot_len == theFirstContext->init_len); + config_1.handle->AddToEnd(config_2.handle.Retain()); - if (theFirstContext != theSecondContext) - { - NL_TEST_ASSERT(inSuite, returned == buffer_2); - } + const PacketBufferHandle popped = config_1.handle.PopHead(); - theSecondContext++; + NL_TEST_ASSERT(inSuite, config_1.handle == config_2.handle); + NL_TEST_ASSERT(inSuite, config_1.handle->next == nullptr); + NL_TEST_ASSERT(inSuite, config_1.handle->tot_len == config_1.init_len); } - - theFirstContext++; } } @@ -698,75 +815,109 @@ void PacketBufferTest::CheckDetachTail(nlTestSuite * inSuite, void * inContext) */ void PacketBufferTest::CheckCompactHead(nlTestSuite * inSuite, void * inContext) { - struct TestContext * theFirstContext = static_cast(inContext); + struct TestContext * const theContext = static_cast(inContext); + PacketBufferTest * const test = theContext->test; + NL_TEST_ASSERT(inSuite, test->mContext == theContext); - for (size_t ith = 0; ith < kTestElements; ith++) + // Single buffer test. + for (auto & config : test->configurations) { - struct TestContext * theSecondContext = static_cast(inContext); + for (size_t i = 0; i < theContext->length_count; ++i) + { + const uint16_t length = theContext->lengths[i]; + + test->PrepareTestBuffer(&config, kRecordHandle | kAllowHandleReuse); + config.handle->SetDataLength(length, config.handle); + const uint16_t data_length = config.handle->DataLength(); + + config.handle->CompactHead(); + + NL_TEST_ASSERT(inSuite, config.handle->payload == (config.start_buffer + CHIP_SYSTEM_PACKETBUFFER_HEADER_SIZE)); + NL_TEST_ASSERT(inSuite, config.handle->tot_len == data_length); + } - for (size_t jth = 0; jth < kTestElements; jth++) + config.handle = nullptr; + } + NL_TEST_ASSERT(inSuite, test->ResetHandles()); + + // Chained buffers test. + for (auto & config_1 : test->configurations) + { + for (auto & config_2 : test->configurations) { + if (&config_1 == &config_2) + { + continue; + } + // start with various initial length for the first buffer - for (uint16_t firstLength : sLengths) + for (size_t i = 0; i < theContext->length_count; ++i) { + const uint16_t length_1 = theContext->lengths[i]; + // start with various initial length for the second buffer - for (uint16_t secondLength : sLengths) + for (size_t j = 0; j < theContext->length_count; ++j) { - PacketBuffer * buffer_1 = PrepareTestBuffer(theFirstContext); - PacketBuffer * buffer_2 = PrepareTestBuffer(theSecondContext); - uint16_t len1 = 0; - uint16_t len2 = 0; + const uint16_t length_2 = theContext->lengths[j]; - buffer_1->SetDataLength(firstLength, buffer_1); - len1 = buffer_1->DataLength(); + test->PrepareTestBuffer(&config_1, kRecordHandle | kAllowHandleReuse); + NL_TEST_ASSERT(inSuite, config_1.handle->ref == 2); - if (theFirstContext != theSecondContext) - { - theFirstContext->buf->next = theSecondContext->buf; + // CompactHead requires that there be no other references to the chained buffer, + // so we manage it manually. + test->PrepareTestBuffer(&config_2); + NL_TEST_ASSERT(inSuite, config_2.handle->ref == 1); + PacketBuffer * buffer_2 = config_2.handle.Release_ForNow(); + NL_TEST_ASSERT(inSuite, config_2.handle.IsNull()); - // Add various lengths to the second buffer - buffer_2->SetDataLength(secondLength, buffer_1); - len2 = buffer_2->DataLength(); - } + config_1.handle->SetDataLength(length_1, config_1.handle); + const uint16_t data_length_1 = config_1.handle->DataLength(); - buffer_1->CompactHead(); + // This chain will cause buffer_2 to be freed. + config_1.handle->next = buffer_2; + + // Add various lengths to the second buffer + buffer_2->SetDataLength(length_2, config_1.handle); + const uint16_t data_length_2 = buffer_2->DataLength(); + + config_1.handle->CompactHead(); NL_TEST_ASSERT(inSuite, - theFirstContext->buf->payload == - (theFirstContext->start_buffer + CHIP_SYSTEM_PACKETBUFFER_HEADER_SIZE)); + config_1.handle->payload == (config_1.start_buffer + CHIP_SYSTEM_PACKETBUFFER_HEADER_SIZE)); - /* verify length of the first buffer */ - if (theFirstContext == theSecondContext) + if (config_1.handle->tot_len > config_1.handle->MaxDataLength()) { - NL_TEST_ASSERT(inSuite, theFirstContext->buf->tot_len == len1); - } - else if (theFirstContext->buf->tot_len > buffer_1->MaxDataLength()) - { - NL_TEST_ASSERT(inSuite, theFirstContext->buf->len == buffer_1->MaxDataLength()); - NL_TEST_ASSERT(inSuite, - theSecondContext->buf->len == theFirstContext->buf->tot_len - buffer_1->MaxDataLength()); + NL_TEST_ASSERT(inSuite, config_1.handle->len == config_1.handle->MaxDataLength()); + NL_TEST_ASSERT(inSuite, buffer_2->len == config_1.handle->tot_len - config_1.handle->MaxDataLength()); + NL_TEST_ASSERT(inSuite, config_1.handle->next == buffer_2); + NL_TEST_ASSERT(inSuite, config_1.handle->ref == 2); + NL_TEST_ASSERT(inSuite, buffer_2->ref == 1); } else { - NL_TEST_ASSERT(inSuite, theFirstContext->buf->len == theFirstContext->buf->tot_len); - if (len1 >= buffer_1->MaxDataLength() && len2 == 0) + NL_TEST_ASSERT(inSuite, config_1.handle->len == config_1.handle->tot_len); + if (data_length_1 >= config_1.handle->MaxDataLength() && data_length_2 == 0) { /* make sure the second buffer is not freed */ - NL_TEST_ASSERT(inSuite, theFirstContext->buf->next == theSecondContext->buf); + NL_TEST_ASSERT(inSuite, config_1.handle->next == buffer_2); + NL_TEST_ASSERT(inSuite, buffer_2->ref == 1); } else { /* make sure the second buffer is freed */ - NL_TEST_ASSERT(inSuite, theFirstContext->buf->next == nullptr); - theSecondContext->buf = nullptr; + NL_TEST_ASSERT(inSuite, config_1.handle->next == nullptr); + buffer_2 = nullptr; } } + + NL_TEST_ASSERT(inSuite, config_1.handle->ref == 2); + config_1.handle = nullptr; + + // Verify and release handles. + NL_TEST_ASSERT(inSuite, test->ResetHandles()); } } - theSecondContext++; } - - theFirstContext++; } } @@ -782,36 +933,32 @@ void PacketBufferTest::CheckCompactHead(nlTestSuite * inSuite, void * inContext) */ void PacketBufferTest::CheckConsumeHead(nlTestSuite * inSuite, void * inContext) { - struct TestContext * theContext = static_cast(inContext); + struct TestContext * const theContext = static_cast(inContext); + PacketBufferTest * const test = theContext->test; + NL_TEST_ASSERT(inSuite, test->mContext == theContext); - for (size_t ith = 0; ith < kTestElements; ith++) + for (auto & config : test->configurations) { - for (uint16_t length : sLengths) + for (size_t i = 0; i < theContext->length_count; ++i) { - PacketBuffer * buffer = PrepareTestBuffer(theContext); + const uint16_t length = theContext->lengths[i]; + test->PrepareTestBuffer(&config, kRecordHandle | kAllowHandleReuse); - buffer->ConsumeHead(length); + config.handle->ConsumeHead(length); - if (length > theContext->init_len) + if (length > config.init_len) { - NL_TEST_ASSERT(inSuite, theContext->buf->payload == (theContext->payload_ptr + theContext->init_len)); - NL_TEST_ASSERT(inSuite, theContext->buf->len == 0); - NL_TEST_ASSERT(inSuite, theContext->buf->tot_len == 0); + NL_TEST_ASSERT(inSuite, config.handle->payload == (config.payload_ptr + config.init_len)); + NL_TEST_ASSERT(inSuite, config.handle->len == 0); + NL_TEST_ASSERT(inSuite, config.handle->tot_len == 0); } else { - NL_TEST_ASSERT(inSuite, theContext->buf->payload == (theContext->payload_ptr + length)); - NL_TEST_ASSERT(inSuite, theContext->buf->len == (theContext->buf->len - length)); - NL_TEST_ASSERT(inSuite, theContext->buf->tot_len == (theContext->buf->tot_len - length)); - } - - if (theContext->buf->ref == 0) - { - theContext->buf = nullptr; + NL_TEST_ASSERT(inSuite, config.handle->payload == (config.payload_ptr + length)); + NL_TEST_ASSERT(inSuite, config.handle->len == (config.handle->len - length)); + NL_TEST_ASSERT(inSuite, config.handle->tot_len == (config.handle->tot_len - length)); } } - - theContext++; } } @@ -829,79 +976,90 @@ void PacketBufferTest::CheckConsumeHead(nlTestSuite * inSuite, void * inContext) */ void PacketBufferTest::CheckConsume(nlTestSuite * inSuite, void * inContext) { - struct TestContext * theFirstContext = static_cast(inContext); + struct TestContext * const theContext = static_cast(inContext); + PacketBufferTest * const test = theContext->test; + NL_TEST_ASSERT(inSuite, test->mContext == theContext); - for (size_t ith = 0; ith < kTestElements; ith++) + for (auto & config_1 : test->configurations) { - struct TestContext * theSecondContext = static_cast(inContext); - - for (size_t jth = 0; jth < kTestElements; jth++) + for (auto & config_2 : test->configurations) { + if (&config_1 == &config_2) + { + continue; + } + // consume various amounts of memory - for (uint16_t consumeLength : sLengths) + for (size_t i = 0; i < theContext->length_count; ++i) { + const uint16_t consumeLength = theContext->lengths[i]; // start with various initial length for the first buffer - for (uint16_t firstLength : sLengths) + for (size_t j = 0; j < theContext->length_count; ++j) { + const uint16_t len_1 = theContext->lengths[j]; // start with various initial length for the second buffer - for (uint16_t secondLength : sLengths) + for (size_t k = 0; k < theContext->length_count; ++k) { - PacketBuffer * buffer_1; - PacketBuffer * buffer_2; - PacketBuffer * returned; - uint16_t buf_1_len = 0; - uint16_t buf_2_len = 0; - - if (theFirstContext == theSecondContext) - { - continue; - } + const uint16_t len_2 = theContext->lengths[k]; - buffer_1 = PrepareTestBuffer(theFirstContext); - buffer_2 = PrepareTestBuffer(theSecondContext); + test->PrepareTestBuffer(&config_1); + test->PrepareTestBuffer(&config_2); + NL_TEST_ASSERT(inSuite, config_1.handle->ref == 1); + NL_TEST_ASSERT(inSuite, config_2.handle->ref == 1); - theFirstContext->buf->next = theSecondContext->buf; + config_1.handle->AddToEnd(config_2.handle.Retain()); // Add various lengths to buffers - buffer_1->SetDataLength(firstLength, buffer_1); - buffer_2->SetDataLength(secondLength, buffer_1); + config_1.handle->SetDataLength(len_1, config_1.handle); + config_2.handle->SetDataLength(len_2, config_1.handle); + + const uint16_t buf_1_len = config_1.handle->len; + const uint16_t buf_2_len = config_2.handle->len; - buf_1_len = theFirstContext->buf->len; - buf_2_len = theSecondContext->buf->len; + PacketBufferHandle original_handle_1 = config_1.handle.Retain(); + NL_TEST_ASSERT(inSuite, config_1.handle->ref == 2); // config_1.handle and original_handle_1 + NL_TEST_ASSERT(inSuite, config_2.handle->ref == 2); // config_2.handle and config_1.handle->next - returned = buffer_1->Consume(consumeLength); + config_1.handle.Consume(consumeLength); if (consumeLength == 0) { - NL_TEST_ASSERT(inSuite, returned == buffer_1); - continue; + NL_TEST_ASSERT(inSuite, config_1.handle == original_handle_1); + NL_TEST_ASSERT(inSuite, config_1.handle->len == buf_1_len); + NL_TEST_ASSERT(inSuite, config_2.handle->len == buf_2_len); + NL_TEST_ASSERT(inSuite, config_1.handle->ref == 2); // config_1.handle and original_handle_1 + NL_TEST_ASSERT(inSuite, config_2.handle->ref == 2); // config_2.handle and config_1.handle->next } - - if (consumeLength < buf_1_len) + else if (consumeLength < buf_1_len) { - NL_TEST_ASSERT(inSuite, returned == buffer_1); + NL_TEST_ASSERT(inSuite, config_1.handle == original_handle_1); + NL_TEST_ASSERT(inSuite, config_1.handle->len == buf_1_len - consumeLength); + NL_TEST_ASSERT(inSuite, config_2.handle->len == buf_2_len); + NL_TEST_ASSERT(inSuite, config_1.handle->ref == 2); // config_1.handle and original_handle_1 + NL_TEST_ASSERT(inSuite, config_2.handle->ref == 2); // config_2.handle and config_1.handle->next } - else if ((consumeLength >= buf_1_len) && - (consumeLength < buf_1_len + buf_2_len || + else if ((consumeLength < buf_1_len + buf_2_len || (consumeLength == buf_1_len + buf_2_len && buf_2_len == 0))) { - NL_TEST_ASSERT(inSuite, returned == buffer_2); - theFirstContext->buf = nullptr; + NL_TEST_ASSERT(inSuite, config_1.handle == config_2.handle); + NL_TEST_ASSERT(inSuite, config_2.handle->len == buf_1_len + buf_2_len - consumeLength); + NL_TEST_ASSERT(inSuite, original_handle_1->ref == 1); // original_handle_1 + NL_TEST_ASSERT(inSuite, config_2.handle->ref == 2); // config_1.handle and config_2.handle } - else if (consumeLength >= (buf_1_len + buf_2_len)) + else { - NL_TEST_ASSERT(inSuite, returned == nullptr); - theFirstContext->buf = nullptr; - theSecondContext->buf = nullptr; + NL_TEST_ASSERT(inSuite, config_1.handle.IsNull()); + NL_TEST_ASSERT(inSuite, original_handle_1->ref == 1); // original_handle_1 + NL_TEST_ASSERT(inSuite, config_2.handle->ref == 1); // config_2.handle } + + original_handle_1 = nullptr; + config_1.handle = nullptr; + config_2.handle = nullptr; } } } - - theSecondContext++; } - - theFirstContext++; } } @@ -916,38 +1074,40 @@ void PacketBufferTest::CheckConsume(nlTestSuite * inSuite, void * inContext) */ void PacketBufferTest::CheckEnsureReservedSize(nlTestSuite * inSuite, void * inContext) { - struct TestContext * theContext = static_cast(inContext); + struct TestContext * const theContext = static_cast(inContext); + PacketBufferTest * const test = theContext->test; + NL_TEST_ASSERT(inSuite, test->mContext == theContext); - for (size_t ith = 0; ith < kTestElements; ith++) + for (auto & config : test->configurations) { - for (uint16_t length : sLengths) + for (size_t i = 0; i < theContext->length_count; ++i) { - PacketBuffer & lBuffer = *PrepareTestBuffer(theContext); - const uint16_t kAllocSize = lBuffer.AllocSize(); - uint16_t reserved_size = theContext->reserved_size; + const uint16_t length = theContext->lengths[i]; - if (CHIP_SYSTEM_PACKETBUFFER_HEADER_SIZE + theContext->reserved_size > kAllocSize) + test->PrepareTestBuffer(&config, kRecordHandle | kAllowHandleReuse); + const uint16_t kAllocSize = config.handle->AllocSize(); + uint16_t reserved_size = config.reserved_size; + + if (CHIP_SYSTEM_PACKETBUFFER_HEADER_SIZE + config.reserved_size > kAllocSize) { reserved_size = static_cast(kAllocSize - CHIP_SYSTEM_PACKETBUFFER_HEADER_SIZE); } if (length <= reserved_size) { - NL_TEST_ASSERT(inSuite, lBuffer.EnsureReservedSize(length) == true); + NL_TEST_ASSERT(inSuite, config.handle->EnsureReservedSize(length) == true); continue; } - if ((length + theContext->init_len) > (kAllocSize - CHIP_SYSTEM_PACKETBUFFER_HEADER_SIZE)) + if ((length + config.init_len) > (kAllocSize - CHIP_SYSTEM_PACKETBUFFER_HEADER_SIZE)) { - NL_TEST_ASSERT(inSuite, lBuffer.EnsureReservedSize(length) == false); + NL_TEST_ASSERT(inSuite, config.handle->EnsureReservedSize(length) == false); continue; } - NL_TEST_ASSERT(inSuite, lBuffer.EnsureReservedSize(length) == true); - NL_TEST_ASSERT(inSuite, theContext->buf->payload == (theContext->payload_ptr + length - reserved_size)); + NL_TEST_ASSERT(inSuite, config.handle->EnsureReservedSize(length) == true); + NL_TEST_ASSERT(inSuite, config.handle->payload == (config.payload_ptr + length - reserved_size)); } - - theContext++; } } @@ -962,44 +1122,45 @@ void PacketBufferTest::CheckEnsureReservedSize(nlTestSuite * inSuite, void * inC */ void PacketBufferTest::CheckAlignPayload(nlTestSuite * inSuite, void * inContext) { - struct TestContext * theContext = static_cast(inContext); + struct TestContext * const theContext = static_cast(inContext); + PacketBufferTest * const test = theContext->test; + NL_TEST_ASSERT(inSuite, test->mContext == theContext); - for (size_t ith = 0; ith < kTestElements; ith++) + for (auto & config : test->configurations) { - for (size_t n = 0; n < kTestLengths - 1; n++) + for (size_t n = 0; n < theContext->length_count; ++n) { - PacketBuffer & lBuffer = *PrepareTestBuffer(theContext); - const uint16_t kAllocSize = lBuffer.AllocSize(); + test->PrepareTestBuffer(&config, kRecordHandle | kAllowHandleReuse); + const uint16_t kAllocSize = config.handle->AllocSize(); - if (sLengths[n] == 0) + if (theContext->lengths[n] == 0) { - NL_TEST_ASSERT(inSuite, lBuffer.AlignPayload(sLengths[n]) == false); + NL_TEST_ASSERT(inSuite, config.handle->AlignPayload(theContext->lengths[n]) == false); continue; } - uint16_t reserved_size = theContext->reserved_size; - if (theContext->reserved_size > kAllocSize) + uint16_t reserved_size = config.reserved_size; + if (config.reserved_size > kAllocSize) { reserved_size = kAllocSize; } - uint16_t payload_offset = static_cast(reinterpret_cast(lBuffer.Start()) % sLengths[n]); - uint16_t payload_shift = 0; + const uint16_t payload_offset = + static_cast(reinterpret_cast(config.handle->Start()) % theContext->lengths[n]); + uint16_t payload_shift = 0; if (payload_offset > 0) - payload_shift = static_cast(sLengths[n] - payload_offset); + payload_shift = static_cast(theContext->lengths[n] - payload_offset); if (payload_shift <= kAllocSize - reserved_size) { - NL_TEST_ASSERT(inSuite, lBuffer.AlignPayload(sLengths[n]) == true); - NL_TEST_ASSERT(inSuite, ((unsigned long) lBuffer.Start() % sLengths[n]) == 0); + NL_TEST_ASSERT(inSuite, config.handle->AlignPayload(theContext->lengths[n]) == true); + NL_TEST_ASSERT(inSuite, ((unsigned long) config.handle->Start() % theContext->lengths[n]) == 0); } else { - NL_TEST_ASSERT(inSuite, lBuffer.AlignPayload(sLengths[n]) == false); + NL_TEST_ASSERT(inSuite, config.handle->AlignPayload(theContext->lengths[n]) == false); } } - - theContext++; } } @@ -1008,112 +1169,100 @@ void PacketBufferTest::CheckAlignPayload(nlTestSuite * inSuite, void * inContext */ void PacketBufferTest::CheckNext(nlTestSuite * inSuite, void * inContext) { - struct TestContext * theFirstContext = static_cast(inContext); + struct TestContext * const theContext = static_cast(inContext); + PacketBufferTest * const test = theContext->test; + NL_TEST_ASSERT(inSuite, test->mContext == theContext); - for (size_t ith = 0; ith < kTestElements; ith++) + for (auto & config_1 : test->configurations) { - struct TestContext * theSecondContext = static_cast(inContext); - - for (size_t jth = 0; jth < kTestElements; jth++) + for (auto & config_2 : test->configurations) { - PacketBuffer * buffer_1 = PrepareTestBuffer(theFirstContext); - PacketBuffer * buffer_2 = PrepareTestBuffer(theSecondContext); + test->PrepareTestBuffer(&config_1, kRecordHandle | kAllowHandleReuse); + test->PrepareTestBuffer(&config_2, kRecordHandle | kAllowHandleReuse); - if (theFirstContext != theSecondContext) + if (&config_1 != &config_2) { - theFirstContext->buf->next = theSecondContext->buf; + NL_TEST_ASSERT(inSuite, config_1.handle->Next().IsNull()); + + config_1.handle->AddToEnd(config_2.handle.Retain()); - NL_TEST_ASSERT(inSuite, buffer_1->Next_ForNow() == buffer_2); + NL_TEST_ASSERT(inSuite, config_1.handle->Next() == config_2.handle); + NL_TEST_ASSERT(inSuite, config_1.handle->ChainedBuffer() == config_2.handle.Get()); } else { - NL_TEST_ASSERT(inSuite, !buffer_1->HasChainedBuffer()); + NL_TEST_ASSERT(inSuite, !config_1.handle->HasChainedBuffer()); } - NL_TEST_ASSERT(inSuite, !buffer_2->HasChainedBuffer()); - theSecondContext++; + NL_TEST_ASSERT(inSuite, !config_2.handle->HasChainedBuffer()); } - - theFirstContext++; } } /** - * Test PacketBuffer::AddRef() function. + * Test PacketBuffer::Last() function. */ -void PacketBufferTest::CheckAddRef(nlTestSuite * inSuite, void * inContext) +void PacketBufferTest::CheckLast(nlTestSuite * inSuite, void * inContext) { - struct TestContext * theContext = static_cast(inContext); + struct TestContext * const theContext = static_cast(inContext); + PacketBufferTest * const test = theContext->test; + NL_TEST_ASSERT(inSuite, test->mContext == theContext); - for (size_t ith = 0; ith < kTestElements; ith++) + for (auto & config_1 : test->configurations) { - PacketBuffer * buffer = PrepareTestBuffer(theContext); - buffer->AddRef(); - - NL_TEST_ASSERT(inSuite, theContext->buf->ref == 2); - - theContext++; - } -} + for (auto & config_2 : test->configurations) + { + for (auto & config_3 : test->configurations) + { + if (&config_1 == &config_2 || &config_1 == &config_3 || &config_2 == &config_3) + { + continue; + } -/** - * Test PacketBuffer::NewWithAvailableSize() and PacketBuffer::Free() functions. - * - * Description: For every buffer-configuration from inContext, create a - * buffer's instance using NewWithAvailableSize() method. Then, verify that - * when the size of the reserved space passed to NewWithAvailableSize() is - * greater than #CHIP_SYSTEM_CONFIG_PACKETBUFFER_CAPACITY_MAX, the method - * returns NULL. Otherwise, check for correctness of initializing - * the new buffer's internal state. Finally, free the buffer. - */ -void PacketBufferTest::CheckNewWithAvailableSizeAndFree(nlTestSuite * inSuite, void * inContext) -{ - struct TestContext * theContext = static_cast(inContext); - PacketBufferHandle buffer; + test->PrepareTestBuffer(&config_1); + test->PrepareTestBuffer(&config_2); + test->PrepareTestBuffer(&config_3); - for (size_t ith = 0; ith < kTestElements; ith++) - { - struct pbuf * pb = nullptr; + NL_TEST_ASSERT(inSuite, config_1.handle->Last() == config_1.handle); + NL_TEST_ASSERT(inSuite, config_2.handle->Last() == config_2.handle); + NL_TEST_ASSERT(inSuite, config_3.handle->Last() == config_3.handle); - buffer = PacketBuffer::NewWithAvailableSize(theContext->reserved_size, 0); + config_1.handle->AddToEnd(config_2.handle.Retain()); - if (theContext->reserved_size > CHIP_SYSTEM_CONFIG_PACKETBUFFER_CAPACITY_MAX) - { - NL_TEST_ASSERT(inSuite, buffer.IsNull()); - theContext++; - continue; - } + NL_TEST_ASSERT(inSuite, config_1.handle->Last() == config_2.handle); + NL_TEST_ASSERT(inSuite, config_2.handle->Last() == config_2.handle); + NL_TEST_ASSERT(inSuite, config_3.handle->Last() == config_3.handle); - NL_TEST_ASSERT(inSuite, theContext->reserved_size <= buffer->AllocSize()); - NL_TEST_ASSERT(inSuite, !buffer.IsNull()); + config_1.handle->AddToEnd(config_3.handle.Retain()); - if (!buffer.IsNull()) - { - pb = TO_LWIP_PBUF(buffer.Get()); + NL_TEST_ASSERT(inSuite, config_1.handle->Last() == config_3.handle); + NL_TEST_ASSERT(inSuite, config_2.handle->Last() == config_3.handle); + NL_TEST_ASSERT(inSuite, config_3.handle->Last() == config_3.handle); - NL_TEST_ASSERT(inSuite, pb->len == 0); - NL_TEST_ASSERT(inSuite, pb->tot_len == 0); - NL_TEST_ASSERT(inSuite, pb->next == nullptr); - NL_TEST_ASSERT(inSuite, pb->ref == 1); + config_1.handle = nullptr; + config_2.handle = nullptr; + config_3.handle = nullptr; + } } - - theContext++; } +} - // Use the rest of the buffer space - for (;;) +/** + * Test PacketBuffer::AddRef() function. + */ +void PacketBufferTest::CheckAddRef(nlTestSuite * inSuite, void * inContext) +{ + struct TestContext * const theContext = static_cast(inContext); + PacketBufferTest * const test = theContext->test; + NL_TEST_ASSERT(inSuite, test->mContext == theContext); + + for (auto & config : test->configurations) { - buffer = PacketBuffer::NewWithAvailableSize(0, 0); - if (buffer.IsNull()) - { - break; - } - // Leak the buffer on purpose, to use up all the buffer space. - // (Compilers other than GCC recognize the `(void)` idiom, which is mandated in C++20.) -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wunused-result" - (void) buffer.Release_ForNow(); -#pragma GCC diagnostic pop + test->PrepareTestBuffer(&config, kRecordHandle); + const auto refs = config.handle->ref; + config.handle->AddRef(); + NL_TEST_ASSERT(inSuite, config.handle->ref == refs + 1); + config.handle->ref = refs; // Don't leak buffers. } } @@ -1130,69 +1279,88 @@ void PacketBufferTest::CheckNewWithAvailableSizeAndFree(nlTestSuite * inSuite, v */ void PacketBufferTest::CheckFree(nlTestSuite * inSuite, void * inContext) { - struct TestContext * theFirstContext = static_cast(inContext); + struct TestContext * const theContext = static_cast(inContext); + PacketBufferTest * const test = theContext->test; + NL_TEST_ASSERT(inSuite, test->mContext == theContext); - for (size_t ith = 0; ith < kTestElements; ith++) - { - struct TestContext * theSecondContext = static_cast(inContext); + const decltype(PacketBuffer::ref) init_ref_count[] = { 1, 2, 3 }; + constexpr size_t kRefs = sizeof(init_ref_count) / sizeof(init_ref_count[0]); - for (size_t jth = 0; jth < kTestElements; jth++) + for (auto & config_1 : test->configurations) + { + for (auto & config_2 : test->configurations) { - const uint8_t init_ref_count[] = { 1, 2, 3 }; - const int refs = sizeof(init_ref_count) / sizeof(uint16_t); + if (&config_1 == &config_2) + { + continue; + } // start with various buffer ref counts - for (size_t r = 0; r < refs; r++) + for (size_t r = 0; r < kRefs; r++) { - PacketBuffer * buffer_1; - - if (theFirstContext == theSecondContext) + config_1.handle = PacketBuffer::New(0); + config_2.handle = PacketBuffer::New(0); + NL_TEST_ASSERT(inSuite, !config_1.handle.IsNull()); + NL_TEST_ASSERT(inSuite, !config_2.handle.IsNull()); + + test->PrepareTestBuffer(&config_1, kAllowHandleReuse); + test->PrepareTestBuffer(&config_2, kAllowHandleReuse); + NL_TEST_ASSERT(inSuite, config_1.handle->ref == 1); + NL_TEST_ASSERT(inSuite, config_2.handle->ref == 1); + + // Chain buffers. + config_1.handle->next = config_2.handle.Get(); + + // Add various buffer ref counts. + const auto initial_refs_1 = config_1.handle->ref = init_ref_count[r]; + const auto initial_refs_2 = config_2.handle->ref = init_ref_count[(r + 1) % kRefs]; + + // Free head. + PacketBuffer::Free(config_1.handle.mBuffer); + if (initial_refs_1 == 1) { - continue; + config_1.handle.mBuffer = nullptr; } - buffer_1 = PrepareTestBuffer(theFirstContext); - (void) PrepareTestBuffer(theSecondContext); - - theFirstContext->buf->next = theSecondContext->buf; - - // Add various buffer ref counts - theFirstContext->buf->ref = init_ref_count[r]; - theSecondContext->buf->ref = init_ref_count[(r + 1) % refs]; - - PacketBuffer::Free(buffer_1); - - NL_TEST_ASSERT(inSuite, theFirstContext->buf->ref == (init_ref_count[r] - 1)); - - if (init_ref_count[r] == 1) + // Verification. + if (initial_refs_1 > 1) { - NL_TEST_ASSERT(inSuite, theSecondContext->buf->ref == (init_ref_count[(r + 1) % refs] - 1)); + // Verify that head ref count is decremented. + NL_TEST_ASSERT(inSuite, config_1.handle->ref == initial_refs_1 - 1); + // Verify that chain is maintained. + NL_TEST_ASSERT(inSuite, config_1.handle->next == config_2.handle.Get()); + // Verify that chained buffer ref count has not changed. + NL_TEST_ASSERT(inSuite, config_2.handle->ref == initial_refs_2); } else { - NL_TEST_ASSERT(inSuite, theSecondContext->buf->ref == (init_ref_count[(r + 1) % refs])); - } - - if (init_ref_count[r] > 1) - { - NL_TEST_ASSERT(inSuite, theFirstContext->buf->next == theSecondContext->buf); + if (initial_refs_2 > 1) + { + // Verify that chained buffer ref count is decremented. + NL_TEST_ASSERT(inSuite, config_2.handle->ref == initial_refs_2 - 1); + } + else + { + // Since the test used fake ref counts, config_2.handle now points + // to a freed buffer; clear the handle's internal pointer. + config_2.handle.mBuffer = nullptr; + } } - if (theFirstContext->buf->ref == 0) + // Clean up. + if (!config_1.handle.IsNull()) { - theFirstContext->buf = nullptr; + config_1.handle->next = nullptr; + config_1.handle->ref = 1; + config_1.handle = nullptr; } - - if (theSecondContext->buf->ref == 0) + if (!config_2.handle.IsNull()) { - theSecondContext->buf = nullptr; + config_2.handle->ref = 1; + config_2.handle = nullptr; } } - - theSecondContext++; } - - theFirstContext++; } } @@ -1207,133 +1375,323 @@ void PacketBufferTest::CheckFree(nlTestSuite * inSuite, void * inContext) */ void PacketBufferTest::CheckFreeHead(nlTestSuite * inSuite, void * inContext) { - struct TestContext * theFirstContext = static_cast(inContext); + struct TestContext * const theContext = static_cast(inContext); + PacketBufferTest * const test = theContext->test; + NL_TEST_ASSERT(inSuite, test->mContext == theContext); - for (size_t ith = 0; ith < kTestElements; ith++) + for (auto & config_1 : test->configurations) { - struct TestContext * theSecondContext = static_cast(inContext); - - for (size_t jth = 0; jth < kTestElements; jth++) + for (auto & config_2 : test->configurations) { - PacketBuffer * buffer_1; - PacketBuffer * buffer_2; - PacketBuffer * returned = nullptr; - - if (theFirstContext == theSecondContext) + if (&config_1 == &config_2) { continue; } - buffer_1 = PrepareTestBuffer(theFirstContext); - buffer_2 = PrepareTestBuffer(theSecondContext); + // Test PacketBuffer::FreeHead - theFirstContext->buf->next = theSecondContext->buf; + test->PrepareTestBuffer(&config_1, kAllowHandleReuse); + test->PrepareTestBuffer(&config_2, kAllowHandleReuse); + NL_TEST_ASSERT(inSuite, config_1.handle->ref == 1); + NL_TEST_ASSERT(inSuite, config_2.handle->ref == 1); - returned = PacketBuffer::FreeHead(buffer_1); + PacketBufferHandle handle_1 = config_1.handle.Retain(); + config_1.handle->AddToEnd(config_2.handle.Retain()); + NL_TEST_ASSERT(inSuite, config_1.handle->ref == 2); + NL_TEST_ASSERT(inSuite, config_2.handle->ref == 2); // config_2.handle and config_1.handle->next - NL_TEST_ASSERT(inSuite, returned == buffer_2); + PacketBuffer * const returned = PacketBuffer::FreeHead(config_1.handle.Release_ForNow()); - theFirstContext->buf = nullptr; - theSecondContext++; - } + NL_TEST_ASSERT(inSuite, handle_1->ref == 1); + NL_TEST_ASSERT(inSuite, config_2.handle->ref == 2); // config_2.handle and returned + NL_TEST_ASSERT(inSuite, returned == config_2.handle.Get()); + + config_1.handle = nullptr; + NL_TEST_ASSERT(inSuite, config_2.handle->ref == 2); + config_2.handle = nullptr; + NL_TEST_ASSERT(inSuite, returned->ref == 1); + PacketBuffer::Free(returned); + + // Test PacketBufferHandle::FreeHead + + test->PrepareTestBuffer(&config_1, kAllowHandleReuse); + test->PrepareTestBuffer(&config_2, kAllowHandleReuse); + NL_TEST_ASSERT(inSuite, config_1.handle->ref == 1); + NL_TEST_ASSERT(inSuite, config_2.handle->ref == 1); + + handle_1 = config_1.handle.Retain(); + config_1.handle->AddToEnd(config_2.handle.Retain()); + NL_TEST_ASSERT(inSuite, config_1.handle->ref == 2); + NL_TEST_ASSERT(inSuite, config_2.handle->ref == 2); // config_2.handle and config_1.handle->next + + PacketBuffer * const buffer_1 = config_1.handle.Get(); - theFirstContext++; + config_1.handle.FreeHead(); + + NL_TEST_ASSERT(inSuite, buffer_1->ref == 1); + NL_TEST_ASSERT(inSuite, config_1.handle == config_2.handle); + NL_TEST_ASSERT(inSuite, config_2.handle->ref == 2); // config_2.handle and config_1.handle + + config_1.handle = nullptr; + config_2.handle = nullptr; + } } } -/** - * Test PacketBuffer::BuildFreeList() function. - */ -void PacketBufferTest::CheckBuildFreeList(nlTestSuite * inSuite, void * inContext) +void PacketBufferTest::CheckHandleConstruct(nlTestSuite * inSuite, void * inContext) { - // BuildFreeList() is a private method called automatically. - (void) inSuite; - (void) inContext; + struct TestContext * const theContext = static_cast(inContext); + PacketBufferTest * const test = theContext->test; + NL_TEST_ASSERT(inSuite, test->mContext == theContext); + + PacketBufferHandle handle_1; + NL_TEST_ASSERT(inSuite, handle_1.IsNull()); + + PacketBufferHandle handle_2(nullptr); + NL_TEST_ASSERT(inSuite, handle_2.IsNull()); + + PacketBufferHandle handle_3(PacketBuffer::New()); + NL_TEST_ASSERT(inSuite, !handle_3.IsNull()); + + // Private constructor. + PacketBuffer * const buffer_3 = handle_3.Release_ForNow(); + PacketBufferHandle handle_4(buffer_3); + NL_TEST_ASSERT(inSuite, handle_4.Get() == buffer_3); } -/** - * Test Suite. It lists all the test functions. - */ -// clang-format off -const nlTest sTests[] = +void PacketBufferTest::CheckHandleMove(nlTestSuite * inSuite, void * inContext) { - NL_TEST_DEF("PacketBuffer::NewWithAvailableSize&PacketBuffer::Free", CheckNewWithAvailableSizeAndFree), - NL_TEST_DEF("PacketBuffer::Start", CheckStart), - NL_TEST_DEF("PacketBuffer::SetStart", CheckSetStart), - NL_TEST_DEF("PacketBuffer::DataLength", CheckDataLength), - NL_TEST_DEF("PacketBuffer::SetDataLength", CheckSetDataLength), - NL_TEST_DEF("PacketBuffer::TotalLength", CheckTotalLength), - NL_TEST_DEF("PacketBuffer::MaxDataLength", CheckMaxDataLength), - NL_TEST_DEF("PacketBuffer::AvailableDataLength", CheckAvailableDataLength), - NL_TEST_DEF("PacketBuffer::ReservedSize", CheckReservedSize), - NL_TEST_DEF("PacketBuffer::AddToEnd", CheckAddToEnd), - NL_TEST_DEF("PacketBuffer::DetachTail", CheckDetachTail), - NL_TEST_DEF("PacketBuffer::CompactHead", CheckCompactHead), - NL_TEST_DEF("PacketBuffer::ConsumeHead", CheckConsumeHead), - NL_TEST_DEF("PacketBuffer::Consume", CheckConsume), - NL_TEST_DEF("PacketBuffer::EnsureReservedSize", CheckEnsureReservedSize), - NL_TEST_DEF("PacketBuffer::AlignPayload", CheckAlignPayload), - NL_TEST_DEF("PacketBuffer::Next", CheckNext), - NL_TEST_DEF("PacketBuffer::AddRef", CheckAddRef), - NL_TEST_DEF("PacketBuffer::Free", CheckFree), - NL_TEST_DEF("PacketBuffer::FreeHead", CheckFreeHead), - NL_TEST_DEF("PacketBuffer::BuildFreeList", CheckBuildFreeList), + struct TestContext * const theContext = static_cast(inContext); + PacketBufferTest * const test = theContext->test; + NL_TEST_ASSERT(inSuite, test->mContext == theContext); - NL_TEST_SENTINEL() -}; -// clang-format on + for (auto & config_1 : test->configurations) + { + for (auto & config_2 : test->configurations) + { + if (&config_1 == &config_2) + { + continue; + } -/** - * Set up the test suite. - * - * This is a work-around to initiate PacketBuffer protected class instance's data and set it to a known state, before an instance - * is created. - */ -int TestSetup(void * inContext) + test->PrepareTestBuffer(&config_1, kRecordHandle); + test->PrepareTestBuffer(&config_2, kRecordHandle); + + const PacketBuffer * const buffer_1 = config_1.handle.Get(); + const PacketBuffer * const buffer_2 = config_2.handle.Get(); + NL_TEST_ASSERT(inSuite, buffer_1 != buffer_2); + NL_TEST_ASSERT(inSuite, buffer_1->ref == 2); // test.handles and config_1.handle + NL_TEST_ASSERT(inSuite, buffer_2->ref == 2); // test.handles and config_2.handle + + config_1.handle = std::move(config_2.handle); + NL_TEST_ASSERT(inSuite, config_1.handle.Get() == buffer_2); + NL_TEST_ASSERT(inSuite, config_2.handle.Get() == nullptr); + NL_TEST_ASSERT(inSuite, buffer_1->ref == 1); // test.handles + NL_TEST_ASSERT(inSuite, buffer_2->ref == 2); // test.handles and config_1.handle + + config_1.handle = nullptr; + } + // Verify and release handles. + NL_TEST_ASSERT(inSuite, test->ResetHandles()); + } +} + +void PacketBufferTest::CheckHandleFree(nlTestSuite * inSuite, void * inContext) +{ + struct TestContext * const theContext = static_cast(inContext); + PacketBufferTest * const test = theContext->test; + NL_TEST_ASSERT(inSuite, test->mContext == theContext); + + for (auto & config_1 : test->configurations) + { + test->PrepareTestBuffer(&config_1, kRecordHandle); + + const PacketBuffer * const buffer_1 = config_1.handle.Get(); + NL_TEST_ASSERT(inSuite, buffer_1->ref == 2); // test.handles and config_1.handle + + config_1.handle = nullptr; + NL_TEST_ASSERT(inSuite, config_1.handle.IsNull()); + NL_TEST_ASSERT(inSuite, config_1.handle.Get() == nullptr); + NL_TEST_ASSERT(inSuite, buffer_1->ref == 1); // test.handles only + } +} + +void PacketBufferTest::CheckHandleRetain(nlTestSuite * inSuite, void * inContext) { - struct TestContext * theContext = reinterpret_cast(inContext); + struct TestContext * const theContext = static_cast(inContext); + PacketBufferTest * const test = theContext->test; + NL_TEST_ASSERT(inSuite, test->mContext == theContext); - for (size_t ith = 0; ith < kTestElements; ith++) + for (auto & config_1 : test->configurations) { - BufferAlloc(theContext); - theContext++; + test->PrepareTestBuffer(&config_1, kRecordHandle); + + NL_TEST_ASSERT(inSuite, config_1.handle->ref == 2); // test.handles and config_1.handle + + PacketBufferHandle handle_1 = config_1.handle.Retain(); + + NL_TEST_ASSERT(inSuite, config_1.handle == handle_1); + NL_TEST_ASSERT(inSuite, config_1.handle->ref == 3); // test.handles and config_1.handle and handle_1 } +} + +void PacketBufferTest::CheckHandleAdopt(nlTestSuite * inSuite, void * inContext) +{ + struct TestContext * const theContext = static_cast(inContext); + PacketBufferTest * const test = theContext->test; + NL_TEST_ASSERT(inSuite, test->mContext == theContext); - return (SUCCESS); + for (auto & config_1 : test->configurations) + { + test->PrepareTestBuffer(&config_1, kRecordHandle); + PacketBuffer * buffer_1 = config_1.handle.Release_ForNow(); + + NL_TEST_ASSERT(inSuite, config_1.handle.IsNull()); + NL_TEST_ASSERT(inSuite, buffer_1->ref == 2); // test.handles and buffer_1 + + config_1.handle = PacketBufferHandle::Adopt(buffer_1); + NL_TEST_ASSERT(inSuite, config_1.handle.Get() == buffer_1); + NL_TEST_ASSERT(inSuite, config_1.handle->ref == 2); // test.handles and config_1.handle + + config_1.handle = nullptr; + NL_TEST_ASSERT(inSuite, config_1.handle.IsNull()); + NL_TEST_ASSERT(inSuite, buffer_1->ref == 1); // test.handles only + } } -/** - * Tear down the test suite. - * - * Free memory reserved at TestSetup. - */ -int TestTeardown(void * inContext) +void PacketBufferTest::CheckHandleHold(nlTestSuite * inSuite, void * inContext) { - struct TestContext * theContext = reinterpret_cast(inContext); + struct TestContext * const theContext = static_cast(inContext); + PacketBufferTest * const test = theContext->test; + NL_TEST_ASSERT(inSuite, test->mContext == theContext); - for (size_t ith = 0; ith < kTestElements; ith++) + for (auto & config_1 : test->configurations) { - PacketBufferTest::BufferFree(theContext); - theContext++; + test->PrepareTestBuffer(&config_1, kRecordHandle); + PacketBuffer * buffer_1 = config_1.handle.Release_ForNow(); + + NL_TEST_ASSERT(inSuite, config_1.handle.IsNull()); + NL_TEST_ASSERT(inSuite, buffer_1->ref == 2); // test.handles and buffer_1 + + config_1.handle = PacketBufferHandle::Hold(buffer_1); + NL_TEST_ASSERT(inSuite, config_1.handle.Get() == buffer_1); + NL_TEST_ASSERT(inSuite, config_1.handle->ref == 3); // test.handles and config_1.handle and buffer_1 + + config_1.handle = nullptr; + NL_TEST_ASSERT(inSuite, config_1.handle.IsNull()); + NL_TEST_ASSERT(inSuite, buffer_1->ref == 2); // test.handles only and buffer_1 + + PacketBuffer::Free(buffer_1); } +} + +void PacketBufferTest::CheckHandleAdvance(nlTestSuite * inSuite, void * inContext) +{ + struct TestContext * const theContext = static_cast(inContext); + PacketBufferTest * const test = theContext->test; + NL_TEST_ASSERT(inSuite, test->mContext == theContext); + + for (auto & config_1 : test->configurations) + { + for (auto & config_2 : test->configurations) + { + for (auto & config_3 : test->configurations) + { + if (&config_1 == &config_2 || &config_1 == &config_3 || &config_2 == &config_3) + { + continue; + } + + test->PrepareTestBuffer(&config_1); + test->PrepareTestBuffer(&config_2); + test->PrepareTestBuffer(&config_3); + + PacketBufferHandle handle_1 = config_1.handle.Retain(); + PacketBufferHandle handle_2 = config_2.handle.Retain(); + PacketBufferHandle handle_3 = config_3.handle.Retain(); + + config_1.handle->AddToEnd(config_2.handle.Retain()); + config_1.handle->AddToEnd(config_3.handle.Retain()); + + NL_TEST_ASSERT(inSuite, config_1.handle->ChainedBuffer() == config_2.handle.Get()); + NL_TEST_ASSERT(inSuite, config_2.handle->ChainedBuffer() == config_3.handle.Get()); + NL_TEST_ASSERT(inSuite, config_3.handle->HasChainedBuffer() == false); + NL_TEST_ASSERT(inSuite, handle_1->ref == 2); // handle_1 and config_1.handle + NL_TEST_ASSERT(inSuite, handle_2->ref == 3); // handle_2 and config_2.handle and config_1.handle->next + NL_TEST_ASSERT(inSuite, handle_3->ref == 3); // handle_3 and config_3.handle and config_2.handle->next - return (SUCCESS); + config_1.handle.Advance(); + + NL_TEST_ASSERT(inSuite, config_1.handle == handle_2); + NL_TEST_ASSERT(inSuite, handle_1->ref == 1); // handle_1 only + NL_TEST_ASSERT(inSuite, handle_2->ref == 4); // handle_2, config_[12].handle, handle_1->next + NL_TEST_ASSERT(inSuite, handle_3->ref == 3); // handle_3, config_3.handle, config_2.handle->next + + config_1.handle.Advance(); + + NL_TEST_ASSERT(inSuite, config_1.handle == handle_3); + NL_TEST_ASSERT(inSuite, handle_1->ref == 1); // handle_1 only + NL_TEST_ASSERT(inSuite, handle_2->ref == 3); // handle_2, config_2.handle, handle_1->next + NL_TEST_ASSERT(inSuite, handle_3->ref == 4); // handle_3, config_[13].handle, handle_2->next + + config_1.handle = nullptr; + config_2.handle = nullptr; + config_3.handle = nullptr; + } + } + } } -int TestSystemPacketBuffer(void) -{ /* - #if CHIP_SYSTEM_CONFIG_USE_LWIP - tcpip_init(NULL, NULL); - #endif // CHIP_SYSTEM_CONFIG_USE_LWIP +/** + * Test Suite. It lists all the test functions. */ +// clang-format off +const nlTest sTests[] = +{ + NL_TEST_DEF("PacketBuffer::NewWithAvailableSize&PacketBuffer::Free", PacketBufferTest::CheckNewWithAvailableSizeAndFree), + NL_TEST_DEF("PacketBuffer::Start", PacketBufferTest::CheckStart), + NL_TEST_DEF("PacketBuffer::SetStart", PacketBufferTest::CheckSetStart), + NL_TEST_DEF("PacketBuffer::DataLength", PacketBufferTest::CheckDataLength), + NL_TEST_DEF("PacketBuffer::SetDataLength", PacketBufferTest::CheckSetDataLength), + NL_TEST_DEF("PacketBuffer::TotalLength", PacketBufferTest::CheckTotalLength), + NL_TEST_DEF("PacketBuffer::MaxDataLength", PacketBufferTest::CheckMaxDataLength), + NL_TEST_DEF("PacketBuffer::AvailableDataLength", PacketBufferTest::CheckAvailableDataLength), + NL_TEST_DEF("PacketBuffer::HasChainedBuffer", PacketBufferTest::CheckHasChainedBuffer), + NL_TEST_DEF("PacketBuffer::ReservedSize", PacketBufferTest::CheckReservedSize), + NL_TEST_DEF("PacketBuffer::AddToEnd", PacketBufferTest::CheckAddToEnd), + NL_TEST_DEF("PacketBuffer::PopHead", PacketBufferTest::CheckPopHead), + NL_TEST_DEF("PacketBuffer::CompactHead", PacketBufferTest::CheckCompactHead), + NL_TEST_DEF("PacketBuffer::ConsumeHead", PacketBufferTest::CheckConsumeHead), + NL_TEST_DEF("PacketBuffer::Consume", PacketBufferTest::CheckConsume), + NL_TEST_DEF("PacketBuffer::EnsureReservedSize", PacketBufferTest::CheckEnsureReservedSize), + NL_TEST_DEF("PacketBuffer::AlignPayload", PacketBufferTest::CheckAlignPayload), + NL_TEST_DEF("PacketBuffer::Next", PacketBufferTest::CheckNext), + NL_TEST_DEF("PacketBuffer::Last", PacketBufferTest::CheckLast), + NL_TEST_DEF("PacketBuffer::AddRef", PacketBufferTest::CheckAddRef), + NL_TEST_DEF("PacketBuffer::Free", PacketBufferTest::CheckFree), + NL_TEST_DEF("PacketBuffer::FreeHead", PacketBufferTest::CheckFreeHead), + NL_TEST_DEF("PacketBuffer::HandleConstruct", PacketBufferTest::CheckHandleConstruct), + NL_TEST_DEF("PacketBuffer::HandleMove", PacketBufferTest::CheckHandleMove), + NL_TEST_DEF("PacketBuffer::HandleFree", PacketBufferTest::CheckHandleFree), + NL_TEST_DEF("PacketBuffer::HandleRetain", PacketBufferTest::CheckHandleRetain), + NL_TEST_DEF("PacketBuffer::HandleAdopt", PacketBufferTest::CheckHandleAdopt), + NL_TEST_DEF("PacketBuffer::HandleHold", PacketBufferTest::CheckHandleHold), + NL_TEST_DEF("PacketBuffer::HandleAdvance", PacketBufferTest::CheckHandleAdvance), + NL_TEST_SENTINEL() +}; +// clang-format on + +int TestSystemPacketBuffer(void) +{ // clang-format off - nlTestSuite theSuite = - { - "chip-system-packetbuffer", - &sTests[0], - TestSetup, - TestTeardown + nlTestSuite theSuite = { + .name ="chip-system-packetbuffer", + .tests = &sTests[0], + .setup = PacketBufferTest::TestSetup, + .tear_down = PacketBufferTest::TestTeardown, + // .initialize = PacketBufferTest::TestInitialize, + .terminate = PacketBufferTest::TestTerminate }; // clang-format on diff --git a/src/test_driver/happy/README.md b/src/test_driver/happy/README.md index 0142224d652a19..1c0c82b5db7061 100644 --- a/src/test_driver/happy/README.md +++ b/src/test_driver/happy/README.md @@ -18,7 +18,7 @@ --entrypoint /bin/bash \ --sysctl "net.ipv6.conf.all.disable_ipv6=0 net.ipv4.conf.all.forwarding=1 net.ipv6.conf.all.forwarding=1" \ -it --mount type=bind,source=`pwd`,target=`pwd` \ - connectedhomeip/chip-build:0.4.16 + connectedhomeip/chip-build:0.4.18 Mount your checkout to the same path as your local path avoids errors during bootstrap. diff --git a/src/test_driver/linux-cirque/EchoTest.sh b/src/test_driver/linux-cirque/EchoTest.sh new file mode 100755 index 00000000000000..cce46f2f35f9f6 --- /dev/null +++ b/src/test_driver/linux-cirque/EchoTest.sh @@ -0,0 +1,46 @@ +#!/usr/bin/env bash + +# +# 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. +# + +set -e + +SOURCE="${BASH_SOURCE[0]}" +SOURCE_DIR="$(cd -P "$(dirname "$SOURCE")" >/dev/null 2>&1 && pwd)" +REPO_DIR="$SOURCE_DIR/../../../" + +echo_source=$REPO_DIR/src/messaging/tests/echo + +function build_image() { + # These files should be successfully compiled elsewhere. + source "$REPO_DIR/scripts/activate.sh" >/dev/null + set -x + cd "$echo_source" + gn gen out >/dev/null + run_ninja -C out + docker build -t chip_echo_requester -f Dockerfile.requester . 2>&1 + docker build -t chip_echo_responder -f Dockerfile.responder . 2>&1 +} + +function main() { + pushd . + build_image + popd + python3 "$SOURCE_DIR/test-echo.py" +} + +source "$SOURCE_DIR"/shell-helpers.sh +main diff --git a/src/test_driver/linux-cirque/InteractionModelTest.sh b/src/test_driver/linux-cirque/InteractionModelTest.sh new file mode 100755 index 00000000000000..8ed10e8419e7fb --- /dev/null +++ b/src/test_driver/linux-cirque/InteractionModelTest.sh @@ -0,0 +1,46 @@ +#!/usr/bin/env bash + +# +# 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. +# + +set -e + +SOURCE="${BASH_SOURCE[0]}" +SOURCE_DIR="$(cd -P "$(dirname "$SOURCE")" >/dev/null 2>&1 && pwd)" +REPO_DIR="$SOURCE_DIR/../../../" + +im_source=$REPO_DIR/src/app/tests/integration + +function build_image() { + # These files should be successfully compiled elsewhere. + source "$REPO_DIR/scripts/activate.sh" >/dev/null + set -x + cd "$im_source" + gn gen out >/dev/null + run_ninja -C out + docker build -t chip_im_initiator -f Dockerfile.initiator . 2>&1 + docker build -t chip_im_responder -f Dockerfile.responder . 2>&1 +} + +function main() { + pushd . + build_image + popd + python3 "$SOURCE_DIR/test-interaction-model.py" +} + +source "$SOURCE_DIR"/shell-helpers.sh +main diff --git a/src/test_driver/linux-cirque/README.md b/src/test_driver/linux-cirque/README.md new file mode 100644 index 00000000000000..62e5787e2a41b9 --- /dev/null +++ b/src/test_driver/linux-cirque/README.md @@ -0,0 +1,79 @@ +# The cirque testing suite + +Cirque simulates complex network topologies based upon docker nodes. On a single +Linux machine, it can create multiple nodes with network stacks that are +independent from each other. Some nodes may be connected to simulated Thread +networks, others may connect to simulated BLE or WiFi. + +In Project CHIP, cirque is used for tntegration tests. + +There is a script for running cirque tests, you can find it at +`scripts/tests/cirque_tests.sh` + +## Setting up cirque environment + +After checkout, in your local project chip directory, run: + +``` +scripts/tests/cirque_tests.sh bootstrap +``` + +It will: + +1. Install necessary packages required by cirque, + +2. Build `chip-cirque-device-base` docker image for running devices, + +3. Build openthread for simulating thread network. + +> Note: Suggest using a clean checkout before running this. + +## Run tests + +You can run the tests by: + +``` +scripts/tests/cirque_tests.sh run_all_tests +``` + +You can get more infomation from the terminal output (like the location of +logs). + +> Note: The container (as well as the networks) will be preserved for debugging. +> You may need to clean it by yourself. + +## Run specific test + +You can run a single cirque test by: + +``` +scripts/tests/cirque_tests.sh run_test +``` + +The test name is the script (`.sh`) file in `src/test_driver/linux-cirque`, like +`OnOffClusterTest`. + +For example, you can run `OnOffClusterTest` by: + +``` +scripts/tests/cirque_tests.sh run_test OnOffClusterTest +``` + +The output of the test will be written to `stdout` and `stderr`. + +## Specify log directory + +To specify log directory, simplily set `LOG_DIR` variable. + +``` +export LOG_DIR=/some/log/directory +scripts/tests/cirque_tests.sh run_all_tests +scripts/tests/cirque_tests.sh run_test OnOffClusterTest +``` + +Or + +``` +LOG_DIR=/some/log/directory scripts/tests/cirque_tests.sh run_all_tests +LOG_DIR=/some/log/directory scripts/tests/cirque_tests.sh run_test OnOffClusterTest +``` diff --git a/src/test_driver/linux-cirque/test-echo.py b/src/test_driver/linux-cirque/test-echo.py new file mode 100644 index 00000000000000..7a4da6eafd809e --- /dev/null +++ b/src/test_driver/linux-cirque/test-echo.py @@ -0,0 +1,84 @@ +#!/usr/bin/env python3 +""" +Copyright (c) 2020 Project CHIP Authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +""" + +import logging +import os +import time +import sys + +from helper.CHIPTestBase import CHIPVirtualHome + +logger = logging.getLogger('CHIPEchoTest') +logger.setLevel(logging.INFO) + +sh = logging.StreamHandler() +sh.setFormatter( + logging.Formatter( + '%(asctime)s [%(name)s] %(levelname)s %(message)s')) +logger.addHandler(sh) + +DEVICE_CONFIG = { + 'device0': { + 'type': 'CHIP-Echo-Requester', + 'base_image': 'chip_echo_requester', + 'capability': ['Thread', 'Interactive'], + 'rcp_mode': True, + }, + 'device1': { + 'type': 'CHIP-Echo-Responder', + 'base_image': 'chip_echo_responder', + 'capability': ['Thread', 'Interactive'], + 'rcp_mode': True, + } +} + +CHIP_PORT = 11097 + +CIRQUE_URL = "http://localhost:5000" + + +class TestEcho(CHIPVirtualHome): + def __init__(self, device_config): + super().__init__(CIRQUE_URL, device_config) + self.logger = logger + + def setup(self): + self.initialize_home() + self.connect_to_thread_network() + + def test_routine(self): + self.run_data_model_test() + + def run_data_model_test(self): + resp_ips = [device['description']['ipv4_addr'] for device in self.non_ap_devices + if device['type'] == 'CHIP-Echo-Responder'] + req_ids = [device['id'] for device in self.non_ap_devices + if device['type'] == 'CHIP-Echo-Requester'] + + req_device_id = req_ids[0] + + command = "chip-echo-requester {}" + + for ip in resp_ips: + ret = self.execute_device_cmd( + req_device_id, command.format(ip)) + self.assertEqual( + ret['return_code'], '0', "{} failure: {}".format("Echo", ret['output'])) + + +if __name__ == "__main__": + sys.exit(TestEcho(DEVICE_CONFIG).run_test()) diff --git a/src/test_driver/linux-cirque/test-interaction-model.py b/src/test_driver/linux-cirque/test-interaction-model.py new file mode 100644 index 00000000000000..4fbd057e324896 --- /dev/null +++ b/src/test_driver/linux-cirque/test-interaction-model.py @@ -0,0 +1,84 @@ +#!/usr/bin/env python3 +""" +Copyright (c) 2021 Project CHIP Authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +""" + +import logging +import os +import time +import sys + +from helper.CHIPTestBase import CHIPVirtualHome + +logger = logging.getLogger('CHIPInteractionModelTest') +logger.setLevel(logging.INFO) + +sh = logging.StreamHandler() +sh.setFormatter( + logging.Formatter( + '%(asctime)s [%(name)s] %(levelname)s %(message)s')) +logger.addHandler(sh) + +DEVICE_CONFIG = { + 'device0': { + 'type': 'CHIP-IM-Initiator', + 'base_image': 'chip_im_initiator', + 'capability': ['Thread', 'Interactive'], + 'rcp_mode': True, + }, + 'device1': { + 'type': 'CHIP-IM-Responder', + 'base_image': 'chip_im_responder', + 'capability': ['Thread', 'Interactive'], + 'rcp_mode': True, + } +} + +CHIP_PORT = 11097 + +CIRQUE_URL = "http://localhost:5000" + + +class TestInteractionModel(CHIPVirtualHome): + def __init__(self, device_config): + super().__init__(CIRQUE_URL, device_config) + self.logger = logger + + def setup(self): + self.initialize_home() + self.connect_to_thread_network() + + def test_routine(self): + self.run_data_model_test() + + def run_data_model_test(self): + resp_ips = [device['description']['ipv4_addr'] for device in self.non_ap_devices + if device['type'] == 'CHIP-IM-Responder'] + req_ids = [device['id'] for device in self.non_ap_devices + if device['type'] == 'CHIP-IM-Initiator'] + + req_device_id = req_ids[0] + + command = "chip-im-initiator {}" + + for ip in resp_ips: + ret = self.execute_device_cmd( + req_device_id, command.format(ip)) + self.assertEqual( + ret['return_code'], '0', "{} failure: {}".format("IM", ret['output'])) + + +if __name__ == "__main__": + sys.exit(TestInteractionModel(DEVICE_CONFIG).run_test()) diff --git a/src/test_driver/nrfconnect/CMakeLists.txt b/src/test_driver/nrfconnect/CMakeLists.txt index e1bae2c7af5481..cacfb978189007 100644 --- a/src/test_driver/nrfconnect/CMakeLists.txt +++ b/src/test_driver/nrfconnect/CMakeLists.txt @@ -16,41 +16,27 @@ # # @file -# CMake project for building and running all CHIP unit tests +# CMake project for building and running selected CHIP unit tests using +# 'nrfconnect' platform integration layer in CHIP and Zephyr +# 'native_posix[_64]' platforms. Note that certain design decisions behind +# the native_posix platforms make them inapplicable for some unit tests, +# hence only a subset of CHIP unit tests is listed in the project. +# See: https://docs.zephyrproject.org/1.12.0/boards/posix/native_posix/doc/board.html +# for more details. # -# TODO: -# As long as we use autotools under the hood we build all CHIP libraries and tests in this project -# but ideally we would have a subdirectory for each CHIP test directory so that it be possible to -# build a test driver for a single test directory and required dependencies, e.g. -# -# src/test_driver/zephyr/: -# - CMakeLists.txt <- build test driver and run all tests -# - system/CMakeLists.txt <- build and run only system tests -# - inet/CMakeLists.txt <- build and run only inet tests -# - ... - cmake_minimum_required(VERSION 3.13.1) -set(CHIP_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/third_party/connectedhomeip) -get_filename_component(CHIP_ROOT ${CHIP_ROOT} REALPATH) -set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CHIP_ROOT}/config/nrfconnect/) +get_filename_component(CHIP_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/third_party/connectedhomeip REALPATH) -# Make sure all components can see our mbedtls config +# Make sure all components can see project mbedTLS config include_directories(AFTER ${CMAKE_CURRENT_SOURCE_DIR}/main/include) # ================================================== -# Load NCS/Zephyr build system +# Setup CHIP build # ================================================== -find_package(Zephyr HINTS $ENV{ZEPHYR_BASE}) -# ================================================== -# General settings -# ================================================== - -include(chip-lib) - -set(CHIP_COMMON_FLAGS +set(CHIP_CFLAGS -DCHIP_SYSTEM_CONFIG_USE_POSIX_TIME_FUNCTS=1 -DCHIP_SYSTEM_CONFIG_USE_ZEPHYR_SOCKET_EXTENSIONS=0 -DCHIP_SYSTEM_CONFIG_USE_ZEPHYR_NET_IF=0 @@ -60,13 +46,6 @@ set(CHIP_COMMON_FLAGS -isystem${ZEPHYR_BASE}/../mbedtls/include ) -set(CHIP_LIBRARIES - -lCHIP - -lInetTestHelpers - -lNetworkTestHelpers - -lnlunit-test -) - set(CHIP_TESTS # TODO: this list is hard to maintain manually (and currently incomplete). # An automated way that includes figuring out dependencies would be much better @@ -86,30 +65,26 @@ set(CHIP_TESTS -lTransportLayerTests ) -# ================================================== -# Setup CHIP build (including unit tests) -# ================================================== -project(AllChipTests) -enable_testing() - -chip_configure(ChipConfig - BUILD_TESTS - PROJECT_CONFIG ${CMAKE_CURRENT_SOURCE_DIR}/main/include/CHIPProjectConfig.h - CFLAGS ${CHIP_COMMON_FLAGS} - CXXFLAGS ${CHIP_COMMON_FLAGS} +set(CHIP_LIBRARIES + -lCHIP + -lInetTestHelpers + -lNetworkTestHelpers + -lnlunit-test + ${CHIP_TESTS} ) -chip_build(ChipLib ChipConfig - BUILD_COMMAND ninja - BUILD_ARTIFACTS ${CHIP_LIBRARIES} ${CHIP_TESTS} -) +include(${CHIP_ROOT}/config/nrfconnect/app/app.cmake) # ================================================== # Build 'all tests' runner # ================================================== + +project(AllChipTests) +enable_testing() + target_sources(app PRIVATE main/runner.cpp) target_link_options(app PUBLIC -Wl,--whole-archive ${CHIP_TESTS} -Wl,--no-whole-archive) -target_link_libraries(app PUBLIC ChipLib $) +target_link_libraries(app PUBLIC chip $) target_compile_definitions(app PUBLIC CHIP_HAVE_CONFIG_H) add_test(AllChipTests zephyr/zephyr.exe) diff --git a/src/test_driver/nrfconnect/prj.conf b/src/test_driver/nrfconnect/prj.conf index 46e6d1c8f704c2..af0aea1b954b11 100644 --- a/src/test_driver/nrfconnect/prj.conf +++ b/src/test_driver/nrfconnect/prj.conf @@ -14,11 +14,6 @@ # limitations under the License. # -# Enable support for C++ language -# NOTE if this option is missing the application may still build successfully, but crash -# later at run-time due to various structure incompatibilities between C and C++. -CONFIG_CPLUSPLUS=y - # Application stack size CONFIG_MAIN_STACK_SIZE=8192 @@ -50,10 +45,6 @@ CONFIG_FLASH_MAP=y CONFIG_NVS=y CONFIG_SETTINGS=y -# Kernel options for RNG -CONFIG_ENTROPY_GENERATOR=y -CONFIG_INIT_STACKS=y - # Network buffers CONFIG_NET_PKT_RX_COUNT=16 CONFIG_NET_PKT_TX_COUNT=16 @@ -66,16 +57,6 @@ CONFIG_NET_IF_UNICAST_IPV6_ADDR_COUNT=6 CONFIG_NET_IF_MCAST_IPV6_ADDR_COUNT=8 CONFIG_NET_MAX_CONTEXTS=10 -# Disable Bluetooth Low Energy temporarily until dynamic multiprotocol is available -# To enable Bluetooth, set CONFIG_BT=y and uncomment the below configs. You will also -# have to set CONFIG_NET_L2_OPENTHREAD=n. -CONFIG_BT=n -# CONFIG_BT_PERIPHERAL=y -# CONFIG_BT_DEVICE_APPEARANCE=0 -# CONFIG_BT_DEVICE_NAME_DYNAMIC=y -# CONFIG_BT_DEVICE_NAME_MAX=15 -# CONFIG_BT_MAX_CONN=2 - # mbedTLS tweaks CONFIG_MBEDTLS=y CONFIG_MBEDTLS_ENABLE_HEAP=y @@ -93,7 +74,7 @@ CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED=y CONFIG_MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED=y CONFIG_MBEDTLS_CIPHER_CCM_ENABLED=y -#Enable entropy +# Enable entropy CONFIG_ENTROPY_GENERATOR=y # Disable OpenThread @@ -101,3 +82,10 @@ CONFIG_NET_L2_OPENTHREAD=n # Additional configs for debbugging experience. CONFIG_THREAD_NAME=y +CONFIG_INIT_STACKS=y +CONFIG_REBOOT=n + +# CHIP configuration +CONFIG_CHIP=y +CONFIG_CHIP_BUILD_TESTS=y + diff --git a/src/transport/BLE.cpp b/src/transport/BLE.cpp index ee0c8fb614efc4..0cbbfc6bdfecc4 100644 --- a/src/transport/BLE.cpp +++ b/src/transport/BLE.cpp @@ -134,14 +134,12 @@ CHIP_ERROR BLE::DelegateConnection(const uint16_t connDiscriminator) return err; } -CHIP_ERROR BLE::SendMessage(const PacketHeader & header, const Transport::PeerAddress & address, System::PacketBuffer * msgIn) +CHIP_ERROR BLE::SendMessage(const PacketHeader & header, const Transport::PeerAddress & address, System::PacketBufferHandle msgBuf) { CHIP_ERROR err = CHIP_NO_ERROR; const uint16_t headerSize = header.EncodeSizeBytes(); uint16_t actualEncodedHeaderSize; - PacketBufferHandle msgBuf; - msgBuf.Adopt(msgIn); VerifyOrExit(address.GetTransportType() == Type::kBle, err = CHIP_ERROR_INVALID_ARGUMENT); VerifyOrExit(mState == State::kInitialized, err = CHIP_ERROR_INCORRECT_STATE); VerifyOrExit(mBleEndPoint != nullptr, err = CHIP_ERROR_INCORRECT_STATE); diff --git a/src/transport/BLE.h b/src/transport/BLE.h index 1df4d7a6975e6e..13b7b0e176bad7 100644 --- a/src/transport/BLE.h +++ b/src/transport/BLE.h @@ -69,7 +69,7 @@ class DLL_EXPORT BLE : public Base CHIP_ERROR Init(RendezvousSessionDelegate * delegate, const RendezvousParameters & params); CHIP_ERROR SendMessage(const PacketHeader & header, const Transport::PeerAddress & address, - System::PacketBuffer * msgBuf) override; + System::PacketBufferHandle msgBuf) override; bool CanSendToPeer(const Transport::PeerAddress & address) override { diff --git a/src/transport/NetworkProvisioning.cpp b/src/transport/NetworkProvisioning.cpp index 09a096d133d8f5..1807d717f416a8 100644 --- a/src/transport/NetworkProvisioning.cpp +++ b/src/transport/NetworkProvisioning.cpp @@ -176,7 +176,7 @@ CHIP_ERROR NetworkProvisioning::SendIPAddress(const Inet::IPAddress & addr) buffer->SetDataLength(static_cast(addrLen)); err = mDelegate->SendSecureMessage(Protocols::kProtocol_NetworkProvisioning, NetworkProvisioning::MsgTypes::kIPAddressAssigned, - buffer.Release_ForNow()); + std::move(buffer)); SuccessOrExit(err); exit: @@ -202,7 +202,7 @@ CHIP_ERROR NetworkProvisioning::SendNetworkCredentials(const char * ssid, const buffer->SetDataLength(static_cast(bbuf.Needed())); err = mDelegate->SendSecureMessage(Protocols::kProtocol_NetworkProvisioning, - NetworkProvisioning::MsgTypes::kWiFiAssociationRequest, buffer.Release_ForNow()); + NetworkProvisioning::MsgTypes::kWiFiAssociationRequest, std::move(buffer)); SuccessOrExit(err); exit: @@ -237,7 +237,7 @@ CHIP_ERROR NetworkProvisioning::SendThreadCredentials(const DeviceLayer::Interna buffer->SetDataLength(static_cast(bbuf.Needed())); err = mDelegate->SendSecureMessage(Protocols::kProtocol_NetworkProvisioning, - NetworkProvisioning::MsgTypes::kThreadAssociationRequest, buffer.Release_ForNow()); + NetworkProvisioning::MsgTypes::kThreadAssociationRequest, std::move(buffer)); } exit: diff --git a/src/transport/NetworkProvisioning.h b/src/transport/NetworkProvisioning.h index 6da6acb3cf99e8..145bd03284fe6e 100644 --- a/src/transport/NetworkProvisioning.h +++ b/src/transport/NetworkProvisioning.h @@ -48,7 +48,7 @@ class DLL_EXPORT NetworkProvisioningDelegate * @param msgBuf the new message that should be sent to the peer * @return CHIP_ERROR Error thrown when sending the message */ - virtual CHIP_ERROR SendSecureMessage(Protocols::CHIPProtocolId protocol, uint8_t msgType, System::PacketBuffer * msgBuf) + virtual CHIP_ERROR SendSecureMessage(Protocols::CHIPProtocolId protocol, uint8_t msgType, System::PacketBufferHandle msgBuf) { return CHIP_NO_ERROR; } diff --git a/src/transport/PeerConnections.h b/src/transport/PeerConnections.h index 439b208d181e9a..95938da5ff603e 100644 --- a/src/transport/PeerConnections.h +++ b/src/transport/PeerConnections.h @@ -24,6 +24,11 @@ namespace chip { namespace Transport { +// TODO; use 0xffff to match any key id, this is a temporary solution for +// InteractionModel, where key id is not obtainable. This will be removed when +// InteractionModel is migrated to messaging layer +constexpr const uint16_t kAnyKeyId = 0xffff; + /** * Handles a set of peer connection states. * @@ -219,7 +224,7 @@ class PeerConnections { continue; } - if (iter->GetPeerKeyID() == peerKeyId) + if (peerKeyId == kAnyKeyId || iter->GetPeerKeyID() == peerKeyId) { if (!nodeId.HasValue() || iter->GetPeerNodeId() == kUndefinedNodeId || iter->GetPeerNodeId() == nodeId.Value()) { diff --git a/src/transport/RendezvousSession.cpp b/src/transport/RendezvousSession.cpp index e0d23b18e7cb38..038425910f40cc 100644 --- a/src/transport/RendezvousSession.cpp +++ b/src/transport/RendezvousSession.cpp @@ -92,36 +92,31 @@ RendezvousSession::~RendezvousSession() } CHIP_ERROR RendezvousSession::SendPairingMessage(const PacketHeader & header, const Transport::PeerAddress & peerAddress, - System::PacketBuffer * msgIn) + System::PacketBufferHandle msgIn) { if (mCurrentState != State::kSecurePairing) { - PacketBuffer::Free(msgIn); return CHIP_ERROR_INCORRECT_STATE; } if (peerAddress.GetTransportType() == Transport::Type::kBle) { - return mTransport->SendMessage(header, peerAddress, msgIn); + return mTransport->SendMessage(header, peerAddress, std::move(msgIn)); } else if (mTransportMgr != nullptr) { - return mTransportMgr->SendMessage(header, peerAddress, msgIn); + return mTransportMgr->SendMessage(header, peerAddress, std::move(msgIn)); } else { - PacketBuffer::Free(msgIn); ChipLogError(Ble, "SendPairingMessage dropped since no transport mgr for IP rendezvous"); return CHIP_ERROR_INVALID_ADDRESS; } } -CHIP_ERROR RendezvousSession::SendSecureMessage(Protocols::CHIPProtocolId protocol, uint8_t msgType, System::PacketBuffer * msgIn) +CHIP_ERROR RendezvousSession::SendSecureMessage(Protocols::CHIPProtocolId protocol, uint8_t msgType, + System::PacketBufferHandle msgBuf) { - System::PacketBufferHandle msgBuf; - - msgBuf.Adopt(msgIn); - PayloadHeader payloadHeader; payloadHeader.SetProtocolID(static_cast(protocol)).SetMessageType(msgType); @@ -159,7 +154,7 @@ CHIP_ERROR RendezvousSession::SendSecureMessage(Protocols::CHIPProtocolId protoc msgBuf->SetDataLength(static_cast(totalLen + taglen)); - ReturnErrorOnFailure(mTransport->SendMessage(packetHeader, Transport::PeerAddress::BLE(), msgBuf.Release_ForNow())); + ReturnErrorOnFailure(mTransport->SendMessage(packetHeader, Transport::PeerAddress::BLE(), std::move(msgBuf))); mSecureMessageIndex++; @@ -444,9 +439,7 @@ CHIP_ERROR RendezvousSession::WaitForPairing(Optional nodeId, uint32_t s CHIP_ERROR RendezvousSession::Pair(Optional nodeId, uint32_t setupPINCode) { UpdateState(State::kSecurePairing); - return mPairingSession.Pair(mParams.GetPeerAddress(), setupPINCode, kSpake2p_Iteration_Count, - reinterpret_cast(kSpake2pKeyExchangeSalt), strlen(kSpake2pKeyExchangeSalt), - nodeId, mNextKeyId++, this); + return mPairingSession.Pair(mParams.GetPeerAddress(), setupPINCode, nodeId, mNextKeyId++, this); } void RendezvousSession::SendNetworkCredentials(const char * ssid, const char * passwd) diff --git a/src/transport/RendezvousSession.h b/src/transport/RendezvousSession.h index 7a80affc68fc6b..6b41148500f92d 100644 --- a/src/transport/RendezvousSession.h +++ b/src/transport/RendezvousSession.h @@ -103,7 +103,7 @@ class RendezvousSession : public SecurePairingSessionDelegate, //////////// SecurePairingSessionDelegate Implementation /////////////// CHIP_ERROR SendPairingMessage(const PacketHeader & header, const Transport::PeerAddress & peerAddress, - System::PacketBuffer * msgBuf) override; + System::PacketBufferHandle msgBuf) override; void OnPairingError(CHIP_ERROR err) override; void OnPairingComplete() override; @@ -120,7 +120,7 @@ class RendezvousSession : public SecurePairingSessionDelegate, void SendOperationalCredentials() override; //////////// NetworkProvisioningDelegate Implementation /////////////// - CHIP_ERROR SendSecureMessage(Protocols::CHIPProtocolId protocol, uint8_t msgType, System::PacketBuffer * msgBug) override; + CHIP_ERROR SendSecureMessage(Protocols::CHIPProtocolId protocol, uint8_t msgType, System::PacketBufferHandle msgBug) override; void OnNetworkProvisioningError(CHIP_ERROR error) override; void OnNetworkProvisioningComplete() override; diff --git a/src/transport/SecurePairingSession.cpp b/src/transport/SecurePairingSession.cpp index dc370dd73467e5..acc7f01af0b79d 100644 --- a/src/transport/SecurePairingSession.cpp +++ b/src/transport/SecurePairingSession.cpp @@ -32,9 +32,11 @@ #include #include +#include #include #include #include +#include #include #include @@ -42,7 +44,7 @@ namespace chip { using namespace Crypto; -const char * kSpake2pContext = "CHIP 1.0 Provisioning"; +const char * kSpake2pContext = "SPAKE2+ Commissioning"; const char * kSpake2pI2RSessionInfo = "Commissioning I2R Key"; const char * kSpake2pR2ISessionInfo = "Commissioning R2I Key"; @@ -50,9 +52,34 @@ SecurePairingSession::SecurePairingSession() {} SecurePairingSession::~SecurePairingSession() { + // Let's clear out any security state stored in the object, before destroying it. + Clear(); +} + +void SecurePairingSession::Clear() +{ + // This function zeroes out and resets the memory used by the object. + // It's done so that no security related information will be leaked. memset(&mPoint[0], 0, sizeof(mPoint)); memset(&mWS[0][0], 0, sizeof(mWS)); memset(&mKe[0], 0, sizeof(mKe)); + mNextExpectedMsg = Protocols::SecureChannel::MsgType::PASE_Spake2pError; + mSpake2p.Init(nullptr); + mCommissioningHash.Clear(); + mIterationCount = 0; + mSaltLength = 0; + if (mSalt != nullptr) + { + chip::Platform::MemoryFree(mSalt); + mSalt = nullptr; + } + mLocalNodeId = Optional::Value(kUndefinedNodeId); + mPeerNodeId = Optional::Value(kUndefinedNodeId); + mLocalKeyId = 0; + mPeerKeyId = 0; + mPeerAddress = Transport::PeerAddress::Uninitialized(); + mKeLen = sizeof(mKe); + mPairingComplete = false; } CHIP_ERROR SecurePairingSession::Serialize(SecurePairingSessionSerialized & output) @@ -145,25 +172,41 @@ CHIP_ERROR SecurePairingSession::FromSerializable(const SecurePairingSessionSeri return error; } -CHIP_ERROR SecurePairingSession::Init(uint32_t setupCode, uint32_t pbkdf2IterCount, const uint8_t * salt, size_t saltLen, - Optional myNodeId, uint16_t myKeyId, SecurePairingSessionDelegate * delegate) +CHIP_ERROR SecurePairingSession::Init(Optional myNodeId, uint16_t myKeyId, uint32_t setupCode, + SecurePairingSessionDelegate * delegate) { CHIP_ERROR err = CHIP_NO_ERROR; - VerifyOrExit(salt != nullptr, err = CHIP_ERROR_INVALID_ARGUMENT); - VerifyOrExit(saltLen > 0, err = CHIP_ERROR_INVALID_ARGUMENT); VerifyOrExit(delegate != nullptr, err = CHIP_ERROR_INVALID_ARGUMENT); - err = mSpake2p.Init(Uint8::from_const_char(kSpake2pContext), strlen(kSpake2pContext)); + err = mCommissioningHash.Begin(); SuccessOrExit(err); - err = pbkdf2_sha256(reinterpret_cast(&setupCode), sizeof(setupCode), salt, saltLen, pbkdf2IterCount, + err = mCommissioningHash.AddData(Uint8::from_const_char(kSpake2pContext), strlen(kSpake2pContext)); + SuccessOrExit(err); + + mDelegate = delegate; + mLocalNodeId = myNodeId; + mLocalKeyId = myKeyId; + mSetupPINCode = setupCode; + +exit: + return err; +} + +CHIP_ERROR SecurePairingSession::SetupSpake2p(uint32_t pbkdf2IterCount, const uint8_t * salt, size_t saltLen) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + + VerifyOrExit(salt != nullptr, err = CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrExit(saltLen > 0, err = CHIP_ERROR_INVALID_ARGUMENT); + + err = pbkdf2_sha256(reinterpret_cast(&mSetupPINCode), sizeof(mSetupPINCode), salt, saltLen, pbkdf2IterCount, sizeof(mWS), &mWS[0][0]); SuccessOrExit(err); - mDelegate = delegate; - mLocalNodeId = myNodeId; - mLocalKeyId = myKeyId; + err = mSpake2p.Init(&mCommissioningHash); + SuccessOrExit(err); exit: return err; @@ -173,36 +216,56 @@ CHIP_ERROR SecurePairingSession::WaitForPairing(uint32_t mySetUpPINCode, uint32_ size_t saltLen, Optional myNodeId, uint16_t myKeyId, SecurePairingSessionDelegate * delegate) { - size_t sizeof_point = sizeof(mPoint); + CHIP_ERROR err = CHIP_NO_ERROR; - CHIP_ERROR err = Init(mySetUpPINCode, pbkdf2IterCount, salt, saltLen, myNodeId, myKeyId, delegate); - SuccessOrExit(err); + VerifyOrExit(salt != nullptr, err = CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrExit(saltLen > 0, err = CHIP_ERROR_INVALID_ARGUMENT); - err = mSpake2p.ComputeL(mPoint, &sizeof_point, &mWS[1][0], kSpake2p_WS_Length); + err = Init(myNodeId, myKeyId, mySetUpPINCode, delegate); SuccessOrExit(err); - mNextExpectedMsg = Spake2pMsgType::kSpake2pCompute_pA; + VerifyOrExit(CanCastTo(saltLen), err = CHIP_ERROR_INVALID_ARGUMENT); + mSaltLength = static_cast(saltLen); + + if (mSalt != nullptr) + { + chip::Platform::MemoryFree(mSalt); + mSalt = nullptr; + } + + mSalt = static_cast(chip::Platform::MemoryAlloc(mSaltLength)); + VerifyOrExit(mSalt != nullptr, err = CHIP_ERROR_NO_MEMORY); + + memmove(mSalt, salt, mSaltLength); + + mIterationCount = pbkdf2IterCount; + + mNextExpectedMsg = Protocols::SecureChannel::MsgType::PBKDFParamRequest; mPairingComplete = false; + ChipLogDetail(Ble, "Waiting for PBKDF param request"); + exit: + if (err != CHIP_NO_ERROR) + { + Clear(); + } return err; } -CHIP_ERROR SecurePairingSession::AttachHeaderAndSend(uint8_t msgType, System::PacketBuffer * msgIn) +CHIP_ERROR SecurePairingSession::AttachHeaderAndSend(Protocols::SecureChannel::MsgType msgType, System::PacketBufferHandle msgBuf) { CHIP_ERROR err = CHIP_NO_ERROR; - System::PacketBufferHandle msgBuf; PayloadHeader payloadHeader; payloadHeader - .SetMessageType(msgType) // + .SetMessageType(static_cast(msgType)) // .SetProtocolID(Protocols::kProtocol_SecureChannel); uint16_t headerSize = payloadHeader.EncodeSizeBytes(); uint16_t actualEncodedHeaderSize = 0; - msgBuf.Adopt(msgIn); VerifyOrExit(msgBuf->EnsureReservedSize(headerSize), err = CHIP_ERROR_NO_MEMORY); msgBuf->SetStart(msgBuf->Start() - headerSize); @@ -211,75 +274,250 @@ CHIP_ERROR SecurePairingSession::AttachHeaderAndSend(uint8_t msgType, System::Pa VerifyOrExit(headerSize == actualEncodedHeaderSize, err = CHIP_ERROR_INTERNAL); err = mDelegate->SendPairingMessage(PacketHeader().SetSourceNodeId(mLocalNodeId).SetEncryptionKeyID(mLocalKeyId), mPeerAddress, - msgBuf.Release_ForNow()); + std::move(msgBuf)); SuccessOrExit(err); exit: return err; } -CHIP_ERROR SecurePairingSession::Pair(const Transport::PeerAddress peerAddress, uint32_t peerSetUpPINCode, uint32_t pbkdf2IterCount, - const uint8_t * salt, size_t saltLen, Optional myNodeId, uint16_t myKeyId, - SecurePairingSessionDelegate * delegate) +CHIP_ERROR SecurePairingSession::Pair(const Transport::PeerAddress peerAddress, uint32_t peerSetUpPINCode, + Optional myNodeId, uint16_t myKeyId, SecurePairingSessionDelegate * delegate) { - uint8_t X[kMAX_Point_Length]; - size_t X_len = sizeof(X); - uint16_t data_len; // Will be the same as X_len in practice. + CHIP_ERROR err = Init(myNodeId, myKeyId, peerSetUpPINCode, delegate); + SuccessOrExit(err); - System::PacketBufferHandle resp; + mPeerAddress = peerAddress; - CHIP_ERROR err = Init(peerSetUpPINCode, pbkdf2IterCount, salt, saltLen, myNodeId, myKeyId, delegate); + err = SendPBKDFParamRequest(); SuccessOrExit(err); - mPeerAddress = peerAddress; +exit: + if (err != CHIP_NO_ERROR) + { + Clear(); + } + return err; +} - err = mSpake2p.BeginProver(reinterpret_cast(""), 0, reinterpret_cast(""), 0, &mWS[0][0], - kSpake2p_WS_Length, &mWS[1][0], kSpake2p_WS_Length); +CHIP_ERROR SecurePairingSession::DeriveSecureSession(const uint8_t * info, size_t info_len, SecureSession & session) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + + VerifyOrExit(info != nullptr, err = CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrExit(info_len > 0, err = CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrExit(mPairingComplete, err = CHIP_ERROR_INCORRECT_STATE); + + err = session.InitFromSecret(mKe, mKeLen, nullptr, 0, info, info_len); SuccessOrExit(err); - err = mSpake2p.ComputeRoundOne(X, &X_len); +exit: + return err; +} + +CHIP_ERROR SecurePairingSession::SendPBKDFParamRequest() +{ + CHIP_ERROR err = CHIP_NO_ERROR; + + System::PacketBufferHandle req = System::PacketBuffer::NewWithAvailableSize(kPBKDFParamRandomNumberSize); + VerifyOrExit(!req.IsNull(), err = CHIP_SYSTEM_ERROR_NO_MEMORY); + + err = DRBG_get_bytes(req->Start(), kPBKDFParamRandomNumberSize); SuccessOrExit(err); - VerifyOrExit(CanCastTo(X_len), err = CHIP_ERROR_INVALID_MESSAGE_LENGTH); - data_len = static_cast(X_len); - resp = System::PacketBuffer::NewWithAvailableSize(data_len); + req->SetDataLength(kPBKDFParamRandomNumberSize); + + // Update commissioning hash with the pbkdf2 param request that's being sent. + err = mCommissioningHash.AddData(req->Start(), req->DataLength()); + SuccessOrExit(err); + + mNextExpectedMsg = Protocols::SecureChannel::MsgType::PBKDFParamResponse; + + err = AttachHeaderAndSend(Protocols::SecureChannel::MsgType::PBKDFParamRequest, std::move(req)); + SuccessOrExit(err); + + ChipLogDetail(Ble, "Sent PBKDF param request"); + +exit: + + if (err != CHIP_NO_ERROR) + { + Clear(); + } + return err; +} + +CHIP_ERROR SecurePairingSession::HandlePBKDFParamRequest(const PacketHeader & header, const System::PacketBufferHandle & msg) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + + // Request message processing + const uint8_t * req = msg->Start(); + size_t reqlen = msg->DataLength(); + + VerifyOrExit(req != nullptr, err = CHIP_ERROR_MESSAGE_INCOMPLETE); + VerifyOrExit(reqlen == kPBKDFParamRandomNumberSize, err = CHIP_ERROR_INVALID_MESSAGE_LENGTH); + + ChipLogDetail(Ble, "Received PBKDF param request"); + + // Update commissioning hash with the received pbkdf2 param request + err = mCommissioningHash.AddData(req, reqlen); + SuccessOrExit(err); + + err = SendPBKDFParamResponse(); + SuccessOrExit(err); + +exit: + + if (err != CHIP_NO_ERROR) + { + SendErrorMsg(Spake2pErrorType::kUnexpected); + } + return err; +} + +CHIP_ERROR SecurePairingSession::SendPBKDFParamResponse() +{ + CHIP_ERROR err = CHIP_NO_ERROR; + + System::PacketBufferHandle resp; + static_assert(CHAR_BIT == 8, "Assuming sizeof() returns octets here and for sizeof(mPoint)"); + size_t resplen = kPBKDFParamRandomNumberSize + sizeof(uint64_t) + sizeof(uint32_t) + mSaltLength; + uint16_t u16len = 0; + + size_t sizeof_point = sizeof(mPoint); + + uint8_t * msg = nullptr; + + VerifyOrExit(CanCastTo(resplen), err = CHIP_ERROR_INVALID_MESSAGE_LENGTH); + u16len = static_cast(resplen); + + resp = System::PacketBuffer::NewWithAvailableSize(u16len); VerifyOrExit(!resp.IsNull(), err = CHIP_SYSTEM_ERROR_NO_MEMORY); + msg = resp->Start(); + + // Fill in the random value + err = DRBG_get_bytes(msg, kPBKDFParamRandomNumberSize); + SuccessOrExit(err); + + // Let's construct the rest of the message using BufBound { - BufBound bbuf(resp->Start(), data_len); - bbuf.Put(&X[0], X_len); + BufBound bbuf(&msg[kPBKDFParamRandomNumberSize], resplen - kPBKDFParamRandomNumberSize); + bbuf.Put64(mIterationCount); + bbuf.Put32(mSaltLength); + bbuf.Put(mSalt, mSaltLength); VerifyOrExit(bbuf.Fit(), err = CHIP_ERROR_NO_MEMORY); } - resp->SetDataLength(data_len); - mNextExpectedMsg = Spake2pMsgType::kSpake2pCompute_pB_cB; + resp->SetDataLength(u16len); - // Call delegate to send the Compute_pA to peer - err = AttachHeaderAndSend(Spake2pMsgType::kSpake2pCompute_pA, resp.Release_ForNow()); + // Update commissioning hash with the pbkdf2 param response that's being sent. + err = mCommissioningHash.AddData(resp->Start(), resp->DataLength()); + SuccessOrExit(err); + + err = SetupSpake2p(mIterationCount, mSalt, mSaltLength); + SuccessOrExit(err); + + err = mSpake2p.ComputeL(mPoint, &sizeof_point, &mWS[1][0], kSpake2p_WS_Length); + SuccessOrExit(err); + + mNextExpectedMsg = Protocols::SecureChannel::MsgType::PASE_Spake2p1; + + err = AttachHeaderAndSend(Protocols::SecureChannel::MsgType::PBKDFParamResponse, std::move(resp)); SuccessOrExit(err); - return err; + + ChipLogDetail(Ble, "Sent PBKDF param response"); exit: - mNextExpectedMsg = Spake2pMsgType::kSpake2pMsgTypeMax; return err; } -CHIP_ERROR SecurePairingSession::DeriveSecureSession(const uint8_t * info, size_t info_len, SecureSession & session) +CHIP_ERROR SecurePairingSession::HandlePBKDFParamResponse(const PacketHeader & header, const System::PacketBufferHandle & msg) { CHIP_ERROR err = CHIP_NO_ERROR; - VerifyOrExit(info != nullptr, err = CHIP_ERROR_INVALID_ARGUMENT); - VerifyOrExit(info_len > 0, err = CHIP_ERROR_INVALID_ARGUMENT); - VerifyOrExit(mPairingComplete, err = CHIP_ERROR_INCORRECT_STATE); + // Response message processing + const uint8_t * resp = msg->Start(); + size_t resplen = msg->DataLength(); - err = session.InitFromSecret(mKe, mKeLen, nullptr, 0, info, info_len); + // This the fixed part of the message. The variable part of the message contains the salt. + // The length of the variable part is determined by the salt length in the fixed header. + static_assert(CHAR_BIT == 8, "Assuming that sizeof returns octets"); + size_t fixed_resplen = kPBKDFParamRandomNumberSize + sizeof(uint64_t) + sizeof(uint32_t); + + ChipLogDetail(Ble, "Received PBKDF param response"); + + VerifyOrExit(resp != nullptr, err = CHIP_ERROR_MESSAGE_INCOMPLETE); + VerifyOrExit(resplen >= fixed_resplen, err = CHIP_ERROR_INVALID_MESSAGE_LENGTH); + + { + // Let's skip the random number portion of the message + const uint8_t * msgptr = &resp[kPBKDFParamRandomNumberSize]; + uint64_t iterCount = chip::Encoding::LittleEndian::Read64(msgptr); + uint32_t saltlen = chip::Encoding::LittleEndian::Read32(msgptr); + + VerifyOrExit(resplen == fixed_resplen + saltlen, err = CHIP_ERROR_INVALID_MESSAGE_LENGTH); + + // Specifications allow message to carry a uint64_t sized iteration count. Current APIs are + // limiting it to uint32_t. Let's make sure it'll fit the size limit. + VerifyOrExit(CanCastTo(iterCount), err = CHIP_ERROR_INVALID_MESSAGE_LENGTH); + + // Update commissioning hash with the received pbkdf2 param response + err = mCommissioningHash.AddData(resp, resplen); + SuccessOrExit(err); + + err = SetupSpake2p(static_cast(iterCount), msgptr, saltlen); + SuccessOrExit(err); + } + + err = SendMsg1(); SuccessOrExit(err); exit: + if (err != CHIP_NO_ERROR) + { + SendErrorMsg(Spake2pErrorType::kUnexpected); + } return err; } -CHIP_ERROR SecurePairingSession::HandleCompute_pA(const PacketHeader & header, const System::PacketBufferHandle & msg) +CHIP_ERROR SecurePairingSession::SendMsg1() +{ + uint8_t X[kMAX_Point_Length]; + size_t X_len = sizeof(X); + uint16_t data_len; // Will be the same as X_len in practice. + + System::PacketBufferHandle msg_pA; + + CHIP_ERROR err = mSpake2p.BeginProver(reinterpret_cast(""), 0, reinterpret_cast(""), 0, + &mWS[0][0], kSpake2p_WS_Length, &mWS[1][0], kSpake2p_WS_Length); + SuccessOrExit(err); + + err = mSpake2p.ComputeRoundOne(X, &X_len); + SuccessOrExit(err); + VerifyOrExit(CanCastTo(X_len), err = CHIP_ERROR_INVALID_MESSAGE_LENGTH); + data_len = static_cast(X_len); + + msg_pA = System::PacketBuffer::NewWithAvailableSize(data_len); + VerifyOrExit(!msg_pA.IsNull(), err = CHIP_SYSTEM_ERROR_NO_MEMORY); + + memcpy(msg_pA->Start(), &X[0], X_len); + + msg_pA->SetDataLength(data_len); + mNextExpectedMsg = Protocols::SecureChannel::MsgType::PASE_Spake2p2; + + // Call delegate to send the Msg1 to peer + err = AttachHeaderAndSend(Protocols::SecureChannel::MsgType::PASE_Spake2p1, std::move(msg_pA)); + SuccessOrExit(err); + + ChipLogDetail(Ble, "Sent spake2p msg1"); + +exit: + return err; +} + +CHIP_ERROR SecurePairingSession::HandleMsg1_and_SendMsg2(const PacketHeader & header, const System::PacketBufferHandle & msg) { CHIP_ERROR err = CHIP_NO_ERROR; @@ -292,10 +530,12 @@ CHIP_ERROR SecurePairingSession::HandleCompute_pA(const PacketHeader & header, c uint16_t data_len; // To be initialized once we compute it. const uint8_t * buf = msg->Start(); - size_t buf_len = msg->TotalLength(); + size_t buf_len = msg->DataLength(); System::PacketBufferHandle resp; + ChipLogDetail(Ble, "Received spake2p msg1"); + VerifyOrExit(buf != nullptr, err = CHIP_ERROR_MESSAGE_INCOMPLETE); VerifyOrExit(buf_len == kMAX_Point_Length, err = CHIP_ERROR_INVALID_MESSAGE_LENGTH); @@ -328,20 +568,24 @@ CHIP_ERROR SecurePairingSession::HandleCompute_pA(const PacketHeader & header, c } resp->SetDataLength(data_len); - mNextExpectedMsg = Spake2pMsgType::kSpake2pCompute_cA; + mNextExpectedMsg = Protocols::SecureChannel::MsgType::PASE_Spake2p3; - // Call delegate to send the Compute_pB_cB to peer - err = AttachHeaderAndSend(Spake2pMsgType::kSpake2pCompute_pB_cB, resp.Release_ForNow()); + // Call delegate to send the Msg2 to peer + err = AttachHeaderAndSend(Protocols::SecureChannel::MsgType::PASE_Spake2p2, std::move(resp)); SuccessOrExit(err); - return err; + + ChipLogDetail(Ble, "Sent spake2p msg2"); exit: - mNextExpectedMsg = Spake2pMsgType::kSpake2pMsgTypeMax; + if (err != CHIP_NO_ERROR) + { + SendErrorMsg(Spake2pErrorType::kUnexpected); + } return err; } -CHIP_ERROR SecurePairingSession::HandleCompute_pB_cB(const PacketHeader & header, const System::PacketBufferHandle & msg) +CHIP_ERROR SecurePairingSession::HandleMsg2_and_SendMsg3(const PacketHeader & header, const System::PacketBufferHandle & msg) { CHIP_ERROR err = CHIP_NO_ERROR; @@ -350,10 +594,14 @@ CHIP_ERROR SecurePairingSession::HandleCompute_pB_cB(const PacketHeader & header uint16_t verifier_len; // To be inited one we check length is small enough const uint8_t * buf = msg->Start(); - size_t buf_len = msg->TotalLength(); + size_t buf_len = msg->DataLength(); System::PacketBufferHandle resp; + Spake2pErrorType spake2pErr = Spake2pErrorType::kUnexpected; + + ChipLogDetail(Ble, "Received spake2p msg2"); + VerifyOrExit(buf != nullptr, err = CHIP_ERROR_MESSAGE_INCOMPLETE); VerifyOrExit(buf_len == kMAX_Point_Length + kMAX_Hash_Length, err = CHIP_ERROR_INVALID_MESSAGE_LENGTH); @@ -376,14 +624,20 @@ CHIP_ERROR SecurePairingSession::HandleCompute_pB_cB(const PacketHeader & header resp->SetDataLength(verifier_len); - // Call delegate to send the Compute_cA to peer - err = AttachHeaderAndSend(Spake2pMsgType::kSpake2pCompute_cA, resp.Release_ForNow()); + // Call delegate to send the Msg3 to peer + err = AttachHeaderAndSend(Protocols::SecureChannel::MsgType::PASE_Spake2p3, std::move(resp)); SuccessOrExit(err); + ChipLogDetail(Ble, "Sent spake2p msg3"); + { const uint8_t * hash = &buf[kMAX_Point_Length]; err = mSpake2p.KeyConfirm(hash, kMAX_Hash_Length); - SuccessOrExit(err); + if (err != CHIP_NO_ERROR) + { + spake2pErr = Spake2pErrorType::kInvalidKeyConfirmation; + SuccessOrExit(err); + } err = mSpake2p.GetKeys(mKe, &mKeLen); SuccessOrExit(err); @@ -396,27 +650,37 @@ CHIP_ERROR SecurePairingSession::HandleCompute_pB_cB(const PacketHeader & header exit: - mNextExpectedMsg = Spake2pMsgType::kSpake2pMsgTypeMax; + if (err != CHIP_NO_ERROR) + { + SendErrorMsg(spake2pErr); + } return err; } -CHIP_ERROR SecurePairingSession::HandleCompute_cA(const PacketHeader & header, const System::PacketBufferHandle & msg) +CHIP_ERROR SecurePairingSession::HandleMsg3(const PacketHeader & header, const System::PacketBufferHandle & msg) { - CHIP_ERROR err = CHIP_NO_ERROR; - const uint8_t * hash = msg->Start(); + CHIP_ERROR err = CHIP_NO_ERROR; + const uint8_t * hash = msg->Start(); + Spake2pErrorType spake2pErr = Spake2pErrorType::kUnexpected; + + ChipLogDetail(Ble, "Received spake2p msg3"); - // We will set NextExpectedMsg to kSpake2pMsgTypeMax in all cases - // However, when we are using IP rendezvous, we might set it to kSpake2pCompute_pA. - mNextExpectedMsg = Spake2pMsgType::kSpake2pMsgTypeMax; + // We will set NextExpectedMsg to PASE_Spake2pError in all cases + // However, when we are using IP rendezvous, we might set it to PASE_Spake2p1. + mNextExpectedMsg = Protocols::SecureChannel::MsgType::PASE_Spake2pError; VerifyOrExit(hash != nullptr, err = CHIP_ERROR_MESSAGE_INCOMPLETE); - VerifyOrExit(msg->TotalLength() == kMAX_Hash_Length, err = CHIP_ERROR_INVALID_MESSAGE_LENGTH); + VerifyOrExit(msg->DataLength() == kMAX_Hash_Length, err = CHIP_ERROR_INVALID_MESSAGE_LENGTH); VerifyOrExit(header.GetSourceNodeId() == mPeerNodeId, err = CHIP_ERROR_WRONG_NODE_ID); VerifyOrExit(header.GetEncryptionKeyID() == mPeerKeyId, err = CHIP_ERROR_INVALID_KEY_ID); err = mSpake2p.KeyConfirm(hash, kMAX_Hash_Length); - SuccessOrExit(err); + if (err != CHIP_NO_ERROR) + { + spake2pErr = Spake2pErrorType::kInvalidKeyConfirmation; + SuccessOrExit(err); + } err = mSpake2p.GetKeys(mKe, &mKeLen); SuccessOrExit(err); @@ -427,9 +691,54 @@ CHIP_ERROR SecurePairingSession::HandleCompute_cA(const PacketHeader & header, c mDelegate->OnPairingComplete(); exit: + + if (err != CHIP_NO_ERROR) + { + SendErrorMsg(spake2pErr); + } return err; } +void SecurePairingSession::SendErrorMsg(Spake2pErrorType errorCode) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + + System::PacketBufferHandle msg; + uint16_t msglen = sizeof(Spake2pErrorMsg); + Spake2pErrorMsg * pMsg = nullptr; + + msg = System::PacketBuffer::NewWithAvailableSize(msglen); + VerifyOrExit(!msg.IsNull(), err = CHIP_SYSTEM_ERROR_NO_MEMORY); + + pMsg = reinterpret_cast(msg->Start()); + pMsg->error = errorCode; + + msg->SetDataLength(msglen); + + err = AttachHeaderAndSend(Protocols::SecureChannel::MsgType::PASE_Spake2pError, std::move(msg)); + SuccessOrExit(err); + +exit: + Clear(); +} + +void SecurePairingSession::HandleErrorMsg(const PacketHeader & header, const System::PacketBufferHandle & msg) +{ + // Request message processing + const uint8_t * buf = msg->Start(); + size_t buflen = msg->DataLength(); + Spake2pErrorMsg * pMsg = nullptr; + + VerifyOrExit(buf != nullptr, ChipLogError(Ble, "Null error msg received during pairing")); + VerifyOrExit(buflen == sizeof(Spake2pErrorMsg), ChipLogError(Ble, "Error msg with incorrect length received during pairing")); + + pMsg = reinterpret_cast(msg->Start()); + ChipLogError(Ble, "Received error (%d) during pairing process", pMsg->error); + +exit: + Clear(); +} + CHIP_ERROR SecurePairingSession::HandlePeerMessage(const PacketHeader & packetHeader, const Transport::PeerAddress & peerAddress, System::PacketBufferHandle msg) { @@ -449,18 +758,26 @@ CHIP_ERROR SecurePairingSession::HandlePeerMessage(const PacketHeader & packetHe mPeerAddress = peerAddress; - switch (static_cast(payloadHeader.GetMessageType())) + switch (static_cast(payloadHeader.GetMessageType())) { - case Spake2pMsgType::kSpake2pCompute_pA: - err = HandleCompute_pA(packetHeader, msg); + case Protocols::SecureChannel::MsgType::PBKDFParamRequest: + err = HandlePBKDFParamRequest(packetHeader, msg); + break; + + case Protocols::SecureChannel::MsgType::PBKDFParamResponse: + err = HandlePBKDFParamResponse(packetHeader, msg); + break; + + case Protocols::SecureChannel::MsgType::PASE_Spake2p1: + err = HandleMsg1_and_SendMsg2(packetHeader, msg); break; - case Spake2pMsgType::kSpake2pCompute_pB_cB: - err = HandleCompute_pB_cB(packetHeader, msg); + case Protocols::SecureChannel::MsgType::PASE_Spake2p2: + err = HandleMsg2_and_SendMsg3(packetHeader, msg); break; - case Spake2pMsgType::kSpake2pCompute_cA: - err = HandleCompute_cA(packetHeader, msg); + case Protocols::SecureChannel::MsgType::PASE_Spake2p3: + err = HandleMsg3(packetHeader, msg); break; default: diff --git a/src/transport/SecurePairingSession.h b/src/transport/SecurePairingSession.h index 7693c2d94ecf9d..ea01fd17cb23d3 100644 --- a/src/transport/SecurePairingSession.h +++ b/src/transport/SecurePairingSession.h @@ -27,6 +27,7 @@ #pragma once #include +#include #include #include #include @@ -38,6 +39,8 @@ namespace chip { extern const char * kSpake2pI2RSessionInfo; extern const char * kSpake2pR2ISessionInfo; +constexpr uint16_t kPBKDFParamRandomNumberSize = 32; + using namespace Crypto; class DLL_EXPORT SecurePairingSessionDelegate @@ -53,7 +56,7 @@ class DLL_EXPORT SecurePairingSessionDelegate * @return CHIP_ERROR Error thrown when sending the message */ virtual CHIP_ERROR SendPairingMessage(const PacketHeader & header, const Transport::PeerAddress & peerAddress, - System::PacketBuffer * msgBuf) + System::PacketBufferHandle msgBuf) { return CHIP_ERROR_NOT_IMPLEMENTED; } @@ -122,18 +125,14 @@ class DLL_EXPORT SecurePairingSession * * @param peerAddress Address of peer to pair * @param peerSetUpPINCode Setup PIN code of the peer device - * @param pbkdf2IterCount Iteration count for PBKDF2 function - * @param salt Salt to be used for SPAKE2P opertation - * @param saltLen Length of salt * @param myNodeId Optional node id of local node * @param myKeyId Key ID to be assigned to the secure session on the peer node * @param delegate Callback object * * @return CHIP_ERROR The result of initialization */ - CHIP_ERROR Pair(const Transport::PeerAddress peerAddress, uint32_t peerSetUpPINCode, uint32_t pbkdf2IterCount, - const uint8_t * salt, size_t saltLen, Optional myNodeId, uint16_t myKeyId, - SecurePairingSessionDelegate * delegate); + CHIP_ERROR Pair(const Transport::PeerAddress peerAddress, uint32_t peerSetUpPINCode, Optional myNodeId, + uint16_t myKeyId, SecurePairingSessionDelegate * delegate); /** * @brief @@ -209,28 +208,40 @@ class DLL_EXPORT SecurePairingSession CHIP_ERROR FromSerializable(const SecurePairingSessionSerializable & output); private: - CHIP_ERROR Init(uint32_t setupCode, uint32_t pbkdf2IterCount, const uint8_t * salt, size_t saltLen, Optional myNodeId, - uint16_t myKeyId, SecurePairingSessionDelegate * delegate); + enum Spake2pErrorType : uint8_t + { + kInvalidKeyConfirmation = 0x00, + kUnexpected = 0xff, + }; - CHIP_ERROR HandleCompute_pA(const PacketHeader & header, const System::PacketBufferHandle & msg); - CHIP_ERROR HandleCompute_pB_cB(const PacketHeader & header, const System::PacketBufferHandle & msg); - CHIP_ERROR HandleCompute_cA(const PacketHeader & header, const System::PacketBufferHandle & msg); + CHIP_ERROR Init(Optional myNodeId, uint16_t myKeyId, uint32_t setupCode, SecurePairingSessionDelegate * delegate); - CHIP_ERROR AttachHeaderAndSend(uint8_t msgType, System::PacketBuffer * msgBuf); + CHIP_ERROR SetupSpake2p(uint32_t pbkdf2IterCount, const uint8_t * salt, size_t saltLen); - static constexpr size_t kSpake2p_WS_Length = kP256_FE_Length + 8; + CHIP_ERROR SendPBKDFParamRequest(); + CHIP_ERROR HandlePBKDFParamRequest(const PacketHeader & header, const System::PacketBufferHandle & msg); - enum Spake2pMsgType : uint8_t - { - kSpake2pCompute_pA = 0, - kSpake2pCompute_pB_cB = 1, - kSpake2pCompute_cA = 2, - kSpake2pMsgTypeMax = 3, - }; + CHIP_ERROR SendPBKDFParamResponse(); + CHIP_ERROR HandlePBKDFParamResponse(const PacketHeader & header, const System::PacketBufferHandle & msg); + + CHIP_ERROR SendMsg1(); + + CHIP_ERROR HandleMsg1_and_SendMsg2(const PacketHeader & header, const System::PacketBufferHandle & msg); + CHIP_ERROR HandleMsg2_and_SendMsg3(const PacketHeader & header, const System::PacketBufferHandle & msg); + CHIP_ERROR HandleMsg3(const PacketHeader & header, const System::PacketBufferHandle & msg); + + void SendErrorMsg(Spake2pErrorType errorCode); + void HandleErrorMsg(const PacketHeader & header, const System::PacketBufferHandle & msg); + + CHIP_ERROR AttachHeaderAndSend(Protocols::SecureChannel::MsgType msgType, System::PacketBufferHandle msgBuf); + + void Clear(); + + static constexpr size_t kSpake2p_WS_Length = kP256_FE_Length + 8; SecurePairingSessionDelegate * mDelegate = nullptr; - Spake2pMsgType mNextExpectedMsg = Spake2pMsgType::kSpake2pMsgTypeMax; + Protocols::SecureChannel::MsgType mNextExpectedMsg = Protocols::SecureChannel::MsgType::PASE_Spake2pError; Spake2p_P256_SHA256_HKDF_HMAC mSpake2p; @@ -239,6 +250,18 @@ class DLL_EXPORT SecurePairingSession /* w0s and w1s */ uint8_t mWS[2][kSpake2p_WS_Length]; + uint32_t mSetupPINCode; + + Hash_SHA256_stream mCommissioningHash; + uint32_t mIterationCount = 0; + uint16_t mSaltLength = 0; + uint8_t * mSalt = nullptr; + + struct Spake2pErrorMsg + { + Spake2pErrorType error; + }; + protected: Optional mLocalNodeId = Optional::Value(kUndefinedNodeId); diff --git a/src/transport/SecureSessionMgr.cpp b/src/transport/SecureSessionMgr.cpp index 35f13b18f46f5f..5d570e753d4721 100644 --- a/src/transport/SecureSessionMgr.cpp +++ b/src/transport/SecureSessionMgr.cpp @@ -31,6 +31,7 @@ #include #include +#include #include #include #include @@ -63,9 +64,8 @@ SecureSessionMgr::~SecureSessionMgr() CHIP_ERROR SecureSessionMgr::Init(NodeId localNodeId, System::Layer * systemLayer, TransportMgrBase * transportMgr) { - CHIP_ERROR err = CHIP_NO_ERROR; - VerifyOrExit(mState == State::kNotReady, err = CHIP_ERROR_INCORRECT_STATE); - VerifyOrExit(transportMgr != nullptr, err = CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrReturnError(mState == State::kNotReady, CHIP_ERROR_INCORRECT_STATE); + VerifyOrReturnError(transportMgr != nullptr, CHIP_ERROR_INVALID_ARGUMENT); mState = State::kInitialized; mLocalNodeId = localNodeId; @@ -74,28 +74,131 @@ CHIP_ERROR SecureSessionMgr::Init(NodeId localNodeId, System::Layer * systemLaye ChipLogProgress(Inet, "local node id is %llu\n", mLocalNodeId); - Mdns::DiscoveryManager::GetInstance().Init(); - Mdns::DiscoveryManager::GetInstance().RegisterResolveDelegate(this); - ScheduleExpiryTimer(); mTransportMgr->SetSecureSessionMgr(this); -exit: - return err; + return CHIP_NO_ERROR; +} + +Transport::Type SecureSessionMgr::GetTransportType(NodeId peerNodeId) +{ + PeerConnectionState * state = mPeerConnections.FindPeerConnectionState(peerNodeId, nullptr); + + if (state) + { + return state->GetPeerAddress().GetTransportType(); + } + + return Transport::Type::kUndefined; +} + +CHIP_ERROR SecureSessionMgr::SendMessage(SecureSessionHandle session, System::PacketBufferHandle msgBuf) +{ + PayloadHeader unusedPayloadHeader; + return SendMessage(session, unusedPayloadHeader, std::move(msgBuf)); } -CHIP_ERROR SecureSessionMgr::SendMessage(NodeId peerNodeId, System::PacketBufferHandle msgBuf) +CHIP_ERROR SecureSessionMgr::SendMessage(SecureSessionHandle session, PayloadHeader & payloadHeader, + System::PacketBufferHandle msgBuf, EncryptedPacketBufferHandle * bufferRetainSlot) { + PacketHeader ununsedPacketHeader; + return SendMessage(session, payloadHeader, ununsedPacketHeader, std::move(msgBuf), bufferRetainSlot, + EncryptionState::kPayloadIsUnencrypted); +} + +CHIP_ERROR SecureSessionMgr::SendEncryptedMessage(SecureSessionHandle session, EncryptedPacketBufferHandle msgBuf, + EncryptedPacketBufferHandle * bufferRetainSlot) +{ + VerifyOrReturnError(!msgBuf.IsNull(), CHIP_ERROR_INVALID_ARGUMENT); + + uint16_t headerSize = 0; + PacketHeader packetHeader; + ReturnErrorOnFailure(packetHeader.Decode(msgBuf->Start(), msgBuf->DataLength(), &headerSize)); + + // Advancing the start to encrypted header, since the transport will attach the packet header on top of it + msgBuf->SetStart(msgBuf->Start() + headerSize); + PayloadHeader payloadHeader; + return SendMessage(session, payloadHeader, packetHeader, std::move(msgBuf), bufferRetainSlot, + EncryptionState::kPayloadIsEncrypted); +} + +CHIP_ERROR SecureSessionMgr::EncryptPayload(Transport::PeerConnectionState * state, PayloadHeader & payloadHeader, + PacketHeader & packetHeader, System::PacketBufferHandle & msgBuf) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + uint8_t * data = nullptr; + uint32_t payloadLength = 0; // Make sure it's big enough to add two 16-bit ints without overflowing. + uint16_t totalLen = 0; + uint16_t taglen = 0; + uint16_t actualEncodedHeaderSize; + MessageAuthenticationCode mac; + + uint32_t msgId = state->GetSendMessageIndex(); + + static_assert(std::is_sameTotalLength()), uint16_t>::value, + "Addition to generate payloadLength might overflow"); + + uint16_t headerSize = payloadHeader.EncodeSizeBytes(); + payloadLength = static_cast(headerSize + msgBuf->TotalLength()); + VerifyOrExit(CanCastTo(payloadLength), err = CHIP_ERROR_NO_MEMORY); + + packetHeader + .SetSourceNodeId(mLocalNodeId) // + .SetDestinationNodeId(state->GetPeerNodeId()) // + .SetMessageId(msgId) // + .SetEncryptionKeyID(state->GetLocalKeyID()) // + .SetPayloadLength(static_cast(payloadLength)); + packetHeader.GetFlags().Set(Header::FlagValues::kSecure); + + VerifyOrExit(msgBuf->EnsureReservedSize(headerSize), err = CHIP_ERROR_NO_MEMORY); + + msgBuf->SetStart(msgBuf->Start() - headerSize); + data = msgBuf->Start(); + totalLen = msgBuf->TotalLength(); + + err = payloadHeader.Encode(data, totalLen, &actualEncodedHeaderSize); + SuccessOrExit(err); + + err = state->GetSecureSession().Encrypt(data, totalLen, data, packetHeader, mac); + SuccessOrExit(err); + err = mac.Encode(packetHeader, &data[totalLen], kMaxTagLen, &taglen); + SuccessOrExit(err); + + VerifyOrExit(CanCastTo(totalLen + taglen), err = CHIP_ERROR_INTERNAL); + msgBuf->SetDataLength(static_cast(totalLen + taglen)); - return SendMessage(payloadHeader, peerNodeId, std::move(msgBuf)); + ChipLogDetail(Inet, "Secure transport encrypted msg %u", msgId); + +exit: + if (err != CHIP_NO_ERROR) + { + const char * errStr = ErrorStr(err); + ChipLogError(Inet, "Secure transport failed to encrypt msg %u: %s", state->GetSendMessageIndex(), errStr); + } + else + { + state->IncrementSendMessageIndex(); + } + + return err; } -CHIP_ERROR SecureSessionMgr::SendMessage(PayloadHeader & payloadHeader, NodeId peerNodeId, System::PacketBufferHandle msgBuf) +CHIP_ERROR SecureSessionMgr::SendMessage(SecureSessionHandle session, PayloadHeader & payloadHeader, PacketHeader & packetHeader, + System::PacketBufferHandle msgBuf, EncryptedPacketBufferHandle * bufferRetainSlot, + EncryptionState encryptionState) { CHIP_ERROR err = CHIP_NO_ERROR; - PeerConnectionState * state = mPeerConnections.FindPeerConnectionState(peerNodeId, nullptr); + PeerConnectionState * state = nullptr; + uint8_t * msgStart = nullptr; + uint16_t msgLen = 0; + uint16_t headerSize = 0; + + // Hold the reference to encrypted message in stack variable. + // In case of any failures, the reference is not returned, and this stack variable + // will automatically free the reference on returning from the function. + EncryptedPacketBufferHandle encryptedMsg; VerifyOrExit(mState == State::kInitialized, err = CHIP_ERROR_INCORRECT_STATE); @@ -104,61 +207,43 @@ CHIP_ERROR SecureSessionMgr::SendMessage(PayloadHeader & payloadHeader, NodeId p VerifyOrExit(msgBuf->TotalLength() < kMax_SecureSDU_Length, err = CHIP_ERROR_INVALID_MESSAGE_LENGTH); // Find an active connection to the specified peer node - VerifyOrExit(state != nullptr, err = CHIP_ERROR_INVALID_DESTINATION_NODE_ID); + state = GetPeerConnectionState(session); + VerifyOrExit(state != nullptr, err = CHIP_ERROR_NOT_CONNECTED); // This marks any connection where we send data to as 'active' mPeerConnections.MarkConnectionActive(state); + if (encryptionState == EncryptionState::kPayloadIsUnencrypted) { - uint8_t * data = nullptr; - PacketHeader packetHeader; - MessageAuthenticationCode mac; - - const uint16_t headerSize = payloadHeader.EncodeSizeBytes(); - uint16_t actualEncodedHeaderSize; - uint16_t totalLen = 0; - uint16_t taglen = 0; - uint32_t payloadLength; // Make sure it's big enough to add two 16-bit - // ints without overflowing. - static_assert(std::is_sameTotalLength()), uint16_t>::value, - "Addition to generate payloadLength might overflow"); - payloadLength = static_cast(headerSize + msgBuf->TotalLength()); - VerifyOrExit(CanCastTo(payloadLength), err = CHIP_ERROR_NO_MEMORY); - - packetHeader - .SetSourceNodeId(mLocalNodeId) // - .SetDestinationNodeId(peerNodeId) // - .SetMessageId(state->GetSendMessageIndex()) // - .SetEncryptionKeyID(state->GetLocalKeyID()) // - .SetPayloadLength(static_cast(payloadLength)); - packetHeader.GetFlags().Set(Header::FlagValues::kSecure); - - ChipLogProgress(Inet, "Sending msg from %llu to %llu", mLocalNodeId, peerNodeId); - - VerifyOrExit(msgBuf->EnsureReservedSize(headerSize), err = CHIP_ERROR_NO_MEMORY); - - msgBuf->SetStart(msgBuf->Start() - headerSize); - data = msgBuf->Start(); - totalLen = msgBuf->TotalLength(); - - err = payloadHeader.Encode(data, totalLen, &actualEncodedHeaderSize); + err = EncryptPayload(state, payloadHeader, packetHeader, msgBuf); SuccessOrExit(err); + } - err = state->GetSecureSession().Encrypt(data, totalLen, data, packetHeader, mac); - SuccessOrExit(err); + // The start of buffer points to the beginning of the encrypted header, and the length of buffer + // contains both the encrypted header and encrypted data. + // Locally store the start and length of the retained buffer after accounting for the size of packet header. + headerSize = packetHeader.EncodeSizeBytes(); - err = mac.Encode(packetHeader, &data[totalLen], kMaxTagLen, &taglen); - SuccessOrExit(err); + msgStart = static_cast(msgBuf->Start() - headerSize); + msgLen = static_cast(msgBuf->DataLength() + headerSize); - VerifyOrExit(CanCastTo(totalLen + taglen), err = CHIP_ERROR_INTERNAL); - msgBuf->SetDataLength(static_cast(totalLen + taglen), nullptr); + // Retain the PacketBuffer in case it's needed for retransmissions. + encryptedMsg = msgBuf.Retain(); + encryptedMsg.mMsgId = packetHeader.GetMessageId(); - ChipLogDetail(Inet, "Secure transport transmitting msg %u after encryption", state->GetSendMessageIndex()); + ChipLogProgress(Inet, "Sending msg from %llu to %llu", mLocalNodeId, state->GetPeerNodeId()); - err = mTransportMgr->SendMessage(packetHeader, state->GetPeerAddress(), msgBuf.Release_ForNow()); - } + err = mTransportMgr->SendMessage(packetHeader, state->GetPeerAddress(), std::move(msgBuf)); SuccessOrExit(err); - state->IncrementSendMessageIndex(); + + if (bufferRetainSlot != nullptr) + { + // Rewind the start and len of the buffer back to pre-send state for following possible retransmition. + encryptedMsg->SetStart(msgStart); + encryptedMsg->SetDataLength(msgLen); + + (*bufferRetainSlot) = std::move(encryptedMsg); + } exit: if (!msgBuf.IsNull()) @@ -168,10 +253,6 @@ CHIP_ERROR SecureSessionMgr::SendMessage(PayloadHeader & payloadHeader, NodeId p { ChipLogError(Inet, "Secure transport could not find a valid PeerConnection: %s", errStr); } - else - { - ChipLogError(Inet, "Secure transport failed to encrypt msg %u: %s", state->GetSendMessageIndex(), errStr); - } } return err; @@ -196,8 +277,8 @@ CHIP_ERROR SecureSessionMgr::NewPairing(const Optional & ChipLogDetail(Inet, "New pairing for device %llu, key %d!!", peerNodeId, peerKeyId); state = nullptr; - err = mPeerConnections.CreateNewPeerConnectionState(Optional::Value(peerNodeId), peerKeyId, localKeyId, &state); - SuccessOrExit(err); + ReturnErrorOnFailure( + mPeerConnections.CreateNewPeerConnectionState(Optional::Value(peerNodeId), peerKeyId, localKeyId, &state)); if (peerAddr.HasValue() && peerAddr.Value().GetIPAddress() != Inet::IPAddress::Any) { @@ -207,56 +288,20 @@ CHIP_ERROR SecureSessionMgr::NewPairing(const Optional & (peerAddr.Value().GetTransportType() == Transport::Type::kTcp || peerAddr.Value().GetTransportType() == Transport::Type::kUdp)) { - uint64_t fabricId = 0; - -#if !CHIP_DEVICE_LAYER_NONE - SuccessOrExit(err = chip::DeviceLayer::ConfigurationMgr().GetFabricId(fabricId)); -#endif - SuccessOrExit(err = Mdns::DiscoveryManager::GetInstance().ResolveNodeId(peerNodeId, fabricId)); + return CHIP_ERROR_INVALID_ARGUMENT; } if (state != nullptr) { err = pairing->DeriveSecureSession(reinterpret_cast(kSpake2pI2RSessionInfo), strlen(kSpake2pI2RSessionInfo), state->GetSecureSession()); - } - -exit: - return err; -} - -void SecureSessionMgr::HandleNodeIdResolve(CHIP_ERROR error, NodeId nodeId, const Mdns::MdnsService & service) -{ - if (error != CHIP_NO_ERROR && mCB != nullptr) - { - mCB->OnAddressResolved(error, kUndefinedNodeId, this); - } - else if (nodeId == kUndefinedNodeId && mCB != nullptr) - { - mCB->OnAddressResolved(CHIP_ERROR_UNKNOWN_RESOURCE_ID, kUndefinedNodeId, this); - } - else if (error == CHIP_NO_ERROR && nodeId != kUndefinedNodeId) - { - PeerConnectionState * state = nullptr; - PeerAddress addr; - bool hasAddressUpdate = false; - - // Though the spec says the service name is _chip._tcp, we are not supporting tcp for now. - addr.SetTransportType(Transport::Type::kUdp).SetIPAddress(service.mAddress.Value()).SetPort(service.mPort); - - while ((state = mPeerConnections.FindPeerConnectionState(nodeId, state)) != nullptr) - { - if (state->GetPeerAddress().GetIPAddress() == Inet::IPAddress::Any) - { - hasAddressUpdate = true; - state->SetPeerAddress(addr); - } - } - if (hasAddressUpdate) + if (mCB != nullptr) { - mCB->OnAddressResolved(CHIP_NO_ERROR, nodeId, this); + mCB->OnNewConnection({ state->GetPeerNodeId(), state->GetPeerKeyID() }, this); } } + + return err; } void SecureSessionMgr::ScheduleExpiryTimer() @@ -328,7 +373,7 @@ void SecureSessionMgr::OnMessageReceived(const PacketHeader & packetHeader, cons err = mac.Decode(packetHeader, &data[payloadlen], static_cast(len - payloadlen), &taglen); VerifyOrExit(err == CHIP_NO_ERROR, ChipLogError(Inet, "Secure transport failed to decode MAC Tag: err %d", err)); len = static_cast(len - taglen); - msg->SetDataLength(len, nullptr); + msg->SetDataLength(len); err = state->GetSecureSession().Decrypt(data, len, plainText, packetHeader, mac); VerifyOrExit(err == CHIP_NO_ERROR, ChipLogError(Inet, "Secure transport failed to decrypt msg: err %d", err)); @@ -347,7 +392,8 @@ void SecureSessionMgr::OnMessageReceived(const PacketHeader & packetHeader, cons if (mCB != nullptr) { - mCB->OnMessageReceived(packetHeader, payloadHeader, state, std::move(msg), this); + mCB->OnMessageReceived(packetHeader, payloadHeader, { state->GetPeerNodeId(), state->GetPeerKeyID() }, std::move(msg), + this); } } @@ -367,7 +413,7 @@ void SecureSessionMgr::HandleConnectionExpired(const Transport::PeerConnectionSt if (mCB != nullptr) { - mCB->OnConnectionExpired(&state, this); + mCB->OnConnectionExpired({ state.GetPeerNodeId(), state.GetPeerKeyID() }, this); } mTransportMgr->Disconnect(state.GetPeerAddress()); @@ -386,4 +432,9 @@ void SecureSessionMgr::ExpiryTimerCallback(System::Layer * layer, void * param, mgr->ScheduleExpiryTimer(); // re-schedule the oneshot timer } +PeerConnectionState * SecureSessionMgr::GetPeerConnectionState(SecureSessionHandle session) +{ + return mPeerConnections.FindPeerConnectionState(Optional::Value(session.mPeerNodeId), session.mPeerKeyId, nullptr); +} + } // namespace chip diff --git a/src/transport/SecureSessionMgr.h b/src/transport/SecureSessionMgr.h index ec7400e083be89..c1ba6815129510 100644 --- a/src/transport/SecureSessionMgr.h +++ b/src/transport/SecureSessionMgr.h @@ -30,7 +30,6 @@ #include #include #include -#include #include #include #include @@ -38,12 +37,77 @@ #include #include #include +#include #include namespace chip { class SecureSessionMgr; +class SecureSessionHandle +{ +public: + SecureSessionHandle() : mPeerNodeId(kAnyNodeId), mPeerKeyId(0) {} + SecureSessionHandle(NodeId peerNodeId, uint16_t peerKeyId) : mPeerNodeId(peerNodeId), mPeerKeyId(peerKeyId) {} + + bool operator==(const SecureSessionHandle & that) const + { + return mPeerNodeId == that.mPeerNodeId && mPeerKeyId == that.mPeerKeyId; + } + +private: + friend class SecureSessionMgr; + NodeId mPeerNodeId; + uint16_t mPeerKeyId; +}; + +/** + * @brief + * Tracks ownership of a encrypted PacketBuffer. + * + * EncryptedPacketBufferHandle is a kind of PacketBufferHandle class and used to hold a PacketBuffer + * object whose payload has already been encrypted. + */ +class EncryptedPacketBufferHandle final : public System::PacketBufferHandle +{ +public: + EncryptedPacketBufferHandle() : mMsgId(0) {} + EncryptedPacketBufferHandle(EncryptedPacketBufferHandle && aBuffer) : + PacketBufferHandle(std::move(aBuffer)), mMsgId(aBuffer.mMsgId) + {} + + void operator=(EncryptedPacketBufferHandle && aBuffer) + { + PacketBufferHandle::operator=(std::move(aBuffer)); + mMsgId = aBuffer.mMsgId; + } + + uint32_t GetMsgId() const { return mMsgId; } + + /** + * Creates a copy of the data in this packet. + * + * Does NOT support chained buffers. + * + * @returns empty handle on allocation failure. + */ + EncryptedPacketBufferHandle CloneData() { return EncryptedPacketBufferHandle(PacketBufferHandle::CloneData()); } + +private: + // Allow SecureSessionMgr to assign or construct us from a PacketBufferHandle + friend class SecureSessionMgr; + + EncryptedPacketBufferHandle(PacketBufferHandle && aBuffer) : PacketBufferHandle(std::move(aBuffer)), mMsgId(0) {} + + void operator=(PacketBufferHandle && aBuffer) + { + PacketBufferHandle::operator=(std::move(aBuffer)); + mMsgId = 0; + } + + uint32_t mMsgId; // The message identifier of the CHIP message awaiting acknowledgment. +}; + /** * @brief * This class provides a skeleton for the callback functions. The functions will be @@ -61,13 +125,12 @@ class DLL_EXPORT SecureSessionMgrDelegate * * @param packetHeader The message header * @param payloadHeader The payload header - * @param state The connection state + * @param session The handle to the secure session * @param msgBuf The received message * @param mgr A pointer to the SecureSessionMgr */ virtual void OnMessageReceived(const PacketHeader & packetHeader, const PayloadHeader & payloadHeader, - const Transport::PeerConnectionState * state, System::PacketBufferHandle msgBuf, - SecureSessionMgr * mgr) + SecureSessionHandle session, System::PacketBufferHandle msgBuf, SecureSessionMgr * mgr) {} /** @@ -84,44 +147,45 @@ class DLL_EXPORT SecureSessionMgrDelegate * @brief * Called when a new pairing is being established * - * @param state connection state + * @param session The handle to the secure session * @param mgr A pointer to the SecureSessionMgr */ - virtual void OnNewConnection(const Transport::PeerConnectionState * state, SecureSessionMgr * mgr) {} + virtual void OnNewConnection(SecureSessionHandle session, SecureSessionMgr * mgr) {} /** * @brief * Called when a new connection is closing * - * @param state connection state - * @param mgr A pointer to the SecureSessionMgr - */ - virtual void OnConnectionExpired(const Transport::PeerConnectionState * state, SecureSessionMgr * mgr) {} - - /** - * @brief - * Called when the peer address is resolved from NodeID. - * - * @param error The resolution resolve error code - * @param nodeId The node ID resolved, 0 on error + * @param session The handle to the secure session * @param mgr A pointer to the SecureSessionMgr */ - virtual void OnAddressResolved(CHIP_ERROR error, NodeId nodeId, SecureSessionMgr * mgr) {} + virtual void OnConnectionExpired(SecureSessionHandle session, SecureSessionMgr * mgr) {} virtual ~SecureSessionMgrDelegate() {} }; -class DLL_EXPORT SecureSessionMgr : public Mdns::ResolveDelegate, public TransportMgrDelegate +class DLL_EXPORT SecureSessionMgr : public TransportMgrDelegate { public: + SecureSessionMgr(); + ~SecureSessionMgr() override; + /** * @brief - * Send a message to a currently connected peer + * Send a message to a currently connected peer. + * + * @details + * msgBuf contains the data to be transmitted. If bufferRetainSlot is not null and this function + * returns success, the encrypted data that was sent, as well as various other information needed + * to retransmit it, will be stored in *bufferRetainSlot. */ - CHIP_ERROR SendMessage(NodeId peerNodeId, System::PacketBufferHandle msgBuf); - CHIP_ERROR SendMessage(PayloadHeader & payloadHeader, NodeId peerNodeId, System::PacketBufferHandle msgBuf); - SecureSessionMgr(); - ~SecureSessionMgr() override; + CHIP_ERROR SendMessage(SecureSessionHandle session, System::PacketBufferHandle msgBuf); + CHIP_ERROR SendMessage(SecureSessionHandle session, PayloadHeader & payloadHeader, System::PacketBufferHandle msgBuf, + EncryptedPacketBufferHandle * bufferRetainSlot = nullptr); + CHIP_ERROR SendEncryptedMessage(SecureSessionHandle session, EncryptedPacketBufferHandle msgBuf, + EncryptedPacketBufferHandle * bufferRetainSlot); + + Transport::PeerConnectionState * GetPeerConnectionState(SecureSessionHandle session); /** * @brief @@ -159,6 +223,14 @@ class DLL_EXPORT SecureSessionMgr : public Mdns::ResolveDelegate, public Transpo */ CHIP_ERROR Init(NodeId localNodeId, System::Layer * systemLayer, TransportMgrBase * transportMgr); + /** + * @brief + * Return the transport type of current connection to the node with id peerNodeId. + * 'Transport::Type::kUndefined' will be returned if the connection to the specified + * peer node does not exist. + */ + Transport::Type GetTransportType(NodeId peerNodeId); + protected: /** * @brief @@ -181,6 +253,12 @@ class DLL_EXPORT SecureSessionMgr : public Mdns::ResolveDelegate, public Transpo kInitialized, /**< State when the object is ready connect to other peers. */ }; + enum class EncryptionState + { + kPayloadIsEncrypted, + kPayloadIsUnencrypted, + }; + System::Layer * mSystemLayer = nullptr; NodeId mLocalNodeId; // < Id of the current node Transport::PeerConnections mPeerConnections; // < Active connections to other peers @@ -189,6 +267,13 @@ class DLL_EXPORT SecureSessionMgr : public Mdns::ResolveDelegate, public Transpo SecureSessionMgrDelegate * mCB = nullptr; TransportMgrBase * mTransportMgr = nullptr; + CHIP_ERROR EncryptPayload(Transport::PeerConnectionState * state, PayloadHeader & payloadHeader, PacketHeader & packetHeader, + System::PacketBufferHandle & msgBuf); + + CHIP_ERROR SendMessage(SecureSessionHandle session, PayloadHeader & payloadHeader, PacketHeader & packetHeader, + System::PacketBufferHandle msgBuf, EncryptedPacketBufferHandle * bufferRetainSlot, + EncryptionState encryptionState); + /** Schedules a new oneshot timer for checking connection expiry. */ void ScheduleExpiryTimer(); @@ -204,8 +289,6 @@ class DLL_EXPORT SecureSessionMgr : public Mdns::ResolveDelegate, public Transpo * Callback for timer expiry check */ static void ExpiryTimerCallback(System::Layer * layer, void * param, System::Error error); - - void HandleNodeIdResolve(CHIP_ERROR error, NodeId nodeId, const Mdns::MdnsService & service) override; }; } // namespace chip diff --git a/src/transport/TransportMgr.h b/src/transport/TransportMgr.h index a2f8a085c50f24..c1c2ca07a74562 100644 --- a/src/transport/TransportMgr.h +++ b/src/transport/TransportMgr.h @@ -59,9 +59,9 @@ class TransportMgrBase public: CHIP_ERROR Init(Transport::Base * transport); - CHIP_ERROR SendMessage(const PacketHeader & header, const Transport::PeerAddress & address, System::PacketBuffer * msgBuf) + CHIP_ERROR SendMessage(const PacketHeader & header, const Transport::PeerAddress & address, System::PacketBufferHandle msgBuf) { - return mTransport->SendMessage(header, address, msgBuf); + return mTransport->SendMessage(header, address, std::move(msgBuf)); } void Disconnect(const Transport::PeerAddress & address) { mTransport->Disconnect(address); } diff --git a/src/transport/raw/Base.h b/src/transport/raw/Base.h index a7230562ff0ebb..d244e1de6e8aa5 100644 --- a/src/transport/raw/Base.h +++ b/src/transport/raw/Base.h @@ -62,12 +62,8 @@ class Base * @brief Send a message to the specified target. * * On connection-oriented transports, sending a message implies connecting to the target first. - * - * @details - * This method calls chip::System::PacketBuffer::Free on - * behalf of the caller regardless of the return status. */ - virtual CHIP_ERROR SendMessage(const PacketHeader & header, const PeerAddress & address, System::PacketBuffer * msgBuf) = 0; + virtual CHIP_ERROR SendMessage(const PacketHeader & header, const PeerAddress & address, System::PacketBufferHandle msgBuf) = 0; /** * Determine if this transport can SendMessage to the specified peer address. @@ -103,7 +99,7 @@ class Base * This function is the application callback that is invoked when a message is received over a * Chip connection. * - * @param[in] msgBuf A pointer to the PacketBuffer object holding the message. + * @param[in] msgBuf A handle to the PacketBuffer object holding the message. * * Callback *MUST* free msgBuf as a result of handling. */ diff --git a/src/transport/raw/TCP.cpp b/src/transport/raw/TCP.cpp index 137e7d10efedd0..3768615d8d431c 100644 --- a/src/transport/raw/TCP.cpp +++ b/src/transport/raw/TCP.cpp @@ -81,11 +81,7 @@ TCPBase::~TCPBase() for (size_t i = 0; i < mPendingPacketsSize; i++) { - if (mPendingPackets[i].packetBuffer != nullptr) - { - System::PacketBuffer::Free(mPendingPackets[i].packetBuffer); - mPendingPackets[i].packetBuffer = nullptr; - } + mPendingPackets[i].packetBuffer = nullptr; } } @@ -171,11 +167,9 @@ Inet::TCPEndPoint * TCPBase::FindActiveConnection(const PeerAddress & address) return nullptr; } -CHIP_ERROR TCPBase::SendMessage(const PacketHeader & header, const Transport::PeerAddress & address, System::PacketBuffer * msgBuf) +CHIP_ERROR TCPBase::SendMessage(const PacketHeader & header, const Transport::PeerAddress & address, + System::PacketBufferHandle msgBuf) { - System::PacketBufferHandle autofree; - autofree.Adopt(msgBuf); - // Sent buffer data format is: // - packet size as a uint16_t (inludes size of header and actual data) // - header @@ -210,15 +204,15 @@ CHIP_ERROR TCPBase::SendMessage(const PacketHeader & header, const Transport::Pe if (endPoint != nullptr) { - return endPoint->Send(autofree.Release_ForNow()); + return endPoint->Send(std::move(msgBuf)); } else { - return SendAfterConnect(address, autofree.Release_ForNow()); + return SendAfterConnect(address, std::move(msgBuf)); } } -CHIP_ERROR TCPBase::SendAfterConnect(const PeerAddress & addr, System::PacketBuffer * msg) +CHIP_ERROR TCPBase::SendAfterConnect(const PeerAddress & addr, System::PacketBufferHandle msg) { // This will initiate a connection to the specified peer CHIP_ERROR err = CHIP_NO_ERROR; @@ -231,7 +225,7 @@ CHIP_ERROR TCPBase::SendAfterConnect(const PeerAddress & addr, System::PacketBuf // does NOT need to be re-established. for (size_t i = 0; i < mPendingPacketsSize; i++) { - if (mPendingPackets[i].packetBuffer == nullptr) + if (mPendingPackets[i].packetBuffer.IsNull()) { if (packet == nullptr) { @@ -247,10 +241,9 @@ CHIP_ERROR TCPBase::SendAfterConnect(const PeerAddress & addr, System::PacketBuf // ensure packets are ORDERED if (packet != nullptr) { - packet->peerAddress = addr; - packet->packetBuffer = mPendingPackets[i].packetBuffer; - mPendingPackets[i].packetBuffer = nullptr; - packet = mPendingPackets + i; + packet->peerAddress = addr; + packet->packetBuffer = std::move(mPendingPackets[i].packetBuffer); + packet = mPendingPackets + i; } } } @@ -283,18 +276,12 @@ CHIP_ERROR TCPBase::SendAfterConnect(const PeerAddress & addr, System::PacketBuf // enqueue the packet once the connection succeeds packet->peerAddress = addr; - packet->packetBuffer = msg; - msg = nullptr; + packet->packetBuffer = std::move(msg); mUsedEndPointCount++; exit: if (err != CHIP_NO_ERROR) { - if (msg != nullptr) - { - System::PacketBuffer::Free(msg); - msg = nullptr; - } if (endPoint != nullptr) { endPoint->Free(); @@ -434,23 +421,19 @@ void TCPBase::OnConnectionComplete(Inet::TCPEndPoint * endPoint, INET_ERROR inet // Send any pending packets for (size_t i = 0; i < tcp->mPendingPacketsSize; i++) { - if ((tcp->mPendingPackets[i].peerAddress != addr) || (tcp->mPendingPackets[i].packetBuffer == nullptr)) + if ((tcp->mPendingPackets[i].peerAddress != addr) || (tcp->mPendingPackets[i].packetBuffer.IsNull())) { continue; } foundPendingPacket = true; + System::PacketBufferHandle buffer = std::move(tcp->mPendingPackets[i].packetBuffer); + tcp->mPendingPackets[i].peerAddress = PeerAddress::Uninitialized(); + if ((inetErr == CHIP_NO_ERROR) && (err == CHIP_NO_ERROR)) { - err = endPoint->Send(tcp->mPendingPackets[i].packetBuffer); - } - else - { - System::PacketBuffer::Free(tcp->mPendingPackets[i].packetBuffer); + err = endPoint->Send(std::move(buffer)); } - - tcp->mPendingPackets[i].packetBuffer = nullptr; - tcp->mPendingPackets[i].peerAddress = PeerAddress::Uninitialized(); } if (err == CHIP_NO_ERROR) diff --git a/src/transport/raw/TCP.h b/src/transport/raw/TCP.h index 407f5dcd1682f4..ec355fe67f2ce8 100644 --- a/src/transport/raw/TCP.h +++ b/src/transport/raw/TCP.h @@ -25,6 +25,7 @@ #pragma once #include +#include #include #include @@ -83,8 +84,8 @@ class TcpListenParameters */ struct PendingPacket { - PeerAddress peerAddress; // where the packet is being sent to - System::PacketBuffer * packetBuffer; // what data needs to be sent + PeerAddress peerAddress; // where the packet is being sent to + System::PacketBufferHandle packetBuffer; // what data needs to be sent }; /** Implements a transport using TCP. */ @@ -105,13 +106,15 @@ class DLL_EXPORT TCPBase : public Base mActiveConnections(activeConnectionsBuffer), mActiveConnectionsSize(bufferSize), mPendingPackets(packetBuffers), mPendingPacketsSize(packetsBuffersSize) { - PendingPacket emptyPending{ - .peerAddress = PeerAddress::Uninitialized(), - .packetBuffer = nullptr, - }; - std::fill(mActiveConnections, mActiveConnections + mActiveConnectionsSize, nullptr); - std::fill(mPendingPackets, mPendingPackets + mPendingPacketsSize, emptyPending); + for (size_t i = 0; i < mPendingPacketsSize; ++i) + { + mPendingPackets[i].peerAddress = PeerAddress::Uninitialized(); + // In the typical case, the TCPBase constructor is invoked from the TCP constructor on its mPendingPackets, + // which has not yet been initialized. That means we can't do a normal move assignment or construction of + // the PacketBufferHandle, since that would call PacketBuffer::Free on the uninitialized data. + new (&mPendingPackets[i].packetBuffer) System::PacketBufferHandle(); + } } ~TCPBase() override; @@ -127,7 +130,7 @@ class DLL_EXPORT TCPBase : public Base */ CHIP_ERROR Init(TcpListenParameters & params); - CHIP_ERROR SendMessage(const PacketHeader & header, const PeerAddress & address, System::PacketBuffer * msgBuf) override; + CHIP_ERROR SendMessage(const PacketHeader & header, const PeerAddress & address, System::PacketBufferHandle msgBuf) override; void Disconnect(const PeerAddress & address) override; @@ -165,7 +168,7 @@ class DLL_EXPORT TCPBase : public Base * Ownership of msg is taken over and will be freed at some unspecified time * in the future (once connection succeeds/fails). */ - CHIP_ERROR SendAfterConnect(const PeerAddress & addr, System::PacketBuffer * msg); + CHIP_ERROR SendAfterConnect(const PeerAddress & addr, System::PacketBufferHandle msg); /** * Process a single received buffer from the specified peer address. @@ -238,7 +241,7 @@ class TCP : public TCPBase TCP() : TCPBase(mConnectionsBuffer, kActiveConnectionsSize, mPendingPackets, kPendingPacketSize) {} private: - Inet::TCPEndPoint * mConnectionsBuffer[kActiveConnectionsSize]; + Inet::TCPEndPoint * mConnectionsBuffer[kActiveConnectionsSize] = { 0 }; PendingPacket mPendingPackets[kPendingPacketSize]; }; diff --git a/src/transport/raw/Tuple.h b/src/transport/raw/Tuple.h index 810cbb89986315..509371fae218b1 100644 --- a/src/transport/raw/Tuple.h +++ b/src/transport/raw/Tuple.h @@ -81,9 +81,9 @@ template class Tuple : public Base { public: - CHIP_ERROR SendMessage(const PacketHeader & header, const PeerAddress & address, System::PacketBuffer * msgBuf) override + CHIP_ERROR SendMessage(const PacketHeader & header, const PeerAddress & address, System::PacketBufferHandle msgBuf) override { - return SendMessageImpl<0>(header, address, msgBuf); + return SendMessageImpl<0>(header, address, std::move(msgBuf)); } bool CanSendToPeer(const PeerAddress & address) override { return CanSendToPeerImpl<0>(address); } @@ -163,23 +163,22 @@ class Tuple : public Base * @param msgBuf the data to send. */ template ::type * = nullptr> - CHIP_ERROR SendMessageImpl(const PacketHeader & header, const PeerAddress & address, System::PacketBuffer * msgBuf) + CHIP_ERROR SendMessageImpl(const PacketHeader & header, const PeerAddress & address, System::PacketBufferHandle msgBuf) { Base * base = &std::get(mTransports); if (base->CanSendToPeer(address)) { - return base->SendMessage(header, address, msgBuf); + return base->SendMessage(header, address, std::move(msgBuf)); } - return SendMessageImpl(header, address, msgBuf); + return SendMessageImpl(header, address, std::move(msgBuf)); } /** * SendMessageImpl when N is out of range. Always returns an error code. */ template = sizeof...(TransportTypes))>::type * = nullptr> - CHIP_ERROR SendMessageImpl(const PacketHeader & header, const PeerAddress & address, System::PacketBuffer * msgBuf) + CHIP_ERROR SendMessageImpl(const PacketHeader & header, const PeerAddress & address, System::PacketBufferHandle msgBuf) { - System::PacketBuffer::Free(msgBuf); return CHIP_ERROR_NO_MESSAGE_HANDLER; } diff --git a/src/transport/raw/UDP.cpp b/src/transport/raw/UDP.cpp index bb9b5d870fe108..e31a247991f842 100644 --- a/src/transport/raw/UDP.cpp +++ b/src/transport/raw/UDP.cpp @@ -88,11 +88,8 @@ void UDP::Close() mState = State::kNotReady; } -CHIP_ERROR UDP::SendMessage(const PacketHeader & header, const Transport::PeerAddress & address, System::PacketBuffer * msgIn) +CHIP_ERROR UDP::SendMessage(const PacketHeader & header, const Transport::PeerAddress & address, System::PacketBufferHandle msgBuf) { - System::PacketBufferHandle msgBuf; - msgBuf.Adopt(msgIn); - const uint16_t headerSize = header.EncodeSizeBytes(); VerifyOrReturnError(address.GetTransportType() == Type::kUdp, CHIP_ERROR_INVALID_ARGUMENT); @@ -115,7 +112,7 @@ CHIP_ERROR UDP::SendMessage(const PacketHeader & header, const Transport::PeerAd VerifyOrReturnError(headerSize == actualEncodedHeaderSize, CHIP_ERROR_INTERNAL); - return mUDPEndPoint->SendMsg(&addrInfo, msgBuf.Release_ForNow()); + return mUDPEndPoint->SendMsg(&addrInfo, std::move(msgBuf)); } void UDP::OnUdpReceive(Inet::IPEndPointBasis * endPoint, System::PacketBufferHandle buffer, const Inet::IPPacketInfo * pktInfo) diff --git a/src/transport/raw/UDP.h b/src/transport/raw/UDP.h index 9db98220e5e9d0..e77b60343ca426 100644 --- a/src/transport/raw/UDP.h +++ b/src/transport/raw/UDP.h @@ -111,7 +111,7 @@ class DLL_EXPORT UDP : public Base void Close() override; CHIP_ERROR SendMessage(const PacketHeader & header, const Transport::PeerAddress & address, - System::PacketBuffer * msgBuf) override; + System::PacketBufferHandle msgBuf) override; bool CanSendToPeer(const Transport::PeerAddress & address) override { diff --git a/src/transport/raw/tests/TestTCP.cpp b/src/transport/raw/tests/TestTCP.cpp index c702447bce1c02..d0197042c2e509 100644 --- a/src/transport/raw/tests/TestTCP.cpp +++ b/src/transport/raw/tests/TestTCP.cpp @@ -123,7 +123,7 @@ void CheckMessageTest(nlTestSuite * inSuite, void * inContext, const IPAddress & header.SetSourceNodeId(kSourceNodeId).SetDestinationNodeId(kDestinationNodeId).SetMessageId(kMessageId); // Should be able to send a message to itself by just calling send. - err = tcp.SendMessage(header, Transport::PeerAddress::TCP(addr), buffer.Release_ForNow()); + err = tcp.SendMessage(header, Transport::PeerAddress::TCP(addr), std::move(buffer)); if (err == System::MapErrorPOSIX(EADDRNOTAVAIL)) { // TODO(#2698): the underlying system does not support IPV6. This early return diff --git a/src/transport/raw/tests/TestUDP.cpp b/src/transport/raw/tests/TestUDP.cpp index 147fa45116f2e3..1c55ddd83371d3 100644 --- a/src/transport/raw/tests/TestUDP.cpp +++ b/src/transport/raw/tests/TestUDP.cpp @@ -120,7 +120,7 @@ void CheckMessageTest(nlTestSuite * inSuite, void * inContext, const IPAddress & header.SetSourceNodeId(kSourceNodeId).SetDestinationNodeId(kDestinationNodeId).SetMessageId(kMessageId); // Should be able to send a message to itself by just calling send. - err = udp.SendMessage(header, Transport::PeerAddress::UDP(addr), buffer.Release_ForNow()); + err = udp.SendMessage(header, Transport::PeerAddress::UDP(addr), std::move(buffer)); if (err == System::MapErrorPOSIX(EADDRNOTAVAIL)) { // TODO(#2698): the underlying system does not support IPV6. This early return diff --git a/src/transport/tests/BUILD.gn b/src/transport/tests/BUILD.gn index 59416f30c21976..cbce6e5a635e9e 100644 --- a/src/transport/tests/BUILD.gn +++ b/src/transport/tests/BUILD.gn @@ -34,6 +34,7 @@ chip_test_suite("tests") { "${chip_root}/src/inet/tests:helpers", "${chip_root}/src/lib/core", "${chip_root}/src/lib/support", + "${chip_root}/src/protocols", "${chip_root}/src/transport", "${chip_root}/src/transport/raw/tests:helpers", "${nlio_root}:nlio", diff --git a/src/transport/tests/TestSecurePairingSession.cpp b/src/transport/tests/TestSecurePairingSession.cpp index 98208b9581751d..9d2d4c42e6e5a2 100644 --- a/src/transport/tests/TestSecurePairingSession.cpp +++ b/src/transport/tests/TestSecurePairingSession.cpp @@ -38,12 +38,10 @@ class TestSecurePairingDelegate : public SecurePairingSessionDelegate { public: CHIP_ERROR SendPairingMessage(const PacketHeader & header, const Transport::PeerAddress & peerAddress, - System::PacketBuffer * msgBuf) override + System::PacketBufferHandle msgBuf) override { mNumMessageSend++; - System::PacketBufferHandle msg_ForNow; - msg_ForNow.Adopt(msgBuf); - return (peer != nullptr) ? peer->HandlePeerMessage(header, peerAddress, std::move(msg_ForNow)) : mMessageSendError; + return (peer != nullptr) ? peer->HandlePeerMessage(header, peerAddress, std::move(msgBuf)) : mMessageSendError; } void OnPairingError(CHIP_ERROR error) override { mNumPairingErrors++; } @@ -82,14 +80,11 @@ void SecurePairingStartTest(nlTestSuite * inSuite, void * inContext) SecurePairingSession pairing; NL_TEST_ASSERT(inSuite, - pairing.Pair(Transport::PeerAddress(Transport::Type::kBle), 1234, 500, nullptr, 0, Optional::Value(1), 0, - &delegate) == CHIP_ERROR_INVALID_ARGUMENT); - NL_TEST_ASSERT(inSuite, - pairing.Pair(Transport::PeerAddress(Transport::Type::kBle), 1234, 500, (const uint8_t *) "salt", 4, - Optional::Value(1), 0, nullptr) == CHIP_ERROR_INVALID_ARGUMENT); + pairing.Pair(Transport::PeerAddress(Transport::Type::kBle), 1234, Optional::Value(1), 0, nullptr) != + CHIP_NO_ERROR); NL_TEST_ASSERT(inSuite, - pairing.Pair(Transport::PeerAddress(Transport::Type::kBle), 1234, 500, (const uint8_t *) "salt", 4, - Optional::Value(1), 0, &delegate) == CHIP_NO_ERROR); + pairing.Pair(Transport::PeerAddress(Transport::Type::kBle), 1234, Optional::Value(1), 0, &delegate) == + CHIP_NO_ERROR); NL_TEST_ASSERT(inSuite, delegate.mNumMessageSend == 1); @@ -98,8 +93,8 @@ void SecurePairingStartTest(nlTestSuite * inSuite, void * inContext) SecurePairingSession pairing1; NL_TEST_ASSERT(inSuite, - pairing1.Pair(Transport::PeerAddress(Transport::Type::kBle), 1234, 500, (const uint8_t *) "salt", 4, - Optional::Value(1), 0, &delegate) == CHIP_ERROR_BAD_REQUEST); + pairing1.Pair(Transport::PeerAddress(Transport::Type::kBle), 1234, Optional::Value(1), 0, &delegate) == + CHIP_ERROR_BAD_REQUEST); } void SecurePairingHandshakeTestCommon(nlTestSuite * inSuite, void * inContext, SecurePairingSession & pairingCommissioner, @@ -116,13 +111,13 @@ void SecurePairingHandshakeTestCommon(nlTestSuite * inSuite, void * inContext, S pairingAccessory.WaitForPairing(1234, 500, (const uint8_t *) "salt", 4, Optional::Value(1), 0, &delegateAccessory) == CHIP_NO_ERROR); NL_TEST_ASSERT(inSuite, - pairingCommissioner.Pair(Transport::PeerAddress(Transport::Type::kBle), 1234, 500, (const uint8_t *) "salt", 4, - Optional::Value(2), 0, &delegateCommissioner) == CHIP_NO_ERROR); + pairingCommissioner.Pair(Transport::PeerAddress(Transport::Type::kBle), 1234, Optional::Value(2), 0, + &delegateCommissioner) == CHIP_NO_ERROR); - NL_TEST_ASSERT(inSuite, delegateAccessory.mNumMessageSend == 1); + NL_TEST_ASSERT(inSuite, delegateAccessory.mNumMessageSend == 2); NL_TEST_ASSERT(inSuite, delegateAccessory.mNumPairingComplete == 1); - NL_TEST_ASSERT(inSuite, delegateCommissioner.mNumMessageSend == 2); + NL_TEST_ASSERT(inSuite, delegateCommissioner.mNumMessageSend == 3); NL_TEST_ASSERT(inSuite, delegateCommissioner.mNumPairingComplete == 1); } @@ -254,6 +249,7 @@ void LogV(uint8_t module, uint8_t category, const char * format, va_list argptr) { (void) module, (void) category; vfprintf(stderr, format, argptr); + fprintf(stderr, "\n"); } } // namespace Logging } // namespace chip diff --git a/src/transport/tests/TestSecureSessionMgr.cpp b/src/transport/tests/TestSecureSessionMgr.cpp index 7c72b78156e8e9..be2f9c47e1326a 100644 --- a/src/transport/tests/TestSecureSessionMgr.cpp +++ b/src/transport/tests/TestSecureSessionMgr.cpp @@ -22,7 +22,10 @@ */ #include +#include +#include #include +#include #include #include #include @@ -53,11 +56,34 @@ class LoopbackTransport : public Transport::Base /// Transports are required to have a constructor that takes exactly one argument CHIP_ERROR Init(const char * unused) { return CHIP_NO_ERROR; } - CHIP_ERROR SendMessage(const PacketHeader & header, const PeerAddress & address, System::PacketBuffer * msgBuf) override + CHIP_ERROR SendMessage(const PacketHeader & header, const PeerAddress & address, System::PacketBufferHandle msgBuf) override { - System::PacketBufferHandle msg_ForNow; - msg_ForNow.Adopt(msgBuf); - HandleMessageReceived(header, address, std::move(msg_ForNow)); + HandleMessageReceived(header, address, std::move(msgBuf)); + return CHIP_NO_ERROR; + } + + bool CanSendToPeer(const PeerAddress & address) override { return true; } +}; + +class OutgoingTransport : public Transport::Base +{ +public: + /// Transports are required to have a constructor that takes exactly one argument + CHIP_ERROR Init(const char * unused) { return CHIP_NO_ERROR; } + + CHIP_ERROR SendMessage(const PacketHeader & header, const PeerAddress & address, System::PacketBufferHandle msgBuf) override + { + const uint16_t headerSize = header.EncodeSizeBytes(); + System::PacketBufferHandle recvdMsg = msgBuf.CloneData(); + + VerifyOrReturnError(msgBuf->EnsureReservedSize(headerSize), CHIP_ERROR_NO_MEMORY); + + msgBuf->SetStart(msgBuf->Start() - headerSize); + + uint16_t actualEncodedHeaderSize; + ReturnErrorOnFailure(header.Encode(msgBuf->Start(), msgBuf->DataLength(), &actualEncodedHeaderSize)); + + HandleMessageReceived(header, address, std::move(recvdMsg)); return CHIP_NO_ERROR; } @@ -67,12 +93,12 @@ class LoopbackTransport : public Transport::Base class TestSessMgrCallback : public SecureSessionMgrDelegate { public: - void OnMessageReceived(const PacketHeader & header, const PayloadHeader & payloadHeader, const PeerConnectionState * state, + void OnMessageReceived(const PacketHeader & header, const PayloadHeader & payloadHeader, SecureSessionHandle session, System::PacketBufferHandle msgBuf, SecureSessionMgr * mgr) override { NL_TEST_ASSERT(mSuite, header.GetSourceNodeId() == Optional::Value(kSourceNodeId)); NL_TEST_ASSERT(mSuite, header.GetDestinationNodeId() == Optional::Value(kDestinationNodeId)); - NL_TEST_ASSERT(mSuite, state->GetPeerNodeId() == kSourceNodeId); + NL_TEST_ASSERT(mSuite, session == mRemoteToLocalSession); // Packet received by remote peer size_t data_len = msgBuf->DataLength(); @@ -82,9 +108,19 @@ class TestSessMgrCallback : public SecureSessionMgrDelegate ReceiveHandlerCallCount++; } - void OnNewConnection(const PeerConnectionState * state, SecureSessionMgr * mgr) override { NewConnectionHandlerCallCount++; } + void OnNewConnection(SecureSessionHandle session, SecureSessionMgr * mgr) override + { + if (NewConnectionHandlerCallCount == 0) + mRemoteToLocalSession = session; + if (NewConnectionHandlerCallCount == 1) + mLocalToRemoteSession = session; + NewConnectionHandlerCallCount++; + } + void OnConnectionExpired(SecureSessionHandle session, SecureSessionMgr * mgr) override {} - nlTestSuite * mSuite = nullptr; + nlTestSuite * mSuite = nullptr; + SecureSessionHandle mRemoteToLocalSession; + SecureSessionHandle mLocalToRemoteSession; int ReceiveHandlerCallCount = 0; int NewConnectionHandlerCallCount = 0; }; @@ -137,25 +173,237 @@ void CheckMessageTest(nlTestSuite * inSuite, void * inContext) secureSessionMgr.SetDelegate(&callback); + Optional peer(Transport::PeerAddress::UDP(addr, CHIP_PORT)); + + SecurePairingUsingTestSecret pairing1(Optional::Value(kSourceNodeId), 1, 2); + err = secureSessionMgr.NewPairing(peer, kSourceNodeId, &pairing1); + NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + + SecurePairingUsingTestSecret pairing2(Optional::Value(kDestinationNodeId), 2, 1); + err = secureSessionMgr.NewPairing(peer, kDestinationNodeId, &pairing2); + NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + + SecureSessionHandle localToRemoteSessoin = callback.mLocalToRemoteSession; + + // Should be able to send a message to itself by just calling send. + callback.ReceiveHandlerCallCount = 0; + + err = secureSessionMgr.SendMessage(localToRemoteSessoin, std::move(buffer)); + NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + + ctx.DriveIOUntil(1000 /* ms */, []() { return callback.ReceiveHandlerCallCount != 0; }); + + NL_TEST_ASSERT(inSuite, callback.ReceiveHandlerCallCount == 1); +} + +void SendEncryptedPacketTest(nlTestSuite * inSuite, void * inContext) +{ + TestContext & ctx = *reinterpret_cast(inContext); + + uint16_t payload_len = sizeof(PAYLOAD); + + ctx.GetInetLayer().SystemLayer()->Init(nullptr); + + chip::System::PacketBufferHandle buffer = chip::System::PacketBuffer::NewWithAvailableSize(payload_len); + NL_TEST_ASSERT(inSuite, !buffer.IsNull()); + + memmove(buffer->Start(), PAYLOAD, payload_len); + buffer->SetDataLength(payload_len); + + IPAddress addr; + IPAddress::FromString("127.0.0.1", addr); + CHIP_ERROR err = CHIP_NO_ERROR; + + TransportMgr transportMgr; + SecureSessionMgr secureSessionMgr; + + err = transportMgr.Init("LOOPBACK"); + NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + err = secureSessionMgr.Init(kSourceNodeId, ctx.GetInetLayer().SystemLayer(), &transportMgr); + NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + + callback.mSuite = inSuite; + + secureSessionMgr.SetDelegate(&callback); + + Optional peer(Transport::PeerAddress::UDP(addr, CHIP_PORT)); + SecurePairingUsingTestSecret pairing1(Optional::Value(kSourceNodeId), 1, 2); + err = secureSessionMgr.NewPairing(peer, kSourceNodeId, &pairing1); + NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + + SecurePairingUsingTestSecret pairing2(Optional::Value(kDestinationNodeId), 2, 1); + err = secureSessionMgr.NewPairing(peer, kDestinationNodeId, &pairing2); + NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + + SecureSessionHandle localToRemoteSessoin = callback.mLocalToRemoteSession; + + // Should be able to send a message to itself by just calling send. + callback.ReceiveHandlerCallCount = 0; + + PayloadHeader payloadHeader; + EncryptedPacketBufferHandle msgBuf; + + // Set the exchange ID for this header. + payloadHeader.SetExchangeID(0); + + // Set the protocol ID for this header. + payloadHeader.SetProtocolID(chip::Protocols::kProtocol_Echo); + + // Set the message type for this header. + payloadHeader.SetMessageType(chip::Protocols::kEchoMessageType_EchoRequest); + + payloadHeader.SetInitiator(true); + + err = secureSessionMgr.SendMessage(localToRemoteSessoin, payloadHeader, std::move(buffer), &msgBuf); + NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + + ctx.DriveIOUntil(1000 /* ms */, []() { return callback.ReceiveHandlerCallCount != 0; }); + NL_TEST_ASSERT(inSuite, callback.ReceiveHandlerCallCount == 1); + + err = secureSessionMgr.SendEncryptedMessage(localToRemoteSessoin, std::move(msgBuf), nullptr); + NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + + ctx.DriveIOUntil(1000 /* ms */, []() { return callback.ReceiveHandlerCallCount != 1; }); + NL_TEST_ASSERT(inSuite, callback.ReceiveHandlerCallCount == 2); +} + +void SendBadEncryptedPacketTest(nlTestSuite * inSuite, void * inContext) +{ + TestContext & ctx = *reinterpret_cast(inContext); + + uint16_t payload_len = sizeof(PAYLOAD); + + ctx.GetInetLayer().SystemLayer()->Init(nullptr); + + chip::System::PacketBufferHandle buffer = chip::System::PacketBuffer::NewWithAvailableSize(payload_len); + NL_TEST_ASSERT(inSuite, !buffer.IsNull()); + + memmove(buffer->Start(), PAYLOAD, payload_len); + buffer->SetDataLength(payload_len); + + IPAddress addr; + IPAddress::FromString("127.0.0.1", addr); + CHIP_ERROR err = CHIP_NO_ERROR; + + TransportMgr transportMgr; + SecureSessionMgr secureSessionMgr; + + err = transportMgr.Init("LOOPBACK"); + NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + err = secureSessionMgr.Init(kSourceNodeId, ctx.GetInetLayer().SystemLayer(), &transportMgr); + NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + + callback.mSuite = inSuite; + + secureSessionMgr.SetDelegate(&callback); + Optional peer(Transport::PeerAddress::UDP(addr, CHIP_PORT)); - err = secureSessionMgr.NewPairing(peer, kDestinationNodeId, &pairing1); + SecurePairingUsingTestSecret pairing1(Optional::Value(kSourceNodeId), 1, 2); + err = secureSessionMgr.NewPairing(peer, kSourceNodeId, &pairing1); NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); SecurePairingUsingTestSecret pairing2(Optional::Value(kDestinationNodeId), 2, 1); - err = secureSessionMgr.NewPairing(peer, kSourceNodeId, &pairing2); + err = secureSessionMgr.NewPairing(peer, kDestinationNodeId, &pairing2); NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + SecureSessionHandle localToRemoteSessoin = callback.mLocalToRemoteSession; + // Should be able to send a message to itself by just calling send. callback.ReceiveHandlerCallCount = 0; - err = secureSessionMgr.SendMessage(kDestinationNodeId, std::move(buffer)); + PayloadHeader payloadHeader; + EncryptedPacketBufferHandle msgBuf; + + // Set the exchange ID for this header. + payloadHeader.SetExchangeID(0); + + // Set the protocol ID for this header. + payloadHeader.SetProtocolID(chip::Protocols::kProtocol_Echo); + + // Set the message type for this header. + payloadHeader.SetMessageType(chip::Protocols::kEchoMessageType_EchoRequest); + + payloadHeader.SetInitiator(true); + + err = secureSessionMgr.SendMessage(localToRemoteSessoin, payloadHeader, std::move(buffer), &msgBuf); NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); ctx.DriveIOUntil(1000 /* ms */, []() { return callback.ReceiveHandlerCallCount != 0; }); + NL_TEST_ASSERT(inSuite, callback.ReceiveHandlerCallCount == 1); + + uint16_t headerSize = 0; + PacketHeader packetHeader; + + // Change Destination Node ID + EncryptedPacketBufferHandle badDestNodeIdMsg = msgBuf.CloneData(); + NL_TEST_ASSERT(inSuite, + packetHeader.Decode(badDestNodeIdMsg->Start(), badDestNodeIdMsg->DataLength(), &headerSize) == CHIP_NO_ERROR); + + NL_TEST_ASSERT(inSuite, packetHeader.GetDestinationNodeId().Value() == kDestinationNodeId); + packetHeader.SetDestinationNodeId(kSourceNodeId); + packetHeader.Encode(badDestNodeIdMsg->Start(), badDestNodeIdMsg->DataLength(), &headerSize); + + err = secureSessionMgr.SendEncryptedMessage(localToRemoteSessoin, std::move(badDestNodeIdMsg), nullptr); + NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + + ctx.DriveIOUntil(1000 /* ms */, []() { return callback.ReceiveHandlerCallCount != 1; }); NL_TEST_ASSERT(inSuite, callback.ReceiveHandlerCallCount == 1); + + // Change Source Node ID + EncryptedPacketBufferHandle badSrcNodeIdMsg = msgBuf.CloneData(); + NL_TEST_ASSERT(inSuite, + packetHeader.Decode(badSrcNodeIdMsg->Start(), badSrcNodeIdMsg->DataLength(), &headerSize) == CHIP_NO_ERROR); + + packetHeader.SetSourceNodeId(kDestinationNodeId); + packetHeader.Encode(badSrcNodeIdMsg->Start(), badSrcNodeIdMsg->DataLength(), &headerSize); + + err = secureSessionMgr.SendEncryptedMessage(localToRemoteSessoin, std::move(badSrcNodeIdMsg), nullptr); + NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + + ctx.DriveIOUntil(1000 /* ms */, []() { return callback.ReceiveHandlerCallCount != 1; }); + + NL_TEST_ASSERT(inSuite, callback.ReceiveHandlerCallCount == 1); + + // Change Message ID + EncryptedPacketBufferHandle badMessageIdMsg = msgBuf.CloneData(); + NL_TEST_ASSERT(inSuite, + packetHeader.Decode(badMessageIdMsg->Start(), badMessageIdMsg->DataLength(), &headerSize) == CHIP_NO_ERROR); + + uint32_t msgID = packetHeader.GetMessageId(); + packetHeader.SetMessageId(msgID + 1); + packetHeader.Encode(badMessageIdMsg->Start(), badMessageIdMsg->DataLength(), &headerSize); + + err = secureSessionMgr.SendEncryptedMessage(localToRemoteSessoin, std::move(badMessageIdMsg), nullptr); + NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + + ctx.DriveIOUntil(1000 /* ms */, []() { return callback.ReceiveHandlerCallCount != 1; }); + + NL_TEST_ASSERT(inSuite, callback.ReceiveHandlerCallCount == 1); + + // Change Key ID + EncryptedPacketBufferHandle badKeyIdMsg = msgBuf.CloneData(); + NL_TEST_ASSERT(inSuite, packetHeader.Decode(badKeyIdMsg->Start(), badKeyIdMsg->DataLength(), &headerSize) == CHIP_NO_ERROR); + + // the secure channel is setup to use key ID 1, and 2. So let's use 3 here. + packetHeader.SetEncryptionKeyID(3); + packetHeader.Encode(badKeyIdMsg->Start(), badKeyIdMsg->DataLength(), &headerSize); + + err = secureSessionMgr.SendEncryptedMessage(localToRemoteSessoin, std::move(badKeyIdMsg), nullptr); + NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + + ctx.DriveIOUntil(1000 /* ms */, []() { return callback.ReceiveHandlerCallCount != 1; }); + + NL_TEST_ASSERT(inSuite, callback.ReceiveHandlerCallCount == 1); + + // Send the correct encrypted msg + err = secureSessionMgr.SendEncryptedMessage(localToRemoteSessoin, std::move(msgBuf), nullptr); + NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + + ctx.DriveIOUntil(1000 /* ms */, []() { return callback.ReceiveHandlerCallCount != 1; }); + NL_TEST_ASSERT(inSuite, callback.ReceiveHandlerCallCount == 2); } // Test Suite @@ -166,8 +414,10 @@ void CheckMessageTest(nlTestSuite * inSuite, void * inContext) // clang-format off const nlTest sTests[] = { - NL_TEST_DEF("Simple Init Test", CheckSimpleInitTest), - NL_TEST_DEF("Message Self Test", CheckMessageTest), + NL_TEST_DEF("Simple Init Test", CheckSimpleInitTest), + NL_TEST_DEF("Message Self Test", CheckMessageTest), + NL_TEST_DEF("Send Encrypted Packet Test", SendEncryptedPacketTest), + NL_TEST_DEF("Send Bad Encrypted Packet Test", SendBadEncryptedPacketTest), NL_TEST_SENTINEL() }; diff --git a/third_party/freertos/BUILD.gn b/third_party/freertos/BUILD.gn new file mode 100644 index 00000000000000..d0c441c76900ec --- /dev/null +++ b/third_party/freertos/BUILD.gn @@ -0,0 +1,29 @@ +# Copyright (c) 2020 Project CHIP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +declare_args() { + # Use a different target, such as a prebuilt FreeRTOS + freertos_target = "" +} + +if (freertos_target != "") { + group("freertos") { + public_deps = [ freertos_target ] + } +} else { + import("freertos.gni") + + freertos_target("freertos") { + } +} diff --git a/third_party/freertos/freertos.gni b/third_party/freertos/freertos.gni new file mode 100644 index 00000000000000..a687ab84274a47 --- /dev/null +++ b/third_party/freertos/freertos.gni @@ -0,0 +1,53 @@ +# Copyright (c) 2020 Project CHIP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build_overrides/freertos.gni") + +template("freertos_target") { + freertos_target_name = target_name + + _freertos_root = "${freertos_root}/repo" + + config("${freertos_target_name}_config") { + include_dirs = [ "${_freertos_root}/include" ] + } + + source_set(freertos_target_name) { + forward_variables_from(invoker, "*") + + if (!defined(sources)) { + sources = [] + } + + sources += [ + "${_freertos_root}/croutine.c", + "${_freertos_root}/event_groups.c", + "${_freertos_root}/list.c", + "${_freertos_root}/queue.c", + "${_freertos_root}/stream_buffer.c", + "${_freertos_root}/tasks.c", + "${_freertos_root}/timers.c", + ] + + if (!defined(configs)) { + configs = [] + } + + if (!defined(public_configs)) { + public_configs = [] + } + + public_configs += [ ":${freertos_target_name}_config" ] + } +} diff --git a/third_party/freertos/repo b/third_party/freertos/repo new file mode 160000 index 00000000000000..88e32327e975dd --- /dev/null +++ b/third_party/freertos/repo @@ -0,0 +1 @@ +Subproject commit 88e32327e975ddde97c390bc5b6c1f8e7d9d239e diff --git a/third_party/mbedtls/mbedtls.gni b/third_party/mbedtls/mbedtls.gni index d56d81a88a7c3a..2ca76311b82e04 100644 --- a/third_party/mbedtls/mbedtls.gni +++ b/third_party/mbedtls/mbedtls.gni @@ -103,6 +103,7 @@ template("mbedtls_target") { "${_mbedtls_root}/library/x509.c", "${_mbedtls_root}/library/x509_create.c", "${_mbedtls_root}/library/x509_crl.c", + "${_mbedtls_root}/library/x509_crt.c", "${_mbedtls_root}/library/x509_csr.c", "${_mbedtls_root}/library/x509write_crt.c", "${_mbedtls_root}/library/x509write_csr.c", diff --git a/third_party/pigweed/repo b/third_party/pigweed/repo index e65ddc8b766dff..5a4db08b7b1df9 160000 --- a/third_party/pigweed/repo +++ b/third_party/pigweed/repo @@ -1 +1 @@ -Subproject commit e65ddc8b766dffdad83b74d440e836c1f7bcb2ed +Subproject commit 5a4db08b7b1df9261f5e2491ccb4d0caa10e6bb3 diff --git a/third_party/qpg_sdk/repo b/third_party/qpg_sdk/repo index 21e818a5a28a24..a5ce0ab12abb28 160000 --- a/third_party/qpg_sdk/repo +++ b/third_party/qpg_sdk/repo @@ -1 +1 @@ -Subproject commit 21e818a5a28a24fa7c97fbade5102cd54cad5b37 +Subproject commit a5ce0ab12abb28e9feb76e49e327b9127f3f4b40 diff --git a/third_party/ti_simplelink_sdk/BUILD.gn b/third_party/ti_simplelink_sdk/BUILD.gn new file mode 100644 index 00000000000000..9b8a69c55e56e5 --- /dev/null +++ b/third_party/ti_simplelink_sdk/BUILD.gn @@ -0,0 +1,71 @@ +# Copyright (c) 2020 Project CHIP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build_overrides/ti_simplelink_sdk.gni") +import("${ti_simplelink_sdk_build_root}/ti_simplelink_sdk.gni") + +declare_args() { + # Build target to use for TI SimpleLink SDK. Use this to set global SDK defines. + ti_simplelink_sdk_target = "" + ti_simplelink_sysconfig_target = "" +} + +assert(ti_simplelink_sdk_target != "", + "ti_simplelink_sdk_target must be specified") +assert(ti_simplelink_sysconfig_target != "", + "ti_simplelink_sysconfig_target must be specified") + +group("ti_simplelink_sdk") { + public_deps = [ ti_simplelink_sdk_target ] +} + +group("ti_simplelink_sysconfig") { + public_deps = [ ti_simplelink_sysconfig_target ] +} + +config("ti_simplelink_mbedtls_config") { + defines = [ "MBEDTLS_CONFIG_FILE=\"cc13x2_26x2-mbedtls-config.h\"" ] + + include_dirs = [ + "${chip_root}/src/platform/cc13x2_26x2", + "${ti_simplelink_sdk_root}/source", + "${ti_simplelink_sdk_root}/source/ti/thread/rtos/${ti_simplelink_board}/thread/libmbedcrypto/config", + ] +} + +mbedtls_target("mbedtls") { + sources = [ + # XXX: fill in hardware accelerated versions, how to link sysconfig dependent code? + ] + + public_configs = [ ":ti_simplelink_mbedtls_config" ] + + public_deps = [] +} + +config("ti_simplelink_freertos_config") { + include_dirs = [ + "${chip_root}/src/platform/cc13x2_26x2", + "${freertos_root}/repo/portable/GCC/ARM_CM4F", + ] +} + +freertos_target("freertos") { + sources = [ + "${freertos_root}/repo/portable/GCC/ARM_CM4F/port.c", + "${freertos_root}/repo/portable/MemMang/heap_4.c", + ] + + public_configs = [ ":ti_simplelink_freertos_config" ] +} diff --git a/third_party/ti_simplelink_sdk/run_sysconfig.py b/third_party/ti_simplelink_sdk/run_sysconfig.py new file mode 100644 index 00000000000000..0059ffab0f371a --- /dev/null +++ b/third_party/ti_simplelink_sdk/run_sysconfig.py @@ -0,0 +1,32 @@ +# Copyright 2020 Texas Instruments Incorporated + +"""A wrapper to run SysConfig. + +This script provides a basic Python wrapper for GN integration. + +Run with: + python run_sysconfig.py + +This script will attempt to run sh or cmd to run the wrapper scripts for the +SysConfig cmd line. +""" + +import sys +import subprocess + +# Select OS specific helper script +if sys.platform.startswith('linux'): + proc_call = [ sys.argv[1] + '/sysconfig_cli.sh' ] + +elif sys.platform.startswith('win'): + proc_call = [sys.argv[1] + '/sysconfig_cli.bat' ] + +else: + # guess sh? + proc_call = [sys.argv[1] + '/sysconfig_cli.sh' ] + +# Append cmd options +proc_call += sys.argv[2:] + +# exec +subprocess.call(proc_call) diff --git a/third_party/ti_simplelink_sdk/ti_simplelink_arm_platform_config.gni b/third_party/ti_simplelink_sdk/ti_simplelink_arm_platform_config.gni new file mode 100644 index 00000000000000..956a4828197209 --- /dev/null +++ b/third_party/ti_simplelink_sdk/ti_simplelink_arm_platform_config.gni @@ -0,0 +1,26 @@ +# Copyright (c) 2020 Project CHIP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("ti_simplelink_board.gni") + +if (ti_simplelink_device_family == "cc13x2_26x2") { + arm_arch = "armv7e-m" + arm_abi = "aapcs" + arm_cpu = "cortex-m4" + arm_float_abi = "hard" + arm_fpu = "fpv5-sp-d16" + arm_use_thumb = true +} else { + assert(false, "ti_simplelink_device_family must be specified") +} diff --git a/third_party/ti_simplelink_sdk/ti_simplelink_board.gni b/third_party/ti_simplelink_sdk/ti_simplelink_board.gni new file mode 100644 index 00000000000000..9c8dacfc524fec --- /dev/null +++ b/third_party/ti_simplelink_sdk/ti_simplelink_board.gni @@ -0,0 +1,49 @@ +# 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. + +declare_args() { + # TI SimpleLink board used + ti_simplelink_board = "" +} + +if (ti_simplelink_board == "") { + ti_simplelink_board = getenv("TI_SIMPLELINK_BOARD") +} + +assert(ti_simplelink_board != "", "ti_simplelink_board must be specified") + +# Differentiate between boards +# +# | Development Kit | Device Family | SoC | +# | ----------------- | ------------- | ---------- | +# | CC1352R1_LAUNCHXL | cc13x2_26x2 | cc1352r1f3 | +# | CC2652R1_LAUNCHXL | cc13x2_26x2 | cc2652r1f3 | + +# XXX: Can we do an array with a case statement? +if (ti_simplelink_board == "CC1352R1_LAUNCHXL") { + ti_simplelink_device_family = "cc13x2_26x2" + ti_simplelink_soc_family = "cc13x2" + + # set -DDeviceFamily_CC13X2? + ti_simplelink_soc = "cc1352r1f3" +} else if (ti_simplelink_board == "CC2652R1_LAUNCHXL") { + ti_simplelink_device_family = "cc13x2_26x2" + ti_simplelink_soc_family = "cc26x2" + + # set -DDeviceFamily_CC26X2? + ti_simplelink_soc = "cc2652r1f3" +} else { + print("Please provide a valid value for TI_SIMPLELINK_BOARD env variable") + assert(false, "The board ${ti_simplelink_board} is unsupported as for now.") +} diff --git a/third_party/ti_simplelink_sdk/ti_simplelink_executable.gni b/third_party/ti_simplelink_sdk/ti_simplelink_executable.gni new file mode 100644 index 00000000000000..0392032a83599d --- /dev/null +++ b/third_party/ti_simplelink_sdk/ti_simplelink_executable.gni @@ -0,0 +1,26 @@ +# Copyright (c) 2020 Project CHIP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/toolchain/flashable_executable.gni") + +template("ti_simplelink_executable") { + # we really only need the ELF + objcopy_image_name = invoker.output_name + ".hex" + objcopy_image_format = "ihex" + objcopy = "arm-none-eabi-objcopy" + + flashable_executable(target_name) { + forward_variables_from(invoker, "*") + } +} diff --git a/third_party/ti_simplelink_sdk/ti_simplelink_sdk.gni b/third_party/ti_simplelink_sdk/ti_simplelink_sdk.gni new file mode 100644 index 00000000000000..c444ba07d5fb19 --- /dev/null +++ b/third_party/ti_simplelink_sdk/ti_simplelink_sdk.gni @@ -0,0 +1,267 @@ +# Copyright (c) 2020 Project CHIP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build_overrides/chip.gni") +import("//build_overrides/freertos.gni") +import("//build_overrides/mbedtls.gni") +import("//build_overrides/ti_simplelink_sdk.gni") + +import("${freertos_root}/freertos.gni") +import("${mbedtls_root}/mbedtls.gni") +import("ti_simplelink_board.gni") + +declare_args() { + # Location of the TI SimpleLink SDK. + ti_simplelink_sdk_root = "" + ti_sysconfig_root = "" +} + +assert(ti_simplelink_sdk_root != "", "ti_simplelink_sdk_root must be specified") +assert(ti_sysconfig_root != "", "ti_sysconfig_root must be specified") + +template("ti_sysconfig") { + assert(ti_sysconfig_root != "", "ti_sysconfig_root must be specified") + assert(ti_simplelink_sdk_root != "", + "ti_simplelink_sdk_root must be specified") + + output_dir = "${target_gen_dir}/${target_name}" + gen_outputs = [] + foreach(output, invoker.outputs) { + gen_outputs += [ output_dir + "/" + output ] + } + + config("${target_name}_config") { + include_dirs = [ + output_dir, + "${ti_simplelink_sdk_root}/source", + ] + defines = [] + ldflags = [] + + if (defined(invoker.include_dirs)) { + include_dirs += invoker.include_dirs + } + + if (ti_simplelink_device_family == "cc13x2_26x2") { + assert(ti_simplelink_soc_family != "", + "ti_simplelink_soc_family must be specified") + + ldflags += [ "-nostartfiles" ] + defines += [ "DeviceFamily_CC13X2_CC26X2" ] + } + } + + action("${target_name}_gen") { + script = "${ti_simplelink_sdk_build_root}/run_sysconfig.py" + sources = invoker.sources + outputs = gen_outputs + + args = [ + ti_sysconfig_root, + "-s", + ti_simplelink_sdk_root + "/.metadata/product.json", + "-o", + rebase_path(output_dir, root_build_dir), + "--compiler", + "gcc", + "--board", + "/ti/boards/" + ti_simplelink_board, + ] + + foreach(source, sources) { + args += [ rebase_path(source, root_build_dir) ] + } + } + + source_set(target_name) { + sources = gen_outputs + + public_configs = [ ":${target_name}_config" ] + public_deps = [ ":${target_name}_gen" ] + } +} + +template("ti_simplelink_sdk") { + if (defined(invoker.ti_simplelink_sdk_root)) { + ti_simplelink_sdk_root = invoker.ti_simplelink_sdk_root + } + + assert(ti_simplelink_sdk_root != "", + "ti_simplelink_sdk_root must be specified") + + sdk_target_name = target_name + + config("${sdk_target_name}_config") { + include_dirs = [] + libs = [] + if (defined(invoker.include_dirs)) { + include_dirs += invoker.include_dirs + } + + # Treat these includes as system includes, so warnings in them are not fatal. + include_dirs += [ + "${ti_simplelink_sdk_root}/kernel/freertos/builds/${ti_simplelink_device_family}/release", + + "${ti_simplelink_sdk_root}/source", + "${ti_simplelink_sdk_root}/source/third_party/CMSIS/Include", + + "${chip_root}/third_party/mbedtls/repo/include", + ] + defines = [] + + if (ti_simplelink_device_family == "cc13x2_26x2") { + assert(ti_simplelink_soc_family != "", + "ti_simplelink_soc_family must be specified") + + defines += [ "DeviceFamily_CC13X2_CC26X2" ] + + libs += [ + "${ti_simplelink_sdk_root}/source/ti/drivers/lib/gcc/m4f/drivers_${ti_simplelink_soc_family}.a", + "${ti_simplelink_sdk_root}/source/ti/devices/cc13x2_cc26x2/driverlib/bin/gcc/driverlib.lib", + "${ti_simplelink_sdk_root}/source/ti/drivers/rf/lib/rf_multiMode_${ti_simplelink_soc_family}.am4fg", + ] + } + + if (defined(invoker.defines)) { + defines += invoker.defines + } + } + + source_set("${sdk_target_name}_dpl") { + defines = [] + include_dirs = [] + + cflags = [ "-Wno-sign-compare" ] + + sources = [ + "${ti_simplelink_sdk_root}/kernel/freertos/dpl/AppHooks_freertos.c", + "${ti_simplelink_sdk_root}/kernel/freertos/dpl/ClockPCC26X2_freertos.c", + "${ti_simplelink_sdk_root}/kernel/freertos/dpl/DebugP_freertos.c", + "${ti_simplelink_sdk_root}/kernel/freertos/dpl/HwiPCC26X2_freertos.c", + "${ti_simplelink_sdk_root}/kernel/freertos/dpl/MutexP_freertos.c", + "${ti_simplelink_sdk_root}/kernel/freertos/dpl/PowerCC26X2_freertos.c", + "${ti_simplelink_sdk_root}/kernel/freertos/dpl/QueueP_freertos.c", + "${ti_simplelink_sdk_root}/kernel/freertos/dpl/SemaphoreP_freertos.c", + "${ti_simplelink_sdk_root}/kernel/freertos/dpl/StaticAllocs_freertos.c", + "${ti_simplelink_sdk_root}/kernel/freertos/dpl/SwiP_freertos.c", + "${ti_simplelink_sdk_root}/kernel/freertos/dpl/SystemP_freertos.c", + "${ti_simplelink_sdk_root}/kernel/freertos/dpl/TimerPCC26XX_freertos.c", + "${ti_simplelink_sdk_root}/kernel/freertos/startup/startup_cc13x2_cc26x2_gcc.c", + ] + + if (defined(invoker.sources)) { + sources += invoker.sources + } + + public_deps = [ "${chip_root}/third_party/ti_simplelink_sdk:freertos" ] + + public_configs = [ ":${sdk_target_name}_config" ] + } + + config("${sdk_target_name}_posix_config") { + include_dirs = [ "${ti_simplelink_sdk_root}/source/ti/posix/gcc" ] + cflags = [ + "-std=c11", + "-Wno-maybe-uninitialized", + "-Wno-sign-compare", + ] + } + + source_set("${sdk_target_name}_freertos") { + defines = [] + include_dirs = [] + + # POSIX-like porting layer is incompatable with the gnu definitions from -std=gnu11 + configs -= [ "//build/config/compiler:std_default" ] + configs += [ ":${sdk_target_name}_posix_config" ] + sources = [ + "${ti_simplelink_sdk_root}/source/ti/posix/freertos/clock.c", + "${ti_simplelink_sdk_root}/source/ti/posix/freertos/memory.c", + "${ti_simplelink_sdk_root}/source/ti/posix/freertos/mqueue.c", + "${ti_simplelink_sdk_root}/source/ti/posix/freertos/pthread.c", + "${ti_simplelink_sdk_root}/source/ti/posix/freertos/pthread_barrier.c", + "${ti_simplelink_sdk_root}/source/ti/posix/freertos/pthread_cond.c", + "${ti_simplelink_sdk_root}/source/ti/posix/freertos/pthread_mutex.c", + "${ti_simplelink_sdk_root}/source/ti/posix/freertos/pthread_rwlock.c", + "${ti_simplelink_sdk_root}/source/ti/posix/freertos/sched.c", + "${ti_simplelink_sdk_root}/source/ti/posix/freertos/semaphore.c", + "${ti_simplelink_sdk_root}/source/ti/posix/freertos/sleep.c", + "${ti_simplelink_sdk_root}/source/ti/posix/freertos/timer.c", + ] + + public_deps = [ ":${sdk_target_name}_dpl" ] + + public_configs = [ ":${sdk_target_name}_config" ] + } + + config("${sdk_target_name}_openthread_platform_config") { + defines = [ "NVOCMP_POSIX_MUTEX" ] + include_dirs = [ + "${chip_root}/third_party/openthread/repo/examples/platforms", + "${chip_root}/third_party/openthread/repo/src/core", + "${ti_simplelink_sdk_root}/source/ti/devices/cc13x2_cc26x2", + "${ti_simplelink_sdk_root}/examples/rtos/${ti_simplelink_board}/thread/cli_mtd", + ] + } + + source_set("${sdk_target_name}_openthread_platform") { + cflags = [ + "-Wno-int-conversion", + "-Wno-address-of-packed-member", + "-Wno-implicit-fallthrough", + ] + public_deps = [ + ":${sdk_target_name}_freertos", + "${chip_root}/third_party/ti_simplelink_sdk:freertos", + "${chip_root}/third_party/ti_simplelink_sdk:mbedtls", + "${chip_root}/third_party/ti_simplelink_sdk:ti_simplelink_sysconfig", + ] + + configs -= [ "//build/config/compiler:std_default" ] + configs += [ ":${sdk_target_name}_posix_config" ] + sources = [ + "${ti_simplelink_sdk_root}/examples/rtos/${ti_simplelink_board}/thread/cli_mtd/platform/alarm.c", + "${ti_simplelink_sdk_root}/examples/rtos/${ti_simplelink_board}/thread/cli_mtd/platform/alarm_micro.c", + "${ti_simplelink_sdk_root}/examples/rtos/${ti_simplelink_board}/thread/cli_mtd/platform/crypto/aes_alt.c", + "${ti_simplelink_sdk_root}/examples/rtos/${ti_simplelink_board}/thread/cli_mtd/platform/crypto/ecjpake_alt.c", + "${ti_simplelink_sdk_root}/examples/rtos/${ti_simplelink_board}/thread/cli_mtd/platform/crypto/sha256_alt.c", + "${ti_simplelink_sdk_root}/examples/rtos/${ti_simplelink_board}/thread/cli_mtd/platform/diag.c", + "${ti_simplelink_sdk_root}/examples/rtos/${ti_simplelink_board}/thread/cli_mtd/platform/entropy.c", + "${ti_simplelink_sdk_root}/examples/rtos/${ti_simplelink_board}/thread/cli_mtd/platform/misc.c", + "${ti_simplelink_sdk_root}/examples/rtos/${ti_simplelink_board}/thread/cli_mtd/platform/nv/crc.c", + "${ti_simplelink_sdk_root}/examples/rtos/${ti_simplelink_board}/thread/cli_mtd/platform/nv/nvocmp.c", + "${ti_simplelink_sdk_root}/examples/rtos/${ti_simplelink_board}/thread/cli_mtd/platform/radio.c", + "${ti_simplelink_sdk_root}/examples/rtos/${ti_simplelink_board}/thread/cli_mtd/platform/settings.c", + "${ti_simplelink_sdk_root}/examples/rtos/${ti_simplelink_board}/thread/cli_mtd/platform/system.c", + "${ti_simplelink_sdk_root}/examples/rtos/${ti_simplelink_board}/thread/cli_mtd/platform/uart.c", + ] + + public_configs = [ + ":${sdk_target_name}_config", + ":${sdk_target_name}_openthread_platform_config", + "${chip_root}/third_party/openthread/repo:openthread_config", + "${chip_root}/third_party/openthread/repo:openthread_mtd_config", + ] + } + + group(sdk_target_name) { + public_deps = [ + ":${sdk_target_name}_dpl", + ":${sdk_target_name}_freertos", + ] + if (ti_simplelink_device_family == "cc13x2_26x2") { + public_deps += [ ":${sdk_target_name}_openthread_platform" ] + } + } +}