From 7351aebe37781e121a19bc64af8159c6e6a5d715 Mon Sep 17 00:00:00 2001 From: Torsten Rasmussen Date: Tue, 26 Jan 2021 15:43:08 +0100 Subject: [PATCH 001/421] [nrf noup] ci: set `ZEPHYR__KCONFIG` for NCS modules MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit sets `ZEPHYR__KCONFIG` variable for each Kconfig file discovered in `nrf/modules//Kconfig`. This is not meant as a permanent solution; we should do more careful consideration on the optimal approach forward that will allow compliance_check.py to be used downstream with custom module_ext_roots, and at the same time keep current flexibility for module glue code handling intact. Signed-off-by: Torsten Rasmussen Signed-off-by: Martí Bolívar (cherry picked from commit c78a6eaec795464633b7fa68a8bc3a1ef4bf35c4) (cherry picked from commit 67e3d5e54b697a309b6095425d2fcb6971778dee) --- scripts/ci/check_compliance.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/scripts/ci/check_compliance.py b/scripts/ci/check_compliance.py index 8a70ffabeeb..74ddf19b2fb 100755 --- a/scripts/ci/check_compliance.py +++ b/scripts/ci/check_compliance.py @@ -310,6 +310,13 @@ def get_modules(self, modules_file): modules = [name for name in os.listdir(modules_dir) if os.path.exists(os.path.join(modules_dir, name, 'Kconfig'))] + nrf_modules_dir = ZEPHYR_BASE + '/../nrf/modules' + nrf_modules = [] + if os.path.exists(nrf_modules_dir): + nrf_modules = [name for name in os.listdir(nrf_modules_dir) if + os.path.exists(os.path.join(nrf_modules_dir, name, + 'Kconfig'))] + with open(modules_file, 'r') as fp_module_file: content = fp_module_file.read() @@ -319,6 +326,15 @@ def get_modules(self, modules_file): re.sub('[^a-zA-Z0-9]', '_', module).upper(), modules_dir + '/' + module + '/Kconfig' )) + for module in nrf_modules: + fp_module_file.write("ZEPHYR_{}_KCONFIG = {}\n".format( + re.sub('[^a-zA-Z0-9]', '_', module).upper(), + nrf_modules_dir + '/' + module + '/Kconfig' + )) + fp_module_file.write("NCS_{}_KCONFIG = {}\n".format( + re.sub('[^a-zA-Z0-9]', '_', module).upper(), + modules_dir + '/' + module + '/Kconfig' + )) fp_module_file.write(content) def get_kconfig_dts(self, kconfig_dts_file): From ed6a2048c3ab68de67b3fc37275fff453bfe5dfa Mon Sep 17 00:00:00 2001 From: Sebastian Wezel Date: Tue, 15 Mar 2022 13:12:25 +0100 Subject: [PATCH 002/421] [nrf noup] ci: add .github/test-spec.yml MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This file is used for NCS-specific testing configuration based on modifications to files in this repository. Signed-off-by: Alperen Sener Signed-off-by: Dominik Ermel Signed-off-by: Elisabeth Solheim Klakken Signed-off-by: Mariusz Poslinski Signed-off-by: Markus Swarowsky Signed-off-by: Robert Lubos Signed-off-by: Sebastian Wezel Signed-off-by: Tomasz Tyzenhauz Signed-off-by: Fredrik Ås Signed-off-by: Michał Szablowski Signed-off-by: Tony Le Signed-off-by: Krishna T (cherry picked from commit 2a59fbdf425895a357fc6bff919d3108b6e35469) (cherry picked from commit acb96b140c95e933546acc41cc6df22b609342db) (cherry picked from commit e102ad15b3804c9d71447dda2bf4e321ec4185fb) (cherry picked from commit f9eac37be8ef89db5b2cbb06e38aef09e13fc448) --- .github/test-spec.yml | 147 ++++++++++++++++++++++++++++++++++++++++++ CODEOWNERS | 1 + 2 files changed, 148 insertions(+) create mode 100644 .github/test-spec.yml diff --git a/.github/test-spec.yml b/.github/test-spec.yml new file mode 100644 index 00000000000..3fe9ba5fbec --- /dev/null +++ b/.github/test-spec.yml @@ -0,0 +1,147 @@ +# This is the Jenkins ci variant of the .github/labler.yaml +"CI-iot-zephyr-lwm2m-test": + - "drivers/console/**/*" + - "drivers/flash/**/*" + - "subsys/dfu/boot/**/*" + - "subsys/net/ip/**/*" + - "subsys/net/lib/http/**/*" + - "subsys/net/lib/lwm2m//**/*" + - "subsys/net/**/*" + +"CI-iot-samples-test": + - "boards/arm/nrf9160dk_nrf9160/**/*" + - "dts/arm/nordic/nrf9160*" + - "include/net/**/*" + - "subsys/net/lib/**/*" + +"CI-iot-libraries-test": + - "boards/arm/nrf9160dk_nrf9160/**/*" + - "dts/arm/nordic/nrf9160*" + - "include/net/socket_ncs.h" + - "subsys/testsuite/ztest/**/*" + +"CI-lwm2m-test": + - "**/*" + +"CI-boot-dfu-test": + - "subsys/mgmt/mcumgr/**/*" + - "subsys/dfu/**/*" + - "include/mgmt/mcumgr/**/*" + - "include/dfu/**/*" + - "samples/subsys/mgmt/mcumgr/smp_svr/**/*" + +"CI-tfm-test": + - "**/*" + +"CI-ble-test": + - "**/*" + +"CI-mesh-test": + - "subsys/bluetooth/mesh/**/*" + - "include/bluetooth/mesh/**/*" + - "samples/bluetooth/mesh/**/*" + - "samples/bluetooth/mesh_demo/**/*" + - "samples/bluetooth/mesh_provisioner/**/*" + - "tests/bluetooth/mesh/**/*" + - "tests/bluetooth/mesh_shell/**/*" + +"CI-zigbee-test": + - "subsys/mgmt/mcumgr/**/*" + - "subsys/dfu/**/*" + - "include/mgmt/mcumgr/**/*" + - "include/dfu/**/*" + +"CI-thingy91-test": + - "**/*" + +"CI-desktop-test": + - "**/*" + +"CI-crypto-test": + - "**/*" + +"CI-rs-test": + - "**/*" + +"CI-homekit-test": + - "include/dfu/**/*" + - "include/mgmt/mcumgr/**/*" + - "soc/arm/nordic_nrf/**/*" + - "subsys/dfu/**/*" + - "subsys/settings/**/*" + - "subsys/net/lib/openthread/**/*" + - "subsys/mgmt/mcumgr/**/*" + - "samples/hci_rpmsg/**/*" + - "samples/subsys/mgmt/mcumgr/smp_svr/**/*" + - any: + - "subsys/bluetooth/**/*" + - "!subsys/bluetooth/mesh/**/*" + +"CI-thread-test": + - "**/*" + +"CI-nfc-test": + - "**/*" + +"CI-matter-test": + - "include/dfu/**/*" + - "include/mgmt/mcumgr/**/*" + - "soc/arm/nordic_nrf/**/*" + - "subsys/dfu/**/*" + - "subsys/settings/**/*" + - "subsys/net/**/*" + - "subsys/mgmt/mcumgr/**/*" + - "drivers/net/**/*" + - "samples/hci_rpmsg/**/*" + - any: + - "subsys/bluetooth/**/*" + - "!subsys/bluetooth/mesh/**/*" + - "!subsys/bluetooth/audio/**/*" + +"CI-find-my-test": + - "**/*" + +"CI-gazell-test": + - "**/*" + +"CI-rpc-test": + - "**/*" + +"CI-modemshell-test": + - "include/net/**/*" + - "include/posix/**/*" + - "include/shell/**/*" + - "drivers/net/**/*" + - "drivers/serial/**/*" + - "drivers/wifi/**/*" + - "subsys/shell/**/*" + - "subsys/net/**/*" + - "subsys/settings/**/*" + +"CI-positioning-test": + - "include/net/**/*" + - "include/posix/**/*" + - "drivers/net/**/*" + - "drivers/wifi/**/*" + - "subsys/net/**/*" + - "subsys/settings/**/*" + +"CI-cloud-test": + - "include/zephyr/dfu/**/*" + - "include/zephyr/net/**/*" + - "include/zephyr/posix/**/*" + - "include/zephyr/settings/**/*" + - "drivers/led/**/*" + - "drivers/net/**/*" + - "drivers/sensor/**/*" + - "drivers/serial/**/*" + - "drivers/wifi/**/*" + - "lib/posix/**/*" + - "soc/arm/nordic_nrf/**/*" + - "subsys/dfu/**/*" + - "subsys/net/**/*" + - "subsys/settings/**/*" + +"CI-wifi": + - "subsys/net/l2/wifi/**/*" + - "subsys/net/l2/ethernet/**/*" diff --git a/CODEOWNERS b/CODEOWNERS index 25cf3791114..a670048c779 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -14,6 +14,7 @@ # * @galak @nashif /.github/ @nashif @stephanosio +/.github/test-spec.yml @nrfconnect/ncs-test-leads /.github/workflows/ @galak @nashif /MAINTAINERS.yml @MaureenHelm /arch/arc/ @abrodkin @ruuddw @evgeniy-paltsev From 9b9ec58b0c575e15c57cb1e5de2d1c4ac5266a1f Mon Sep 17 00:00:00 2001 From: Carles Cufi Date: Fri, 30 Nov 2018 14:07:56 +0100 Subject: [PATCH 003/421] [nrf noup] ci: NCS-specific CI tweaks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Necessary changes for NCS CI. - Add a Jenkinsfile - compliance.yml: Disable check for merge commits, since we have upmerges downstream. Add an additional check for sauce tags (details in scripts/gitlint) Also, since in the code we refer to Kconfig symbols that are defined in the sdk-nrf repository, the Kconfig checks (Kconfig and KconfigBasic) will not pass so exclude them. - Extend the max commit line lengths for Gitlint to account for sauce tags - Add a commit-tags workflow: This enables sauce tag checking in sdk-zephyr - scripts/gitlint: Add support for sauce tags checks. In order to not interfere with CI in other repos (namely sdk-nrf) this is run as an independent gitlint invocation and not as part of check_compliance.py. This invocation enables the ncs-sauce-tags rule and, since it runs before rebasing and thus will run on merge commits, disables the title-starts-with-subsystem rule by setting a catch-all regex. Signed-off-by: Carles Cufi Signed-off-by: Dominik Ermel Signed-off-by: Martí Bolívar Signed-off-by: Vinayak Kariappa Chettimada Signed-off-by: Krishna T (cherry picked from commit d34b035bcc569431b7008c72edc55db1b29bccf3) (cherry picked from commit 4a6d5fc57fe7589b2585ee5e44341f50821cc653) (cherry picked from commit a01c3a4caccb6964a29078172ba7f590bcdbe790) --- .github/workflows/commit-tags.yml | 31 +++++++++++++++++++++++++++++++ .github/workflows/compliance.yml | 8 ++++---- .gitlint | 4 ++-- Jenkinsfile | 5 +++++ 4 files changed, 42 insertions(+), 6 deletions(-) create mode 100644 .github/workflows/commit-tags.yml create mode 100644 Jenkinsfile diff --git a/.github/workflows/commit-tags.yml b/.github/workflows/commit-tags.yml new file mode 100644 index 00000000000..9e0323f9498 --- /dev/null +++ b/.github/workflows/commit-tags.yml @@ -0,0 +1,31 @@ +name: Commit tags + +on: pull_request + +jobs: + commit_tags: + runs-on: ubuntu-22.04 + name: Run commit tags checks on patch series (PR) + steps: + - name: Update PATH for west + run: | + echo "$HOME/.local/bin" >> $GITHUB_PATH + + - name: Checkout the code + uses: actions/checkout@v3 + with: + ref: ${{ github.event.pull_request.head.sha }} + fetch-depth: 0 + + - name: Install python dependencies + run: | + pip3 install setuptools + pip3 install wheel + pip3 install gitlint + + - name: Run the commit tags + uses: nrfconnect/action-commit-tags@main + with: + target: '.' + baserev: origin/${{ github.base_ref }} + revrange: 'none' diff --git a/.github/workflows/compliance.yml b/.github/workflows/compliance.yml index f84faff3e4a..f17780c38e3 100644 --- a/.github/workflows/compliance.yml +++ b/.github/workflows/compliance.yml @@ -38,8 +38,8 @@ jobs: git config --global user.name "Your Name" git remote -v # Ensure there's no merge commits in the PR - [[ "$(git rev-list --merges --count origin/${BASE_REF}..)" == "0" ]] || \ - (echo "::error ::Merge commits not allowed, rebase instead";false) + #[[ "$(git rev-list --merges --count origin/${BASE_REF}..)" == "0" ]] || \ + #(echo "::error ::Merge commits not allowed, rebase instead";false) git rebase origin/${BASE_REF} # debug git log --pretty=oneline | head -n 10 @@ -56,8 +56,8 @@ jobs: # debug ls -la git log --pretty=oneline | head -n 10 - ./scripts/ci/check_compliance.py --annotate -e KconfigBasic \ - -c origin/${BASE_REF}.. + ./scripts/ci/check_compliance.py --annotate -e KconfigBasic -e Kconfig \ + -e KconfigBasicNoModules -c origin/${BASE_REF}.. - name: upload-results uses: actions/upload-artifact@v3 diff --git a/.gitlint b/.gitlint index b8d25ce49b9..8a33f140b2a 100644 --- a/.gitlint +++ b/.gitlint @@ -16,7 +16,7 @@ debug = false extra-path=scripts/gitlint [title-max-length-no-revert] -line-length=75 +line-length=120 [body-min-line-count] min-line-count=1 @@ -42,7 +42,7 @@ words=wip [max-line-length-with-exceptions] # B1 = body-max-line-length -line-length=75 +line-length=120 [body-min-length] min-length=3 diff --git a/Jenkinsfile b/Jenkinsfile new file mode 100644 index 00000000000..3b9cf002239 --- /dev/null +++ b/Jenkinsfile @@ -0,0 +1,5 @@ +@Library("CI_LIB") _ + +def pipeline = new ncs.sdk_zephyr.Main() + +pipeline.run(JOB_NAME) From 0f53ec25dcb9dc3fef27bcd024690ec69f3e85db Mon Sep 17 00:00:00 2001 From: Piotr Golyzniak Date: Mon, 1 Aug 2022 13:06:01 +0200 Subject: [PATCH 004/421] [nrf noup] ci: scripts: add quarantine file MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add scripts/quarantine.yaml file, which will be used in CI. Signed-off-by: Piotr Golyzniak Signed-off-by: Andrzej Głąbek Signed-off-by: Maciej Perkowski Signed-off-by: Robert Lubos (cherry picked from commit d08f81fe56931040f77ce9a2f703bf445b0c0bdc) (cherry picked from commit 9a7ce33cfd8cfcbbf0ab2cedd8c94f09b9c4e9d2) (cherry picked from commit b1766970c8cf3309ef93597a52c6999a864883eb) (cherry picked from commit 1667b8f0abd8095b2593420e14ba3f4b68c33e59) --- scripts/quarantine.yaml | 88 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 scripts/quarantine.yaml diff --git a/scripts/quarantine.yaml b/scripts/quarantine.yaml new file mode 100644 index 00000000000..20c4f9248ea --- /dev/null +++ b/scripts/quarantine.yaml @@ -0,0 +1,88 @@ +# The configurations resulting as a product of scenarios and platforms +# will be skipped if quarantine is used. More details here: +# https://docs.zephyrproject.org/latest/guides/test/twister.html#quarantine + +- scenarios: + - testing.ztest.busy_sim + - testing.ztest.busy_sim_nrf52840dk_pin + platforms: + - nrf52840dk_nrf52840 + +# Already reported, but will not be fixed (look at the discussion): +# https://github.com/zephyrproject-rtos/zephyr/issues/44947 +- scenarios: + - libraries.cmsis_dsp.matrix.unary_f64 + platforms: + - nrf5340dk_nrf5340_cpunet + - qemu_cortex_m3 + comment: "Flash overflows" + +# Already reported, but will not be fixed (look at the discussion): +# https://github.com/zephyrproject-rtos/zephyr/issues/44947 +- scenarios: + - libraries.cmsis_dsp.matrix.binary_f16 + - libraries.cmsis_dsp.matrix.binary_f16.fpu + platforms: + - nrf5340dk_nrf5340_cpuapp_ns + comment: "Flash overflows" + +# Already reported, but will not be fixed (look at the discussion): +# https://github.com/zephyrproject-rtos/zephyr/issues/44947 +- scenarios: + - libraries.cmsis_dsp.matrix.binary_q15 + - libraries.cmsis_dsp.matrix.binary_q15.fpu + - libraries.cmsis_dsp.matrix.unary_f32 + - libraries.cmsis_dsp.matrix.unary_f32.fpu + - libraries.cmsis_dsp.matrix.unary_f64 + - libraries.cmsis_dsp.matrix.unary_f64.fpu + platforms: + - nrf5340dk_nrf5340_cpuapp_ns + - nrf9160dk_nrf9160_ns + comment: "Flash overflows" + +# libsdl2-dev package should be added into docker image +- scenarios: + - sample.boards.nrf.nrf_led_matrix + - sample.display.lvgl.gui + platforms: + - native_posix + comment: "libsdl2-dev package not available" + +- scenarios: + - sample.net.sockets.echo_server.usbnet + - sample.net.sockets.echo_server.usbnet_composite + platforms: + - nrf5340dk_nrf5340_cpuapp_ns + comment: "Ram/flash overflows, also in the upstream" + +- scenarios: + - sample.net.zperf.netusb_ecm + - sample.net.zperf.netusb_eem + - sample.net.zperf.netusb_rndis + platforms: + - nrf52833dk_nrf52833 + - nrf5340dk_nrf5340_cpuapp_ns + comment: "Ram/flash overflows, also in the upstream" + +- scenarios: + - net.mqtt.tls + platforms: + - nrf5340dk_nrf5340_cpuapp_ns + - nrf9160dk_nrf9160_ns + comment: "Ram/flash overflows, also in the upstream" + +- scenarios: + - kernel.common.picolibc + - libraries.picolibc + - libraries.libc.picolibc.mem_alloc + - libraries.picolibc.sprintf_new + platforms: + - nrf52dk_nrf52832 + comment: "Ram overflows, also in the upstream" + +- scenarios: + - sample.psa_crypto + platforms: + - nrf5340dk_nrf5340_cpuapp_ns + - nrf9160dk_nrf9160_ns + comment: "Due to using sdk-zephyr manifest instead of nrf. Should be fixed after the change" From 69bfcfb11e2be0951163506b689daa881a21c441 Mon Sep 17 00:00:00 2001 From: Gerard Marull-Paretas Date: Thu, 3 Mar 2022 15:28:16 +0100 Subject: [PATCH 005/421] [nrf noup] doc: remove Kconfig search Kconfig search is handled in a separate docset in NCS, so remove the page. This is a long-term noup patch. Signed-off-by: Gerard Marull-Paretas Signed-off-by: Krishna T (cherry picked from commit 89babe6a30bb3e5c4fa411168cd4135dbb99e70f) (cherry picked from commit fdbdd8017796455cba30971c153289aa17236b9b) (cherry picked from commit aa9e63340ee7824e1d9294eea4629e8dabd9ffd9) --- MAINTAINERS.yml | 1 - doc/build/kconfig/setting.rst | 6 ++---- doc/develop/application/index.rst | 5 ++--- doc/kconfig.rst | 8 -------- 4 files changed, 4 insertions(+), 16 deletions(-) delete mode 100644 doc/kconfig.rst diff --git a/MAINTAINERS.yml b/MAINTAINERS.yml index 8d581406981..08ad5c8d61b 100644 --- a/MAINTAINERS.yml +++ b/MAINTAINERS.yml @@ -611,7 +611,6 @@ Documentation: - doc/images/Zephyr-Kite-in-tree.png - doc/index-tex.rst - doc/index.rst - - doc/kconfig.rst - doc/known-warnings.txt - doc/templates/sample.tmpl - doc/templates/board.tmpl diff --git a/doc/build/kconfig/setting.rst b/doc/build/kconfig/setting.rst index 2fd78ff463b..5f37e831e9e 100644 --- a/doc/build/kconfig/setting.rst +++ b/doc/build/kconfig/setting.rst @@ -7,8 +7,7 @@ The :ref:`menuconfig and guiconfig interfaces ` can be used to test out configurations during application development. This page explains how to make settings permanent. -All Kconfig options can be searched in the :ref:`Kconfig search page -`. +All Kconfig options can be searched in the Kconfig search page. .. note:: @@ -115,8 +114,7 @@ Assignments in configuration files are only respected if the dependencies for the symbol are satisfied. A warning is printed otherwise. To figure out what the dependencies of a symbol are, use one of the :ref:`interactive configuration interfaces ` (you can jump directly to a symbol with -:kbd:`/`), or look up the symbol in the :ref:`Kconfig search page -`. +:kbd:`/`), or look up the symbol in the Kconfig search page. .. _initial-conf: diff --git a/doc/develop/application/index.rst b/doc/develop/application/index.rst index 7307d6c572c..3fd971ad945 100644 --- a/doc/develop/application/index.rst +++ b/doc/develop/application/index.rst @@ -640,9 +640,8 @@ started. See :ref:`setting_configuration_values` for detailed documentation on setting Kconfig configuration values. The :ref:`initial-conf` section on the same page -explains how the initial configuration is derived. See :ref:`kconfig-search` -for a complete list of configuration options. -See :ref:`hardening` for security information related with Kconfig options. +explains how the initial configuration is derived. See :ref:`hardening` for +security information related with Kconfig options. The other pages in the :ref:`Kconfig section of the manual ` are also worth going through, especially if you planning to add new configuration diff --git a/doc/kconfig.rst b/doc/kconfig.rst deleted file mode 100644 index 1123de2adbd..00000000000 --- a/doc/kconfig.rst +++ /dev/null @@ -1,8 +0,0 @@ -:orphan: - -.. _kconfig-search: - -Kconfig Search -============== - -.. kconfig:search:: From 910bb5fe9e14e8afcf0c8b65c846e294821d693e Mon Sep 17 00:00:00 2001 From: Joakim Andersson Date: Mon, 16 Jan 2023 14:15:22 +0100 Subject: [PATCH 006/421] [nrf noup] dts: choose cryptocell for entropy when available This is a long-term noup patch because driver support is NCS-only. Set HAS_HW_NRF_CC3XX to be defined in NS build when cryptocell is accessed through the PSA API. We need to know which CC3XX features are available. Signed-off-by: Georgios Vasilakis Signed-off-by: Joakim Andersson (cherry picked from commit c76cf8776d7bcbb7eef8023191a941f8e9410cb4) (cherry picked from commit 214533fa69601f52933977a39fff855d955c886f) (cherry picked from commit 3819c4ae701f0b4265bbd3409e37e5bba5c4abcb) --- dts/arm/nordic/nrf52840.dtsi | 2 +- dts/arm/nordic/nrf5340_cpuapp.dtsi | 2 +- dts/arm/nordic/nrf91.dtsi | 1 + soc/arm/nordic_nrf/Kconfig.peripherals | 6 ++++-- 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/dts/arm/nordic/nrf52840.dtsi b/dts/arm/nordic/nrf52840.dtsi index 8c89968c108..f4209c67d19 100644 --- a/dts/arm/nordic/nrf52840.dtsi +++ b/dts/arm/nordic/nrf52840.dtsi @@ -5,7 +5,7 @@ / { chosen { - zephyr,entropy = &rng; + zephyr,entropy = &cryptocell; zephyr,flash-controller = &flash_controller; }; diff --git a/dts/arm/nordic/nrf5340_cpuapp.dtsi b/dts/arm/nordic/nrf5340_cpuapp.dtsi index 7a32c5398db..1294203f00a 100644 --- a/dts/arm/nordic/nrf5340_cpuapp.dtsi +++ b/dts/arm/nordic/nrf5340_cpuapp.dtsi @@ -33,7 +33,7 @@ }; chosen { - zephyr,entropy = &rng_hci; + zephyr,entropy = &cryptocell; zephyr,flash-controller = &flash_controller; }; diff --git a/dts/arm/nordic/nrf91.dtsi b/dts/arm/nordic/nrf91.dtsi index d872680fb20..a2a490ab0b1 100644 --- a/dts/arm/nordic/nrf91.dtsi +++ b/dts/arm/nordic/nrf91.dtsi @@ -28,6 +28,7 @@ }; chosen { + zephyr,entropy = &cryptocell; zephyr,flash-controller = &flash_controller; }; diff --git a/soc/arm/nordic_nrf/Kconfig.peripherals b/soc/arm/nordic_nrf/Kconfig.peripherals index c7bfb552409..1645cf34ea0 100644 --- a/soc/arm/nordic_nrf/Kconfig.peripherals +++ b/soc/arm/nordic_nrf/Kconfig.peripherals @@ -13,10 +13,12 @@ config HAS_HW_NRF_BPROT def_bool $(dt_compat_enabled,$(DT_COMPAT_NORDIC_NRF_BPROT)) config HAS_HW_NRF_CC310 - def_bool $(dt_compat_enabled,$(DT_COMPAT_NORDIC_NRF_CC310)) + def_bool $(dt_compat_enabled,$(DT_COMPAT_NORDIC_NRF_CC310)) || \ + ($(dt_nodelabel_enabled,psa_rng) && SOC_SERIES_NRF91X) config HAS_HW_NRF_CC312 - def_bool $(dt_compat_enabled,$(DT_COMPAT_NORDIC_NRF_CC312)) + def_bool $(dt_compat_enabled,$(DT_COMPAT_NORDIC_NRF_CC312)) || \ + ($(dt_nodelabel_enabled,psa_rng) && SOC_NRF5340_CPUAPP) config HAS_HW_NRF_CCM def_bool $(dt_compat_enabled,$(DT_COMPAT_NORDIC_NRF_CCM)) From 8e9c90fce4c36d8ba326e34a5e4fab4ce0c86f01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Frank=20Audun=20Kvamtr=C3=B8?= Date: Tue, 30 Nov 2021 09:41:05 +0100 Subject: [PATCH 007/421] [nrf noup] modules: mbedtls: add PSA configurations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit -Adds Kconfig.psa -Add standardized algorithms, curve types etc as Kconfig variables -Add configurations for internal logic to see if a feature is enabled by PSA_WANTS_XXX ref: NCSDK-11689 ref: NCSDK-17840 ref: NCSDK-17840 Signed-off-by: Frank Audun Kvamtrø Signed-off-by: Joakim Andersson (cherry picked from commit c913e3aaa7c59737c9f25a7c58cfbb20503f791c) (cherry picked from commit 6ae8ab054126778fcc0054d5243580e72197359c) (cherry picked from commit a7d1b3ddd1b740db3e04e967e12bfdf6e76e4d48) --- drivers/entropy/Kconfig.psa_crypto | 1 + modules/mbedtls/Kconfig | 5 +- modules/mbedtls/Kconfig.psa | 484 +++++++++++++++++++++++++++++ 3 files changed, 489 insertions(+), 1 deletion(-) create mode 100644 modules/mbedtls/Kconfig.psa diff --git a/drivers/entropy/Kconfig.psa_crypto b/drivers/entropy/Kconfig.psa_crypto index 50f31509004..455a2c9b55b 100644 --- a/drivers/entropy/Kconfig.psa_crypto +++ b/drivers/entropy/Kconfig.psa_crypto @@ -8,6 +8,7 @@ config ENTROPY_PSA_CRYPTO_RNG depends on BUILD_WITH_TFM depends on DT_HAS_ZEPHYR_PSA_CRYPTO_RNG_ENABLED select ENTROPY_HAS_DRIVER + select PSA_WANT_GENERATE_RANDOM default y help Enable the PSA Crypto source Entropy driver. diff --git a/modules/mbedtls/Kconfig b/modules/mbedtls/Kconfig index 67277fb24c4..6e59709323e 100644 --- a/modules/mbedtls/Kconfig +++ b/modules/mbedtls/Kconfig @@ -5,6 +5,7 @@ config ZEPHYR_MBEDTLS_MODULE bool + config MBEDTLS_PROMPTLESS bool help @@ -13,7 +14,6 @@ config MBEDTLS_PROMPTLESS mbed TLS menu prompt and instead handle the selection of MBEDTLS from dependent sub-configurations and thus prevent stuck symbol behavior. - menuconfig MBEDTLS bool "mbed TLS Support" if !MBEDTLS_PROMPTLESS help @@ -233,3 +233,6 @@ config APP_LINK_WITH_MBEDTLS issues for 'app'. endif # MBEDTLS + +# Add PSA configurations +rsource "Kconfig.psa" diff --git a/modules/mbedtls/Kconfig.psa b/modules/mbedtls/Kconfig.psa new file mode 100644 index 00000000000..399d18a3797 --- /dev/null +++ b/modules/mbedtls/Kconfig.psa @@ -0,0 +1,484 @@ +# +# Copyright (c) 2022 Nordic Semiconductor +# +# SPDX-License-Identifier: Apache-2.0 +# +menu "PSA RNG support" + +config PSA_WANT_GENERATE_RANDOM + bool + prompt "PSA RNG support" + help + Provide random number generator (RNG) support. + +config PSA_WANT_ALG_CTR_DRBG + bool + prompt "PSA RNG using CTR-DRBG as PRNG" + help + Provide random number generator (RNG) using CTR-DRBG as the + pseudo-random number generator (PRNG), seeded by a true random + number generator (TRNG). + +config PSA_WANT_ALG_HMAC_DRBG + bool + prompt "PSA RNG using HMAC-DRBG as PRNG" + help + Provide random number generator (RNG) using HMAC-DRBG as the + pseudo-random number generator (PRNG), seeded by a true random + number generator (TRNG). + +endmenu # RNG support + +menu "PSA key type support" + +config PSA_HAS_KEY_SUPPORT + bool + default y + depends on PSA_WANT_KEY_TYPE_DERIVE || \ + PSA_WANT_KEY_TYPE_HMAC || \ + PSA_WANT_KEY_TYPE_RAW_DATA || \ + PSA_WANT_KEY_TYPE_PASSWORD || \ + PSA_WANT_KEY_TYPE_PASSWORD_HASH || \ + PSA_WANT_KEY_TYPE_PEPPER || \ + PSA_WANT_KEY_TYPE_AES || \ + PSA_WANT_KEY_TYPE_CHACHA20 || \ + PSA_WANT_KEY_TYPE_ECC_KEY_PAIR || \ + PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY || \ + PSA_WANT_KEY_TYPE_RSA_KEY_PAIR || \ + PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY || \ + PSA_WANT_KEY_TYPE_DH_KEY_PAIR || \ + PSA_WANT_KEY_TYPE_DH_KEY_PAIR + +config PSA_WANT_KEY_TYPE_DERIVE + bool "PSA derive key type support" + help + This key type is for high-entropy secrets only. + For low-entropy secrets, password key type should be used instead. + +config PSA_WANT_KEY_TYPE_RAW_DATA + bool "PSA raw data key type support" + help + A "key" of this type cannot be used for any cryptographic operation. + Applications can use this type to store arbitrary data in the keystore. + +config PSA_WANT_KEY_TYPE_HMAC + bool "PSA HMAC key type support" + help + HMAC key. + +config PSA_WANT_KEY_TYPE_PASSWORD + bool "PSA password key type support" + help + A low-entropy secret for password hashing or key derivation. + +config PSA_WANT_KEY_TYPE_PASSWORD_HASH + bool "PSA password hash key type support" + help + A secret value that can be used to verify a password hash. + +config PSA_WANT_KEY_TYPE_PEPPER + bool "PSA pepper key type support" + help + A secret value that can be used when computing a password hash. + +config PSA_WANT_KEY_TYPE_AES + bool "PSA AES key type support" + help + Key for cipher, AEAD or MAC algorithm based on the AES block cipher. + +config PSA_WANT_KEY_TYPE_CHACHA20 + bool "PSA ChaCha20 key type support" + default y + depends on PSA_WANT_ALG_CHACHA20_POLY1305 || \ + PSA_WANT_ALG_STREAM_CIPHER + help + Key for the ChaCha20 stream cipher or the ChaCha20-Poly1305 AEAD algorithm. + +config PSA_WANT_KEY_TYPE_ECC_KEY_PAIR + bool "PSA ECC key pair support" + select PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY + help + Elliptic curve key pair: both the private and public key. + +config PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY + bool "PSA ECC public key support" + help + Elliptic curve public key. + +config PSA_WANT_KEY_TYPE_RSA_KEY_PAIR + bool "PSA RSA key pair type support" + select PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY + help + RSA key pair: both the private and public key. + +config PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY + bool "PSA RSA public key support" + help + RSA public key. + +config PSA_WANT_KEY_TYPE_DH_KEY_PAIR + bool "PSA DH key pair type support" + select PSA_WANT_KEY_TYPE_DH_PUBLIC_KEY + help + Finite-field Diffie-Hellman key pair: both the private key and public key. + +config PSA_WANT_KEY_TYPE_DH_PUBLIC_KEY + bool "PSA DH public key support" + help + Finite-field Diffie-Hellman public key. + +endmenu # PSA Key type support + +menu "PSA AEAD support" + +config PSA_HAS_AEAD_SUPPORT + bool + default y + depends on PSA_WANT_ALG_CCM || \ + PSA_WANT_ALG_CCM_STAR_NO_TAG || \ + PSA_WANT_ALG_GCM || \ + PSA_WANT_ALG_CHACHA20_POLY1305 + help + Prompt-less configuration that states that AEAD is supported. + +config PSA_WANT_ALG_CCM + bool + prompt "PSA CCM support" if !PSA_PROMPTLESS + +config PSA_WANT_ALG_CCM_STAR_NO_TAG + bool + prompt "PSA AES CCM star with no tag support" if !PSA_PROMPTLESS + +config PSA_WANT_ALG_GCM + bool + prompt "PSA GCM support" if !PSA_PROMPTLESS + +config PSA_WANT_ALG_CHACHA20_POLY1305 + bool + prompt "PSA ChaCha20-Poly1305 support" if !PSA_PROMPTLESS + +endmenu # PSA AEAD support + + +menu "PSA MAC support" + +config PSA_HAS_MAC_SUPPORT + bool + default y + depends on PSA_WANT_ALG_CBC_MAC || \ + PSA_WANT_ALG_CMAC || \ + PSA_WANT_ALG_HMAC + help + Prompt-less configuration that states that MAC is supported. + +config PSA_WANT_ALG_CBC_MAC + bool + help + CBC-MAC is not yet supported via the PSA API in Mbed TLS. + +config PSA_WANT_ALG_CMAC + bool + prompt "PSA CMAC support" if !PSA_PROMPTLESS + +config PSA_WANT_ALG_HMAC + bool + prompt "PSA HMAC support" if !PSA_PROMPTLESS + +endmenu # PSA MAC support + + +menu "PSA Hash support" + +config PSA_HAS_HASH_SUPPORT + bool + default y + depends on PSA_WANT_ALG_SHA_1 || \ + PSA_WANT_ALG_SHA_224 || \ + PSA_WANT_ALG_SHA_256 || \ + PSA_WANT_ALG_SHA_384 || \ + PSA_WANT_ALG_SHA_512 || \ + PSA_WANT_ALG_RIPEMD160 || \ + PSA_WANT_ALG_MD5 + help + Prompt-less configuration that states that hash is supported. + +config PSA_WANT_ALG_SHA_1 + bool + prompt "PSA SHA-1 support (weak)" if !PSA_PROMPTLESS + help + Warning: The SHA-1 hash is weak and deprecated and is only recommended + for use in legacy protocols. + +config PSA_WANT_ALG_SHA_224 + bool + prompt "PSA SHA-224 support" if !PSA_PROMPTLESS + +config PSA_WANT_ALG_SHA_256 + bool + prompt "PSA SHA-256 support" if !PSA_PROMPTLESS + +config PSA_WANT_ALG_SHA_384 + bool + prompt "PSA SHA-384 support" if !PSA_PROMPTLESS + +config PSA_WANT_ALG_SHA_512 + bool + prompt "PSA SHA-512 support" if !PSA_PROMPTLESS + +config PSA_WANT_ALG_RIPEMD160 + bool + prompt "PSA RIPEMD-160 support" if !PSA_PROMPTLESS + +config PSA_WANT_ALG_MD5 + bool + prompt "PSA MD5 support (weak)" if !PSA_PROMPTLESS + help + Warning: The MD5 hash is weak and deprecated and is only recommended + for use in legacy protocols. + +endmenu # PSA Hash support + +menu "PSA Cipher support" + +config PSA_HAS_CIPHER_SUPPORT + bool + default y + depends on PSA_WANT_ALG_ECB_NO_PADDING || \ + PSA_WANT_ALG_CBC_NO_PADDING || \ + PSA_WANT_ALG_CBC_PKCS7 || \ + PSA_WANT_ALG_CFB || \ + PSA_WANT_ALG_CTR || \ + PSA_WANT_ALG_OFB || \ + PSA_WANT_ALG_CTR || \ + PSA_WANT_ALG_XTS || \ + PSA_WANT_ALG_STREAM_CIPHER + help + Prompt-less configuration that states that cipher is supported. + +config PSA_WANT_ALG_ECB_NO_PADDING + bool + prompt "PSA ECB block cipher mode support (with no padding)" if !PSA_PROMPTLESS + +config PSA_WANT_ALG_CBC_NO_PADDING + bool + prompt "PSA CBC block cipher mode support (with no padding)" if !PSA_PROMPTLESS + +config PSA_WANT_ALG_CBC_PKCS7 + bool + prompt "PSA CBC block cipher mode support (with PKCS#7 padding)" if !PSA_PROMPTLESS + +config PSA_WANT_ALG_CFB + bool + prompt "PSA stream cipher using CFB block cipher mode support" if !PSA_PROMPTLESS + +config PSA_WANT_ALG_CTR + bool + prompt "PSA stream cipher using CTR block cipher mode support" if !PSA_PROMPTLESS + +config PSA_WANT_ALG_OFB + bool + prompt "PSA stream cipher using OFB block cipher mode support" if !PSA_PROMPTLESS + +config PSA_WANT_ALG_XTS + bool + prompt "PSA XTS block cipher mode support" if !PSA_PROMPTLESS + +config PSA_WANT_ALG_STREAM_CIPHER + bool + prompt "PSA stream cipher support" if !PSA_PROMPTLESS + +endmenu # PSA Cipher Support + + +menu "PSA Key derivation support" + +config PSA_HAS_KEY_DERIVATION + bool + default y + depends on PSA_WANT_ALG_HKDF || \ + PSA_WANT_ALG_HKDF_EXPAND || \ + PSA_WANT_ALG_HKDF_EXTRACT || \ + PSA_WANT_ALG_PBKDF2_HMAC || \ + PSA_WANT_ALG_TLS12_PRF || \ + PSA_WANT_ALG_TLS12_PSK_TO_MS + help + Prompt-less configuration that states that key derivation is supported. + +config PSA_WANT_ALG_HKDF + bool + prompt "PSA HKDF support" if !PSA_PROMPTLESS + depends on PSA_WANT_ALG_HMAC + +config PSA_WANT_ALG_HKDF_EXTRACT + bool + prompt "PSA HKDF extract support" if !PSA_PROMPTLESS + +config PSA_WANT_ALG_HKDF_EXPAND + bool + prompt "PSA HKDF expand support" if !PSA_PROMPTLESS + +config PSA_WANT_ALG_PBKDF2_HMAC + bool + depends on PSA_WANT_ALG_HMAC + help + PBKDF2-HMAC is not yet supported via the PSA APIs in Mbed TLS. + +config PSA_WANT_ALG_TLS12_PRF + bool + prompt "PSA PRF support (TLS1.2)" if !PSA_PROMPTLESS + +config PSA_WANT_ALG_TLS12_PSK_TO_MS + bool + prompt "PSA TLS 1.2 PSK to MS support" if !PSA_PROMPTLESS + +endmenu # PSA Key derivation support + + +menu "PSA Asymmetric support" + +config PSA_HAS_ASYM_ENCRYPT_SUPPORT + bool + default y + depends on PSA_WANT_ALG_RSA_OAEP || \ + PSA_WANT_ALG_RSA_PKCS1V15_CRYPT + help + Prompt-less configuration that states that asymmetric encryption + is supported. + + +config PSA_HAS_ASYM_SIGN_SUPPORT + bool + default y + depends on PSA_WANT_ALG_DETERMINISTIC_ECDSA || \ + PSA_WANT_ALG_ECDSA || \ + PSA_WANT_ALG_RSA_PKCS1V15_SIGN || \ + PSA_WANT_ALG_RSA_PSS + help + Prompt-less configuration that states that asymmetric signing + is supported. + +config PSA_HAS_ECC_SUPPORT + bool + depends on PSA_WANT_ALG_ECDH || \ + PSA_WANT_ALG_ECDSA || \ + PSA_WANT_ALG_DETERMINISTIC_ECDSA || \ + PSA_WANT_KEY_TYPE_ECC_KEY_PAIR || \ + PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY + default y + help + Prompt-less configuration that states that ECC is supported. + +config PSA_WANT_ALG_ECDH + bool + prompt "PSA ECDH support" if !PSA_PROMPTLESS + +config PSA_WANT_ALG_ECDSA + bool + prompt "PSA ECDSA support" if !PSA_PROMPTLESS + +config PSA_WANT_ALG_DETERMINISTIC_ECDSA + bool + prompt "PSA ECDSA support (deterministic mode)" if !PSA_PROMPTLESS + +menu "Elliptic Curve type support" + depends on PSA_HAS_ECC_SUPPORT + +config PSA_WANT_ECC_BRAINPOOL_P_R1_256 + bool + prompt "PSA ECC Brainpool256r1 support" + +config PSA_WANT_ECC_BRAINPOOL_P_R1_384 + bool "PSA ECC Brainpool384r1 support" + +config PSA_WANT_ECC_BRAINPOOL_P_R1_512 + bool "PSA ECC Brainpool512r1 support" + +config PSA_WANT_ECC_MONTGOMERY_255 + bool "PSA ECC Curve25519 (X25519) support" + +config PSA_WANT_ECC_MONTGOMERY_448 + bool "PSA ECC Curve448 (X448) support" + +config PSA_WANT_ECC_TWISTED_EDWARDS_255 + bool "PSA ECC Edwards25519 (Ed25519) support" + +config PSA_WANT_ECC_SECP_K1_192 + bool "PSA ECC secp192k1 support" + +config PSA_WANT_ECC_SECP_K1_224 + bool + help + SECP224K1 is buggy via the PSA API in Mbed TLS + See https://github.com/ARMmbed/mbedtls/issues/3541 + +config PSA_WANT_ECC_SECP_K1_256 + bool + prompt "PSA ECC secp256k1 support" if !PSA_PROMPTLESS + +config PSA_WANT_ECC_SECP_R1_192 + bool + prompt "PSA ECC secp192r1" if !PSA_PROMPTLESS + +config PSA_WANT_ECC_SECP_R1_224 + bool + prompt "PSA ECC secp224r1" if !PSA_PROMPTLESS + +config PSA_WANT_ECC_SECP_R1_256 + bool + prompt "PSA ECC secp256r1" if !PSA_PROMPTLESS + +config PSA_WANT_ECC_SECP_R1_384 + bool + prompt "PSA ECC secp384r1" if !PSA_PROMPTLESS + +config PSA_WANT_ECC_SECP_R1_521 + bool + prompt "PSA ECC secp521r1" if !PSA_PROMPTLESS + +endmenu # Elliptic Curve type support + +config PSA_HAS_RSA_SUPPORT + bool + depends on PSA_WANT_ALG_RSA_OAEP || \ + PSA_WANT_ALG_RSA_PKCS1V15_CRYPT || \ + PSA_WANT_ALG_RSA_PKCS1V15_SIGN || \ + PSA_WANT_ALG_RSA_PSS || \ + PSA_WANT_KEY_TYPE_RSA_KEY_PAIR || \ + PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY + default y + help + Prompt-less configuration that states that RSA is supported. + +config PSA_WANT_ALG_RSA_OAEP + bool + prompt "PSA RSA OAEP support" if !PSA_PROMPTLESS + +config PSA_WANT_ALG_RSA_PKCS1V15_CRYPT + bool + prompt "PSA RSA crypt support (PKCS#1 v1.5 mode)" if !PSA_PROMPTLESS + +config PSA_WANT_ALG_RSA_PKCS1V15_SIGN + bool + prompt "PSA RSA signature support (PKCS#1 v1.5 mode)" if !PSA_PROMPTLESS + +config PSA_WANT_ALG_RSA_PSS + bool + prompt "PSA RSA (PSS mode)" if !PSA_PROMPTLESS + +endmenu # PSA Asymmetric support + +config PSA_WANT_ALG_JPAKE + bool + prompt "PSA EC J-PAKE support" if !PSA_PROMPTLESS + select EXPERIMENTAL + +config PSA_WANT_ALG_SPAKE2P + bool + prompt "PSA SPAKE2+ support" if !PSA_PROMPTLESS + select EXPERIMENTAL + +config PSA_WANT_ALG_SRP + bool + prompt "PSA SRP support" if !PSA_PROMPTLESS + default n + select EXPERIMENTAL From 746136896ba8cb66f41742690e1021e7e83c0997 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20B=C3=B8e?= Date: Sat, 29 Jan 2022 13:03:08 +0100 Subject: [PATCH 008/421] [nrf noup] modules: mbedtls: Allow MBEDTLS_BUILTIN to be deselected MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Out-of-tree crypto subsystems need to deselect MBEDTLS_BUILTIN, but deselection is not supported. It is however supported to select a dependency in a ! expression. Signed-off-by: Sebastian Bøe (cherry picked from commit d2eb105082a6df51584e6cd49838cce7ac39d20c) (cherry picked from commit 1a12d6cd21e3dc31472694881a027e19b3283db2) --- modules/mbedtls/Kconfig | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/modules/mbedtls/Kconfig b/modules/mbedtls/Kconfig index 6e59709323e..2a05ee28d36 100644 --- a/modules/mbedtls/Kconfig +++ b/modules/mbedtls/Kconfig @@ -27,6 +27,7 @@ choice MBEDTLS_IMPLEMENTATION config MBEDTLS_BUILTIN bool "Use Zephyr in-tree mbedTLS version" + depends on ! DISABLE_MBEDTLS_BUILTIN help Link with mbedTLS sources included with Zephyr distribution. Included mbedTLS version is well integrated with and supported @@ -40,6 +41,11 @@ config MBEDTLS_LIBRARY endchoice +# subsystems cannot deselect MBEDTLS_BUILTIN, but they can select +# DISABLE_MBEDTLS_BUILTIN. +config DISABLE_MBEDTLS_BUILTIN + bool + config CUSTOM_MBEDTLS_CFG_FILE bool "Custom mbed TLS configuration file" help From 77360dd3f121c37f9df9399ff2c5c0b09d50c8cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Frank=20Audun=20Kvamtr=C3=B8?= Date: Thu, 13 Jan 2022 11:37:18 +0100 Subject: [PATCH 009/421] [nrf noup] modules: tf-m: use of PSA_HAS_XXXX_SUPPORT MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit -This allows configurations enabled by PSA_WANTS_ALG_XXXX to be used to control which TF-M module is enabled -If the TF-M image doesn't support e.g. the MAC APIs, then the MAC interface is not enabled Note: This functionality requires that nrf_security is enabled ref: NCSDK-11689 Signed-off-by: Frank Audun Kvamtrø (cherry picked from commit 55015d61ea589ab77987c3e74d9d2c8ed73d1590) (cherry picked from commit 4ab6d30e95770e5dabc601d5a491733a097a763b) --- modules/trusted-firmware-m/Kconfig.tfm.crypto_modules | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/modules/trusted-firmware-m/Kconfig.tfm.crypto_modules b/modules/trusted-firmware-m/Kconfig.tfm.crypto_modules index 1d70a2c44d2..89893686143 100644 --- a/modules/trusted-firmware-m/Kconfig.tfm.crypto_modules +++ b/modules/trusted-firmware-m/Kconfig.tfm.crypto_modules @@ -17,6 +17,7 @@ config TFM_CRYPTO_RNG_MODULE_ENABLED config TFM_CRYPTO_KEY_MODULE_ENABLED bool "KEY crypto module" default y + depends on PSA_HAS_KEY_SUPPORT && NRF_SECURITY help Enables the KEY crypto module within the crypto partition. Unset this option if the functionality provided by 'crypto_key_management.c' @@ -25,6 +26,7 @@ config TFM_CRYPTO_KEY_MODULE_ENABLED config TFM_CRYPTO_AEAD_MODULE_ENABLED bool "AEAD crypto module" default y + depends on PSA_HAS_AEAD_SUPPORT && NRF_SECURITY help Enables the AEAD crypto module within the crypto partition. Unset this option if the functionality provided by 'crypto_aead.c' @@ -33,6 +35,7 @@ config TFM_CRYPTO_AEAD_MODULE_ENABLED config TFM_CRYPTO_MAC_MODULE_ENABLED bool "MAC crypto module" default y + depends on PSA_HAS_MAC_SUPPORT && NRF_SECURITY help Enables the MAC crypto module within the crypto partition. Unset this option if the functionality provided by 'crypto_mac.c' @@ -41,6 +44,7 @@ config TFM_CRYPTO_MAC_MODULE_ENABLED config TFM_CRYPTO_HASH_MODULE_ENABLED bool "HASH crypto module" default y + depends on PSA_HAS_HASH_SUPPORT && NRF_SECURITY help Enables the HASH crypto module within the crypto partition. Unset this option if the functionality provided by 'crypto_hash.c' @@ -49,6 +53,7 @@ config TFM_CRYPTO_HASH_MODULE_ENABLED config TFM_CRYPTO_CIPHER_MODULE_ENABLED bool "CIPHER crypto module" default y + depends on PSA_HAS_CIPHER_SUPPORT && NRF_SECURITY help Enables the CIPHER crypto module within the crypto partition. Unset this option if the functionality provided by 'crypto_cipher.c' @@ -57,6 +62,7 @@ config TFM_CRYPTO_CIPHER_MODULE_ENABLED config TFM_CRYPTO_ASYM_ENCRYPT_MODULE_ENABLED bool "ASYM ENCRYPT crypto module" default y + depends on PSA_HAS_ASYM_ENCRYPT_SUPPORT && NRF_SECURITY help Enables the ASYM ENCRYPT crypto module within the crypto partition. Unset this option if the encrypt functionality provided by 'crypto_asymmetric.c' @@ -65,6 +71,7 @@ config TFM_CRYPTO_ASYM_ENCRYPT_MODULE_ENABLED config TFM_CRYPTO_ASYM_SIGN_MODULE_ENABLED bool "ASYM SIGN crypto module" default y + depends on PSA_HAS_ASYM_SIGN_SUPPORT && NRF_SECURITY help Enables the ASYM SIGN crypto module within the crypto partition. Unset this option if the sign functionality provided by 'crypto_asymmetric.c' @@ -73,6 +80,7 @@ config TFM_CRYPTO_ASYM_SIGN_MODULE_ENABLED config TFM_CRYPTO_KEY_DERIVATION_MODULE_ENABLED bool "KEY DERIVATION crypto module" default y + depends on PSA_HAS_KEY_DERIVATION && NRF_SECURITY help Enables the KEY_DERIVATION crypto module within the crypto partition. Unset this option if the functionality provided by 'crypto_key_derivation.c' From 05e424a60315d7083c1b2c3391010b54bd42443a Mon Sep 17 00:00:00 2001 From: Jan Tore Guggedal Date: Mon, 18 May 2020 20:50:13 +0200 Subject: [PATCH 010/421] [nrf noup] net: mqtt: Provide option to enable TLS session caching Provides an option to enable TLS session caching for an MQTT client's secure socket. Signed-off-by: Jan Tore Guggedal Signed-off-by: Robert Lubos Signed-off-by: Dominik Ermel Signed-off-by: Johann Fischer (cherry picked from commit 97e75e91a3ffaa585c69052c14134f13ea9c54fc) (cherry picked from commit 60fed8dbcb765eea06cd02fc2e080fa77a3c7310) --- include/zephyr/net/mqtt.h | 3 +++ subsys/net/lib/mqtt/mqtt_transport_socket_tls.c | 10 ++++++++++ 2 files changed, 13 insertions(+) diff --git a/include/zephyr/net/mqtt.h b/include/zephyr/net/mqtt.h index 1980b95bbea..b28e9e87612 100644 --- a/include/zephyr/net/mqtt.h +++ b/include/zephyr/net/mqtt.h @@ -356,6 +356,9 @@ struct mqtt_sec_config { /** Indicates the list of security tags to be used for the session. */ sec_tag_t *sec_tag_list; + /** Indicates the preference for enabling TLS session caching. */ + int session_cache; + /** Peer hostname for ceritificate verification. * May be NULL to skip hostname verification. */ diff --git a/subsys/net/lib/mqtt/mqtt_transport_socket_tls.c b/subsys/net/lib/mqtt/mqtt_transport_socket_tls.c index c835656b6cf..363ff51afef 100644 --- a/subsys/net/lib/mqtt/mqtt_transport_socket_tls.c +++ b/subsys/net/lib/mqtt/mqtt_transport_socket_tls.c @@ -78,6 +78,16 @@ int mqtt_client_tls_connect(struct mqtt_client *client) } } + if (tls_config->session_cache == TLS_SESSION_CACHE_ENABLED) { + ret = zsock_setsockopt(client->transport.tls.sock, SOL_TLS, + TLS_SESSION_CACHE, + &tls_config->session_cache, + sizeof(tls_config->session_cache)); + if (ret < 0) { + goto error; + } + } + if (tls_config->cert_nocopy != TLS_CERT_NOCOPY_NONE) { ret = zsock_setsockopt(client->transport.tls.sock, SOL_TLS, TLS_CERT_NOCOPY, &tls_config->cert_nocopy, From 63940d988b3879983d2c36270e703422c5dd7d05 Mon Sep 17 00:00:00 2001 From: Mirko Covizzi Date: Thu, 10 Mar 2022 00:25:50 -0800 Subject: [PATCH 011/421] [nrf noup] net: mqtt: add native TLS support This commit adds an extra parameter in the configuration structure to configure native TLS support at runtime. Signed-off-by: Mirko Covizzi (cherry picked from commit a719cd235202700bf2a874abce66a41fe715954e) (cherry picked from commit 30140d610d67a52e7ed830b81f042be696fe74b6) --- doc/connectivity/networking/api/mqtt.rst | 3 +++ include/zephyr/net/mqtt.h | 3 +++ subsys/net/lib/mqtt/mqtt_transport_socket_tls.c | 7 ++++++- 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/doc/connectivity/networking/api/mqtt.rst b/doc/connectivity/networking/api/mqtt.rst index b1090c8d394..dcc71e3320b 100644 --- a/doc/connectivity/networking/api/mqtt.rst +++ b/doc/connectivity/networking/api/mqtt.rst @@ -149,6 +149,7 @@ additional configuration information: tls_config->sec_tag_list = m_sec_tags; tls_config->sec_tag_count = ARRAY_SIZE(m_sec_tags); tls_config->hostname = MQTT_BROKER_HOSTNAME; + tls_config->set_native_tls = true; In this sample code, the ``m_sec_tags`` array holds a list of tags, referencing TLS credentials that the MQTT library should use for authentication. We do not specify @@ -161,6 +162,8 @@ Note, that TLS credentials referenced by the ``m_sec_tags`` array must be registered in the system first. For more information on how to do that, refer to :ref:`secure sockets documentation `. +Finally, ``set_native_tls`` can be optionally set to enable native TLS support instead of offloading TLS operations to the modem. + An example of how to use TLS with MQTT is also present in :ref:`mqtt-publisher-sample`. diff --git a/include/zephyr/net/mqtt.h b/include/zephyr/net/mqtt.h index b28e9e87612..ecdefea120b 100644 --- a/include/zephyr/net/mqtt.h +++ b/include/zephyr/net/mqtt.h @@ -366,6 +366,9 @@ struct mqtt_sec_config { /** Indicates the preference for copying certificates to the heap. */ int cert_nocopy; + + /** Set socket to native TLS */ + bool set_native_tls; }; /** @brief MQTT transport type. */ diff --git a/subsys/net/lib/mqtt/mqtt_transport_socket_tls.c b/subsys/net/lib/mqtt/mqtt_transport_socket_tls.c index 363ff51afef..8e9cc87239a 100644 --- a/subsys/net/lib/mqtt/mqtt_transport_socket_tls.c +++ b/subsys/net/lib/mqtt/mqtt_transport_socket_tls.c @@ -22,10 +22,15 @@ int mqtt_client_tls_connect(struct mqtt_client *client) { const struct sockaddr *broker = client->broker; struct mqtt_sec_config *tls_config = &client->transport.tls.config; + int type = SOCK_STREAM; int ret; + if (tls_config->set_native_tls) { + type |= SOCK_NATIVE_TLS; + } + client->transport.tls.sock = zsock_socket(broker->sa_family, - SOCK_STREAM, IPPROTO_TLS_1_2); + type, IPPROTO_TLS_1_2); if (client->transport.tls.sock < 0) { return -errno; } From a3139d834c6bd8ee1228ec5f054661683f21612a Mon Sep 17 00:00:00 2001 From: Kamil Piszczek Date: Fri, 18 Mar 2022 14:46:42 +0100 Subject: [PATCH 012/421] [nrf noup] ipc: backends: rpmsg: initialize shared memory to zero Added a code for initializing shared memory to zero. This operation normalizes the memory state so that the IPC service is no longer prone to reading status bits from the previous reset session. Signed-off-by: Kamil Piszczek Signed-off-by: Dominik Ermel (cherry picked from commit 5e850cf31fc07d3e9f8042bb45845c4ad17d949a) (cherry picked from commit 22a279bf1d28f83ae9ea6bc4a5e0bf7e04e7589f) --- .../backends/ipc_rpmsg_static_vrings.c | 27 +++++++++++-------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/subsys/ipc/ipc_service/backends/ipc_rpmsg_static_vrings.c b/subsys/ipc/ipc_service/backends/ipc_rpmsg_static_vrings.c index 41f0a77ea22..5d04d029e8c 100644 --- a/subsys/ipc/ipc_service/backends/ipc_rpmsg_static_vrings.c +++ b/subsys/ipc/ipc_service/backends/ipc_rpmsg_static_vrings.c @@ -774,8 +774,8 @@ static int backend_init(const struct device *instance) return 0; } -#define DEFINE_BACKEND_DEVICE(i) \ - static struct backend_config_t backend_config_##i = { \ +#define BACKEND_CONFIG_POPULATE(i) \ + { \ .role = DT_ENUM_IDX_OR(DT_DRV_INST(i), role, ROLE_HOST), \ .shm_size = DT_REG_SIZE(DT_INST_PHANDLE(i, memory_region)), \ .shm_addr = DT_REG_ADDR(DT_INST_PHANDLE(i, memory_region)), \ @@ -790,8 +790,10 @@ static int backend_init(const struct device *instance) .buffer_size = DT_INST_PROP_OR(i, zephyr_buffer_size, \ RPMSG_BUFFER_SIZE), \ .id = i, \ - }; \ - \ + } + +#define BACKEND_DEVICE_DEFINE(i) \ + static struct backend_config_t backend_config_##i = BACKEND_CONFIG_POPULATE(i); \ static struct backend_data_t backend_data_##i; \ \ DEVICE_DT_INST_DEFINE(i, \ @@ -803,20 +805,23 @@ static int backend_init(const struct device *instance) CONFIG_IPC_SERVICE_REG_BACKEND_PRIORITY, \ &backend_ops); -DT_INST_FOREACH_STATUS_OKAY(DEFINE_BACKEND_DEVICE) +DT_INST_FOREACH_STATUS_OKAY(BACKEND_DEVICE_DEFINE) -#define BACKEND_CONFIG_INIT(n) &backend_config_##n, +#define BACKEND_CONFIG_DEFINE(i) BACKEND_CONFIG_POPULATE(i), #if defined(CONFIG_IPC_SERVICE_BACKEND_RPMSG_SHMEM_RESET) static int shared_memory_prepare(void) { - static const struct backend_config_t *config[] = { - DT_INST_FOREACH_STATUS_OKAY(BACKEND_CONFIG_INIT) + const struct backend_config_t *backend_config; + const struct backend_config_t backend_configs[] = { + DT_INST_FOREACH_STATUS_OKAY(BACKEND_CONFIG_DEFINE) }; - for (int i = 0; i < DT_NUM_INST_STATUS_OKAY(DT_DRV_COMPAT); i++) { - if (config[i]->role == ROLE_HOST) { - memset((void *) config[i]->shm_addr, 0, VDEV_STATUS_SIZE); + for (backend_config = backend_configs; + backend_config < backend_configs + ARRAY_SIZE(backend_configs); + backend_config++) { + if (backend_config->role == ROLE_HOST) { + memset((void *) backend_config->shm_addr, 0, VDEV_STATUS_SIZE); } } From 5f2514e36a2b5da0fb2a477bb92fec23d88519f2 Mon Sep 17 00:00:00 2001 From: Azizah Ibrahim Date: Wed, 7 Apr 2021 13:03:19 +0100 Subject: [PATCH 013/421] [nrf noup] samples: bluetooth: hci_pwr_ctrl: add dynamic control Enable dynamic power control in hci_pwr_ctrl sample for platforms using hci_rpmsg as controller Signed-off-by: Azizah Ibrahim Signed-off-by: Trond Einar Snekvik (cherry picked from commit 14f6d9c0682df75df177253797bb5c904860e632) (cherry picked from commit cda81c03ba45ec242fac84666759ec360968aa29) --- samples/bluetooth/hci_pwr_ctrl/child_image/hci_rpmsg.conf | 1 + 1 file changed, 1 insertion(+) create mode 100644 samples/bluetooth/hci_pwr_ctrl/child_image/hci_rpmsg.conf diff --git a/samples/bluetooth/hci_pwr_ctrl/child_image/hci_rpmsg.conf b/samples/bluetooth/hci_pwr_ctrl/child_image/hci_rpmsg.conf new file mode 100644 index 00000000000..e6749ae6399 --- /dev/null +++ b/samples/bluetooth/hci_pwr_ctrl/child_image/hci_rpmsg.conf @@ -0,0 +1 @@ +CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL=y From 51f1731ef438b20bffa00c56c0fdd19fb8118a1a Mon Sep 17 00:00:00 2001 From: Kamil Piszczek Date: Mon, 20 Jun 2022 10:14:39 +0200 Subject: [PATCH 014/421] [nrf noup] samples: mgmt: mcumgr: add hci_rpmsg child image config Added a configuration file for the HCI RPMsg child image that is necessary for multi-core targets. Signed-off-by: Kamil Piszczek (cherry picked from commit 761f5fd8491635bb3a72006d83a2071c7c379b1f) (cherry picked from commit 5689592f52a43cd26d1d5ae3fb6e662a5cf98780) --- .../mgmt/mcumgr/smp_svr/child_image/hci_rpmsg.conf | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 samples/subsys/mgmt/mcumgr/smp_svr/child_image/hci_rpmsg.conf diff --git a/samples/subsys/mgmt/mcumgr/smp_svr/child_image/hci_rpmsg.conf b/samples/subsys/mgmt/mcumgr/smp_svr/child_image/hci_rpmsg.conf new file mode 100644 index 00000000000..98260877332 --- /dev/null +++ b/samples/subsys/mgmt/mcumgr/smp_svr/child_image/hci_rpmsg.conf @@ -0,0 +1,10 @@ +# +# Copyright (c) 2022 Nordic Semiconductor +# +# SPDX-License-Identifier: Apache-2.0 +# + +CONFIG_BT_MAX_CONN=2 +CONFIG_BT_BUF_ACL_RX_SIZE=502 +CONFIG_BT_BUF_ACL_TX_SIZE=502 +CONFIG_BT_CTLR_DATA_LENGTH_MAX=251 From 9eb6436610f0a0cde6d1ffc6c1cfd70ec1377a15 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20G=C5=82=C4=85bek?= Date: Thu, 1 Dec 2022 14:41:13 +0100 Subject: [PATCH 015/421] [nrf noup] samples&tests: Restore a few CONFIG_NEWLIB_LIBC_NANO=n MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is a follow-up to commit 9dd570f8a2207a02c886480b0065cd5a0e3a2e94. Since in NCS, unlike in vanilla Zephyr, the nano variant of newlib is the default one, restore entries that disable the nano variant in one sample and one test that require the full newlib variant. This patch is supposed to be removed when picolibc becomes the default. Signed-off-by: Andrzej Głąbek (cherry picked from commit 56204202e86fb7fa89f7ae74c916f73a00a22044) (cherry picked from commit 4edd3681905057c345eb622ffe144fac958593e0) --- samples/posix/eventfd/prj.conf | 1 + tests/lib/newlib/heap_listener/prj.conf | 1 + 2 files changed, 2 insertions(+) diff --git a/samples/posix/eventfd/prj.conf b/samples/posix/eventfd/prj.conf index 7ff74543b2f..a0bfcdf747b 100644 --- a/samples/posix/eventfd/prj.conf +++ b/samples/posix/eventfd/prj.conf @@ -1,5 +1,6 @@ # General config CONFIG_NEWLIB_LIBC=y +CONFIG_NEWLIB_LIBC_NANO=n CONFIG_POSIX_API=y CONFIG_EVENTFD=y diff --git a/tests/lib/newlib/heap_listener/prj.conf b/tests/lib/newlib/heap_listener/prj.conf index 31bc1ca7e76..8d8ebf99baf 100644 --- a/tests/lib/newlib/heap_listener/prj.conf +++ b/tests/lib/newlib/heap_listener/prj.conf @@ -1,4 +1,5 @@ CONFIG_ZTEST=y CONFIG_NEWLIB_LIBC=y +CONFIG_NEWLIB_LIBC_NANO=n CONFIG_NEWLIB_LIBC_HEAP_LISTENER=y CONFIG_ZTEST_NEW_API=y From cb04671ad6e0de80e4441e996cc29416af40caaa Mon Sep 17 00:00:00 2001 From: Marek Pieta Date: Mon, 14 Nov 2022 11:22:06 +0100 Subject: [PATCH 016/421] [nrf noup] boards: thingy53_nrf5340: Add common partition map Change introduces common static Partition Manager configuration. The tfm_nonsecure partition must be SPU region aligned. Ref: NCSDK-18033 Ref: NCSDK-19515 Signed-off-by: Marek Pieta Signed-off-by: Markus Swarowsky (cherry picked from commit 6a9eba74bdc36576bdc6f562380912ee44f38bf8) (cherry picked from commit a722c66f997db0f1a74004c3f5c424808938abac) --- .../pm_static_thingy53_nrf5340_cpuapp.yml | 55 ++++++++++++++ .../pm_static_thingy53_nrf5340_cpuapp_ns.yml | 73 +++++++++++++++++++ 2 files changed, 128 insertions(+) create mode 100644 boards/arm/thingy53_nrf5340/pm_static_thingy53_nrf5340_cpuapp.yml create mode 100644 boards/arm/thingy53_nrf5340/pm_static_thingy53_nrf5340_cpuapp_ns.yml diff --git a/boards/arm/thingy53_nrf5340/pm_static_thingy53_nrf5340_cpuapp.yml b/boards/arm/thingy53_nrf5340/pm_static_thingy53_nrf5340_cpuapp.yml new file mode 100644 index 00000000000..7a48d51ec33 --- /dev/null +++ b/boards/arm/thingy53_nrf5340/pm_static_thingy53_nrf5340_cpuapp.yml @@ -0,0 +1,55 @@ +app: + address: 0x10200 + region: flash_primary + size: 0xdfe00 +mcuboot: + address: 0x0 + region: flash_primary + size: 0x10000 +mcuboot_pad: + address: 0x10000 + region: flash_primary + size: 0x200 +mcuboot_primary: + address: 0x10000 + orig_span: &id001 + - mcuboot_pad + - app + region: flash_primary + size: 0xe0000 + span: *id001 +mcuboot_primary_app: + address: 0x10200 + orig_span: &id002 + - app + region: flash_primary + size: 0xdfe00 + span: *id002 +settings_storage: + address: 0xf0000 + region: flash_primary + size: 0x10000 +mcuboot_primary_1: + address: 0x0 + size: 0x40000 + device: flash_ctrl + region: ram_flash +mcuboot_secondary: + address: 0x00000 + size: 0xe0000 + device: MX25R64 + region: external_flash +mcuboot_secondary_1: + address: 0xe0000 + size: 0x40000 + device: MX25R64 + region: external_flash +external_flash: + address: 0x120000 + size: 0x6e0000 + device: MX25R64 + region: external_flash +pcd_sram: + address: 0x20000000 + size: 0x2000 + region: sram_primary diff --git a/boards/arm/thingy53_nrf5340/pm_static_thingy53_nrf5340_cpuapp_ns.yml b/boards/arm/thingy53_nrf5340/pm_static_thingy53_nrf5340_cpuapp_ns.yml new file mode 100644 index 00000000000..70ffe6d9c12 --- /dev/null +++ b/boards/arm/thingy53_nrf5340/pm_static_thingy53_nrf5340_cpuapp_ns.yml @@ -0,0 +1,73 @@ +mcuboot: + address: 0x0 + region: flash_primary + size: 0x10000 +mcuboot_pad: + address: 0x10000 + region: flash_primary + size: 0x200 +tfm_secure: + address: 0x10000 + size: 0xc000 + span: [mcuboot_pad, tfm] +tfm_nonsecure: + address: 0x1c000 + size: 0xd4000 + span: [app] +tfm: + address: 0x10200 + region: flash_primary + size: 0xbe00 +app: + address: 0x1c000 + region: flash_primary + size: 0xd4000 +mcuboot_primary: + address: 0x10000 + orig_span: &id001 + - mcuboot_pad + - tfm + - app + region: flash_primary + size: 0xe0000 + span: *id001 +mcuboot_primary_app: + address: 0x10200 + orig_span: &id002 + - tfm + - app + region: flash_primary + size: 0xdfe00 + span: *id002 +nonsecure_storage: + address: 0xf0000 + size: 0x10000 + span: [settings_storage] +settings_storage: + address: 0xf0000 + region: flash_primary + size: 0x10000 +mcuboot_primary_1: + address: 0x0 + size: 0x40000 + device: flash_ctrl + region: ram_flash +mcuboot_secondary: + address: 0x00000 + size: 0xe0000 + device: MX25R64 + region: external_flash +mcuboot_secondary_1: + address: 0xe0000 + size: 0x40000 + device: MX25R64 + region: external_flash +external_flash: + address: 0x120000 + size: 0x6e0000 + device: MX25R64 + region: external_flash +pcd_sram: + address: 0x20000000 + size: 0x2000 + region: sram_primary From 468009977970899f2d250231847e160671f74d18 Mon Sep 17 00:00:00 2001 From: Aleksandr Khromykh Date: Tue, 7 Feb 2023 12:39:12 +0100 Subject: [PATCH 017/421] [nrf noup] Bluetooth: Mesh: zero randomization for friend's adv Friend's replies on LPN's polls do not assume randomization in advertiser. Zero randomization will help to optimize time when LPN keeps receiving window open and save power. Signed-off-by: Aleksandr Khromykh (cherry picked from commit 88d5ef9efab511212a171fe67faf82468bcd0531) (cherry picked from commit a5ab323470201713ded500729f8cd34fc13c96f0) --- subsys/bluetooth/mesh/Kconfig | 2 +- subsys/bluetooth/mesh/adv_ext.c | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/subsys/bluetooth/mesh/Kconfig b/subsys/bluetooth/mesh/Kconfig index 945b45c12cc..9b0c4bd80f0 100644 --- a/subsys/bluetooth/mesh/Kconfig +++ b/subsys/bluetooth/mesh/Kconfig @@ -926,7 +926,7 @@ config BT_MESH_LPN_INIT_POLL_TIMEOUT config BT_MESH_LPN_SCAN_LATENCY int "Latency for enabling scanning" range 0 50 - default 15 + default 2 help Latency in milliseconds that it takes to enable scanning. This is in practice how much time in advance before the Receive Window diff --git a/subsys/bluetooth/mesh/adv_ext.c b/subsys/bluetooth/mesh/adv_ext.c index 88c631a5867..831149bf79e 100644 --- a/subsys/bluetooth/mesh/adv_ext.c +++ b/subsys/bluetooth/mesh/adv_ext.c @@ -13,6 +13,9 @@ #include #include #include +#if defined(CONFIG_BT_LL_SOFTDEVICE) +#include +#endif #include "common/bt_str.h" @@ -137,6 +140,28 @@ static inline struct bt_mesh_ext_adv *gatt_adv_get(void) #endif /* CONFIG_BT_MESH_ADV_EXT_GATT_SEPARATE */ } +static int set_adv_randomness(uint8_t handle, int rand_us) +{ +#if defined(CONFIG_BT_LL_SOFTDEVICE) + struct net_buf *buf; + sdc_hci_cmd_vs_set_adv_randomness_t *cmd_params; + + buf = bt_hci_cmd_create(SDC_HCI_OPCODE_CMD_VS_SET_ADV_RANDOMNESS, sizeof(*cmd_params)); + if (!buf) { + LOG_ERR("Could not allocate command buffer"); + return -ENOMEM; + } + + cmd_params = net_buf_add(buf, sizeof(*cmd_params)); + cmd_params->adv_handle = handle; + cmd_params->rand_us = rand_us; + + return bt_hci_cmd_send_sync(SDC_HCI_OPCODE_CMD_VS_SET_ADV_RANDOMNESS, buf, NULL); +#else + return 0; +#endif /* defined(CONFIG_BT_LL_SOFTDEVICE) */ +} + static int adv_start(struct bt_mesh_ext_adv *adv, const struct bt_le_adv_param *param, struct bt_le_ext_adv_start_param *start, @@ -473,6 +498,13 @@ int bt_mesh_adv_enable(void) if (err) { return err; } + + if (IS_ENABLED(CONFIG_BT_LL_SOFTDEVICE) && adv->tag & BT_MESH_FRIEND_ADV) { + err = set_adv_randomness(adv->instance->handle, 0); + if (err) { + LOG_ERR("Failed to set zero randomness: %d", err); + } + } } return 0; From c88a4a6ae2ee15bc449ce00435dfa323ce4a179f Mon Sep 17 00:00:00 2001 From: Joakim Andersson Date: Fri, 20 Nov 2020 14:44:03 +0100 Subject: [PATCH 018/421] [nrf noup] Bluetooth: update experimental for qualification MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Update Kconfig options for qualification: - Remove experimental on qualified feature. - Add experimental on unqualified feature. - BT_L2CAP_ECRED is not marked as experimental upstream and we qualify it downstream. Signed-off-by: Joakim Andersson Signed-off-by: Trond Einar Snekvik Signed-off-by: Martí Bolívar Signed-off-by: Robert Lubos Signed-off-by: Dominik Ermel Signed-off-by: Ingar Kulbrandstad Signed-off-by: Torsten Rasmussen Signed-off-by: Herman Berget Signed-off-by: Tomasz Moń (cherry picked from commit a6c2e3bbc24b7f565e3a8c0cc3d2d83b6d442487) (cherry picked from commit b182da7fcd6efed1fb177f87328f597cb14662e4) --- subsys/bluetooth/controller/Kconfig | 3 ++- subsys/bluetooth/host/Kconfig.l2cap | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/subsys/bluetooth/controller/Kconfig b/subsys/bluetooth/controller/Kconfig index 404d89cbf06..59ec86d5efe 100644 --- a/subsys/bluetooth/controller/Kconfig +++ b/subsys/bluetooth/controller/Kconfig @@ -114,7 +114,8 @@ choice BT_LL_CHOICE Select the Bluetooth Link Layer to compile. config BT_LL_SW_SPLIT - bool "Software-based BLE Link Layer" + bool "Software-based BLE Link Layer [EXPERIMENTAL]" + select EXPERIMENTAL select ENTROPY_GENERATOR help Use Zephyr software BLE Link Layer ULL LLL split implementation. diff --git a/subsys/bluetooth/host/Kconfig.l2cap b/subsys/bluetooth/host/Kconfig.l2cap index acb948c425a..f8d602acd57 100644 --- a/subsys/bluetooth/host/Kconfig.l2cap +++ b/subsys/bluetooth/host/Kconfig.l2cap @@ -66,7 +66,7 @@ config BT_L2CAP_DYNAMIC_CHANNEL allowing the creation of dynamic L2CAP Channels. config BT_L2CAP_ECRED - bool "L2CAP Enhanced Credit Based Flow Control support" + bool "L2CAP Enhanced Credit Based Flow Control support [EXPERIMENTAL]" depends on BT_L2CAP_DYNAMIC_CHANNEL help This option enables support for LE Connection oriented Channels with From 62a4cadefae85308a801698f8a164eaecaea2358 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anders=20Storr=C3=B8?= Date: Wed, 8 Mar 2023 12:17:09 +0100 Subject: [PATCH 019/421] [nrf noup] Bluetooth: Mesh: Fix adv randomness bug MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes issue where randomness can be removed for advertising sets that have to handle other adv types than the BT_MESH_FRIEND_ADV tag type. Signed-off-by: Anders Storrø (cherry picked from commit f8f113382356934cb6d1ef4cdad95a843f922085) (cherry picked from commit 996037de254a91a9b2da4a288f48c09e90427501) --- subsys/bluetooth/mesh/adv_ext.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/subsys/bluetooth/mesh/adv_ext.c b/subsys/bluetooth/mesh/adv_ext.c index 831149bf79e..5c1a2bc3c32 100644 --- a/subsys/bluetooth/mesh/adv_ext.c +++ b/subsys/bluetooth/mesh/adv_ext.c @@ -499,7 +499,9 @@ int bt_mesh_adv_enable(void) return err; } - if (IS_ENABLED(CONFIG_BT_LL_SOFTDEVICE) && adv->tag & BT_MESH_FRIEND_ADV) { + if (IS_ENABLED(CONFIG_BT_LL_SOFTDEVICE) && + IS_ENABLED(CONFIG_BT_MESH_ADV_EXT_FRIEND_SEPARATE) && + adv->tag == BT_MESH_FRIEND_ADV) { err = set_adv_randomness(adv->instance->handle, 0); if (err) { LOG_ERR("Failed to set zero randomness: %d", err); From 778b2a956086de2f6aec01f39651a25e3613cdae Mon Sep 17 00:00:00 2001 From: Mateusz Kapala Date: Thu, 2 Feb 2023 11:04:23 +0100 Subject: [PATCH 020/421] [nrf noup] boards: arm: thingy53: Disable USB CDC added by MCUBoot Enabling USB CDC by default in Thingy:53 board configuration caused that there were two instances of USB CDC in MCUBoot. Change disables one instance which was added automatically by NCS if MCUBoot bootloader was built as a child image. Jira: NCSDK-18596 Signed-off-by: Mateusz Kapala Signed-off-by: Johann Fischer (cherry picked from commit 5193278031897be51edfac12ac8cb250f9b8ff93) (cherry picked from commit 7f45aa42295533c14994fe1c449da643fa7d6399) --- boards/arm/thingy53_nrf5340/Kconfig.defconfig | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/boards/arm/thingy53_nrf5340/Kconfig.defconfig b/boards/arm/thingy53_nrf5340/Kconfig.defconfig index e4d9e63b7f1..b34d118e59c 100644 --- a/boards/arm/thingy53_nrf5340/Kconfig.defconfig +++ b/boards/arm/thingy53_nrf5340/Kconfig.defconfig @@ -135,6 +135,12 @@ endif # LOG endif # BOARD_SERIAL_BACKEND_CDC_ACM +# By default, a USB CDC ACM instance is already enabled in the board's DTS. +# It is not necessary for nRF Connect SDK to add another instance if MCUBoot +# bootloader is built as a child image. +config MCUBOOT_USB_SUPPORT + default n + endif # BOARD_THINGY53_NRF5340_CPUAPP || BOARD_THINGY53_NRF5340_CPUAPP_NS if BOARD_THINGY53_NRF5340_CPUNET From aa00769d7243809601ea7480a6f7c0cc72ebe82d Mon Sep 17 00:00:00 2001 From: Joakim Andersson Date: Thu, 5 May 2022 12:04:26 +0200 Subject: [PATCH 021/421] [nrf noup] boards: Enable TF-M by default for nordic SoC NS boards Enable TF-M by default for nordic nRF5340 and nrf9160 SoC boards. NCSDK-14811 Signed-off-by: Joakim Andersson Signed-off-by: Jamie McCrae Signed-off-by: Alex Tsamakos Signed-off-by: Johann Fischer (cherry picked from commit 1f9e520d7518322c0cfd40d91f299cfa28ad07fb) (cherry picked from commit 79993350d8494c3cba1e9947925890249aaedde2) --- boards/arm/actinius_icarus/Kconfig.defconfig | 15 +++++++++++++++ boards/arm/actinius_icarus_bee/Kconfig.defconfig | 15 +++++++++++++++ boards/arm/actinius_icarus_som/Kconfig.defconfig | 15 +++++++++++++++ .../circuitdojo_feather_nrf9160/Kconfig.defconfig | 15 +++++++++++++++ .../sparkfun_thing_plus_nrf9160/Kconfig.defconfig | 15 +++++++++++++++ boards/arm/thingy53_nrf5340/Kconfig.defconfig | 15 +++++++++++++++ 6 files changed, 90 insertions(+) diff --git a/boards/arm/actinius_icarus/Kconfig.defconfig b/boards/arm/actinius_icarus/Kconfig.defconfig index 6994aac280d..3b8093275da 100644 --- a/boards/arm/actinius_icarus/Kconfig.defconfig +++ b/boards/arm/actinius_icarus/Kconfig.defconfig @@ -8,6 +8,21 @@ if BOARD_ACTINIUS_ICARUS || BOARD_ACTINIUS_ICARUS_NS config BOARD default "actinius_icarus" +# By default, if we build for a Non-Secure version of the board, +# enable building with TF-M as the Secure Execution Environment. +config BUILD_WITH_TFM + default y if BOARD_ACTINIUS_ICARUS_NS + +if BUILD_WITH_TFM + +# By default, if we build with TF-M, instruct build system to +# flash the combined TF-M (Secure) & Zephyr (Non Secure) image +config TFM_FLASH_MERGED_BINARY + bool + default y + +endif # BUILD_WITH_TFM + source "boards/common/actinius/Kconfig" # For the secure version of the board the firmware is linked at the beginning diff --git a/boards/arm/actinius_icarus_bee/Kconfig.defconfig b/boards/arm/actinius_icarus_bee/Kconfig.defconfig index 309a45a61d4..7b733d910d9 100644 --- a/boards/arm/actinius_icarus_bee/Kconfig.defconfig +++ b/boards/arm/actinius_icarus_bee/Kconfig.defconfig @@ -8,6 +8,21 @@ if BOARD_ACTINIUS_ICARUS_BEE || BOARD_ACTINIUS_ICARUS_BEE_NS config BOARD default "actinius_icarus_bee" +# By default, if we build for a Non-Secure version of the board, +# enable building with TF-M as the Secure Execution Environment. +config BUILD_WITH_TFM + default y if BOARD_ACTINIUS_ICARUS_BEE_NS + +if BUILD_WITH_TFM + +# By default, if we build with TF-M, instruct build system to +# flash the combined TF-M (Secure) & Zephyr (Non Secure) image +config TFM_FLASH_MERGED_BINARY + bool + default y + +endif # BUILD_WITH_TFM + source "boards/common/actinius/Kconfig" # For the secure version of the board the firmware is linked at the beginning diff --git a/boards/arm/actinius_icarus_som/Kconfig.defconfig b/boards/arm/actinius_icarus_som/Kconfig.defconfig index 473acfea29f..cc92427d24c 100644 --- a/boards/arm/actinius_icarus_som/Kconfig.defconfig +++ b/boards/arm/actinius_icarus_som/Kconfig.defconfig @@ -8,6 +8,21 @@ if BOARD_ACTINIUS_ICARUS_SOM || BOARD_ACTINIUS_ICARUS_SOM_NS config BOARD default "actinius_icarus_som" +# By default, if we build for a Non-Secure version of the board, +# enable building with TF-M as the Secure Execution Environment. +config BUILD_WITH_TFM + default y if BOARD_ACTINIUS_ICARUS_SOM_NS + +if BUILD_WITH_TFM + +# By default, if we build with TF-M, instruct build system to +# flash the combined TF-M (Secure) & Zephyr (Non Secure) image +config TFM_FLASH_MERGED_BINARY + bool + default y + +endif # BUILD_WITH_TFM + source "boards/common/actinius/Kconfig" # For the secure version of the board the firmware is linked at the beginning diff --git a/boards/arm/circuitdojo_feather_nrf9160/Kconfig.defconfig b/boards/arm/circuitdojo_feather_nrf9160/Kconfig.defconfig index 73648be3ef1..f37bfbf84fb 100644 --- a/boards/arm/circuitdojo_feather_nrf9160/Kconfig.defconfig +++ b/boards/arm/circuitdojo_feather_nrf9160/Kconfig.defconfig @@ -9,6 +9,21 @@ if BOARD_CIRCUITDOJO_FEATHER_NRF9160 || BOARD_CIRCUITDOJO_FEATHER_NRF9160_NS config BOARD default "circuitdojo_feather_nrf9160" +# By default, if we build for a Non-Secure version of the board, +# enable building with TF-M as the Secure Execution Environment. +config BUILD_WITH_TFM + default y if BOARD_CIRCUITDOJO_FEATHER_NRF9160_NS + +if BUILD_WITH_TFM + +# By default, if we build with TF-M, instruct build system to +# flash the combined TF-M (Secure) & Zephyr (Non Secure) image +config TFM_FLASH_MERGED_BINARY + bool + default y + +endif # BUILD_WITH_TFM + # For the secure version of the board the firmware is linked at the beginning # of the flash, or into the code-partition defined in DT if it is intended to # be loaded by MCUboot. If the secure firmware is to be combined with a non- diff --git a/boards/arm/sparkfun_thing_plus_nrf9160/Kconfig.defconfig b/boards/arm/sparkfun_thing_plus_nrf9160/Kconfig.defconfig index 8ae5b832d89..3d98b1b4cb4 100644 --- a/boards/arm/sparkfun_thing_plus_nrf9160/Kconfig.defconfig +++ b/boards/arm/sparkfun_thing_plus_nrf9160/Kconfig.defconfig @@ -9,6 +9,21 @@ if BOARD_SPARKFUN_THING_PLUS_NRF9160 || BOARD_SPARKFUN_THING_PLUS_NRF9160_NS config BOARD default "sparkfun_thing_plus_nrf9160" +# By default, if we build for a Non-Secure version of the board, +# enable building with TF-M as the Secure Execution Environment. +config BUILD_WITH_TFM + default y if BOARD_SPARKFUN_THING_PLUS_NRF9160_NS + +if BUILD_WITH_TFM + +# By default, if we build with TF-M, instruct build system to +# flash the combined TF-M (Secure) & Zephyr (Non Secure) image +config TFM_FLASH_MERGED_BINARY + bool + default y + +endif # BUILD_WITH_TFM + # For the secure version of the board the firmware is linked at the beginning # of the flash, or into the code-partition defined in DT if it is intended to # be loaded by MCUboot. If the secure firmware is to be combined with a non- diff --git a/boards/arm/thingy53_nrf5340/Kconfig.defconfig b/boards/arm/thingy53_nrf5340/Kconfig.defconfig index b34d118e59c..0afe06dacb9 100644 --- a/boards/arm/thingy53_nrf5340/Kconfig.defconfig +++ b/boards/arm/thingy53_nrf5340/Kconfig.defconfig @@ -8,6 +8,21 @@ if BOARD_THINGY53_NRF5340_CPUAPP || BOARD_THINGY53_NRF5340_CPUAPP_NS config BOARD default "thingy53_nrf5340_cpuapp" +# By default, if we build for a Non-Secure version of the board, +# enable building with TF-M as the Secure Execution Environment. +config BUILD_WITH_TFM + default y if BOARD_THINGY53_NRF5340_CPUAPP_NS + +if BUILD_WITH_TFM + +# By default, if we build with TF-M, instruct build system to +# flash the combined TF-M (Secure) & Zephyr (Non Secure) image +config TFM_FLASH_MERGED_BINARY + bool + default y + +endif # BUILD_WITH_TFM + # Code Partition: # # For the secure version of the board the firmware is linked at the beginning From 542ff4901b820fd0d8fc1e6264059962ebbf96bf Mon Sep 17 00:00:00 2001 From: Marek Pieta Date: Mon, 28 Nov 2022 15:31:33 +0100 Subject: [PATCH 022/421] [nrf noup] boards: thingy53_nrf5340: Enable MCUboot by default Change enables MCUboot bootloader by default to allow programming samples and applications without external programmer (using MCUboot serial recovery). Change also enables network core to prevent build failures when building MCUboot with nRF53 multi image DFU. Jira: NCSDK-18263 Signed-off-by: Marek Pieta Signed-off-by: Vinayak Kariappa Chettimada Signed-off-by: Johann Fischer (cherry picked from commit 46895493bf1b0988e44ea344f4420b543e307eae) (cherry picked from commit ff1db43269579e2a0bdc28c55f2c83d3ad58ebb7) --- boards/arm/thingy53_nrf5340/Kconfig.defconfig | 6 ++++++ boards/arm/thingy53_nrf5340/thingy53_nrf5340_common.dtsi | 1 + 2 files changed, 7 insertions(+) diff --git a/boards/arm/thingy53_nrf5340/Kconfig.defconfig b/boards/arm/thingy53_nrf5340/Kconfig.defconfig index 0afe06dacb9..c79eb908c21 100644 --- a/boards/arm/thingy53_nrf5340/Kconfig.defconfig +++ b/boards/arm/thingy53_nrf5340/Kconfig.defconfig @@ -8,6 +8,12 @@ if BOARD_THINGY53_NRF5340_CPUAPP || BOARD_THINGY53_NRF5340_CPUAPP_NS config BOARD default "thingy53_nrf5340_cpuapp" +config BOOTLOADER_MCUBOOT + default y if !MCUBOOT + +config BOARD_ENABLE_CPUNET + default y if !MCUBOOT + # By default, if we build for a Non-Secure version of the board, # enable building with TF-M as the Secure Execution Environment. config BUILD_WITH_TFM diff --git a/boards/arm/thingy53_nrf5340/thingy53_nrf5340_common.dtsi b/boards/arm/thingy53_nrf5340/thingy53_nrf5340_common.dtsi index 341bb1305e1..515fc3bea7b 100644 --- a/boards/arm/thingy53_nrf5340/thingy53_nrf5340_common.dtsi +++ b/boards/arm/thingy53_nrf5340/thingy53_nrf5340_common.dtsi @@ -16,6 +16,7 @@ zephyr,bt-hci-rpmsg-ipc = &ipc0; nordic,802154-spinel-ipc = &ipc0; zephyr,ieee802154 = &ieee802154; + nordic,pm-ext-flash = &mx25r64; }; buttons { From 16ac80df1b7210957d8c325573326ec6f3d0b931 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eivind=20J=C3=B8lsgard?= Date: Tue, 9 May 2023 12:10:13 +0200 Subject: [PATCH 023/421] [nrf noup] cmake: modules: Add ZEPHYR_NRF_MODULE_DIR to snippets root MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add nRF directory to snippets root to allow placing snippets in the sdk-nrf/snippets directory. CmakeLists.txt in nRF directory is handled after the snippets so that adding the directory in sdk-nrf will not work. Signed-off-by: Eivind Jølsgard (cherry picked from commit b4672df6bb9bb2e3ea44eae8f39051c083f3f124) --- cmake/modules/snippets.cmake | 1 + 1 file changed, 1 insertion(+) diff --git a/cmake/modules/snippets.cmake b/cmake/modules/snippets.cmake index 550d236a2f4..6f8950c5f64 100644 --- a/cmake/modules/snippets.cmake +++ b/cmake/modules/snippets.cmake @@ -59,6 +59,7 @@ function(zephyr_process_snippets) # Set SNIPPET_ROOT. list(APPEND SNIPPET_ROOT ${APPLICATION_SOURCE_DIR}) list(APPEND SNIPPET_ROOT ${ZEPHYR_BASE}) + list(APPEND SNIPPET_ROOT ${ZEPHYR_NRF_MODULE_DIR}) unset(real_snippet_root) foreach(snippet_dir ${SNIPPET_ROOT}) # The user might have put a symbolic link in here, for example. From 07385636ee190aefce8405776eb76d836c791808 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vidar=20Lilleb=C3=B8?= Date: Tue, 9 May 2023 16:21:35 +0200 Subject: [PATCH 024/421] [nrf noup] modules: mbedtls: Add PSA symbols for Oberon PSA extension Add PSA symbols for Oberon extension to the PSA specification. Noup commit until we can decide a better way to include PSA extension options, or these are accepted to be included in PSA specification with naming for the configurations that are compatible with Mbed TLS project. Signed-off-by: Joakim Andersson (cherry picked from commit 0b32fd2743f574aaa293122545caeadd3b01fd41) --- modules/mbedtls/Kconfig.psa | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/modules/mbedtls/Kconfig.psa b/modules/mbedtls/Kconfig.psa index 399d18a3797..9f93771584c 100644 --- a/modules/mbedtls/Kconfig.psa +++ b/modules/mbedtls/Kconfig.psa @@ -300,7 +300,8 @@ config PSA_HAS_KEY_DERIVATION PSA_WANT_ALG_HKDF_EXTRACT || \ PSA_WANT_ALG_PBKDF2_HMAC || \ PSA_WANT_ALG_TLS12_PRF || \ - PSA_WANT_ALG_TLS12_PSK_TO_MS + PSA_WANT_ALG_TLS12_PSK_TO_MS || \ + PSA_WANT_ALG_TLS12_ECJPAKE_TO_PMS help Prompt-less configuration that states that key derivation is supported. @@ -331,6 +332,10 @@ config PSA_WANT_ALG_TLS12_PSK_TO_MS bool prompt "PSA TLS 1.2 PSK to MS support" if !PSA_PROMPTLESS +config PSA_WANT_ALG_TLS12_ECJPAKE_TO_PMS + bool + prompt "PSA TLS 1.2 EC J-PAKE to PMS support" if !PSA_PROMPTLESS + endmenu # PSA Key derivation support @@ -477,8 +482,19 @@ config PSA_WANT_ALG_SPAKE2P prompt "PSA SPAKE2+ support" if !PSA_PROMPTLESS select EXPERIMENTAL -config PSA_WANT_ALG_SRP +config PSA_WANT_ALG_SRP_6 bool - prompt "PSA SRP support" if !PSA_PROMPTLESS - default n + prompt "PSA SRP-6 support" if !PSA_PROMPTLESS select EXPERIMENTAL + +config PSA_WANT_ALG_PURE_EDDSA + bool + prompt "PSA PURE_EDDSA support" if !PSA_PROMPTLESS + +config PSA_WANT_ALG_ED25519PH + bool + prompt "PSA ED25519PH support" if !PSA_PROMPTLESS + +config PSA_WANT_ALG_ED448PH + bool + prompt "PSA ED448PH support" if !PSA_PROMPTLESS From 4d76b6a7403a5d3c14098d4d67e26e284e3c5757 Mon Sep 17 00:00:00 2001 From: Maciej Perkowski Date: Fri, 28 Jan 2022 12:02:58 +0100 Subject: [PATCH 025/421] [nrf noup] ci: clang: parallel execution MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bring back parallel execution to the clang action. In the upstream they went to use a single dedicated powerful agent to run this. We need to keep this as we have to base on agents available in github's cloud. zephyr_runner is upstream's proprietary agent inaccessible outside of upstream's CI. Use ubuntu-latest instead. Signed-off-by: Maciej Perkowski Signed-off-by: Gerard Marull-Paretas Signed-off-by: Dominik Ermel Signed-off-by: Torsten Rasmussen Signed-off-by: Tomasz Moń Signed-off-by: Stephanos Ioannidis Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit 5b3d0ff9ab29e66d52fd7c3ffbd50e9e97b1d7d5) (cherry picked from commit 5e2f4ecc0bd4171ff60bfbc9f60271d0a30142cc) Signed-off-by: Dominik Ermel (cherry picked from commit 0948638f2e3a857bdfcd4bad0e1b5bd6d4760fb6) --- .github/workflows/clang.yaml | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/.github/workflows/clang.yaml b/.github/workflows/clang.yaml index 9108d31b45b..402cbae9f95 100644 --- a/.github/workflows/clang.yaml +++ b/.github/workflows/clang.yaml @@ -8,8 +8,7 @@ concurrency: jobs: clang-build: - if: github.repository_owner == 'zephyrproject-rtos' - runs-on: zephyr-runner-linux-x64-4xlarge + runs-on: ubuntu-latest container: image: ghcr.io/zephyrproject-rtos/ci:v0.26.4 options: '--entrypoint /bin/bash' @@ -19,11 +18,13 @@ jobs: fail-fast: false matrix: platform: ["native_posix"] + subset: [1, 2, 3, 4, 5] env: ZEPHYR_SDK_INSTALL_DIR: /opt/toolchains/zephyr-sdk-0.16.1 LLVM_TOOLCHAIN_PATH: /usr/lib/llvm-16 COMMIT_RANGE: ${{ github.event.pull_request.base.sha }}..${{ github.event.pull_request.head.sha }} BASE_REF: ${{ github.base_ref }} + MATRIX_SIZE: 5 outputs: report_needed: ${{ steps.twister.outputs.report_needed }} steps: @@ -85,7 +86,7 @@ jobs: id: cache-ccache uses: zephyrproject-rtos/action-s3-cache@v1.2.0 with: - key: ${{ steps.ccache_cache_timestamp.outputs.repo }}-${{ github.ref_name }}-clang-${{ matrix.platform }}-ccache + key: ${{ steps.ccache_cache_timestamp.outputs.repo }}-${{ github.ref_name }}-clang-${{ matrix.subset }}-ccache path: /github/home/.cache/ccache aws-s3-bucket: ccache.zephyrproject.org aws-access-key-id: ${{ vars.AWS_CCACHE_ACCESS_KEY_ID }} @@ -98,6 +99,16 @@ jobs: test -d github/home/.cache/ccache && rm -rf /github/home/.cache/ccache && mv github/home/.cache/ccache /github/home/.cache/ccache ccache -M 10G -s + - name: Build test plan with Twister + id: twister_test_plan + run: | + export ZEPHYR_BASE=${PWD} + export ZEPHYR_TOOLCHAIN_VARIANT=llvm + + # check if we need to run a full twister or not based on files changed + python3 ./scripts/ci/test_plan.py -p native_posix -c origin/${BASE_REF}.. + + - name: Run Tests with Twister id: twister run: | @@ -111,7 +122,7 @@ jobs: if [ -s testplan.json ]; then echo "report_needed=1" >> $GITHUB_OUTPUT # Full twister but with options based on changes - ./scripts/twister --force-color --inline-logs -M -N -v --load-tests testplan.json --retry-failed 2 + ./scripts/twister --inline-logs -M -N -v --load-tests testplan.json --retry-failed 2 --subset ${{matrix.subset}}/${MATRIX_SIZE} else # if nothing is run, skip reporting step echo "report_needed=0" >> $GITHUB_OUTPUT @@ -126,7 +137,7 @@ jobs: if: always() && steps.twister.outputs.report_needed != 0 uses: actions/upload-artifact@v3 with: - name: Unit Test Results (Subset ${{ matrix.platform }}) + name: Unit Test Results (Subset ${{ matrix.subset }}) path: twister-out/twister.xml clang-build-results: From 8b234720cb043930a80ebf3aa00b18a82ed9d821 Mon Sep 17 00:00:00 2001 From: Gerard Marull-Paretas Date: Thu, 1 Jun 2023 15:58:56 +0200 Subject: [PATCH 026/421] [nrf noup] tests: drivers: build_all: regulator: use old schema New Twister schema is not supported yet in sdk-zephyr, drop this patch once Twister is updated. Signed-off-by: Gerard Marull-Paretas (cherry picked from commit 4618cfe53df3154a6ee4101c2e68e98531fdda98) Signed-off-by: Dominik Ermel (cherry picked from commit c01ee451273ccb33c211f5b10fa2858ff8a271b9) --- tests/drivers/build_all/regulator/testcase.yaml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tests/drivers/build_all/regulator/testcase.yaml b/tests/drivers/build_all/regulator/testcase.yaml index 9b9c25511c4..c5dbda1913f 100644 --- a/tests/drivers/build_all/regulator/testcase.yaml +++ b/tests/drivers/build_all/regulator/testcase.yaml @@ -3,8 +3,6 @@ tests: drivers.regulator.build: - tags: - - drivers - - regulator + tags: drivers regulator build_only: true platform_allow: native_posix From f3aa7126214fdf6a77afd316a5c0f3e48257f62f Mon Sep 17 00:00:00 2001 From: Dawid Przybylo Date: Fri, 23 Jun 2023 08:15:25 +0200 Subject: [PATCH 027/421] [nrf noup] ci: Update test-spec.yml with adding FEM to CI Extend sdk-zephyr CI with FEM test label. Signed-off-by: Dawid Przybylo (cherry picked from commit d2bc2c3c6ce3d08628a93c3bd246fd688dc6a446) --- .github/test-spec.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/test-spec.yml b/.github/test-spec.yml index 3fe9ba5fbec..5dd281919bc 100644 --- a/.github/test-spec.yml +++ b/.github/test-spec.yml @@ -60,6 +60,9 @@ "CI-crypto-test": - "**/*" +"CI-fem-test": + - "**/*" + "CI-rs-test": - "**/*" From 34f5012ee258e0d090581ed1caf7ba752e327cd5 Mon Sep 17 00:00:00 2001 From: Robert Lubos Date: Mon, 19 Jun 2023 12:19:05 +0200 Subject: [PATCH 028/421] [nrf noup] Revert "twister: Use natural sort when generating hardware map" This reverts commit c37deeb0c4602dc3eeb700a7dc3ed317283fff17. This is only a temporary change, until we align our CI. To be removed once natsort is avaialble in the NCS CI. Signed-off-by: Robert Lubos (cherry picked from commit cc84ffea7210488ec24db09db25dd6df107f0209) --- scripts/pylib/twister/twisterlib/hardwaremap.py | 3 +-- scripts/requirements-run-test.txt | 1 - 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/scripts/pylib/twister/twisterlib/hardwaremap.py b/scripts/pylib/twister/twisterlib/hardwaremap.py index 5e90b7c84c6..a0ea7c59a8e 100644 --- a/scripts/pylib/twister/twisterlib/hardwaremap.py +++ b/scripts/pylib/twister/twisterlib/hardwaremap.py @@ -13,7 +13,6 @@ import scl import logging from pathlib import Path -from natsort import natsorted from twisterlib.environment import ZEPHYR_BASE @@ -322,7 +321,7 @@ def readlink(link): def save(self, hwm_file): # use existing map - self.detected = natsorted(self.detected, key=lambda x: x.serial or '') + self.detected.sort(key=lambda x: x.serial or '') if os.path.exists(hwm_file): with open(hwm_file, 'r') as yaml_file: hwm = yaml.load(yaml_file, Loader=SafeLoader) diff --git a/scripts/requirements-run-test.txt b/scripts/requirements-run-test.txt index 83692128110..3bb0b21c44e 100644 --- a/scripts/requirements-run-test.txt +++ b/scripts/requirements-run-test.txt @@ -7,7 +7,6 @@ pyocd>=0.35.0 # used by twister for board/hardware map tabulate -natsort # used by mcuboot cbor>=1.0.0 From 51bef37071aad3301b4223a59991af71614a13ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20B=C3=B8e?= Date: Tue, 20 Jun 2023 13:27:15 +0200 Subject: [PATCH 029/421] [nrf noup] mbedtls: Add config support for PBKDF2_HMAC MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add config support for PBKDF2_HMAC. This patches an existing noup commit and is therefore also noup. Signed-off-by: Sebastian Bøe (cherry picked from commit 1ff52962ebce37d536949bcc1804fcf502011af6) --- modules/mbedtls/Kconfig.psa | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/modules/mbedtls/Kconfig.psa b/modules/mbedtls/Kconfig.psa index 9f93771584c..5e8e9a8ead0 100644 --- a/modules/mbedtls/Kconfig.psa +++ b/modules/mbedtls/Kconfig.psa @@ -320,9 +320,8 @@ config PSA_WANT_ALG_HKDF_EXPAND config PSA_WANT_ALG_PBKDF2_HMAC bool + prompt "PSA PBKDF2 HMAC support" if !PSA_PROMPTLESS depends on PSA_WANT_ALG_HMAC - help - PBKDF2-HMAC is not yet supported via the PSA APIs in Mbed TLS. config PSA_WANT_ALG_TLS12_PRF bool From 192697c16cc5908a88d0b75440ec319e2c5d211a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20B=C3=B8e?= Date: Tue, 20 Jun 2023 15:04:46 +0200 Subject: [PATCH 030/421] [nrf noup] mbedtls: Add config support for PBKDF2_AES_CMAC_PRF_128 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add config support for PBKDF2_AES_CMAC_PRF_128 Signed-off-by: Sebastian Bøe (cherry picked from commit 743f99947369088ecba6820a720ede8054893866) --- modules/mbedtls/Kconfig.psa | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/modules/mbedtls/Kconfig.psa b/modules/mbedtls/Kconfig.psa index 5e8e9a8ead0..b0d21685f70 100644 --- a/modules/mbedtls/Kconfig.psa +++ b/modules/mbedtls/Kconfig.psa @@ -299,6 +299,7 @@ config PSA_HAS_KEY_DERIVATION PSA_WANT_ALG_HKDF_EXPAND || \ PSA_WANT_ALG_HKDF_EXTRACT || \ PSA_WANT_ALG_PBKDF2_HMAC || \ + PSA_WANT_ALG_PBKDF2_AES_CMAC_PRF_128 || \ PSA_WANT_ALG_TLS12_PRF || \ PSA_WANT_ALG_TLS12_PSK_TO_MS || \ PSA_WANT_ALG_TLS12_ECJPAKE_TO_PMS @@ -323,6 +324,11 @@ config PSA_WANT_ALG_PBKDF2_HMAC prompt "PSA PBKDF2 HMAC support" if !PSA_PROMPTLESS depends on PSA_WANT_ALG_HMAC +config PSA_WANT_ALG_PBKDF2_AES_CMAC_PRF_128 + bool + prompt "PSA PBKDF2-AES-CMAC-PRF-128 support" if !PSA_PROMPTLESS + depends on PSA_WANT_ALG_CMAC + config PSA_WANT_ALG_TLS12_PRF bool prompt "PSA PRF support (TLS1.2)" if !PSA_PROMPTLESS From 6fba504e5e4026e1b563013ac6e7858ca73ea260 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Thu, 13 Jul 2023 13:42:10 +0000 Subject: [PATCH 031/421] [nrf noup] drivers/flashdisk: Add support for Partition Manager The commits adds support for generating flash disks from Partition Manager defined partitions. Signed-off-by: Dominik Ermel (cherry picked from commit 60166d9f304b48febbbaad58a210d0017ed8fdd3) --- drivers/disk/flashdisk.c | 78 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) diff --git a/drivers/disk/flashdisk.c b/drivers/disk/flashdisk.c index 6336ad4dfd0..3e43716c2b3 100644 --- a/drivers/disk/flashdisk.c +++ b/drivers/disk/flashdisk.c @@ -420,6 +420,8 @@ static const struct disk_operations flash_disk_ops = { .ioctl = disk_flash_access_ioctl, }; +#ifndef USE_PARTITION_MANAGER +/* The non-Partition manager, DTS based generators below */ #define DT_DRV_COMPAT zephyr_flash_disk #define PARTITION_PHANDLE(n) DT_PHANDLE_BY_IDX(DT_DRV_INST(n), partition, 0) @@ -461,6 +463,82 @@ DT_INST_FOREACH_STATUS_OKAY(VERIFY_CACHE_SIZE_IS_NOT_ZERO_IF_NOT_READ_ONLY) "Devicetree node " DT_NODE_PATH(DT_DRV_INST(n)) \ " has cache size which is not a multiple of its sector size"); DT_INST_FOREACH_STATUS_OKAY(VERIFY_CACHE_SIZE_IS_MULTIPLY_OF_SECTOR_SIZE) +#else /* ifndef USE_PARTITION_MANAGER */ +/* Partition Manager based generators below */ + +/* Gets the PM_..._EXTRA_PARAM_##param value */ +#define PM_FLASH_DISK_ENTRY_EXTRA_PARAM(name, param) PM_##name##_EXTRA_PARAM_disk_##param + +/* Gets the PM_..._NAME value which is originally cased, as in yaml, partition name */ +#define PM_FLASH_DISK_ENTRY_PARTITION_NAME(name) PM_##name##_NAME + +/* Generates flashdiskN_cache variable name, where N is partition ID */ +#define PM_FLASH_DISK_CACHE_VARIABLE(n) UTIL_CAT(flashdisk, UTIL_CAT(FIXED_PARTITION_ID(n), _cache)) + +/* Generate cache buffers */ +#define CACHE_SIZE(n) (COND_CODE_1(PM_FLASH_DISK_ENTRY_EXTRA_PARAM(n, read_only), (0), (1)) * \ + PM_FLASH_DISK_ENTRY_EXTRA_PARAM(n, cache_size)) +#define DEFINE_FLASHDISKS_CACHE(n) \ + static uint8_t __aligned(4) PM_FLASH_DISK_CACHE_VARIABLE(n)[CACHE_SIZE(n)]; + +PM_FOREACH_AFFILIATED_TO_disk(DEFINE_FLASHDISKS_CACHE) + +/* Generated single Flash Disk device data from Partition Manager partition. + * Partition is required to have type set to disk in partition definitions: + * type: disk + * and following extra params can be provided: + * extra_params: { + * name = "", + * cache_size = , + * sector_size = , + * read_only = + * } + * where: + * is mandatory device name that will be used by Disk Access and FAT FS to mount device; + * is cache r/w cache size, which is mandatory if read_only = 0 or not present, + * and should be multiple of ; + * is mandatory device sector size information, usually should be erase page size, + * for flash devices, for example 4096 bytes; + * read_only is optional, if not present then assumed false; can be 0(false) or 1(true). + */ +#define DEFINE_FLASHDISKS_DEVICE(n) \ +{ \ + .info = { \ + .ops = &flash_disk_ops, \ + .name = STRINGIFY(PM_FLASH_DISK_ENTRY_EXTRA_PARAM(n, name)), \ + }, \ + .area_id = FIXED_PARTITION_ID(n), \ + .offset = FIXED_PARTITION_OFFSET(n), \ + .cache = PM_FLASH_DISK_CACHE_VARIABLE(n), \ + .cache_size = sizeof(PM_FLASH_DISK_CACHE_VARIABLE(n)), \ + .size = FIXED_PARTITION_SIZE(n), \ + .sector_size = PM_FLASH_DISK_ENTRY_EXTRA_PARAM(n, sector_size), \ +}, + +/* The bellow used PM_FOREACH_TYPE_disk is generated by Partition Manager foreach + * loop macro. The lower case _disk is type name for which the macro has been generated; + * partition entry can have multiple types set and foreach macro will be generated + * for every type found across partition definitions. + */ +static struct flashdisk_data flash_disks[] = { + PM_FOREACH_AFFILIATED_TO_disk(DEFINE_FLASHDISKS_DEVICE) +}; + +#define VERIFY_CACHE_SIZE_IS_NOT_ZERO_IF_NOT_READ_ONLY(n) \ + COND_CODE_1(PM_FLASH_DISK_ENTRY_EXTRA_PARAM(n, read_only), \ + (/* cache-size is not used for read-only disks */), \ + (BUILD_ASSERT(PM_FLASH_DISK_ENTRY_EXTRA_PARAM(n, cache_size) != 0, \ + "Flash disk partition " STRINGIFY(PM_FLASH_DISK_ENTRY_PARTITION_NAME(n))\ + " must have non-zero cache-size");)) +PM_FOREACH_AFFILIATED_TO_disk(VERIFY_CACHE_SIZE_IS_NOT_ZERO_IF_NOT_READ_ONLY) + +#define VERIFY_CACHE_SIZE_IS_MULTIPLY_OF_SECTOR_SIZE(n) \ + BUILD_ASSERT(PM_FLASH_DISK_ENTRY_EXTRA_PARAM(n, cache_size) % \ + PM_FLASH_DISK_ENTRY_EXTRA_PARAM(n, sector_size) == 0, \ + "Devicetree node " STRINGIFY(PM_FLASH_DISK_ENTRY_PARTITION_NAME(n)) \ + " has cache size which is not a multiple of its sector size"); +PM_FOREACH_AFFILIATED_TO_disk(VERIFY_CACHE_SIZE_IS_MULTIPLY_OF_SECTOR_SIZE) +#endif /* USE_PARTITION_MANAGER */ static int disk_flash_init(void) { From 0539e2d67b72e5072e5bb04c4cec562c1fab5872 Mon Sep 17 00:00:00 2001 From: Robert Lubos Date: Thu, 13 Jul 2023 15:32:45 +0200 Subject: [PATCH 032/421] [nrf noup] samples: net: Add support for nRF700x Add support for nRF700x to selected networking samples, by providing appropriate overlay configuration files. Signed-off-by: Robert Lubos (cherry picked from commit 4579f028e1e6139786491e352c50bc9528b09c7d) --- .../net/dhcpv4_client/overlay-nrf700x.conf | 14 ++++++++++ samples/net/dns_resolve/overlay-nrf700x.conf | 18 +++++++++++++ .../net/ipv4_autoconf/overlay-nrf700x.conf | 14 ++++++++++ .../net/mdns_responder/overlay-nrf700x.conf | 18 +++++++++++++ .../net/mqtt_publisher/overlay-nrf700x.conf | 19 ++++++++++++++ .../mqtt_sn_publisher/overlay-nrf700x.conf | 20 ++++++++++++++ .../sockets/coap_client/overlay-nrf700x.conf | 16 ++++++++++++ .../sockets/coap_server/overlay-nrf700x.conf | 26 +++++++++++++++++++ samples/net/sockets/echo/overlay-nrf700x.conf | 18 +++++++++++++ .../sockets/echo_async/overlay-nrf700x.conf | 18 +++++++++++++ .../sockets/echo_client/overlay-nrf700x.conf | 20 ++++++++++++++ .../sockets/echo_server/overlay-nrf700x.conf | 20 ++++++++++++++ .../net/sockets/http_get/overlay-nrf700x.conf | 18 +++++++++++++ .../sockets/sntp_client/overlay-nrf700x.conf | 18 +++++++++++++ samples/net/syslog_net/overlay-nrf700x.conf | 18 +++++++++++++ samples/net/telnet/overlay-nrf700x.conf | 18 +++++++++++++ 16 files changed, 293 insertions(+) create mode 100644 samples/net/dhcpv4_client/overlay-nrf700x.conf create mode 100644 samples/net/dns_resolve/overlay-nrf700x.conf create mode 100644 samples/net/ipv4_autoconf/overlay-nrf700x.conf create mode 100644 samples/net/mdns_responder/overlay-nrf700x.conf create mode 100644 samples/net/mqtt_publisher/overlay-nrf700x.conf create mode 100644 samples/net/mqtt_sn_publisher/overlay-nrf700x.conf create mode 100644 samples/net/sockets/coap_client/overlay-nrf700x.conf create mode 100644 samples/net/sockets/coap_server/overlay-nrf700x.conf create mode 100644 samples/net/sockets/echo/overlay-nrf700x.conf create mode 100644 samples/net/sockets/echo_async/overlay-nrf700x.conf create mode 100644 samples/net/sockets/echo_client/overlay-nrf700x.conf create mode 100644 samples/net/sockets/echo_server/overlay-nrf700x.conf create mode 100644 samples/net/sockets/http_get/overlay-nrf700x.conf create mode 100644 samples/net/sockets/sntp_client/overlay-nrf700x.conf create mode 100644 samples/net/syslog_net/overlay-nrf700x.conf create mode 100644 samples/net/telnet/overlay-nrf700x.conf diff --git a/samples/net/dhcpv4_client/overlay-nrf700x.conf b/samples/net/dhcpv4_client/overlay-nrf700x.conf new file mode 100644 index 00000000000..2d552e9c623 --- /dev/null +++ b/samples/net/dhcpv4_client/overlay-nrf700x.conf @@ -0,0 +1,14 @@ +# Wi-Fi +CONFIG_WIFI=y +CONFIG_WIFI_NRF700X=y +CONFIG_WPA_SUPP=y +CONFIG_NET_L2_ETHERNET=y + +# Connection manager +CONFIG_NET_CONNECTION_MANAGER=y + +# Credentials +CONFIG_WIFI_CREDENTIALS=y +CONFIG_WIFI_CREDENTIALS_STATIC=y +CONFIG_WIFI_CREDENTIALS_STATIC_SSID="" +CONFIG_WIFI_CREDENTIALS_STATIC_PASSWORD="" diff --git a/samples/net/dns_resolve/overlay-nrf700x.conf b/samples/net/dns_resolve/overlay-nrf700x.conf new file mode 100644 index 00000000000..aa59e5d5ea2 --- /dev/null +++ b/samples/net/dns_resolve/overlay-nrf700x.conf @@ -0,0 +1,18 @@ +# Wi-Fi +CONFIG_WIFI=y +CONFIG_WIFI_NRF700X=y +CONFIG_WPA_SUPP=y +CONFIG_NET_L2_ETHERNET=y + +# DHCPv4 +CONFIG_NET_CONFIG_MY_IPV4_ADDR="" +CONFIG_NET_DHCPV4=y + +# Connection manager +CONFIG_NET_CONNECTION_MANAGER=y + +# Credentials +CONFIG_WIFI_CREDENTIALS=y +CONFIG_WIFI_CREDENTIALS_STATIC=y +CONFIG_WIFI_CREDENTIALS_STATIC_SSID="" +CONFIG_WIFI_CREDENTIALS_STATIC_PASSWORD="" diff --git a/samples/net/ipv4_autoconf/overlay-nrf700x.conf b/samples/net/ipv4_autoconf/overlay-nrf700x.conf new file mode 100644 index 00000000000..2d552e9c623 --- /dev/null +++ b/samples/net/ipv4_autoconf/overlay-nrf700x.conf @@ -0,0 +1,14 @@ +# Wi-Fi +CONFIG_WIFI=y +CONFIG_WIFI_NRF700X=y +CONFIG_WPA_SUPP=y +CONFIG_NET_L2_ETHERNET=y + +# Connection manager +CONFIG_NET_CONNECTION_MANAGER=y + +# Credentials +CONFIG_WIFI_CREDENTIALS=y +CONFIG_WIFI_CREDENTIALS_STATIC=y +CONFIG_WIFI_CREDENTIALS_STATIC_SSID="" +CONFIG_WIFI_CREDENTIALS_STATIC_PASSWORD="" diff --git a/samples/net/mdns_responder/overlay-nrf700x.conf b/samples/net/mdns_responder/overlay-nrf700x.conf new file mode 100644 index 00000000000..aa59e5d5ea2 --- /dev/null +++ b/samples/net/mdns_responder/overlay-nrf700x.conf @@ -0,0 +1,18 @@ +# Wi-Fi +CONFIG_WIFI=y +CONFIG_WIFI_NRF700X=y +CONFIG_WPA_SUPP=y +CONFIG_NET_L2_ETHERNET=y + +# DHCPv4 +CONFIG_NET_CONFIG_MY_IPV4_ADDR="" +CONFIG_NET_DHCPV4=y + +# Connection manager +CONFIG_NET_CONNECTION_MANAGER=y + +# Credentials +CONFIG_WIFI_CREDENTIALS=y +CONFIG_WIFI_CREDENTIALS_STATIC=y +CONFIG_WIFI_CREDENTIALS_STATIC_SSID="" +CONFIG_WIFI_CREDENTIALS_STATIC_PASSWORD="" diff --git a/samples/net/mqtt_publisher/overlay-nrf700x.conf b/samples/net/mqtt_publisher/overlay-nrf700x.conf new file mode 100644 index 00000000000..a812c7896f6 --- /dev/null +++ b/samples/net/mqtt_publisher/overlay-nrf700x.conf @@ -0,0 +1,19 @@ +# Wi-Fi +CONFIG_WIFI=y +CONFIG_WIFI_NRF700X=y +CONFIG_WPA_SUPP=y +CONFIG_NET_L2_ETHERNET=y + +# DHCPv4 +CONFIG_NET_CONFIG_MY_IPV4_ADDR="" +CONFIG_NET_CONFIG_NEED_IPV4=y +CONFIG_NET_DHCPV4=y + +# Connection manager +CONFIG_NET_CONNECTION_MANAGER=y + +# Credentials +CONFIG_WIFI_CREDENTIALS=y +CONFIG_WIFI_CREDENTIALS_STATIC=y +CONFIG_WIFI_CREDENTIALS_STATIC_SSID="" +CONFIG_WIFI_CREDENTIALS_STATIC_PASSWORD="" diff --git a/samples/net/mqtt_sn_publisher/overlay-nrf700x.conf b/samples/net/mqtt_sn_publisher/overlay-nrf700x.conf new file mode 100644 index 00000000000..cbc47b96572 --- /dev/null +++ b/samples/net/mqtt_sn_publisher/overlay-nrf700x.conf @@ -0,0 +1,20 @@ +CONFIG_POSIX_MAX_FDS=16 + +# Wi-Fi +CONFIG_WIFI=y +CONFIG_WIFI_NRF700X=y +CONFIG_WPA_SUPP=y +CONFIG_NET_L2_ETHERNET=y + +# DHCPv4 +CONFIG_NET_CONFIG_MY_IPV4_ADDR="" +CONFIG_NET_DHCPV4=y + +# Connection manager +CONFIG_NET_CONNECTION_MANAGER=y + +# Credentials +CONFIG_WIFI_CREDENTIALS=y +CONFIG_WIFI_CREDENTIALS_STATIC=y +CONFIG_WIFI_CREDENTIALS_STATIC_SSID="" +CONFIG_WIFI_CREDENTIALS_STATIC_PASSWORD="" diff --git a/samples/net/sockets/coap_client/overlay-nrf700x.conf b/samples/net/sockets/coap_client/overlay-nrf700x.conf new file mode 100644 index 00000000000..a0e436e3537 --- /dev/null +++ b/samples/net/sockets/coap_client/overlay-nrf700x.conf @@ -0,0 +1,16 @@ +CONFIG_HEAP_MEM_POOL_SIZE=153000 + +# Wi-Fi +CONFIG_WIFI=y +CONFIG_WIFI_NRF700X=y +CONFIG_WPA_SUPP=y +CONFIG_NET_L2_ETHERNET=y + +# Connection manager +CONFIG_NET_CONNECTION_MANAGER=y + +# Credentials +CONFIG_WIFI_CREDENTIALS=y +CONFIG_WIFI_CREDENTIALS_STATIC=y +CONFIG_WIFI_CREDENTIALS_STATIC_SSID="" +CONFIG_WIFI_CREDENTIALS_STATIC_PASSWORD="" diff --git a/samples/net/sockets/coap_server/overlay-nrf700x.conf b/samples/net/sockets/coap_server/overlay-nrf700x.conf new file mode 100644 index 00000000000..4817a4f73ba --- /dev/null +++ b/samples/net/sockets/coap_server/overlay-nrf700x.conf @@ -0,0 +1,26 @@ +CONFIG_HEAP_MEM_POOL_SIZE=153000 + +# Wi-Fi +CONFIG_WIFI=y +CONFIG_WIFI_NRF700X=y +CONFIG_WPA_SUPP=y +CONFIG_NET_L2_ETHERNET=y + +# DHCPv4 +CONFIG_NET_CONFIG_MY_IPV4_ADDR="" +CONFIG_NET_DHCPV4=y + +# The sample can run either IPv4 or IPv6, not both +CONFIG_NET_IPV6=n +CONFIG_NET_CONFIG_NEED_IPV6=n +CONFIG_NET_IPV4=y +CONFIG_NET_CONFIG_NEED_IPV4=y + +# Connection manager +CONFIG_NET_CONNECTION_MANAGER=y + +# Credentials +CONFIG_WIFI_CREDENTIALS=y +CONFIG_WIFI_CREDENTIALS_STATIC=y +CONFIG_WIFI_CREDENTIALS_STATIC_SSID="" +CONFIG_WIFI_CREDENTIALS_STATIC_PASSWORD="" diff --git a/samples/net/sockets/echo/overlay-nrf700x.conf b/samples/net/sockets/echo/overlay-nrf700x.conf new file mode 100644 index 00000000000..aa59e5d5ea2 --- /dev/null +++ b/samples/net/sockets/echo/overlay-nrf700x.conf @@ -0,0 +1,18 @@ +# Wi-Fi +CONFIG_WIFI=y +CONFIG_WIFI_NRF700X=y +CONFIG_WPA_SUPP=y +CONFIG_NET_L2_ETHERNET=y + +# DHCPv4 +CONFIG_NET_CONFIG_MY_IPV4_ADDR="" +CONFIG_NET_DHCPV4=y + +# Connection manager +CONFIG_NET_CONNECTION_MANAGER=y + +# Credentials +CONFIG_WIFI_CREDENTIALS=y +CONFIG_WIFI_CREDENTIALS_STATIC=y +CONFIG_WIFI_CREDENTIALS_STATIC_SSID="" +CONFIG_WIFI_CREDENTIALS_STATIC_PASSWORD="" diff --git a/samples/net/sockets/echo_async/overlay-nrf700x.conf b/samples/net/sockets/echo_async/overlay-nrf700x.conf new file mode 100644 index 00000000000..aa59e5d5ea2 --- /dev/null +++ b/samples/net/sockets/echo_async/overlay-nrf700x.conf @@ -0,0 +1,18 @@ +# Wi-Fi +CONFIG_WIFI=y +CONFIG_WIFI_NRF700X=y +CONFIG_WPA_SUPP=y +CONFIG_NET_L2_ETHERNET=y + +# DHCPv4 +CONFIG_NET_CONFIG_MY_IPV4_ADDR="" +CONFIG_NET_DHCPV4=y + +# Connection manager +CONFIG_NET_CONNECTION_MANAGER=y + +# Credentials +CONFIG_WIFI_CREDENTIALS=y +CONFIG_WIFI_CREDENTIALS_STATIC=y +CONFIG_WIFI_CREDENTIALS_STATIC_SSID="" +CONFIG_WIFI_CREDENTIALS_STATIC_PASSWORD="" diff --git a/samples/net/sockets/echo_client/overlay-nrf700x.conf b/samples/net/sockets/echo_client/overlay-nrf700x.conf new file mode 100644 index 00000000000..cbc47b96572 --- /dev/null +++ b/samples/net/sockets/echo_client/overlay-nrf700x.conf @@ -0,0 +1,20 @@ +CONFIG_POSIX_MAX_FDS=16 + +# Wi-Fi +CONFIG_WIFI=y +CONFIG_WIFI_NRF700X=y +CONFIG_WPA_SUPP=y +CONFIG_NET_L2_ETHERNET=y + +# DHCPv4 +CONFIG_NET_CONFIG_MY_IPV4_ADDR="" +CONFIG_NET_DHCPV4=y + +# Connection manager +CONFIG_NET_CONNECTION_MANAGER=y + +# Credentials +CONFIG_WIFI_CREDENTIALS=y +CONFIG_WIFI_CREDENTIALS_STATIC=y +CONFIG_WIFI_CREDENTIALS_STATIC_SSID="" +CONFIG_WIFI_CREDENTIALS_STATIC_PASSWORD="" diff --git a/samples/net/sockets/echo_server/overlay-nrf700x.conf b/samples/net/sockets/echo_server/overlay-nrf700x.conf new file mode 100644 index 00000000000..cbc47b96572 --- /dev/null +++ b/samples/net/sockets/echo_server/overlay-nrf700x.conf @@ -0,0 +1,20 @@ +CONFIG_POSIX_MAX_FDS=16 + +# Wi-Fi +CONFIG_WIFI=y +CONFIG_WIFI_NRF700X=y +CONFIG_WPA_SUPP=y +CONFIG_NET_L2_ETHERNET=y + +# DHCPv4 +CONFIG_NET_CONFIG_MY_IPV4_ADDR="" +CONFIG_NET_DHCPV4=y + +# Connection manager +CONFIG_NET_CONNECTION_MANAGER=y + +# Credentials +CONFIG_WIFI_CREDENTIALS=y +CONFIG_WIFI_CREDENTIALS_STATIC=y +CONFIG_WIFI_CREDENTIALS_STATIC_SSID="" +CONFIG_WIFI_CREDENTIALS_STATIC_PASSWORD="" diff --git a/samples/net/sockets/http_get/overlay-nrf700x.conf b/samples/net/sockets/http_get/overlay-nrf700x.conf new file mode 100644 index 00000000000..aa59e5d5ea2 --- /dev/null +++ b/samples/net/sockets/http_get/overlay-nrf700x.conf @@ -0,0 +1,18 @@ +# Wi-Fi +CONFIG_WIFI=y +CONFIG_WIFI_NRF700X=y +CONFIG_WPA_SUPP=y +CONFIG_NET_L2_ETHERNET=y + +# DHCPv4 +CONFIG_NET_CONFIG_MY_IPV4_ADDR="" +CONFIG_NET_DHCPV4=y + +# Connection manager +CONFIG_NET_CONNECTION_MANAGER=y + +# Credentials +CONFIG_WIFI_CREDENTIALS=y +CONFIG_WIFI_CREDENTIALS_STATIC=y +CONFIG_WIFI_CREDENTIALS_STATIC_SSID="" +CONFIG_WIFI_CREDENTIALS_STATIC_PASSWORD="" diff --git a/samples/net/sockets/sntp_client/overlay-nrf700x.conf b/samples/net/sockets/sntp_client/overlay-nrf700x.conf new file mode 100644 index 00000000000..aa59e5d5ea2 --- /dev/null +++ b/samples/net/sockets/sntp_client/overlay-nrf700x.conf @@ -0,0 +1,18 @@ +# Wi-Fi +CONFIG_WIFI=y +CONFIG_WIFI_NRF700X=y +CONFIG_WPA_SUPP=y +CONFIG_NET_L2_ETHERNET=y + +# DHCPv4 +CONFIG_NET_CONFIG_MY_IPV4_ADDR="" +CONFIG_NET_DHCPV4=y + +# Connection manager +CONFIG_NET_CONNECTION_MANAGER=y + +# Credentials +CONFIG_WIFI_CREDENTIALS=y +CONFIG_WIFI_CREDENTIALS_STATIC=y +CONFIG_WIFI_CREDENTIALS_STATIC_SSID="" +CONFIG_WIFI_CREDENTIALS_STATIC_PASSWORD="" diff --git a/samples/net/syslog_net/overlay-nrf700x.conf b/samples/net/syslog_net/overlay-nrf700x.conf new file mode 100644 index 00000000000..aa59e5d5ea2 --- /dev/null +++ b/samples/net/syslog_net/overlay-nrf700x.conf @@ -0,0 +1,18 @@ +# Wi-Fi +CONFIG_WIFI=y +CONFIG_WIFI_NRF700X=y +CONFIG_WPA_SUPP=y +CONFIG_NET_L2_ETHERNET=y + +# DHCPv4 +CONFIG_NET_CONFIG_MY_IPV4_ADDR="" +CONFIG_NET_DHCPV4=y + +# Connection manager +CONFIG_NET_CONNECTION_MANAGER=y + +# Credentials +CONFIG_WIFI_CREDENTIALS=y +CONFIG_WIFI_CREDENTIALS_STATIC=y +CONFIG_WIFI_CREDENTIALS_STATIC_SSID="" +CONFIG_WIFI_CREDENTIALS_STATIC_PASSWORD="" diff --git a/samples/net/telnet/overlay-nrf700x.conf b/samples/net/telnet/overlay-nrf700x.conf new file mode 100644 index 00000000000..aa59e5d5ea2 --- /dev/null +++ b/samples/net/telnet/overlay-nrf700x.conf @@ -0,0 +1,18 @@ +# Wi-Fi +CONFIG_WIFI=y +CONFIG_WIFI_NRF700X=y +CONFIG_WPA_SUPP=y +CONFIG_NET_L2_ETHERNET=y + +# DHCPv4 +CONFIG_NET_CONFIG_MY_IPV4_ADDR="" +CONFIG_NET_DHCPV4=y + +# Connection manager +CONFIG_NET_CONNECTION_MANAGER=y + +# Credentials +CONFIG_WIFI_CREDENTIALS=y +CONFIG_WIFI_CREDENTIALS_STATIC=y +CONFIG_WIFI_CREDENTIALS_STATIC_SSID="" +CONFIG_WIFI_CREDENTIALS_STATIC_PASSWORD="" From 132cee61e6ce404b25dbc626b57b5df149c136a8 Mon Sep 17 00:00:00 2001 From: Markus Swarowsky Date: Fri, 18 Aug 2023 10:20:45 +0200 Subject: [PATCH 033/421] [nrf noup] modules: mbedtls: Fix key support Kconfig PSA_HAS_KEY_SUPPORT was missing the DH_PUBLIC_KEY only Kconfig as the KEY_PAIR was double in there Signed-off-by: Markus Swarowsky (cherry picked from commit 53c4b20c15611a9d13b91e5dc025733d6dd65adb) --- modules/mbedtls/Kconfig.psa | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/mbedtls/Kconfig.psa b/modules/mbedtls/Kconfig.psa index b0d21685f70..0d43f112aeb 100644 --- a/modules/mbedtls/Kconfig.psa +++ b/modules/mbedtls/Kconfig.psa @@ -47,7 +47,7 @@ config PSA_HAS_KEY_SUPPORT PSA_WANT_KEY_TYPE_RSA_KEY_PAIR || \ PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY || \ PSA_WANT_KEY_TYPE_DH_KEY_PAIR || \ - PSA_WANT_KEY_TYPE_DH_KEY_PAIR + PSA_WANT_KEY_TYPE_DH_PUBLIC_KEY config PSA_WANT_KEY_TYPE_DERIVE bool "PSA derive key type support" From d44fdf9127f611edd051a893c85992d0ace9be7f Mon Sep 17 00:00:00 2001 From: Rubin Gerritsen Date: Fri, 11 Aug 2023 15:37:25 +0200 Subject: [PATCH 034/421] [nrf noup] ci: Only run lwm2m tests when needed There is no need to run those for all PRs. For example: When there are only changes to Bluetooth, we don't want this CI to run. Adding these filters may speedup the time to merge for PRs to sdk-nrf Signed-off-by: Rubin Gerritsen (cherry picked from commit 78106c74f4ac7936ef78dcddb8c6e1e578fe41dd) --- .github/test-spec.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/test-spec.yml b/.github/test-spec.yml index 5dd281919bc..53b811f9ae0 100644 --- a/.github/test-spec.yml +++ b/.github/test-spec.yml @@ -21,7 +21,7 @@ - "subsys/testsuite/ztest/**/*" "CI-lwm2m-test": - - "**/*" +# Not necessary to run tests on changes to this repo. "CI-boot-dfu-test": - "subsys/mgmt/mcumgr/**/*" From 00175bd6e6a27a9b52875cf417398f657889c535 Mon Sep 17 00:00:00 2001 From: Jorgen Kvalvaag Date: Thu, 24 Aug 2023 10:03:43 +0200 Subject: [PATCH 035/421] [nrf noup] ci: Update Thingy91 test-spec entry MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Thingy91 CI tests dependencies added. Signed-off-by: Jørgen Kvalvaag (cherry picked from commit 6a0df6f20645130ef3bf90b8c2ec605510d9b125) --- .github/test-spec.yml | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/.github/test-spec.yml b/.github/test-spec.yml index 53b811f9ae0..ce1d40b330e 100644 --- a/.github/test-spec.yml +++ b/.github/test-spec.yml @@ -52,7 +52,37 @@ - "include/dfu/**/*" "CI-thingy91-test": - - "**/*" + - "boards/arm/nrf9160dk_nrf9160/**/*" + - "arch/x86/core/**/*" + - "arch/x86/include/**/*" + - "drivers/console/**/*" + - "drivers/ethernet/**/*" + - "drivers/flash/**/*" + - "drivers/hwinfo/**/*" + - "drivers/interrupt_controller/**/*" + - "drivers/net/**/*" + - "drivers/serial/**/*" + - "drivers/timer/**/*" + - "include/**/*" + - "kernel/**/*" + - "lib/libc/common/source/stdlib/**/*" + - "lib/libc/newlib/**/*" + - "lib/libc/picolibc/**/*" + - "lib/os/**/*" + - "lib/posix/**/*" + - "misc/**/*" + - "modules/mbedtls/**/*" + - "soc/x86/ia32/**/*" + - "subsys/fs/fcb/**/*" + - "subsys/logging/**/*" + - "subsys/net/**/*" + - "subsys/random/**/*" + - "subsys/settings/include/**/*" + - "subsys/settings/src/**/*" + - "subsys/stats/**/*" + - "subsys/storage/flash_map/**/*" + - "subsys/storage/stream/**/*" + - "subsys/tracing/**/*" "CI-desktop-test": - "**/*" From fe45e34a7acb0709bbe9d0acf15d35405fdb03e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Magne=20V=C3=A6rnes?= Date: Wed, 23 Aug 2023 16:10:42 +0200 Subject: [PATCH 036/421] [nrf noup] ci: Only run crypto and tf-m tests when needed MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Extended the github CI filter for crypto and TF-M tests to reduce the CI load and possibly speed up PRs. Signed-off-by: Magne Værnes (cherry picked from commit c0d21ea8df1bce0d1bc2774a8e7348f3fc90271f) --- .github/test-spec.yml | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/.github/test-spec.yml b/.github/test-spec.yml index ce1d40b330e..102642d4216 100644 --- a/.github/test-spec.yml +++ b/.github/test-spec.yml @@ -31,7 +31,13 @@ - "samples/subsys/mgmt/mcumgr/smp_svr/**/*" "CI-tfm-test": - - "**/*" + - "boards/arm/nrf5340dk_nrf5340/**/*" + - "boards/arm/nrf9160dk_nrf9160/**/*" + - "drivers/entropy/*" + - "dts/arm/nordic/nrf5340*" + - "dts/arm/nordic/nrf9160*" + - "modules/trusted-firmware-m/**/*" + - "samples/tfm_integration/**/*" "CI-ble-test": - "**/*" @@ -88,7 +94,16 @@ - "**/*" "CI-crypto-test": - - "**/*" + - "boards/arm/nrf52840dk_nrf52840/**/*" + - "boards/arm/nrf5340dk_nrf5340/**/*" + - "boards/arm/nrf9160dk_nrf9160/**/*" + - "drivers/entropy/*" + - "drivers/serial/**/*" + - "dts/arm/nordic/nrf52840*" + - "dts/arm/nordic/nrf5340*" + - "dts/arm/nordic/nrf9160*" + - "include/drivers/serial/**/*" + - "modules/mbedtls/**/*" "CI-fem-test": - "**/*" From 090fedd22fbc95498a3540ed63832934d0e66da6 Mon Sep 17 00:00:00 2001 From: Tomasz Tyzenhauz Date: Fri, 25 Aug 2023 13:27:53 +0200 Subject: [PATCH 037/421] [nrf noup] ci: Add Sidewalk to test-spec Add Sidewalk to be trigger on changes in this repo. Correct entry path for hci_rpmsg samples for Matter and Homekit. Signed-off-by: Tomasz Tyzenhauz (cherry picked from commit cd4e36f63fd444d1e850894ca743ee8e9654fc1a) --- .github/test-spec.yml | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/.github/test-spec.yml b/.github/test-spec.yml index 102642d4216..7c4d93cd038 100644 --- a/.github/test-spec.yml +++ b/.github/test-spec.yml @@ -119,7 +119,7 @@ - "subsys/settings/**/*" - "subsys/net/lib/openthread/**/*" - "subsys/mgmt/mcumgr/**/*" - - "samples/hci_rpmsg/**/*" + - "samples/bluetooth/hci_rpmsg/**/*" - "samples/subsys/mgmt/mcumgr/smp_svr/**/*" - any: - "subsys/bluetooth/**/*" @@ -140,7 +140,7 @@ - "subsys/net/**/*" - "subsys/mgmt/mcumgr/**/*" - "drivers/net/**/*" - - "samples/hci_rpmsg/**/*" + - "samples/bluetooth/hci_rpmsg/**/*" - any: - "subsys/bluetooth/**/*" - "!subsys/bluetooth/mesh/**/*" @@ -193,3 +193,16 @@ "CI-wifi": - "subsys/net/l2/wifi/**/*" - "subsys/net/l2/ethernet/**/*" + +"CI-sidewalk-test": + - "include/dfu/**/*" + - "include/mgmt/mcumgr/**/*" + - "soc/arm/nordic_nrf/**/*" + - "subsys/dfu/**/*" + - "subsys/settings/**/*" + - "subsys/mgmt/mcumgr/**/*" + - "samples/bluetooth/hci_rpmsg/**/*" + - any: + - "subsys/bluetooth/**/*" + - "!subsys/bluetooth/mesh/**/*" + - "!subsys/bluetooth/audio/**/*" From d6bb133392a74f9e71a39f8d8cd0ff99501edd8a Mon Sep 17 00:00:00 2001 From: Lang Xie Date: Fri, 8 Sep 2023 13:13:41 +0200 Subject: [PATCH 038/421] [nrf noup] ci: Update ble and mesh test-spec entry Add BLE CI test dependency and update the include path of mesh. Signed-off-by: Lang Xie (cherry picked from commit 02956222c991e2c036810a5e39fd60e72aa75866) --- .github/test-spec.yml | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/.github/test-spec.yml b/.github/test-spec.yml index 7c4d93cd038..f81ac31cf75 100644 --- a/.github/test-spec.yml +++ b/.github/test-spec.yml @@ -40,11 +40,31 @@ - "samples/tfm_integration/**/*" "CI-ble-test": - - "**/*" + - any: + - "drivers/bluetooth/**/*" + - any: + - "dts/arm/nordic/nrf5*" + - any: + - "subsys/bluetooth/**/*" + - "!subsys/bluetooth/mesh/**/*" + - "!subsys/bluetooth/audio/**/*" + - any: + - "include/zephyr/bluetooth/**/*" + - "!include/zephyr/bluetooth/mesh/**/*" + - any: + - "samples/bluetooth/**/*" + - "!samples/bluetooth/mesh/**/*" + - "!samples/bluetooth/mesh_demo/**/*" + - "!samples/bluetooth/mesh_provisioner/**/*" + - any: + - "tests/bluetooth/**/*" + - "!tests/bluetooth/mesh/**/*" + - "!tests/bluetooth/mesh_shell/**/*" + - "!tests/bluetooth/audio/**/*" "CI-mesh-test": - "subsys/bluetooth/mesh/**/*" - - "include/bluetooth/mesh/**/*" + - "include/zephyr/bluetooth/mesh/**/*" - "samples/bluetooth/mesh/**/*" - "samples/bluetooth/mesh_demo/**/*" - "samples/bluetooth/mesh_provisioner/**/*" From 83d5224ee0287aa5a9fe75a3cf90263a5f6fa8f0 Mon Sep 17 00:00:00 2001 From: Chaitanya Tata Date: Tue, 5 Sep 2023 22:13:03 +0530 Subject: [PATCH 039/421] [nrf fromlist] net: Add priority to ping This is handy in testing of setting priority directly rather than deriving from DSCP. Please note ICMP doesn't use net context. This is applicable for both shell and API. Upstream PR: https://github.com/zephyrproject-rtos/zephyr/pull/62313 Signed-off-by: Chaitanya Tata (cherry picked from commit fac11d30f21e445af7b40625c285e66614a22cfb) --- subsys/net/ip/icmpv4.c | 15 +++++++++++++-- subsys/net/ip/icmpv4.h | 3 +++ subsys/net/ip/icmpv6.c | 15 +++++++++++++-- subsys/net/ip/icmpv6.h | 3 +++ subsys/net/ip/net_shell.c | 15 ++++++++++++++- subsys/net/lib/zperf/zperf_shell.c | 2 +- 6 files changed, 47 insertions(+), 6 deletions(-) diff --git a/subsys/net/ip/icmpv4.c b/subsys/net/ip/icmpv4.c index 5c3d844be8a..058233a7f97 100644 --- a/subsys/net/ip/icmpv4.c +++ b/subsys/net/ip/icmpv4.c @@ -507,6 +507,7 @@ int net_icmpv4_send_echo_request(struct net_if *iface, uint16_t identifier, uint16_t sequence, uint8_t tos, + int priority, const void *data, size_t data_size) { @@ -537,8 +538,18 @@ int net_icmpv4_send_echo_request(struct net_if *iface, return -ENOMEM; } - net_pkt_set_ip_dscp(pkt, net_ipv4_get_dscp(tos)); - net_pkt_set_ip_ecn(pkt, net_ipv4_get_ecn(tos)); + if (priority > NET_MAX_PRIORITIES) { + NET_ERR("Priority %d is too large, maximum is %d", + priority, NET_MAX_PRIORITIES); + return -EINVAL; + } + + if (priority < 0) { + net_pkt_set_ip_dscp(pkt, net_ipv4_get_dscp(tos)); + net_pkt_set_ip_ecn(pkt, net_ipv4_get_ecn(tos)); + } else { + net_pkt_set_priority(pkt, priority); + } if (net_ipv4_create(pkt, src, dst) || icmpv4_create(pkt, NET_ICMPV4_ECHO_REQUEST, 0)) { diff --git a/subsys/net/ip/icmpv4.h b/subsys/net/ip/icmpv4.h index bfce2e8d9e6..492fc6e84a0 100644 --- a/subsys/net/ip/icmpv4.h +++ b/subsys/net/ip/icmpv4.h @@ -82,6 +82,7 @@ int net_icmpv4_send_echo_request(struct net_if *iface, uint16_t identifier, uint16_t sequence, uint8_t tos, + int priority, const void *data, size_t data_size); #else @@ -90,6 +91,7 @@ static inline int net_icmpv4_send_echo_request(struct net_if *iface, uint16_t identifier, uint16_t sequence, uint8_t tos, + int priority, const void *data, size_t data_size) { @@ -98,6 +100,7 @@ static inline int net_icmpv4_send_echo_request(struct net_if *iface, ARG_UNUSED(identifier); ARG_UNUSED(sequence); ARG_UNUSED(tos); + ARG_UNUSED(priority); ARG_UNUSED(data); ARG_UNUSED(data_size); diff --git a/subsys/net/ip/icmpv6.c b/subsys/net/ip/icmpv6.c index 95252a7c156..f1286229536 100644 --- a/subsys/net/ip/icmpv6.c +++ b/subsys/net/ip/icmpv6.c @@ -341,6 +341,7 @@ int net_icmpv6_send_echo_request(struct net_if *iface, uint16_t identifier, uint16_t sequence, uint8_t tc, + int priority, const void *data, size_t data_size) { @@ -362,8 +363,18 @@ int net_icmpv6_send_echo_request(struct net_if *iface, return -ENOMEM; } - net_pkt_set_ip_dscp(pkt, net_ipv6_get_dscp(tc)); - net_pkt_set_ip_ecn(pkt, net_ipv6_get_ecn(tc)); + if (priority > NET_MAX_PRIORITIES) { + NET_ERR("Priority %d is too large, maximum is %d", + priority, NET_MAX_PRIORITIES); + return -EINVAL; + } + + if (priority < 0) { + net_pkt_set_ip_dscp(pkt, net_ipv6_get_dscp(tc)); + net_pkt_set_ip_ecn(pkt, net_ipv6_get_ecn(tc)); + } else { + net_pkt_set_priority(pkt, priority); + } if (net_ipv6_create(pkt, src, dst) || net_icmpv6_create(pkt, NET_ICMPV6_ECHO_REQUEST, 0)) { diff --git a/subsys/net/ip/icmpv6.h b/subsys/net/ip/icmpv6.h index f0c586a7cf8..d71d9959c14 100644 --- a/subsys/net/ip/icmpv6.h +++ b/subsys/net/ip/icmpv6.h @@ -222,6 +222,7 @@ int net_icmpv6_send_echo_request(struct net_if *iface, uint16_t identifier, uint16_t sequence, uint8_t tc, + int priority, const void *data, size_t data_size); #else @@ -230,6 +231,7 @@ static inline int net_icmpv6_send_echo_request(struct net_if *iface, uint16_t identifier, uint16_t sequence, uint8_t tc, + int priority, const void *data, size_t data_size) { @@ -238,6 +240,7 @@ static inline int net_icmpv6_send_echo_request(struct net_if *iface, ARG_UNUSED(identifier); ARG_UNUSED(sequence); ARG_UNUSED(tc); + ARG_UNUSED(priority); ARG_UNUSED(data); ARG_UNUSED(data_size); diff --git a/subsys/net/ip/net_shell.c b/subsys/net/ip/net_shell.c index 286d0eca8a9..c5b07afd6aa 100644 --- a/subsys/net/ip/net_shell.c +++ b/subsys/net/ip/net_shell.c @@ -4279,6 +4279,7 @@ static struct ping_context { uint32_t sequence; uint16_t payload_size; uint8_t tos; + int priority; } ping_ctx; static void ping_done(struct ping_context *ctx); @@ -4504,6 +4505,7 @@ static void ping_work(struct k_work *work) sys_rand32_get(), ctx->sequence, ctx->tos, + ctx->priority, NULL, ctx->payload_size); } else { @@ -4512,6 +4514,7 @@ static void ping_work(struct k_work *work) sys_rand32_get(), ctx->sequence, ctx->tos, + ctx->priority, NULL, ctx->payload_size); } @@ -4612,6 +4615,7 @@ static int cmd_net_ping(const struct shell *sh, size_t argc, char *argv[]) int iface_idx = -1; int tos = 0; int payload_size = 4; + int priority = -1; for (size_t i = 1; i < argc; ++i) { @@ -4647,6 +4651,14 @@ static int cmd_net_ping(const struct shell *sh, size_t argc, char *argv[]) } break; + case 'p': + priority = parse_arg(&i, argc, argv); + if (priority < 0 || priority > UINT8_MAX) { + PR_WARNING("Parse error: %s\n", argv[i]); + return -ENOEXEC; + } + break; + case 'Q': tos = parse_arg(&i, argc, argv); if (tos < 0 || tos > UINT8_MAX) { @@ -4683,6 +4695,7 @@ static int cmd_net_ping(const struct shell *sh, size_t argc, char *argv[]) ping_ctx.sh = sh; ping_ctx.count = count; ping_ctx.interval = interval; + ping_ctx.priority = priority; ping_ctx.tos = tos; ping_ctx.payload_size = payload_size; @@ -6584,7 +6597,7 @@ SHELL_STATIC_SUBCMD_SET_CREATE(net_cmd_vlan, SHELL_STATIC_SUBCMD_SET_CREATE(net_cmd_ping, SHELL_CMD(--help, NULL, "'net ping [-c count] [-i interval ms] [-I ] " - "[-Q tos] [-s payload size] ' " + "[-Q tos] [-s payload size] [-p priority] ' " "Send ICMPv4 or ICMPv6 Echo-Request to a network host.", cmd_net_ping), SHELL_SUBCMD_SET_END diff --git a/subsys/net/lib/zperf/zperf_shell.c b/subsys/net/lib/zperf/zperf_shell.c index a30caf08074..d3bf11a7b33 100644 --- a/subsys/net/lib/zperf/zperf_shell.c +++ b/subsys/net/lib/zperf/zperf_shell.c @@ -526,7 +526,7 @@ static int execute_upload(const struct shell *sh, * some time and start the test after that. */ net_icmpv6_send_echo_request(net_if_get_default(), - &ipv6->sin6_addr, 0, 0, 0, NULL, 0); + &ipv6->sin6_addr, 0, 0, 0, -1, NULL, 0); k_sleep(K_SECONDS(1)); } From 1675a8a5e9536587b9225953e08dcb286425d79d Mon Sep 17 00:00:00 2001 From: Chaitanya Tata Date: Fri, 8 Sep 2023 00:37:27 +0530 Subject: [PATCH 040/421] [nrf fromlist] net: Add configuration option to allow any priority This adds support to allow any priority from the user instead of limiting to the protocol values (0-7). This is useful in conveying custom priorities from application to the driver/chipset. Upstream PR: https://github.com/zephyrproject-rtos/zephyr/pull/62313 Signed-off-by: Chaitanya Tata (cherry picked from commit 1977a04ac80bfe471c534eab0214ea48d5d09b63) --- subsys/net/ip/Kconfig | 6 ++++++ subsys/net/ip/icmpv4.c | 3 ++- subsys/net/ip/icmpv6.c | 2 ++ 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/subsys/net/ip/Kconfig b/subsys/net/ip/Kconfig index d7edb988553..d2ca36b845c 100644 --- a/subsys/net/ip/Kconfig +++ b/subsys/net/ip/Kconfig @@ -290,6 +290,12 @@ config NET_RX_DEFAULT_PRIORITY What is the default network RX packet priority if user has not set one. The value 0 means lowest priority and 7 is the highest. +config NET_ALLOW_ANY_PRIORITY + bool "Allow any network packet priority to be used" + help + If this is set, then any user given network packet priority can be used. Otherwise + the network packet priorities are limited to 0-7 range. + config NET_IP_ADDR_CHECK bool "Check IP address validity before sending IP packet" default y diff --git a/subsys/net/ip/icmpv4.c b/subsys/net/ip/icmpv4.c index 058233a7f97..ed69903bd8e 100644 --- a/subsys/net/ip/icmpv4.c +++ b/subsys/net/ip/icmpv4.c @@ -538,12 +538,13 @@ int net_icmpv4_send_echo_request(struct net_if *iface, return -ENOMEM; } +#if !defined(CONFIG_NET_ALLOW_ANY_PRIORITY) if (priority > NET_MAX_PRIORITIES) { NET_ERR("Priority %d is too large, maximum is %d", priority, NET_MAX_PRIORITIES); return -EINVAL; } - +#endif /* !CONFIG_NET_ALLOW_ANY_PRIORITY */ if (priority < 0) { net_pkt_set_ip_dscp(pkt, net_ipv4_get_dscp(tos)); net_pkt_set_ip_ecn(pkt, net_ipv4_get_ecn(tos)); diff --git a/subsys/net/ip/icmpv6.c b/subsys/net/ip/icmpv6.c index f1286229536..9abc034e1fb 100644 --- a/subsys/net/ip/icmpv6.c +++ b/subsys/net/ip/icmpv6.c @@ -363,11 +363,13 @@ int net_icmpv6_send_echo_request(struct net_if *iface, return -ENOMEM; } +#if !defined(CONFIG_NET_ALLOW_ANY_PRIORITY) if (priority > NET_MAX_PRIORITIES) { NET_ERR("Priority %d is too large, maximum is %d", priority, NET_MAX_PRIORITIES); return -EINVAL; } +#endif /* !CONFIG_NET_ALLOW_ANY_PRIORITY */ if (priority < 0) { net_pkt_set_ip_dscp(pkt, net_ipv6_get_dscp(tc)); From 427badb22bfd80c63a691163b2d355bb1e3028a5 Mon Sep 17 00:00:00 2001 From: Chaitanya Tata Date: Fri, 8 Sep 2023 00:57:26 +0530 Subject: [PATCH 041/421] [nrf fromlist] zperf: Add support to configure context priority This is handy in setting a custom priority for the context either through shell or API. Upstream PR: https://github.com/zephyrproject-rtos/zephyr/pull/62313 Signed-off-by: Chaitanya Tata (cherry picked from commit f48f184514f8fb2adbc92d03e6a3a44c5b56d1e0) --- include/zephyr/net/zperf.h | 1 + subsys/net/lib/zperf/zperf_common.c | 20 +++++++++++- subsys/net/lib/zperf/zperf_internal.h | 2 +- subsys/net/lib/zperf/zperf_shell.c | 39 +++++++++++++++++++++++ subsys/net/lib/zperf/zperf_tcp_uploader.c | 2 +- subsys/net/lib/zperf/zperf_udp_uploader.c | 2 +- 6 files changed, 62 insertions(+), 4 deletions(-) diff --git a/include/zephyr/net/zperf.h b/include/zephyr/net/zperf.h index 447ffec670c..cd86541721e 100644 --- a/include/zephyr/net/zperf.h +++ b/include/zephyr/net/zperf.h @@ -37,6 +37,7 @@ struct zperf_upload_params { struct { uint8_t tos; int tcp_nodelay; + int priority; } options; }; diff --git a/subsys/net/lib/zperf/zperf_common.c b/subsys/net/lib/zperf/zperf_common.c index aa29bc99043..efe36cf69cd 100644 --- a/subsys/net/lib/zperf/zperf_common.c +++ b/subsys/net/lib/zperf/zperf_common.c @@ -131,7 +131,7 @@ const struct in6_addr *zperf_get_default_if_in6_addr(void) } int zperf_prepare_upload_sock(const struct sockaddr *peer_addr, int tos, - int proto) + int priority, int proto) { socklen_t addrlen = peer_addr->sa_family == AF_INET6 ? sizeof(struct sockaddr_in6) : @@ -192,6 +192,24 @@ int zperf_prepare_upload_sock(const struct sockaddr *peer_addr, int tos, return -EINVAL; } + if (IS_ENABLED(CONFIG_NET_CONTEXT_PRIORITY) && priority >= 0) { + uint8_t prio = priority; + + if (!IS_ENABLED(CONFIG_NET_ALLOW_ANY_PRIORITY) && + (prio > NET_MAX_PRIORITIES)) { + NET_ERR("Priority %d is too large, maximum is %d", + priority, NET_MAX_PRIORITIES); + return -EINVAL; + } + + if (zsock_setsockopt(sock, SOL_SOCKET, SO_PRIORITY, + &prio, + sizeof(prio)) != 0) { + NET_WARN("Failed to set SOL_SOCKET - SO_PRIORITY socket option."); + return -EINVAL; + } + } + ret = zsock_connect(sock, peer_addr, addrlen); if (ret < 0) { NET_ERR("Connect failed (%d)", errno); diff --git a/subsys/net/lib/zperf/zperf_internal.h b/subsys/net/lib/zperf/zperf_internal.h index 5bef0331f6f..96dd9ea9123 100644 --- a/subsys/net/lib/zperf/zperf_internal.h +++ b/subsys/net/lib/zperf/zperf_internal.h @@ -99,7 +99,7 @@ const struct in_addr *zperf_get_default_if_in4_addr(void); const struct in6_addr *zperf_get_default_if_in6_addr(void); int zperf_prepare_upload_sock(const struct sockaddr *peer_addr, int tos, - int proto); + int priority, int proto); uint32_t zperf_packet_duration(uint32_t packet_size, uint32_t rate_in_kbps); diff --git a/subsys/net/lib/zperf/zperf_shell.c b/subsys/net/lib/zperf/zperf_shell.c index d3bf11a7b33..3a8a9c61c4b 100644 --- a/subsys/net/lib/zperf/zperf_shell.c +++ b/subsys/net/lib/zperf/zperf_shell.c @@ -642,6 +642,7 @@ static int shell_cmd_upload(const struct shell *sh, size_t argc, int start = 0; size_t opt_cnt = 0; + param.options.priority = -1; is_udp = proto == IPPROTO_UDP; /* Parse options */ @@ -680,6 +681,19 @@ static int shell_cmd_upload(const struct shell *sh, size_t argc, opt_cnt += 1; break; +#ifdef CONFIG_NET_CONTEXT_PRIORITY + case 'p': + param.options.priority = parse_arg(&i, argc, argv); + if (param.options.priority < 0 || + param.options.priority > UINT8_MAX) { + shell_fprintf(sh, SHELL_WARNING, + "Parse error: %s\n", argv[i]); + return -ENOEXEC; + } + opt_cnt += 2; + break; +#endif /* CONFIG_NET_CONTEXT_PRIORITY */ + default: shell_fprintf(sh, SHELL_WARNING, "Unrecognized argument: %s\n", argv[i]); @@ -853,6 +867,19 @@ static int shell_cmd_upload2(const struct shell *sh, size_t argc, opt_cnt += 1; break; +#ifdef CONFIG_NET_CONTEXT_PRIORITY + case 'p': + param.options.priority = parse_arg(&i, argc, argv); + if (param.options.priority == -1 || + param.options.priority > UINT8_MAX) { + shell_fprintf(sh, SHELL_WARNING, + "Parse error: %s\n", argv[i]); + return -ENOEXEC; + } + opt_cnt += 2; + break; +#endif /* CONFIG_NET_CONTEXT_PRIORITY */ + default: shell_fprintf(sh, SHELL_WARNING, "Unrecognized argument: %s\n", argv[i]); @@ -1146,6 +1173,9 @@ SHELL_STATIC_SUBCMD_SET_CREATE(zperf_cmd_tcp, "-S tos: Specify IPv4/6 type of service\n" "-a: Asynchronous call (shell will not block for the upload)\n" "-n: Disable Nagle's algorithm\n" +#ifdef CONFIG_NET_CONTEXT_PRIORITY + "-p: Specify custom packet priority\n" +#endif /* CONFIG_NET_CONTEXT_PRIORITY */ "Example: tcp upload 192.0.2.2 1111 1 1K\n" "Example: tcp upload 2001:db8::2\n", cmd_tcp_upload), @@ -1159,6 +1189,9 @@ SHELL_STATIC_SUBCMD_SET_CREATE(zperf_cmd_tcp, "Available options:\n" "-S tos: Specify IPv4/6 type of service\n" "-a: Asynchronous call (shell will not block for the upload)\n" +#ifdef CONFIG_NET_CONTEXT_PRIORITY + "-p: Specify custom packet priority\n" +#endif /* CONFIG_NET_CONTEXT_PRIORITY */ "Example: tcp upload2 v6 1 1K\n" "Example: tcp upload2 v4\n" "-n: Disable Nagle's algorithm\n" @@ -1198,6 +1231,9 @@ SHELL_STATIC_SUBCMD_SET_CREATE(zperf_cmd_udp, "Available options:\n" "-S tos: Specify IPv4/6 type of service\n" "-a: Asynchronous call (shell will not block for the upload)\n" +#ifdef CONFIG_NET_CONTEXT_PRIORITY + "-p: Specify custom packet priority\n" +#endif /* CONFIG_NET_CONTEXT_PRIORITY */ "Example: udp upload 192.0.2.2 1111 1 1K 1M\n" "Example: udp upload 2001:db8::2\n", cmd_udp_upload), @@ -1212,6 +1248,9 @@ SHELL_STATIC_SUBCMD_SET_CREATE(zperf_cmd_udp, "Available options:\n" "-S tos: Specify IPv4/6 type of service\n" "-a: Asynchronous call (shell will not block for the upload)\n" +#ifdef CONFIG_NET_CONTEXT_PRIORITY + "-p: Specify custom packet priority\n" +#endif /* CONFIG_NET_CONTEXT_PRIORITY */ "Example: udp upload2 v4 1 1K 1M\n" "Example: udp upload2 v6\n" #if defined(CONFIG_NET_IPV6) && defined(MY_IP6ADDR_SET) diff --git a/subsys/net/lib/zperf/zperf_tcp_uploader.c b/subsys/net/lib/zperf/zperf_tcp_uploader.c index 97fd4f57f71..3e72f81e54b 100644 --- a/subsys/net/lib/zperf/zperf_tcp_uploader.c +++ b/subsys/net/lib/zperf/zperf_tcp_uploader.c @@ -117,7 +117,7 @@ int zperf_tcp_upload(const struct zperf_upload_params *param, } sock = zperf_prepare_upload_sock(¶m->peer_addr, param->options.tos, - IPPROTO_TCP); + param->options.priority, IPPROTO_TCP); if (sock < 0) { return sock; } diff --git a/subsys/net/lib/zperf/zperf_udp_uploader.c b/subsys/net/lib/zperf/zperf_udp_uploader.c index 1310063437b..e7e2efb9a08 100644 --- a/subsys/net/lib/zperf/zperf_udp_uploader.c +++ b/subsys/net/lib/zperf/zperf_udp_uploader.c @@ -284,7 +284,7 @@ int zperf_udp_upload(const struct zperf_upload_params *param, } sock = zperf_prepare_upload_sock(¶m->peer_addr, param->options.tos, - IPPROTO_UDP); + param->options.priority, IPPROTO_UDP); if (sock < 0) { return sock; } From 6340daeb1824fa7f92d2e847d0eb68be53b21d51 Mon Sep 17 00:00:00 2001 From: Mariusz Poslinski Date: Tue, 5 Sep 2023 09:43:10 +0200 Subject: [PATCH 042/421] [nrf noup] ci: Update Thread test-spec entry Update Thread test-spec entry. Signed-off-by: Mariusz Poslinski (cherry picked from commit 81c640bcccce83f83573234ca1725e6d5576e9c2) --- .github/test-spec.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/test-spec.yml b/.github/test-spec.yml index f81ac31cf75..03e02441069 100644 --- a/.github/test-spec.yml +++ b/.github/test-spec.yml @@ -146,7 +146,11 @@ - "!subsys/bluetooth/mesh/**/*" "CI-thread-test": - - "**/*" + - "subsys/net/**/*" + - "modules/mbedtls/**/*" + - "include/zephyr/net/**/*" + - "modules/openthread/**/*" + - "samples/net/openthread/**/*" "CI-nfc-test": - "**/*" From 488716469816d193dd5b7ffb53d9eb57dfa36c5a Mon Sep 17 00:00:00 2001 From: Mariusz Poslinski Date: Mon, 18 Sep 2023 12:48:52 +0200 Subject: [PATCH 043/421] [nrf noup] ci: Update Thread test-spec entry Update Thread and HomeKit test-spec entries. Signed-off-by: Mariusz Poslinski (cherry picked from commit 4c741f1e2d2542ab23891fff46ed93add2893740) --- .github/test-spec.yml | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/.github/test-spec.yml b/.github/test-spec.yml index 03e02441069..62b92e74d0f 100644 --- a/.github/test-spec.yml +++ b/.github/test-spec.yml @@ -132,25 +132,24 @@ - "**/*" "CI-homekit-test": - - "include/dfu/**/*" - - "include/mgmt/mcumgr/**/*" + - "modules/openthread/**/*" + - "samples/bluetooth/hci_rpmsg/**/*" - "soc/arm/nordic_nrf/**/*" - - "subsys/dfu/**/*" + - "subsys/net/**/*" - "subsys/settings/**/*" - - "subsys/net/lib/openthread/**/*" - - "subsys/mgmt/mcumgr/**/*" - - "samples/bluetooth/hci_rpmsg/**/*" - - "samples/subsys/mgmt/mcumgr/smp_svr/**/*" - any: - "subsys/bluetooth/**/*" - "!subsys/bluetooth/mesh/**/*" + - "!subsys/bluetooth/audio/**/*" "CI-thread-test": - - "subsys/net/**/*" - - "modules/mbedtls/**/*" - "include/zephyr/net/**/*" + - "modules/mbedtls/**/*" - "modules/openthread/**/*" - "samples/net/openthread/**/*" + - "soc/arm/nordic_nrf/**/*" + - "subsys/net/**/*" + - "subsys/settings/**/*" "CI-nfc-test": - "**/*" From 41b1428e720e72bdbea7b811840038b41be5e12b Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Fri, 8 Sep 2023 14:57:48 +0100 Subject: [PATCH 044/421] [nrf fromtree] bluetooth: Make long workqueue init priority configurable Makes the long workqueue init priority configurable and sets the default to 50, this is to allow for relocating bluetooth libraries to other parts of memory e.g. external flash, and allows for those flash drivers to be initialised prior to calling functions residing in them. Signed-off-by: Jamie McCrae (cherry picked from commit da967225528ab7dee89b9696fd8020d80ef76a9a) (cherry picked from commit 347e737db454531065216034597db91bd4696c2a) --- subsys/bluetooth/host/Kconfig | 7 +++++++ subsys/bluetooth/host/long_wq.c | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/subsys/bluetooth/host/Kconfig b/subsys/bluetooth/host/Kconfig index 19754705200..a4cf2e0959b 100644 --- a/subsys/bluetooth/host/Kconfig +++ b/subsys/bluetooth/host/Kconfig @@ -23,6 +23,13 @@ config BT_LONG_WQ_PRIO int "Long workqueue priority. Should be pre-emptible." default 10 range 0 NUM_PREEMPT_PRIORITIES + +config BT_LONG_WQ_INIT_PRIO + int "Long workqueue init priority" + default 50 + help + Init priority level to setup the long workqueue. + endif # BT_LONG_WQ config BT_HCI_HOST diff --git a/subsys/bluetooth/host/long_wq.c b/subsys/bluetooth/host/long_wq.c index 61f86d0c909..2136739c243 100644 --- a/subsys/bluetooth/host/long_wq.c +++ b/subsys/bluetooth/host/long_wq.c @@ -40,4 +40,4 @@ static int long_wq_init(void) return 0; } -SYS_INIT(long_wq_init, POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT); +SYS_INIT(long_wq_init, POST_KERNEL, CONFIG_BT_LONG_WQ_INIT_PRIO); From f769ab6e3e3a96d83aa9ba22bf827840da97e5b9 Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Fri, 8 Sep 2023 14:53:45 +0100 Subject: [PATCH 045/421] [nrf fromtree] drivers: flash: nrf_qspi_nor: Add support for XIP at boot Adds support for forcing XIP support at boot time, and reduces the init priority of the driver so that it inits earlier. Signed-off-by: Jamie McCrae (cherry picked from commit 72167f2acfe12acf58040e63888159062e20145e) (cherry picked from commit 5cf24875cf668a6377bff18a26e195e1ef069299) --- drivers/flash/Kconfig.nordic_qspi_nor | 14 ++++++++++++-- drivers/flash/nrf_qspi_nor.c | 21 ++++++++++++++++++++- 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/drivers/flash/Kconfig.nordic_qspi_nor b/drivers/flash/Kconfig.nordic_qspi_nor index 16252e0812c..7b9fa05eb7f 100644 --- a/drivers/flash/Kconfig.nordic_qspi_nor +++ b/drivers/flash/Kconfig.nordic_qspi_nor @@ -14,8 +14,8 @@ menuconfig NORDIC_QSPI_NOR if NORDIC_QSPI_NOR config NORDIC_QSPI_NOR_INIT_PRIORITY - int - default 80 + int "Init priority" + default 41 help Device driver initialization priority. @@ -39,4 +39,14 @@ config NORDIC_QSPI_NOR_STACK_WRITE_BUFFER_SIZE if the data is larger than the configured size. Must be a multiple of 4. When set to 0, the feature is disabled. +config NORDIC_QSPI_NOR_XIP + bool "XIP (eXecute in place)" + depends on SOC_NRF5340_CPUAPP + help + Enable setting up the QSPI NOR driver to allow for execution of code + stored in QSPI XIP region. Note that for this functionality to work, + the QSPI NOR init priority must be set so that no XIP code in the + QSPI NOR flash chip is executed until the driver has been setup. + This will also disable power management for the QSPI NOR flash chip. + endif # NORDIC_QSPI_NOR diff --git a/drivers/flash/nrf_qspi_nor.c b/drivers/flash/nrf_qspi_nor.c index b2455ba3c6f..e2ce6e6a706 100644 --- a/drivers/flash/nrf_qspi_nor.c +++ b/drivers/flash/nrf_qspi_nor.c @@ -179,6 +179,8 @@ static bool qspi_initialized; static int qspi_device_init(const struct device *dev); static void qspi_device_uninit(const struct device *dev); +void z_impl_nrf_qspi_nor_xip_enable(const struct device *dev, bool enable); +void z_vrfy_nrf_qspi_nor_xip_enable(const struct device *dev, bool enable); #define WORD_SIZE 4 @@ -1229,6 +1231,7 @@ static int qspi_nor_configure(const struct device *dev) */ static int qspi_nor_init(const struct device *dev) { + int rc; const struct qspi_nor_config *dev_config = dev->config; int ret = pinctrl_apply_state(dev_config->pcfg, PINCTRL_STATE_DEFAULT); @@ -1238,7 +1241,19 @@ static int qspi_nor_init(const struct device *dev) IRQ_CONNECT(DT_IRQN(QSPI_NODE), DT_IRQ(QSPI_NODE, priority), nrfx_isr, nrfx_qspi_irq_handler, 0); - return qspi_nor_configure(dev); + + rc = qspi_nor_configure(dev); + +#ifdef CONFIG_NORDIC_QSPI_NOR_XIP + if (!rc) { + /* Enable XIP mode for QSPI NOR flash, this will prevent the + * flash from being powered down + */ + z_impl_nrf_qspi_nor_xip_enable(dev, true); + } +#endif + + return rc; } #if defined(CONFIG_FLASH_PAGE_LAYOUT) @@ -1369,6 +1384,10 @@ static int qspi_nor_pm_action(const struct device *dev, } #endif + if (dev_data->xip_enabled) { + return -EBUSY; + } + if (nrfx_qspi_mem_busy_check() != NRFX_SUCCESS) { return -EBUSY; } From ca0298cc20b632388a8cf75e166dde4a09987847 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Frank=20Audun=20Kvamtr=C3=B8?= Date: Mon, 31 Jan 2022 03:48:11 +0100 Subject: [PATCH 046/421] [nrf noup] modules: mbedtls: Disable configurations in Kconfig.tls-generic MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit -This commit prevents legacy mbed TLS configurations from being in conflict with PSA Configurations while using nrf_security -Removing use of unsupported TLS protocols (TLS 1.0, 1.1) -Required configurations are duplicated inside nrf_security Kconfig -Ensured that mbedtls_platform_zeroize is not duplicated when CONFIG_NRF_CC3XX_PLATFORM is set ref: NCSDK-13503 Signed-off-by: Frank Audun Kvamtrø Signed-off-by: Andrzej Głąbek (cherry picked from commit 84ee8c8015d1362b7888aeb7e0991e3f7092b35a) (cherry picked from commit ea5314da140b632aad85d39ea2dad02929ac83a5) Signed-off-by: Dominik Ermel (cherry picked from commit 8022c47f2ee2ca8c998bc44412ef2742535dcb74) [nrf noup] modules: mbedtls: Disable mbedtls_hardware_poll with CC3xx enabled Precompiled CC3xx libraries silently provide mbedtls_hardware_poll function (used internally by the library on initialization), which creates ambiguity with Zephyr-provided implementation. In result, the CC3xx entropy source is broken when CONFIG_MBEDTLS_ZEPHYR_ENTROPY is enabled. Workaround this, by disabling the Zephyr implementation if CC3xx is enabled, and let mbed TLS use the implementation from the CC library instead. Signed-off-by: Robert Lubos (cherry picked from commit e2ad826809bbcdeaa04f1edc2a57f21a0b2151ff) --- modules/mbedtls/Kconfig.tls-generic | 31 ++++++++++++++++++++ modules/mbedtls/configs/config-tls-generic.h | 4 +++ modules/mbedtls/zephyr_init.c | 2 +- 3 files changed, 36 insertions(+), 1 deletion(-) diff --git a/modules/mbedtls/Kconfig.tls-generic b/modules/mbedtls/Kconfig.tls-generic index 3c0e17c0fe3..d629c1b1d2a 100644 --- a/modules/mbedtls/Kconfig.tls-generic +++ b/modules/mbedtls/Kconfig.tls-generic @@ -9,6 +9,8 @@ menu "TLS configuration" menu "Supported TLS version" +if !(NRF_SECURITY || NORDIC_SECURITY_BACKEND) + config MBEDTLS_TLS_VERSION_1_0 bool "Support for TLS 1.0" select MBEDTLS_CIPHER @@ -33,6 +35,8 @@ config MBEDTLS_DTLS bool "Support for DTLS" depends on MBEDTLS_TLS_VERSION_1_1 || MBEDTLS_TLS_VERSION_1_2 +endif + config MBEDTLS_SSL_EXPORT_KEYS bool "Support for exporting SSL key block and master secret" depends on MBEDTLS_TLS_VERSION_1_0 || MBEDTLS_TLS_VERSION_1_1 || MBEDTLS_TLS_VERSION_1_2 @@ -47,6 +51,8 @@ menu "Ciphersuite configuration" comment "Supported key exchange modes" +if !(NRF_SECURITY || NORDIC_SECURITY_BACKEND) + config MBEDTLS_KEY_EXCHANGE_ALL_ENABLED bool "All available ciphersuite modes" select MBEDTLS_KEY_EXCHANGE_PSK_ENABLED @@ -81,6 +87,8 @@ config MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED || \ MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED +endif + config MBEDTLS_PSK_MAX_LEN int "Max size of TLS pre-shared keys" default 32 @@ -88,6 +96,8 @@ config MBEDTLS_PSK_MAX_LEN help Max size of TLS pre-shared keys, in bytes. +if !(NRF_SECURITY || NORDIC_SECURITY_BACKEND) + config MBEDTLS_KEY_EXCHANGE_RSA_ENABLED bool "RSA-only based ciphersuite modes" default y if !NET_L2_OPENTHREAD @@ -202,6 +212,7 @@ config MBEDTLS_ECP_NIST_OPTIM bool "NSIT curves optimization" endif +endif # !(NRF_SECURITY || NORDIC_SECURITY_BACKEND) comment "Supported hash" @@ -226,6 +237,8 @@ config MBEDTLS_HASH_SHA512_ENABLED comment "Supported cipher modes" +if !(NRF_SECURITY || NORDIC_SECURITY_BACKEND) + config MBEDTLS_CIPHER_ALL_ENABLED bool "All available ciphers" select MBEDTLS_CIPHER_AES_ENABLED @@ -299,8 +312,12 @@ config MBEDTLS_CHACHAPOLY_AEAD_ENABLED bool "ChaCha20-Poly1305 AEAD algorithm" depends on MBEDTLS_CIPHER_CHACHA20_ENABLED || MBEDTLS_MAC_POLY1305_ENABLED +endif + comment "Supported message authentication methods" +if !(NRF_SECURITY || NORDIC_SECURITY_BACKEND) + config MBEDTLS_MAC_ALL_ENABLED bool "All available MAC methods" select MBEDTLS_MAC_MD4_ENABLED @@ -349,10 +366,14 @@ config MBEDTLS_MAC_CMAC_ENABLED bool "CMAC (Cipher-based Message Authentication Code) mode for block ciphers." depends on MBEDTLS_CIPHER_AES_ENABLED || MBEDTLS_CIPHER_DES_ENABLED +endif + endmenu comment "Random number generators" +if !(NRF_SECURITY || NORDIC_SECURITY_BACKEND) + config MBEDTLS_CTR_DRBG_ENABLED bool "CTR_DRBG AES-256-based random generator" depends on MBEDTLS_CIPHER_AES_ENABLED @@ -362,14 +383,20 @@ config MBEDTLS_HMAC_DRBG_ENABLED bool "HMAC_DRBG random generator" select MBEDTLS_MD +endif + comment "Other configurations" config MBEDTLS_CIPHER bool "generic cipher layer." +if !(NRF_SECURITY || NORDIC_SECURITY_BACKEND) + config MBEDTLS_MD bool "generic message digest layer." +endif + config MBEDTLS_GENPRIME_ENABLED bool "prime-number generation code." @@ -387,11 +414,15 @@ config MBEDTLS_HAVE_ASM of asymmetric cryptography, however this might have an impact on the code size. +if !(NRF_SECURITY || NORDIC_SECURITY_BACKEND) + config MBEDTLS_ENTROPY_ENABLED bool "MbedTLS generic entropy pool" depends on MBEDTLS_MAC_SHA256_ENABLED || MBEDTLS_MAC_SHA384_ENABLED || MBEDTLS_MAC_SHA512_ENABLED default y if MBEDTLS_ZEPHYR_ENTROPY +endif + config MBEDTLS_OPENTHREAD_OPTIMIZATIONS_ENABLED bool "MbedTLS optimizations for OpenThread" depends on NET_L2_OPENTHREAD diff --git a/modules/mbedtls/configs/config-tls-generic.h b/modules/mbedtls/configs/config-tls-generic.h index 2268571abe0..7b437c23dcb 100644 --- a/modules/mbedtls/configs/config-tls-generic.h +++ b/modules/mbedtls/configs/config-tls-generic.h @@ -500,4 +500,8 @@ #include "mbedtls/check_config.h" #endif +#if defined(CONFIG_NRF_CC3XX_PLATFORM) +#define MBEDTLS_PLATFORM_ZEROIZE_ALT +#endif + #endif /* MBEDTLS_CONFIG_H */ diff --git a/modules/mbedtls/zephyr_init.c b/modules/mbedtls/zephyr_init.c index 70f7783e2ee..eec9d991c9b 100644 --- a/modules/mbedtls/zephyr_init.c +++ b/modules/mbedtls/zephyr_init.c @@ -45,7 +45,7 @@ static void init_heap(void) #define init_heap(...) #endif /* CONFIG_MBEDTLS_ENABLE_HEAP && MBEDTLS_MEMORY_BUFFER_ALLOC_C */ -#if defined(CONFIG_MBEDTLS_ZEPHYR_ENTROPY) +#if defined(CONFIG_MBEDTLS_ZEPHYR_ENTROPY) && !defined(CONFIG_NRF_CC3XX_PLATFORM) static const struct device *const entropy_dev = DEVICE_DT_GET_OR_NULL(DT_CHOSEN(zephyr_entropy)); From 063b584e78395eb02a1e7cbd82a0ed3251b383f3 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Thu, 23 Jun 2022 14:10:01 +0000 Subject: [PATCH 047/421] [nrf noup] mgmt/mcumgr: Bootutil hooks to handle image-1 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The commit adds bootutil hook, for nrf5340, to allow it handling the non-accessible image-1/primary slot. Signed-off-by: Andrzej Głąbek Signed-off-by: Vinayak Kariappa Chettimada Signed-off-by: Johann Fischer (cherry picked from commit 840b8fa1dba3ddda02fa1652a9408b08b7c310de) (cherry picked from commit 9af7d7ad2f70cee26ccc98b4daadd2260662ff78) (cherry picked from commit 298d8037d2b60b4ca4dd8b2a7727196e33054dd8) Signed-off-by: Dominik Ermel (cherry picked from commit d3aa849948ce548ba46ddb7f6ec0b4422fa53db4) --- subsys/mgmt/mcumgr/CMakeLists.txt | 8 ++++++ subsys/mgmt/mcumgr/Kconfig | 1 + .../mgmt/mcumgr/bootutil_hooks/nrf53_hooks.c | 27 +++++++++++++++++++ 3 files changed, 36 insertions(+) create mode 100644 subsys/mgmt/mcumgr/bootutil_hooks/nrf53_hooks.c diff --git a/subsys/mgmt/mcumgr/CMakeLists.txt b/subsys/mgmt/mcumgr/CMakeLists.txt index 39d4a4ca8ce..ad088eca067 100644 --- a/subsys/mgmt/mcumgr/CMakeLists.txt +++ b/subsys/mgmt/mcumgr/CMakeLists.txt @@ -16,3 +16,11 @@ add_subdirectory(transport) add_subdirectory_ifdef(CONFIG_SMP_CLIENT smp_client) zephyr_library_link_libraries(mgmt_mcumgr) + +if (CONFIG_BOOT_IMAGE_ACCESS_HOOKS) + zephyr_include_directories( + ${ZEPHYR_MCUBOOT_MODULE_DIR}/boot/bootutil/include + ${ZEPHYR_MCUBOOT_MODULE_DIR}/boot/zephyr/include + ) + zephyr_library_sources(bootutil_hooks/nrf53_hooks.c) +endif() diff --git a/subsys/mgmt/mcumgr/Kconfig b/subsys/mgmt/mcumgr/Kconfig index 8af4ffe2738..a25ee0dc625 100644 --- a/subsys/mgmt/mcumgr/Kconfig +++ b/subsys/mgmt/mcumgr/Kconfig @@ -7,6 +7,7 @@ menuconfig MCUMGR depends on NET_BUF depends on ZCBOR imply CRC + imply BOOT_IMAGE_ACCESS_HOOKS if (SOC_NRF5340_CPUAPP_QKAA && MCUMGR_GRP_IMG) help This option enables the mcumgr management library. diff --git a/subsys/mgmt/mcumgr/bootutil_hooks/nrf53_hooks.c b/subsys/mgmt/mcumgr/bootutil_hooks/nrf53_hooks.c new file mode 100644 index 00000000000..9971a4e0843 --- /dev/null +++ b/subsys/mgmt/mcumgr/bootutil_hooks/nrf53_hooks.c @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2022 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include "bootutil/bootutil_public.h" + +int boot_read_swap_state_primary_slot_hook(int image_index, + struct boot_swap_state *state) +{ + if (image_index == 1) { + /* Pretend that primary slot of image 1 unpopulated */ + state->magic = BOOT_MAGIC_UNSET; + state->swap_type = BOOT_SWAP_TYPE_NONE; + state->image_num = image_index; + state->copy_done = BOOT_FLAG_UNSET; + state->image_ok = BOOT_FLAG_UNSET; + + /* Prevent bootutil from trying to obtain true info */ + return 0; + } + + return BOOT_HOOK_REGULAR; +} From a87c9bbd70a2baf0823a4e03e783375e243a4e11 Mon Sep 17 00:00:00 2001 From: Ravi Dondaputi Date: Tue, 16 May 2023 02:19:42 +0530 Subject: [PATCH 048/421] [nrf noup] net: Increase connection manager stack size Connection manager L2 Wi-Fi calls internally invoke WPA supplicant calls which requires higher stack size. Update the default stack size for such cases. Marking this "nrf noup" since supplicant is not upstream yet. Signed-off-by: Ravi Dondaputi (cherry picked from commit 1d11b7423aff13dc3afcac00e78ce73b07707a09) (cherry picked from commit 9c36cddb8834d94411c84e49a2696657a2e7655e) Signed-off-by: Dominik Ermel (cherry picked from commit 34db04f962b7496fb9fc10685529ff751f9fed60) --- subsys/net/conn_mgr/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/subsys/net/conn_mgr/Kconfig b/subsys/net/conn_mgr/Kconfig index e72e614d54c..05686a663eb 100644 --- a/subsys/net/conn_mgr/Kconfig +++ b/subsys/net/conn_mgr/Kconfig @@ -24,6 +24,7 @@ source "subsys/net/Kconfig.template.log_config.net" config NET_CONNECTION_MANAGER_MONITOR_STACK_SIZE int "Size of the stack allocated for the conn_mgr_monitor thread" + default 8192 if WPA_SUPP default 512 help Sets the stack size which will be used by the connection manager for connectivity monitoring. From d1fa3da6c37763e1ae9306c43bfaf5cf965af594 Mon Sep 17 00:00:00 2001 From: Sigvart Hovland Date: Fri, 3 May 2019 14:21:52 +0200 Subject: [PATCH 049/421] [nrf noup] tree-wide: support NCS Partition Manager (PM) definitions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Partition Manager (PM) is a component of the nRF Connect SDK (NCS) which uses yaml files to resolve flash partition placement with a holistic view of the entire device, including each firmware image present on the flash device, and various subsystems, such as settings and NFFS. When this NCS extension is used, various source files which would use partition information from devicetree in "vanilla" zephyr instead use defines generated by PM instead. This commit removes support for HEX_FILES_TO_MERGE, as it conflicts with PM. The settings subsystem pm.yml defines a partition 'settings_storage'. The nffs subsystem pm.yml defines 'nffs_storage'. Leverage label translation to avoid patching partition names. Refer to the NCS documentation page for this feature for more details. This is a long-running out of tree patch which has been worked on by several people. The following sign-offs are in alphabetical order by first name. Signed-off-by: Andrzej Głąbek Signed-off-by: Andrzej Puzdrowski Signed-off-by: Håkon Øye Amundsen Signed-off-by: Ioannis Glaropoulos Signed-off-by: Joakim Andersson Signed-off-by: Johann Fischer Signed-off-by: Martí Bolívar Signed-off-by: Ole Sæther Signed-off-by: Robert Lubos Signed-off-by: Sebastian Bøe Signed-off-by: Sigvart Hovland Signed-off-by: Thomas Stenersen Signed-off-by: Torsten Rasmussen Signed-off-by: Øyvind Rønningstad Signed-off-by: Trond Einar Snekvik Signed-off-by: Gerard Marull-Paretas Signed-off-by: Tomasz Moń (cherry picked from commit ba54fe88dcfe3b25aca4c02f01e47f232b0f8bf7) (cherry picked from commit 68110ee5a75167e8e2c65746211571315618a3e1) (cherry picked from commit 12d1ebfb98a4f89dc018af4e7872382222b3b74a) Signed-off-by: Dominik Ermel (cherry picked from commit 5e8e748917649fc0a4a44a02c2c91c581007856d) --- cmake/modules/kernel.cmake | 4 ++ drivers/flash/soc_flash_nrf.c | 11 +++++ .../arm/aarch32/cortex_m/scripts/linker.ld | 46 +++++++++++++++++++ include/zephyr/storage/flash_map.h | 6 +++ lib/libc/common/source/stdlib/malloc.c | 18 +++++++- lib/os/Kconfig.heap | 2 +- soc/arm/common/cortex_m/arm_mpu_regions.c | 13 ++++++ subsys/fs/littlefs_fs.c | 7 ++- subsys/ipc/rpmsg_service/rpmsg_backend.h | 27 +++++++++++ 9 files changed, 130 insertions(+), 4 deletions(-) diff --git a/cmake/modules/kernel.cmake b/cmake/modules/kernel.cmake index 7e65c9cd186..28ee922d40b 100644 --- a/cmake/modules/kernel.cmake +++ b/cmake/modules/kernel.cmake @@ -242,3 +242,7 @@ if("${CMAKE_EXTRA_GENERATOR}" STREQUAL "Eclipse CDT4") include(${ZEPHYR_BASE}/cmake/ide/eclipse_cdt4_generator_amendment.cmake) eclipse_cdt4_generator_amendment(1) endif() + +if(ZEPHYR_NRF_MODULE_DIR) + include(${ZEPHYR_NRF_MODULE_DIR}/cmake/partition_manager.cmake) +endif() diff --git a/drivers/flash/soc_flash_nrf.c b/drivers/flash/soc_flash_nrf.c index fa433d1044b..f38492a41d1 100644 --- a/drivers/flash/soc_flash_nrf.c +++ b/drivers/flash/soc_flash_nrf.c @@ -37,6 +37,11 @@ LOG_MODULE_REGISTER(flash_nrf); #define SOC_NV_FLASH_NODE DT_INST(0, soc_nv_flash) +#if CONFIG_TRUSTED_EXECUTION_NONSECURE && USE_PARTITION_MANAGER +#include +#include +#endif /* CONFIG_TRUSTED_EXECUTION_NONSECURE && USE_PARTITION_MANAGER */ + #ifndef CONFIG_SOC_FLASH_NRF_RADIO_SYNC_NONE #define FLASH_SLOT_WRITE 7500 #if defined(CONFIG_SOC_FLASH_NRF_PARTIAL_ERASE) @@ -137,6 +142,12 @@ static int flash_nrf_read(const struct device *dev, off_t addr, return 0; } +#if CONFIG_TRUSTED_EXECUTION_NONSECURE && USE_PARTITION_MANAGER && PM_APP_ADDRESS + if (addr < PM_APP_ADDRESS) { + return soc_secure_mem_read(data, (void *)addr, len); + } +#endif + nrf_nvmc_buffer_read(data, (uint32_t)addr, len); return 0; diff --git a/include/zephyr/arch/arm/aarch32/cortex_m/scripts/linker.ld b/include/zephyr/arch/arm/aarch32/cortex_m/scripts/linker.ld index 92b6f02d029..85d55b2de29 100644 --- a/include/zephyr/arch/arm/aarch32/cortex_m/scripts/linker.ld +++ b/include/zephyr/arch/arm/aarch32/cortex_m/scripts/linker.ld @@ -26,6 +26,35 @@ #endif #define RAMABLE_REGION RAM +#if USE_PARTITION_MANAGER + +#include + +#if CONFIG_NCS_IS_VARIANT_IMAGE && defined(PM_S0_ID) +/* We are linking against S1, create symbol containing the flash ID of S0. + * This is used when writing code operating on the "other" slot. + */ +_image_1_primary_slot_id = PM_S0_ID; + +#else /* ! CONFIG_NCS_IS_VARIANT_IMAGE */ + +#ifdef PM_S1_ID +/* We are linking against S0, create symbol containing the flash ID of S1. + * This is used when writing code operating on the "other" slot. + */ +_image_1_primary_slot_id = PM_S1_ID; +#endif /* PM_S1_ID */ + +#endif /* CONFIG_NCS_IS_VARIANT_IMAGE */ + +#define ROM_ADDR PM_ADDRESS +#define ROM_SIZE PM_SIZE + +#define RAM_SIZE PM_SRAM_SIZE +#define RAM_ADDR PM_SRAM_ADDRESS + +#else /* ! USE_PARTITION_MANAGER */ + #if !defined(CONFIG_XIP) && (CONFIG_FLASH_SIZE == 0) #define ROM_ADDR RAM_ADDR #else @@ -52,6 +81,23 @@ #define RAM_ADDR CONFIG_SRAM_BASE_ADDRESS #endif +#endif /* USE_PARTITION_MANAGER */ + +#if DT_NODE_HAS_STATUS(DT_CHOSEN(zephyr_ccm), okay) +#define CCM_SIZE DT_REG_SIZE(DT_CHOSEN(zephyr_ccm)) +#define CCM_ADDR DT_REG_ADDR(DT_CHOSEN(zephyr_ccm)) +#endif + +#if DT_NODE_HAS_STATUS(DT_CHOSEN(zephyr_itcm), okay) +#define ITCM_SIZE DT_REG_SIZE(DT_CHOSEN(zephyr_itcm)) +#define ITCM_ADDR DT_REG_ADDR(DT_CHOSEN(zephyr_itcm)) +#endif + +#if DT_NODE_HAS_STATUS(DT_CHOSEN(zephyr_dtcm), okay) +#define DTCM_SIZE DT_REG_SIZE(DT_CHOSEN(zephyr_dtcm)) +#define DTCM_ADDR DT_REG_ADDR(DT_CHOSEN(zephyr_dtcm)) +#endif + #if defined(CONFIG_CUSTOM_SECTION_ALIGN) _region_min_align = CONFIG_CUSTOM_SECTION_MIN_ALIGN_SIZE; #else diff --git a/include/zephyr/storage/flash_map.h b/include/zephyr/storage/flash_map.h index 380e58691e9..cc4a246105d 100644 --- a/include/zephyr/storage/flash_map.h +++ b/include/zephyr/storage/flash_map.h @@ -271,6 +271,10 @@ const char *flash_area_label(const struct flash_area *fa); */ uint8_t flash_area_erased_val(const struct flash_area *fa); +#if USE_PARTITION_MANAGER +#include +#else + #define FLASH_AREA_LABEL_EXISTS(label) __DEPRECATED_MACRO \ DT_HAS_FIXED_PARTITION_LABEL(label) @@ -343,6 +347,8 @@ uint8_t flash_area_erased_val(const struct flash_area *fa); #define FIXED_PARTITION_DEVICE(label) \ DEVICE_DT_GET(DT_MTD_FROM_FIXED_PARTITION(DT_NODELABEL(label))) +#endif /* USE_PARTITION_MANAGER */ + #ifdef __cplusplus } #endif diff --git a/lib/libc/common/source/stdlib/malloc.c b/lib/libc/common/source/stdlib/malloc.c index 50c688fa7f2..47583982838 100644 --- a/lib/libc/common/source/stdlib/malloc.c +++ b/lib/libc/common/source/stdlib/malloc.c @@ -23,6 +23,20 @@ #include LOG_MODULE_DECLARE(os, CONFIG_KERNEL_LOG_LEVEL); +#if USE_PARTITION_MANAGER + +#include + +#define RAM_SIZE PM_SRAM_SIZE +#define RAM_ADDR PM_SRAM_ADDRESS + +#else /* ! USE_PARTITION_MANAGER */ + +#define RAM_SIZE (KB((size_t) CONFIG_SRAM_SIZE)) +#define RAM_ADDR CONFIG_SRAM_BASE_ADDRESS + +#endif /* USE_PARTITION_MANAGER */ + #ifdef CONFIG_COMMON_LIBC_MALLOC #if (CONFIG_COMMON_LIBC_MALLOC_ARENA_SIZE != 0) @@ -104,8 +118,8 @@ static POOL_SECTION unsigned char __aligned(HEAP_ALIGN) malloc_arena[HEAP_SIZE]; extern char _heap_sentry[]; # define HEAP_SIZE ROUND_DOWN((POINTER_TO_UINT(_heap_sentry) - HEAP_BASE), HEAP_ALIGN) # else -# define HEAP_SIZE ROUND_DOWN((KB((size_t) CONFIG_SRAM_SIZE) - \ - ((size_t) HEAP_BASE - (size_t) CONFIG_SRAM_BASE_ADDRESS)), HEAP_ALIGN) +# define HEAP_SIZE ROUND_DOWN((RAM_SIZE - \ + ((size_t) HEAP_BASE - (size_t) RAM_ADDR)), HEAP_ALIGN) # endif /* else CONFIG_XTENSA */ # endif /* else CONFIG_COMMON_LIBC_MALLOC_ARENA_SIZE > 0 */ diff --git a/lib/os/Kconfig.heap b/lib/os/Kconfig.heap index 14fba87470b..1fa84ff41db 100644 --- a/lib/os/Kconfig.heap +++ b/lib/os/Kconfig.heap @@ -51,7 +51,7 @@ config HEAP_LISTENER choice prompt "Supported heap sizes" depends on !64BIT - default SYS_HEAP_SMALL_ONLY if (SRAM_SIZE <= 256) + default SYS_HEAP_SMALL_ONLY if (SRAM_SIZE <= 256) && !PARTITION_MANAGER_ENABLED default SYS_HEAP_AUTO help Heaps using reduced-size chunk headers can accommodate so called diff --git a/soc/arm/common/cortex_m/arm_mpu_regions.c b/soc/arm/common/cortex_m/arm_mpu_regions.c index 557079ef5bc..a7df11a19e1 100644 --- a/soc/arm/common/cortex_m/arm_mpu_regions.c +++ b/soc/arm/common/cortex_m/arm_mpu_regions.c @@ -9,6 +9,9 @@ #include #include +#if USE_PARTITION_MANAGER +#include +#endif static const struct arm_mpu_region mpu_regions[] = { /* Region 0 */ @@ -22,6 +25,14 @@ static const struct arm_mpu_region mpu_regions[] = { #endif /* Region 1 */ MPU_REGION_ENTRY("SRAM_0", +#if USE_PARTITION_MANAGER + PM_SRAM_ADDRESS, +#if defined(CONFIG_ARMV8_M_BASELINE) || defined(CONFIG_ARMV8_M_MAINLINE) + REGION_RAM_ATTR(PM_SRAM_ADDRESS, PM_SRAM_SIZE)), +#else + REGION_RAM_ATTR(REGION_SRAM_SIZE)), +#endif +#else CONFIG_SRAM_BASE_ADDRESS, #if defined(CONFIG_ARMV8_M_BASELINE) || defined(CONFIG_ARMV8_M_MAINLINE) REGION_RAM_ATTR(CONFIG_SRAM_BASE_ADDRESS, \ @@ -30,6 +41,8 @@ static const struct arm_mpu_region mpu_regions[] = { REGION_RAM_ATTR(REGION_SRAM_SIZE)), #endif +#endif /* USE_PARTITION_MANAGER */ + /* DT-defined regions */ DT_MEMORY_ATTR_APPLY(ARM_MPU_REGION_INIT) }; diff --git a/subsys/fs/littlefs_fs.c b/subsys/fs/littlefs_fs.c index 3058f402d73..c4c75bb48c4 100644 --- a/subsys/fs/littlefs_fs.c +++ b/subsys/fs/littlefs_fs.c @@ -1054,7 +1054,12 @@ struct fs_mount_t FS_FSTAB_ENTRY(DT_DRV_INST(inst)) = { \ .type = FS_LITTLEFS, \ .mnt_point = DT_INST_PROP(inst, mount_point), \ .fs_data = &fs_data_##inst, \ - .storage_dev = (void *)DT_FIXED_PARTITION_ID(FS_PARTITION(inst)), \ + .storage_dev = (void *) \ + COND_CODE_1(USE_PARTITION_MANAGER, \ + (COND_CODE_1(FIXED_PARTITION_EXISTS(littlefs_storage), \ + (FIXED_PARTITION_ID(littlefs_storage)), \ + (FIXED_PARTITION_ID(storage)))), \ + (DT_FIXED_PARTITION_ID(FS_PARTITION(inst)))), \ .flags = FSTAB_ENTRY_DT_MOUNT_FLAGS(DT_DRV_INST(inst)), \ }; diff --git a/subsys/ipc/rpmsg_service/rpmsg_backend.h b/subsys/ipc/rpmsg_service/rpmsg_backend.h index a74e46b8520..9996e1d74d9 100644 --- a/subsys/ipc/rpmsg_service/rpmsg_backend.h +++ b/subsys/ipc/rpmsg_service/rpmsg_backend.h @@ -13,8 +13,35 @@ extern "C" { #endif +#if CONFIG_PARTITION_MANAGER_ENABLED + +#include "pm_config.h" + +#if defined(PM_RPMSG_NRF53_SRAM_ADDRESS) || defined(PM__RPMSG_NRF53_SRAM_ADDRESS) + +#if defined(PM_RPMSG_NRF53_SRAM_ADDRESS) +#define VDEV_START_ADDR PM_RPMSG_NRF53_SRAM_ADDRESS +#define VDEV_SIZE PM_RPMSG_NRF53_SRAM_SIZE +#else +/* The current image is a child image in a different domain than the image + * which defined the required values. To reach the values of the parent domain + * we use the 'PM__' variant of the define. + */ +#define VDEV_START_ADDR PM__RPMSG_NRF53_SRAM_ADDRESS +#define VDEV_SIZE PM__RPMSG_NRF53_SRAM_SIZE +#endif /* defined(PM_RPMSG_NRF53_SRAM_ADDRESS) */ + +#else #define VDEV_START_ADDR DT_REG_ADDR(DT_CHOSEN(zephyr_ipc_shm)) #define VDEV_SIZE DT_REG_SIZE(DT_CHOSEN(zephyr_ipc_shm)) +#endif /* defined(PM_RPMSG_NRF53_SRAM_ADDRESS) || defined(PM__RPMSG_NRF53_SRAM_ADDRESS) */ + +#else + +#define VDEV_START_ADDR DT_REG_ADDR(DT_CHOSEN(zephyr_ipc_shm)) +#define VDEV_SIZE DT_REG_SIZE(DT_CHOSEN(zephyr_ipc_shm)) + +#endif /* CONFIG_PARTITION_MANAGER_ENABLED */ #define VDEV_STATUS_ADDR VDEV_START_ADDR #define VDEV_STATUS_SIZE 0x400 From 3a641f9c4f14104c0f950b33b0b5d3731b431ec9 Mon Sep 17 00:00:00 2001 From: Robert Lubos Date: Mon, 1 Oct 2018 10:27:32 +0200 Subject: [PATCH 050/421] [nrf noup] include: net: add NCS extensions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add some socket options and address family extensions to Zephyr headers, which will be useful for nRF Connect SDK. Add secure socket options: * Add CID socket options to NCS specific options. * Add TLS/DTLS tls ciphersuite chosen socket option to NCS specific options. * Add TLS/DTLS connection save/load socket options to NCS specific options. * Add TLS/DTLS handshake status socket option to NCS specific options. The "author" of this commit is a contact person; various people with s-o-b lines following here have contributed to the maintenance of this patch. Signed-off-by: Andreas Moltumyr Signed-off-by: Andrzej Głąbek Signed-off-by: Christopher Métrailler Signed-off-by: Emanuele Di Santo Signed-off-by: Glenn Ruben Bakke Signed-off-by: Håkon Alseth Signed-off-by: Ioannis Glaropoulos Signed-off-by: Jan Tore Guggedal Signed-off-by: Joakim Andersson Signed-off-by: Martí Bolívar Signed-off-by: Mirko Covizzi Signed-off-by: Petri Honkala Signed-off-by: Robert Lubos Signed-off-by: Tommi Mammela Signed-off-by: Trond Einar Snekvik Signed-off-by: Torsten Rasmussen Signed-off-by: Eivind Jølsgard Signed-off-by: Emanuele Di Santo (cherry picked from commit 11a73e1d2d9ce98d8610281c9b00da688dc31802) (cherry picked from commit 1fbee9f184e0047bc98fe96629dcafe45de5ab09) (cherry picked from commit cf7645feef8bb6dac4b37a689146d0bab3741a4c) (cherry picked from commit 46c99f885eda4b186366e10014c54409208c6679) Signed-off-by: Dominik Ermel (cherry picked from commit 5ce6491cddb4a171e15243eccdcfc77ba8605fa6) --- include/zephyr/net/socket.h | 1 + include/zephyr/net/socket_ncs.h | 148 ++++++++++++++++++++++++++++++++ 2 files changed, 149 insertions(+) create mode 100644 include/zephyr/net/socket_ncs.h diff --git a/include/zephyr/net/socket.h b/include/zephyr/net/socket.h index ff7b2cc2281..50070f0c7a5 100644 --- a/include/zephyr/net/socket.h +++ b/include/zephyr/net/socket.h @@ -29,6 +29,7 @@ #include #include #include +#include #include #ifdef __cplusplus diff --git a/include/zephyr/net/socket_ncs.h b/include/zephyr/net/socket_ncs.h new file mode 100644 index 00000000000..a80e1ddc238 --- /dev/null +++ b/include/zephyr/net/socket_ncs.h @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2021 Nordic Semiconductor + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_NET_SOCKET_NCS_H_ +#define ZEPHYR_INCLUDE_NET_SOCKET_NCS_H_ + +/** + * @file + * @brief NCS specific additions to the BSD sockets API definitions + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* When CONFIG_NET_SOCKETS_OFFLOAD is enabled, offloaded sockets take precedence + * when creating a new socket. Combine this flag with a socket type when + * creating a socket, to enforce native socket creation (e. g. SOCK_STREAM | SOCK_NATIVE). + * If it's desired to create a native TLS socket, but still offload the + * underlying TCP/UDP socket, use e. g. SOCK_STREAM | SOCK_NATIVE_TLS. + */ +#define SOCK_NATIVE 0x80000000 +#define SOCK_NATIVE_TLS 0x40000000 + +/* NCS specific TLS level socket options */ + +/** Socket option to set DTLS handshake timeout, specifically for nRF sockets. + * The option accepts an integer, indicating the total handshake timeout, + * including retransmissions, in seconds. + * Accepted values for the option are: 1, 3, 7, 15, 31, 63, 123. + */ +#define TLS_DTLS_HANDSHAKE_TIMEO 18 + +/** Socket option to save DTLS connection, specifically for nRF sockets. + */ +#define TLS_DTLS_CONN_SAVE 19 + +/** Socket option to load DTLS connection, specifically for nRF sockets. + */ +#define TLS_DTLS_CONN_LOAD 20 + +/** Socket option to get result of latest TLS/DTLS completed handshakes end status, + * specifically for nRF sockets. + * The option accepts an integer, indicating the setting. + * Accepted vaules for the option are: 0 and 1. + */ +#define TLS_DTLS_HANDSHAKE_STATUS 21 + +/* Valid values for TLS_SESSION_CACHE option */ +#define TLS_SESSION_CACHE_DISABLED 0 /**< Disable TLS session caching. */ +#define TLS_SESSION_CACHE_ENABLED 1 /**< Enable TLS session caching. */ + +/* Valid values for TLS_DTLS_HANDSHAKE_TIMEO option */ +#define TLS_DTLS_HANDSHAKE_TIMEO_NONE 0 /**< No timeout */ +#define TLS_DTLS_HANDSHAKE_TIMEO_1S 1 /**< 1 second */ +#define TLS_DTLS_HANDSHAKE_TIMEO_3S 3 /**< 1s + 2s */ +#define TLS_DTLS_HANDSHAKE_TIMEO_7S 7 /**< 1s + 2s + 4s */ +#define TLS_DTLS_HANDSHAKE_TIMEO_15S 15 /**< 1s + 2s + 4s + 8s */ +#define TLS_DTLS_HANDSHAKE_TIMEO_31S 31 /**< 1s + 2s + 4s + 8s + 16s */ +#define TLS_DTLS_HANDSHAKE_TIMEO_63S 63 /**< 1s + 2s + 4s + 8s + 16s + 32s */ +#define TLS_DTLS_HANDSHAKE_TIMEO_123S 123 /**< 1s + 2s + 4s + 8s + 16s + 32s + 60s */ + +/* Valid values for TLS_DTLS_HANDSHAKE_STATUS option */ +#define TLS_DTLS_HANDSHAKE_STATUS_FULL 0 +#define TLS_DTLS_HANDSHAKE_STATUS_CACHED 1 + +/* NCS specific socket options */ + +/** sockopt: enable sending data as part of exceptional events */ +#define SO_EXCEPTIONAL_DATA 33 +/** sockopt: bind to PDN */ +#define SO_BINDTOPDN 40 +/** sockopt: Release Assistance Indication feature: This will indicate that the + * application will not send any more data. + */ +#define SO_RAI_NO_DATA 50 +/** sockopt: Release Assistance Indication feature: This will indicate that the + * next call to send/sendto will be the last one for some time. + */ +#define SO_RAI_LAST 51 +/** sockopt: Release Assistance Indication feature: This will indicate that + * after the next call to send/sendto, the application is expecting to receive + * one more data packet before this socket will not be used again for some time. + */ +#define SO_RAI_ONE_RESP 52 +/** sockopt: Release Assistance Indication feature: If a client application + * expects to use the socket more it can indicate that by setting this socket + * option before the next send call which will keep the network up longer. + */ +#define SO_RAI_ONGOING 53 +/** sockopt: Release Assistance Indication feature: If a server application + * expects to use the socket more it can indicate that by setting this socket + * option before the next send call. + */ +#define SO_RAI_WAIT_MORE 54 + +/* NCS specific IPPROTO_ALL level socket options */ + +/** IPv4 and IPv6 protocol level (pseudo-val) for nRF sockets. */ +#define IPPROTO_ALL 512 +/** sockopt: disable all replies to unexpected traffics */ +#define SO_SILENCE_ALL 30 + +/* NCS specific IPPROTO_IP level socket options */ + +/** sockopt: enable IPv4 ICMP replies */ +#define SO_IP_ECHO_REPLY 31 + +/* NCS specific IPPROTO_IPV6 level socket options */ + +/** sockopt: enable IPv6 ICMP replies */ +#define SO_IPV6_ECHO_REPLY 32 + +/* NCS specific TCP level socket options */ + +/** sockopt: Configurable TCP server session timeout in minutes. + * Range is 0 to 135. 0 is no timeout and 135 is 2 h 15 min. Default is 0 (no timeout). + */ +#define SO_TCP_SRV_SESSTIMEO 55 + +/* NCS specific gettaddrinfo() flags */ + +/** Assume `service` contains a Packet Data Network (PDN) ID. + * When specified together with the AI_NUMERICSERV flag, + * `service` shall be formatted as follows: "port:pdn_id" + * where "port" is the port number and "pdn_id" is the PDN ID. + * Example: "8080:1", port 8080 PDN ID 1. + * Example: "42:0", port 42 PDN ID 0. + */ +#define AI_PDNSERV 0x1000 + +/* NCS specific send() and sendto() flags */ + +/** Request a blocking send operation until the request is acknowledged. + * When used in send() or sendto(), the request will not return until the + * send operation is completed by lower layers, or until the timeout, given by the SO_SNDTIMEO + * socket option, is reached. Valid timeout values are 1 to 600 seconds. + */ +#define MSG_WAITACK 0x200 + +#ifdef __cplusplus +} +#endif + +#endif /* ZEPHYR_INCLUDE_NET_SOCKET_NCS_H_ */ From acd88713225a8bbd89b78b71cba176404cda74c0 Mon Sep 17 00:00:00 2001 From: Marek Pieta Date: Fri, 5 May 2023 11:12:26 +0200 Subject: [PATCH 051/421] [nrf noup] mcumgr: img_mgmt: Fix check for chosen code partition The "zephyr-code-partition" chosen DTS node cannot be used when build uses Partition Manager. In that case, mcumgr must rely on the definitions provided by the Partition Manager. Jira: NCSDK-21381 Signed-off-by: Marek Pieta (cherry picked from commit 394faafd215eaa2405f58f6aa7793afcc62b6e99) (cherry picked from commit 36961d6b72f53b9ff0eef1e398f08da84dae5032) (cherry picked from commit 76ad781c59d359eb4e100440c9ce558f188822ca) Signed-off-by: Dominik Ermel (cherry picked from commit 84b9a1446bea62afd5c2b7ab8b0515284d492fa1) --- subsys/mgmt/mcumgr/grp/img_mgmt/src/img_mgmt.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/subsys/mgmt/mcumgr/grp/img_mgmt/src/img_mgmt.c b/subsys/mgmt/mcumgr/grp/img_mgmt/src/img_mgmt.c index 0d733ce7abc..b2bb39aca86 100644 --- a/subsys/mgmt/mcumgr/grp/img_mgmt/src/img_mgmt.c +++ b/subsys/mgmt/mcumgr/grp/img_mgmt/src/img_mgmt.c @@ -33,6 +33,23 @@ #include #endif +#if USE_PARTITION_MANAGER +#include + +#ifdef PM_MCUBOOT_SECONDARY_PAD_SIZE +BUILD_ASSERT(PM_MCUBOOT_PAD_SIZE == PM_MCUBOOT_SECONDARY_PAD_SIZE); +#endif + +#if CONFIG_BUILD_WITH_TFM + #define PM_ADDRESS_OFFSET (PM_MCUBOOT_PAD_SIZE + PM_TFM_SIZE) +#else + #define PM_ADDRESS_OFFSET (PM_MCUBOOT_PAD_SIZE) +#endif + +#define FIXED_PARTITION_IS_RUNNING_APP_PARTITION(label) \ + (FIXED_PARTITION_OFFSET(label) == (PM_ADDRESS - PM_ADDRESS_OFFSET)) + +#else /* ! USE_PARTITION_MANAGER */ #ifndef CONFIG_FLASH_LOAD_OFFSET #error MCUmgr requires application to be built with CONFIG_FLASH_LOAD_OFFSET set \ to be able to figure out application running slot. @@ -40,6 +57,7 @@ #define FIXED_PARTITION_IS_RUNNING_APP_PARTITION(label) \ (FIXED_PARTITION_OFFSET(label) == CONFIG_FLASH_LOAD_OFFSET) +#endif /* USE_PARTITION_MANAGER */ #if FIXED_PARTITION_EXISTS(slot0_partition) #if FIXED_PARTITION_IS_RUNNING_APP_PARTITION(slot0_partition) From 1479b0fc10df3b7542bb56c8b760287eb58ed3f2 Mon Sep 17 00:00:00 2001 From: Gerard Marull-Paretas Date: Fri, 4 Aug 2023 13:01:24 +0200 Subject: [PATCH 052/421] [nrf noup] ci: doc-build: use ubuntu-22.04 runner We can't use Zephyr custom runners downstream. Signed-off-by: Gerard Marull-Paretas (cherry picked from commit 005068b638d29cc4bbc2d0e15b05255d81ca183d) Signed-off-by: Dominik Ermel (cherry picked from commit 5b374838ae82e4a26aef9c2f573567fb93025b36) --- .github/workflows/doc-build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/doc-build.yml b/.github/workflows/doc-build.yml index 40e170ddc8a..a18507e028d 100644 --- a/.github/workflows/doc-build.yml +++ b/.github/workflows/doc-build.yml @@ -35,7 +35,7 @@ env: jobs: doc-build-html: name: "Documentation Build (HTML)" - runs-on: zephyr-runner-linux-x64-4xlarge + runs-on: ubuntu-22.04 timeout-minutes: 45 concurrency: group: doc-build-html-${{ github.ref }} From be7e604c73b30a27bb9ff61353e2c833bb982f25 Mon Sep 17 00:00:00 2001 From: Torsten Rasmussen Date: Thu, 7 Sep 2023 12:47:44 +0200 Subject: [PATCH 053/421] [nrf fromlist] cmake: Zephyr kernel version.h and app_version.h creation Move the custom commands creating the version.h and app_version.h below the Zephyr modules sourcing. This allows custom user specific Zephyr modules to adjust the value of KERNEL_VERSION_CUSTOMIZATION and APP_VERSION_CUSTOMIZATION values and thereby make use of the functionality introduced with #61635. The creation of the version_h and app_version_h targets, which drives the custom commands, are kept at their current location. This ensure that the targets themselves are still defined when the Zephyr and Zephyr modules CMakeLists trees are sourced. Upstream PR: https://github.com/zephyrproject-rtos/zephyr/pull/62395 Signed-off-by: Torsten Rasmussen (cherry picked from commit 96a0d4e857edbbb03a336cbb06c027355bfb75fc) Signed-off-by: Dominik Ermel (cherry picked from commit 1f8d53dbc4e5af5b1f524163460cd44a6891ccb0) --- CMakeLists.txt | 48 ++++++++++++++++++++++++++---------------------- 1 file changed, 26 insertions(+), 22 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3d761a97d8b..8fc047610fc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -551,31 +551,9 @@ if(ZEPHYR_GIT_INDEX) set(git_dependency ${ZEPHYR_GIT_INDEX}) endif() -add_custom_command( - OUTPUT ${PROJECT_BINARY_DIR}/include/generated/version.h - COMMAND ${CMAKE_COMMAND} -DZEPHYR_BASE=${ZEPHYR_BASE} - -DOUT_FILE=${PROJECT_BINARY_DIR}/include/generated/version.h - -DVERSION_TYPE=KERNEL - -DVERSION_FILE=${ZEPHYR_BASE}/VERSION - -DKERNEL_VERSION_CUSTOMIZATION="${KERNEL_VERSION_CUSTOMIZATION}" - ${build_version_argument} - -P ${ZEPHYR_BASE}/cmake/gen_version_h.cmake - DEPENDS ${ZEPHYR_BASE}/VERSION ${git_dependency} -) add_custom_target(version_h DEPENDS ${PROJECT_BINARY_DIR}/include/generated/version.h) if(EXISTS ${APPLICATION_SOURCE_DIR}/VERSION) - add_custom_command( - OUTPUT ${PROJECT_BINARY_DIR}/include/generated/app_version.h - COMMAND ${CMAKE_COMMAND} -DZEPHYR_BASE=${ZEPHYR_BASE} - -DOUT_FILE=${PROJECT_BINARY_DIR}/include/generated/app_version.h - -DVERSION_TYPE=APP - -DVERSION_FILE=${APPLICATION_SOURCE_DIR}/VERSION - -DAPP_VERSION_CUSTOMIZATION="${APP_VERSION_CUSTOMIZATION}" - ${build_version_argument} - -P ${ZEPHYR_BASE}/cmake/gen_version_h.cmake - DEPENDS ${APPLICATION_SOURCE_DIR}/VERSION ${git_dependency} - ) add_custom_target(app_version_h DEPENDS ${PROJECT_BINARY_DIR}/include/generated/app_version.h) add_dependencies(zephyr_interface app_version_h) endif() @@ -626,6 +604,32 @@ endforeach() set(ZEPHYR_CURRENT_MODULE_DIR) set(ZEPHYR_CURRENT_CMAKE_DIR) +add_custom_command( + OUTPUT ${PROJECT_BINARY_DIR}/include/generated/version.h + COMMAND ${CMAKE_COMMAND} -DZEPHYR_BASE=${ZEPHYR_BASE} + -DOUT_FILE=${PROJECT_BINARY_DIR}/include/generated/version.h + -DVERSION_TYPE=KERNEL + -DVERSION_FILE=${ZEPHYR_BASE}/VERSION + -DKERNEL_VERSION_CUSTOMIZATION="${KERNEL_VERSION_CUSTOMIZATION}" + ${build_version_argument} + -P ${ZEPHYR_BASE}/cmake/gen_version_h.cmake + DEPENDS ${ZEPHYR_BASE}/VERSION ${git_dependency} +) + +if(EXISTS ${APPLICATION_SOURCE_DIR}/VERSION) + add_custom_command( + OUTPUT ${PROJECT_BINARY_DIR}/include/generated/app_version.h + COMMAND ${CMAKE_COMMAND} -DZEPHYR_BASE=${ZEPHYR_BASE} + -DOUT_FILE=${PROJECT_BINARY_DIR}/include/generated/app_version.h + -DVERSION_TYPE=APP + -DVERSION_FILE=${APPLICATION_SOURCE_DIR}/VERSION + -DAPP_VERSION_CUSTOMIZATION="${APP_VERSION_CUSTOMIZATION}" + ${build_version_argument} + -P ${ZEPHYR_BASE}/cmake/gen_version_h.cmake + DEPENDS ${APPLICATION_SOURCE_DIR}/VERSION ${git_dependency} + ) +endif() + get_property(LIBC_LINK_LIBRARIES TARGET zephyr_interface PROPERTY LIBC_LINK_LIBRARIES) zephyr_link_libraries(${LIBC_LINK_LIBRARIES}) From 09864f357bd2a56dc37c693b7bfe8e47df788e1f Mon Sep 17 00:00:00 2001 From: Sachin D Kulkarni Date: Tue, 5 Sep 2023 18:29:38 +0530 Subject: [PATCH 054/421] [nrf fromtree] net: wifi: Fix crash in wifi_utils_parse_scan_bands wifi_utils_parse_scan_bands could cause a crash if a constant string is passed to it. Fix this by duplicating the input string parameter before parsing it with strtok_r. Signed-off-by: Sachin D Kulkarni (cherry picked from commit 0b92327fc31b031a04e3a48d9cbd2cecccb7ac18) Signed-off-by: Dominik Ermel (cherry picked from commit 4a4d63062033a2e8a45fe743b3258dede3b83d17) --- include/zephyr/net/wifi_mgmt.h | 2 ++ subsys/net/l2/wifi/wifi_utils.c | 17 ++++++++++++++++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/include/zephyr/net/wifi_mgmt.h b/include/zephyr/net/wifi_mgmt.h index 0bdb5753531..c7a17e930d6 100644 --- a/include/zephyr/net/wifi_mgmt.h +++ b/include/zephyr/net/wifi_mgmt.h @@ -41,6 +41,8 @@ extern "C" { #define WIFI_MGMT_SCAN_SSID_FILT_MAX 0 #endif /* CONFIG_WIFI_MGMT_SCAN_SSID_FILT_MAX */ +#define WIFI_MGMT_BAND_STR_SIZE_MAX 8 + /** Wi-Fi management commands */ enum net_request_wifi_cmd { /** Scan for Wi-Fi networks */ diff --git a/subsys/net/l2/wifi/wifi_utils.c b/subsys/net/l2/wifi/wifi_utils.c index f7e9d9af4dc..6151f480d21 100644 --- a/subsys/net/l2/wifi/wifi_utils.c +++ b/subsys/net/l2/wifi/wifi_utils.c @@ -215,15 +215,30 @@ static int wifi_utils_validate_chan_str(char *chan_str) int wifi_utils_parse_scan_bands(char *scan_bands_str, uint8_t *band_map) { + char parse_str[WIFI_MGMT_BAND_STR_SIZE_MAX + 1]; char *band_str = NULL; char *ctx = NULL; enum wifi_frequency_bands band = WIFI_FREQ_BAND_UNKNOWN; + int len; if (!scan_bands_str) { return -EINVAL; } - band_str = strtok_r(scan_bands_str, ",", &ctx); + len = strlen(scan_bands_str); + + if (len > WIFI_MGMT_BAND_STR_SIZE_MAX) { + NET_ERR("Band string (%s) size (%d) exceeds maximum allowed value (%d)", + scan_bands_str, + len, + WIFI_MGMT_BAND_STR_SIZE_MAX); + return -EINVAL; + } + + strncpy(parse_str, scan_bands_str, len); + parse_str[len] = '\0'; + + band_str = strtok_r(parse_str, ",", &ctx); while (band_str) { band = wifi_utils_map_band_str_to_idx(band_str); From e4ee01d63ffcf8405d868827ea7e1916b883c760 Mon Sep 17 00:00:00 2001 From: Sachin D Kulkarni Date: Tue, 5 Sep 2023 18:38:54 +0530 Subject: [PATCH 055/421] [nrf fromtree] net: wifi: Fix crash in wifi_utils_parse_scan_ssids wifi_utils_parse_scan_ssids could cause a crash if a constant string is passed to it. Fix this by duplicating the input string parameter before parsing it with strtok_r. Also limit the range of the CONFIG_WIFI_SCAN_SSID_FILT_MAX parameter from 1 to 4 to avoid stack overflow due to users specifying a large value for this parameter. Signed-off-by: Sachin D Kulkarni (cherry picked from commit 85b39b84492605c02daaac4b16227b983dc757f0) Signed-off-by: Dominik Ermel (cherry picked from commit 8cb7f16e1a4797e60deefc79ead837db3285d102) --- subsys/net/l2/wifi/Kconfig | 1 + subsys/net/l2/wifi/wifi_utils.c | 17 ++++++++++++++++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/subsys/net/l2/wifi/Kconfig b/subsys/net/l2/wifi/Kconfig index e034a745b5e..6623456d84b 100644 --- a/subsys/net/l2/wifi/Kconfig +++ b/subsys/net/l2/wifi/Kconfig @@ -76,6 +76,7 @@ config WIFI_MGMT_SCAN_DWELL_TIME_PASSIVE config WIFI_MGMT_SCAN_SSID_FILT_MAX int "Maximum number of SSIDs that can be specified for SSID filtering" default 1 + range 1 4 help Maximum number of SSIDs that can be specified for SSID filtering. This can be set based on the underlying chipsets limitations. diff --git a/subsys/net/l2/wifi/wifi_utils.c b/subsys/net/l2/wifi/wifi_utils.c index 6151f480d21..ea0e42def47 100644 --- a/subsys/net/l2/wifi/wifi_utils.c +++ b/subsys/net/l2/wifi/wifi_utils.c @@ -259,15 +259,30 @@ int wifi_utils_parse_scan_bands(char *scan_bands_str, uint8_t *band_map) int wifi_utils_parse_scan_ssids(char *scan_ssids_str, char ssids[][WIFI_SSID_MAX_LEN + 1]) { + char parse_str[(WIFI_MGMT_SCAN_SSID_FILT_MAX * (WIFI_SSID_MAX_LEN + 1)) + 1]; char *ssid = NULL; char *ctx = NULL; uint8_t i = 0; + int len; if (!scan_ssids_str) { return -EINVAL; } - ssid = strtok_r(scan_ssids_str, ",", &ctx); + len = strlen(scan_ssids_str); + + if (len > (WIFI_MGMT_SCAN_SSID_FILT_MAX * (WIFI_SSID_MAX_LEN + 1))) { + NET_ERR("SSID string (%s) size (%d) exceeds maximum allowed value (%d)", + scan_ssids_str, + len, + (WIFI_MGMT_SCAN_SSID_FILT_MAX * (WIFI_SSID_MAX_LEN + 1))); + return -EINVAL; + } + + strncpy(parse_str, scan_ssids_str, len); + parse_str[len] = '\0'; + + ssid = strtok_r(parse_str, ",", &ctx); while (ssid) { if (strlen(ssid) > WIFI_SSID_MAX_LEN) { From 0feef90eb0216678f3cfe10bbeae034d79ad9840 Mon Sep 17 00:00:00 2001 From: Vivekananda Uppunda Date: Fri, 1 Sep 2023 15:56:38 +0530 Subject: [PATCH 056/421] [nrf fromtree] net: l2: wifi: Add support for W-Fi mode setting and selection This change brings in support for setting various Wi-Fi modes and enables a specific Wi-Fi interface to be also placed into a sniffer operation via monitor mode and promiscuous mode. A raw TX- packet Injection mode is also introduced Signed-off-by: Vivekananda Uppunda (cherry picked from commit 450dbb15efcaccadf546b42931509e5c4581b5eb) (cherry picked from commit 9226e1f518cae9a99d98332a30d8b78673fbaa89) Signed-off-by: Dominik Ermel (cherry picked from commit 5d2baa76d183a9971899f68d4b49b3e7b9a1a77e) --- include/zephyr/net/wifi.h | 33 +++ include/zephyr/net/wifi_mgmt.h | 76 +++++++ subsys/net/l2/wifi/wifi_mgmt.c | 60 +++++ subsys/net/l2/wifi/wifi_shell.c | 388 +++++++++++++++++++++++++++++++- 4 files changed, 556 insertions(+), 1 deletion(-) diff --git a/include/zephyr/net/wifi.h b/include/zephyr/net/wifi.h index aa3096fc5ac..55bd8d71a3a 100644 --- a/include/zephyr/net/wifi.h +++ b/include/zephyr/net/wifi.h @@ -148,6 +148,7 @@ static inline const char *wifi_band_txt(enum wifi_frequency_bands band) #define WIFI_SAE_PSWD_MAX_LEN 128 #define WIFI_MAC_ADDR_LEN 6 +#define WIFI_CHANNEL_MIN 1 #define WIFI_CHANNEL_MAX 233 #define WIFI_CHANNEL_ANY 255 @@ -355,6 +356,38 @@ static const char * const wifi_ps_mode2str[] = { }; /** @endcond */ +/* Interface index Min and Max values */ +#define WIFI_INTERFACE_INDEX_MIN 1 +#define WIFI_INTERFACE_INDEX_MAX 255 + +/** Wifi operational mode */ +enum wifi_operational_modes { + /** STA mode setting enable */ + WIFI_STA_MODE = BIT(0), + /** Monitor mode setting enable */ + WIFI_MONITOR_MODE = BIT(1), + /** TX injection mode setting enable */ + WIFI_TX_INJECTION_MODE = BIT(2), + /** Promiscuous mode setting enable */ + WIFI_PROMISCUOUS_MODE = BIT(3), + /** AP mode setting enable */ + WIFI_AP_MODE = BIT(4), + /** Softap mode setting enable */ + WIFI_SOFTAP_MODE = BIT(5), +}; + +/** Mode filter settings */ +enum wifi_filter { + /** Support management, data and control packet sniffing */ + WIFI_PACKET_FILTER_ALL = BIT(0), + /** Support only sniffing of management packets */ + WIFI_PACKET_FILTER_MGMT = BIT(1), + /** Support only sniffing of data packets */ + WIFI_PACKET_FILTER_DATA = BIT(2), + /** Support only sniffing of control packets */ + WIFI_PACKET_FILTER_CTRL = BIT(3), +}; + /** Wi-Fi Target Wake Time (TWT) operations. */ enum wifi_twt_operation { /** TWT setup operation */ diff --git a/include/zephyr/net/wifi_mgmt.h b/include/zephyr/net/wifi_mgmt.h index c7a17e930d6..ab3225e1408 100644 --- a/include/zephyr/net/wifi_mgmt.h +++ b/include/zephyr/net/wifi_mgmt.h @@ -69,6 +69,12 @@ enum net_request_wifi_cmd { NET_REQUEST_WIFI_CMD_REG_DOMAIN, /** Set power save timeout */ NET_REQUEST_WIFI_CMD_PS_TIMEOUT, + /** Set or get Mode of operation */ + NET_REQUEST_WIFI_CMD_MODE, + /** Set or get packet filter setting for current mode */ + NET_REQUEST_WIFI_CMD_PACKET_FILTER, + /** Set or get Wi-Fi channel for Monitor or TX-Injection mode */ + NET_REQUEST_WIFI_CMD_CHANNEL, NET_REQUEST_WIFI_CMD_MAX }; @@ -131,6 +137,21 @@ NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_WIFI_REG_DOMAIN); NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_WIFI_PS_TIMEOUT); +#define NET_REQUEST_WIFI_MODE \ + (_NET_WIFI_BASE | NET_REQUEST_WIFI_CMD_MODE) + +NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_WIFI_MODE); + +#define NET_REQUEST_WIFI_PACKET_FILTER \ + (_NET_WIFI_BASE | NET_REQUEST_WIFI_CMD_PACKET_FILTER) + +NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_WIFI_PACKET_FILTER); + +#define NET_REQUEST_WIFI_CHANNEL \ + (_NET_WIFI_BASE | NET_REQUEST_WIFI_CMD_CHANNEL) + +NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_WIFI_CHANNEL); + /** Wi-Fi management events */ enum net_event_wifi_cmd { /** Scan results available */ @@ -475,6 +496,37 @@ union wifi_mgmt_events { struct wifi_twt_params twt_params; }; +/** Wi-Fi mode setup */ +struct wifi_mode_info { + /** Mode setting for a specific mode of operation */ + uint8_t mode; + /** Interface index */ + uint8_t if_index; + /** Get or set operation */ + enum wifi_mgmt_op oper; +}; + +/** Wi-Fi filter setting for monitor, prmoiscuous, TX-injection modes */ +struct wifi_filter_info { + /** Filter setting */ + uint8_t filter; + /** Interface index */ + uint8_t if_index; + /** Filter buffer size */ + uint16_t buffer_size; + /** Get or set operation */ + enum wifi_mgmt_op oper; +}; + +/** Wi-Fi channel setting for monitor and TX-injection modes */ +struct wifi_channel_info { + /** Channel value to set */ + uint16_t channel; + /** Interface index */ + uint8_t if_index; + /** Get or set operation */ + enum wifi_mgmt_op oper; +}; #include @@ -596,6 +648,30 @@ struct wifi_mgmt_ops { * @return 0 if ok, < 0 if error */ int (*reg_domain)(const struct device *dev, struct wifi_reg_domain *reg_domain); + /** Set or get packet filter settings for monitor and promiscuous modes + * + * @param dev Pointer to the device structure for the driver instance. + * @param packet filter settings + * + * @return 0 if ok, < 0 if error + */ + int (*filter)(const struct device *dev, struct wifi_filter_info *filter); + /** Set or get mode of operation + * + * @param dev Pointer to the device structure for the driver instance. + * @param mode settings + * + * @return 0 if ok, < 0 if error + */ + int (*mode)(const struct device *dev, struct wifi_mode_info *mode); + /** Set or get current channel of operation + * + * @param dev Pointer to the device structure for the driver instance. + * @param channel settings + * + * @return 0 if ok, < 0 if error + */ + int (*channel)(const struct device *dev, struct wifi_channel_info *channel); }; /** Wi-Fi management offload API */ diff --git a/subsys/net/l2/wifi/wifi_mgmt.c b/subsys/net/l2/wifi/wifi_mgmt.c index 22d54b926ab..7f0f30dc8c1 100644 --- a/subsys/net/l2/wifi/wifi_mgmt.c +++ b/subsys/net/l2/wifi/wifi_mgmt.c @@ -446,6 +446,66 @@ void wifi_mgmt_raise_twt_sleep_state(struct net_if *iface, sizeof(twt_sleep_state)); } +static int wifi_mode(uint32_t mgmt_request, struct net_if *iface, + void *data, size_t len) +{ + const struct device *dev = net_if_get_device(iface); + const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_api(iface); + struct wifi_mode_info *mode_info = data; + + if (dev == NULL) { + return -ENODEV; + } + + if (wifi_mgmt_api == NULL || wifi_mgmt_api->mode == NULL) { + return -ENOTSUP; + } + + return wifi_mgmt_api->mode(dev, mode_info); +} + +NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_WIFI_MODE, wifi_mode); + +static int wifi_packet_filter(uint32_t mgmt_request, struct net_if *iface, + void *data, size_t len) +{ + const struct device *dev = net_if_get_device(iface); + const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_api(iface); + struct wifi_filter_info *filter_info = data; + + if (dev == NULL) { + return -ENODEV; + } + + if (wifi_mgmt_api == NULL || wifi_mgmt_api->filter == NULL) { + return -ENOTSUP; + } + + return wifi_mgmt_api->filter(dev, filter_info); +} + +NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_WIFI_PACKET_FILTER, wifi_packet_filter); + +static int wifi_channel(uint32_t mgmt_request, struct net_if *iface, + void *data, size_t len) +{ + const struct device *dev = net_if_get_device(iface); + const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_api(iface); + struct wifi_channel_info *channel_info = data; + + if (dev == NULL) { + return -ENODEV; + } + + if (wifi_mgmt_api == NULL || wifi_mgmt_api->channel == NULL) { + return -ENOTSUP; + } + + return wifi_mgmt_api->channel(dev, channel_info); +} + +NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_WIFI_CHANNEL, wifi_channel); + #ifdef CONFIG_WIFI_MGMT_RAW_SCAN_RESULTS void wifi_mgmt_raise_raw_scan_result_event(struct net_if *iface, struct wifi_raw_scan_result *raw_scan_result) diff --git a/subsys/net/l2/wifi/wifi_shell.c b/subsys/net/l2/wifi/wifi_shell.c index 0b8c6a74983..21b1f551448 100644 --- a/subsys/net/l2/wifi/wifi_shell.c +++ b/subsys/net/l2/wifi/wifi_shell.c @@ -75,12 +75,20 @@ static bool parse_number(const struct shell *sh, long *param, char *str, long mi { char *endptr; char *str_tmp = str; - long num = strtol(str_tmp, &endptr, 10); + long num = 0; + + if ((str_tmp[0] == '0') && (str_tmp[1] == 'x')) { + /* Hexadecimal numbers take base 0 in strtol */ + num = strtol(str_tmp, &endptr, 0); + } else { + num = strtol(str_tmp, &endptr, 10); + } if (*endptr != '\0') { print(sh, SHELL_ERROR, "Invalid number: %s", str_tmp); return false; } + if ((num) < (min) || (num) > (max)) { print(sh, SHELL_WARNING, "Value out of range: %s, (%ld-%ld)", str_tmp, min, max); return false; @@ -1255,6 +1263,335 @@ static int cmd_wifi_ps_wakeup_mode(const struct shell *sh, size_t argc, char *ar return 0; } +void parse_mode_args_to_params(const struct shell *sh, int argc, + char *argv[], struct wifi_mode_info *mode, + bool *do_mode_oper) +{ + int opt; + int option_index = 0; + + static struct option long_options[] = {{"if_index", optional_argument, 0, 'i'}, + {"sta", no_argument, 0, 's'}, + {"monitor", no_argument, 0, 'm'}, + {"TX-injection", no_argument, 0, 't'}, + {"promiscuous", no_argument, 0, 'p'}, + {"ap", no_argument, 0, 'a'}, + {"softap", no_argument, 0, 'k'}, + {"get", no_argument, 0, 'g'}, + {"help", no_argument, 0, 'h'}, + {0, 0, 0, 0}}; + + while ((opt = getopt_long(argc, argv, "i:smtpakgh", long_options, &option_index)) != -1) { + switch (opt) { + case 's': + mode->mode |= WIFI_STA_MODE; + break; + case 'm': + mode->mode |= WIFI_MONITOR_MODE; + break; + case 't': + mode->mode |= WIFI_TX_INJECTION_MODE; + break; + case 'p': + mode->mode |= WIFI_PROMISCUOUS_MODE; + break; + case 'a': + mode->mode |= WIFI_AP_MODE; + break; + case 'k': + mode->mode |= WIFI_SOFTAP_MODE; + break; + case 'g': + mode->oper = true; + break; + case 'i': + mode->if_index = (uint8_t)atoi(optarg); + break; + case 'h': + shell_help(sh); + *do_mode_oper = false; + break; + case '?': + default: + break; + } + } +} + +static int cmd_wifi_mode(const struct shell *sh, size_t argc, char *argv[]) +{ + struct net_if *iface; + struct wifi_mode_info mode_info = {0}; + int ret; + bool do_mode_oper = true; + + if (argc > 1) { + mode_info.oper = WIFI_MGMT_SET; + parse_mode_args_to_params(sh, argc, argv, &mode_info, &do_mode_oper); + } else { + shell_fprintf(sh, SHELL_ERROR, "Invalid number of arguments\n"); + return -EINVAL; + } + + if (do_mode_oper) { + /* Check interface index value. Mode validation must be performed by + * lower layer + */ + if (mode_info.if_index == 0) { + iface = net_if_get_first_wifi(); + if (iface == NULL) { + shell_fprintf(sh, SHELL_ERROR, + "Cannot find the default wifi interface\n"); + return -ENOEXEC; + } + mode_info.if_index = net_if_get_by_iface(iface); + } else { + iface = net_if_get_by_index(mode_info.if_index); + if (iface == NULL) { + shell_fprintf(sh, SHELL_ERROR, + "Cannot find interface for if_index %d\n", + mode_info.if_index); + return -ENOEXEC; + } + } + + ret = net_mgmt(NET_REQUEST_WIFI_MODE, iface, &mode_info, sizeof(mode_info)); + + if (ret) { + shell_fprintf(sh, SHELL_ERROR, "mode %s operation failed with reason %d\n", + mode_info.oper == WIFI_MGMT_GET ? "get" : "set", ret); + return -ENOEXEC; + } + + if (mode_info.oper == WIFI_MGMT_GET) { + shell_fprintf(sh, SHELL_NORMAL, "Wi-Fi current mode is %x\n", + mode_info.mode); + } else { + shell_fprintf(sh, SHELL_NORMAL, "Wi-Fi mode set to %x\n", mode_info.mode); + } + } + return 0; +} + +void parse_channel_args_to_params(const struct shell *sh, int argc, + char *argv[], struct wifi_channel_info *channel, + bool *do_channel_oper) +{ + int opt; + int option_index = 0; + + static struct option long_options[] = {{"if_index", optional_argument, 0, 'i'}, + {"channel", required_argument, 0, 'c'}, + {"get", no_argument, 0, 'g'}, + {"help", no_argument, 0, 'h'}, + {0, 0, 0, 0}}; + + while ((opt = getopt_long(argc, argv, "i:c:gh", long_options, &option_index)) != -1) { + switch (opt) { + case 'c': + channel->channel = (uint16_t)atoi(optarg); + break; + case 'i': + channel->if_index = (uint8_t)atoi(optarg); + break; + case 'g': + channel->oper = WIFI_MGMT_GET; + break; + case 'h': + shell_help(sh); + *do_channel_oper = false; + break; + case '?': + default: + break; + } + } +} + +static int cmd_wifi_channel(const struct shell *sh, size_t argc, char *argv[]) +{ + struct net_if *iface; + struct wifi_channel_info channel_info = {0}; + int ret; + bool do_channel_oper = true; + + if (argc > 1) { + channel_info.oper = WIFI_MGMT_SET; + parse_channel_args_to_params(sh, argc, argv, &channel_info, &do_channel_oper); + } else { + shell_fprintf(sh, SHELL_ERROR, "Invalid number of arguments\n"); + return -EINVAL; + } + + if (do_channel_oper) { + /* + * Validate parameters before sending to lower layer. + * Do it here instead of parse_channel_args_to_params + * as this is right before sending the parameters to + * the lower layer. + */ + + if (channel_info.if_index == 0) { + iface = net_if_get_first_wifi(); + if (iface == NULL) { + shell_fprintf(sh, SHELL_ERROR, + "Cannot find the default wifi interface\n"); + return -ENOEXEC; + } + channel_info.if_index = net_if_get_by_iface(iface); + } else { + iface = net_if_get_by_index(channel_info.if_index); + if (iface == NULL) { + shell_fprintf(sh, SHELL_ERROR, + "Cannot find interface for if_index %d\n", + channel_info.if_index); + return -ENOEXEC; + } + } + + if (channel_info.oper == WIFI_MGMT_SET) { + if ((channel_info.channel < WIFI_CHANNEL_MIN) || + (channel_info.channel > WIFI_CHANNEL_MAX)) { + shell_fprintf(sh, SHELL_ERROR, + "Invalid channel number. Range is (1-233)\n"); + return -ENOEXEC; + } + } + + ret = net_mgmt(NET_REQUEST_WIFI_CHANNEL, iface, + &channel_info, sizeof(channel_info)); + + if (ret) { + shell_fprintf(sh, SHELL_ERROR, + "channel %s operation failed with reason %d\n", + channel_info.oper == WIFI_MGMT_GET ? "get" : "set", ret); + return -ENOEXEC; + } + + if (channel_info.oper == WIFI_MGMT_GET) { + shell_fprintf(sh, SHELL_NORMAL, "Wi-Fi current channel is: %d\n", + channel_info.channel); + } else { + shell_fprintf(sh, SHELL_NORMAL, "Wi-Fi channel set to %d\n", + channel_info.channel); + } + } + return 0; +} + +void parse_filter_args_to_params(const struct shell *sh, int argc, + char *argv[], struct wifi_filter_info *filter, + bool *do_filter_oper) +{ + int opt; + int option_index = 0; + + static struct option long_options[] = {{"if_index", optional_argument, 0, 'i'}, + {"capture_len", optional_argument, 0, 'b'}, + {"all", no_argument, 0, 'a'}, + {"mgmt", no_argument, 0, 'm'}, + {"ctrl", no_argument, 0, 'c'}, + {"data", no_argument, 0, 'd'}, + {"get", no_argument, 0, 'g'}, + {"help", no_argument, 0, 'h'}, + {0, 0, 0, 0}}; + + while ((opt = getopt_long(argc, argv, "i:b:amcdgh", long_options, &option_index)) != -1) { + switch (opt) { + case 'a': + filter->filter |= WIFI_PACKET_FILTER_ALL; + break; + case 'm': + filter->filter |= WIFI_PACKET_FILTER_MGMT; + break; + case 'c': + filter->filter |= WIFI_PACKET_FILTER_DATA; + break; + case 'd': + filter->filter |= WIFI_PACKET_FILTER_CTRL; + break; + case 'i': + filter->if_index = (uint8_t)atoi(optarg); + break; + case 'b': + filter->buffer_size = (uint16_t)atoi(optarg); + break; + case 'h': + shell_help(sh); + *do_filter_oper = false; + break; + case 'g': + filter->oper = WIFI_MGMT_GET; + break; + case '?': + default: + break; + } + } +} + +static int cmd_wifi_packet_filter(const struct shell *sh, size_t argc, char *argv[]) +{ + struct net_if *iface; + struct wifi_filter_info packet_filter = {0}; + int ret; + bool do_filter_oper = true; + + if (argc > 1) { + packet_filter.oper = WIFI_MGMT_SET; + parse_filter_args_to_params(sh, argc, argv, &packet_filter, &do_filter_oper); + } else { + shell_fprintf(sh, SHELL_ERROR, "Invalid number of arguments\n"); + return -EINVAL; + } + + if (do_filter_oper) { + /* + * Validate parameters before sending to lower layer. + * Do it here instead of parse_filter_args_to_params + * as this is right before sending the parameters to + * the lower layer. filter and packet capture length + * value to be verified by the lower layer. + */ + if (packet_filter.if_index == 0) { + iface = net_if_get_first_wifi(); + if (iface == NULL) { + shell_fprintf(sh, SHELL_ERROR, + "Cannot find the default wifi interface\n"); + return -ENOEXEC; + } + packet_filter.if_index = net_if_get_by_iface(iface); + } else { + iface = net_if_get_by_index(packet_filter.if_index); + if (iface == NULL) { + shell_fprintf(sh, SHELL_ERROR, + "Cannot find interface for if_index %d\n", + packet_filter.if_index); + return -ENOEXEC; + } + } + + ret = net_mgmt(NET_REQUEST_WIFI_PACKET_FILTER, iface, + &packet_filter, sizeof(packet_filter)); + + if (ret) { + shell_fprintf(sh, SHELL_ERROR, + "Wi-Fi packet filter %s operation failed with reason %d\n", + packet_filter.oper == WIFI_MGMT_GET ? "get" : "set", ret); + return -ENOEXEC; + } + + if (packet_filter.oper == WIFI_MGMT_GET) { + shell_fprintf(sh, SHELL_NORMAL, "Wi-Fi current mode packet filter is %d\n", + packet_filter.filter); + } else { + shell_fprintf(sh, SHELL_NORMAL, "Wi-Fi mode packet filter set to %d\n", + packet_filter.filter); + } + } + return 0; +} + SHELL_STATIC_SUBCMD_SET_CREATE(wifi_cmd_ap, SHELL_CMD(disable, NULL, "Disable Access Point mode", @@ -1328,6 +1665,55 @@ SHELL_STATIC_SUBCMD_SET_CREATE(wifi_commands, "-f: Force to use this regulatory hint over any other regulatory hints\n" "Note: This may cause regulatory compliance issues, use it at your own risk.", cmd_wifi_reg_domain), + SHELL_CMD(mode, NULL, "mode operational setting\n" + "This command may be used to set the Wi-Fi device into a specific mode of operation\n" + "parameters:" + "[-i : Interface index - optional argument\n" + "[-s : Station mode.\n" + "[-m : Monitor mode.\n" + "[-p : Promiscuous mode.\n" + "[-t : TX-Injection mode.\n" + "[-a : AP mode.\n" + "[-k : Softap mode.\n" + "[-h : Help.\n" + "[-g : Get current mode for a specific interface index.\n" + "Usage: Get operation example for interface index 1\n" + "wifi mode -g -i1\n" + "Set operation example for interface index 1 - set station+promiscuous\n" + "wifi mode -i1 -sp\n", + cmd_wifi_mode), + SHELL_CMD(packet_filter, NULL, "mode filter setting\n" + "This command is used to set packet filter setting when\n" + "monitor, TX-Injection and promiscuous mode is enabled.\n" + "The different packet filter modes are control, management, data and enable all filters\n" + "parameters:" + "[-i : Interface index - optional argument.\n" + "[-a : Enable all packet filter modes\n" + "[-m : Enable management packets to allowed up the stack.\n" + "[-c : Enable control packets to be allowed up the stack.\n" + "[-d : Enable Data packets to be allowed up the stack.\n" + "[-g : Get current filter settings for a specific interface index.\n" + "<-b : Capture length buffer size for each packet to be captured - optional argument.\n" + "<-h : Help.\n" + "Usage: Get operation example for interface index 1\n" + "wifi packet_filter -g -i1\n" + "Set operation example for interface index 1 - set data+management frame filter\n" + "wifi packet_filter -i1 -md\n", + cmd_wifi_packet_filter), + SHELL_CMD(channel, NULL, "wifi channel setting\n" + "This command is used to set the channel when\n" + "monitor or TX-Injection mode is enabled.\n" + "Currently 20 MHz is only supported and no BW parameter is provided\n" + "parameters:" + "[-i : Interface index - optional argument.\n" + "[-c : Set a specific channel number to the lower layer.\n" + "[-g : Get current set channel number from the lower layer.\n" + "[-h : Help.\n" + "Usage: Get operation example for interface index 1\n" + "wifi channel -g -i1\n" + "Set operation example for interface index 1 (setting channel 5)\n" + "wifi -i1 -c5\n", + cmd_wifi_channel), SHELL_CMD_ARG(ps_timeout, NULL, " - PS inactivity timer(in ms)", From 4ea2d10cee590392888695101091446a4c4605d5 Mon Sep 17 00:00:00 2001 From: Chaitanya Tata Date: Thu, 14 Sep 2023 23:34:45 +0530 Subject: [PATCH 057/421] [nrf fromtree] net: socketpair: Fix use after free In low memory conditions, its possible for socketpair memory allocation to fail and then the socketpair is freed but after that the remote semaphore is released causing a crash. Fix this by freeing the socketpair after releasing the semaphore. Add a test case to induce low memory conditions (low HEAP and high socketpair buffer size), with the fix issue is not seen. Signed-off-by: Chaitanya Tata (cherry picked from commit 40ee8791f21e47cadf2552386b9f16b18f3fb060) Signed-off-by: Dominik Ermel (cherry picked from commit 1878aa707df6b8be09fa1f81345281b7fcc0a57f) --- subsys/net/lib/sockets/socketpair.c | 8 ++++---- tests/net/socket/socketpair/testcase.yaml | 8 ++++++++ 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/subsys/net/lib/sockets/socketpair.c b/subsys/net/lib/sockets/socketpair.c index f3bbb46f6c8..9207f4b659e 100644 --- a/subsys/net/lib/sockets/socketpair.c +++ b/subsys/net/lib/sockets/socketpair.c @@ -191,6 +191,10 @@ static void spair_delete(struct spair *spair) res = k_poll_signal_raise(&spair->writeable, SPAIR_SIG_CANCEL); __ASSERT(res == 0, "k_poll_signal_raise() failed: %d", res); + if (remote != NULL && have_remote_sem) { + k_sem_give(&remote->sem); + } + /* ensure no private information is released to the memory pool */ memset(spair, 0, sizeof(*spair)); #ifdef CONFIG_NET_SOCKETPAIR_STATIC @@ -200,10 +204,6 @@ static void spair_delete(struct spair *spair) #else k_free(spair); #endif - - if (remote != NULL && have_remote_sem) { - k_sem_give(&remote->sem); - } } /** diff --git a/tests/net/socket/socketpair/testcase.yaml b/tests/net/socket/socketpair/testcase.yaml index e771e7c61d4..d2b4462ce2d 100644 --- a/tests/net/socket/socketpair/testcase.yaml +++ b/tests/net/socket/socketpair/testcase.yaml @@ -18,3 +18,11 @@ tests: extra_configs: - CONFIG_PICOLIBC=y platform_exclude: vmu_rt1170 mimxrt1160_evk_cm7 # See #61246 + net.socket.socketpair.high_mem: + min_ram: 64 + extra_configs: + # Low buffer sizes (e.g., 8192) will verify the crash fix, but tests will still + # fail due to insufficient memory. So, use high buffer sizes. + - CONFIG_NET_SOCKETPAIR_BUFFER_SIZE=4096 + - CONFIG_HEAP_MEM_POOL_SIZE=32768 + platform_exclude: vmu_rt1170 mimxrt1160_evk_cm7 # See #61246 From 5327c5408115ece4c62baaa0eb9fdd8086f78f1b Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Thu, 3 Aug 2023 10:56:41 +0100 Subject: [PATCH 058/421] [nrf fromtree] twister: Add support for required snippets Adds support for twister to require using snippets on tests Signed-off-by: Jamie McCrae (cherry picked from commit bc97d8fb1e40328ab32da108508e83e9d8792bf0) (cherry picked from commit a9d71eb9c5fd9d676c3a2493305bd06412f9de68) Signed-off-by: Dominik Ermel (cherry picked from commit 2ddf83d3189e253fc40e290808f55cc669cc79a4) --- .../pylib/twister/twisterlib/config_parser.py | 1 + scripts/pylib/twister/twisterlib/runner.py | 4 ++ scripts/pylib/twister/twisterlib/testplan.py | 42 +++++++++++++++++++ scripts/schemas/twister/testsuite-schema.yaml | 10 +++++ scripts/snippets.py | 16 +++++++ scripts/twister | 3 ++ scripts/west_commands/build.py | 11 ++++- 7 files changed, 86 insertions(+), 1 deletion(-) diff --git a/scripts/pylib/twister/twisterlib/config_parser.py b/scripts/pylib/twister/twisterlib/config_parser.py index c822e9dfc77..f431e2d57c2 100644 --- a/scripts/pylib/twister/twisterlib/config_parser.py +++ b/scripts/pylib/twister/twisterlib/config_parser.py @@ -48,6 +48,7 @@ class TwisterConfigParser: "extra_conf_files": {"type": "list", "default": []}, "extra_overlay_confs" : {"type": "list", "default": []}, "extra_dtc_overlay_files": {"type": "list", "default": []}, + "required_snippets": {"type": "list"}, "build_only": {"type": "bool", "default": False}, "build_on_all": {"type": "bool", "default": False}, "skip": {"type": "bool", "default": False}, diff --git a/scripts/pylib/twister/twisterlib/runner.py b/scripts/pylib/twister/twisterlib/runner.py index ad93145db38..bbbdb18d05a 100644 --- a/scripts/pylib/twister/twisterlib/runner.py +++ b/scripts/pylib/twister/twisterlib/runner.py @@ -359,6 +359,10 @@ def run_cmake(self, args="", filter_stages=[]): cmake_opts = ['-DBOARD={}'.format(self.platform.name)] cmake_args.extend(cmake_opts) + if self.instance.testsuite.required_snippets: + cmake_opts = ['-DSNIPPET={}'.format(';'.join(self.instance.testsuite.required_snippets))] + cmake_args.extend(cmake_opts) + cmake = shutil.which('cmake') cmd = [cmake] + cmake_args diff --git a/scripts/pylib/twister/twisterlib/testplan.py b/scripts/pylib/twister/twisterlib/testplan.py index 85340885dbb..1d9c625b28a 100755 --- a/scripts/pylib/twister/twisterlib/testplan.py +++ b/scripts/pylib/twister/twisterlib/testplan.py @@ -16,6 +16,8 @@ import copy import shutil import random +import snippets +from pathlib import Path logger = logging.getLogger('twister') logger.setLevel(logging.DEBUG) @@ -819,6 +821,46 @@ def apply_filters(self, **kwargs): if plat.only_tags and not set(plat.only_tags) & ts.tags: instance.add_filter("Excluded tags per platform (only_tags)", Filters.PLATFORM) + if ts.required_snippets: + missing_snippet = False + snippet_args = {"snippets": ts.required_snippets} + found_snippets = snippets.find_snippets_in_roots(snippet_args, [Path(ZEPHYR_BASE), Path(ts.source_dir)]) + + # Search and check that all required snippet files are found + for this_snippet in snippet_args['snippets']: + if this_snippet not in found_snippets: + logger.error(f"Can't find snippet '%s' for test '%s'", this_snippet, ts.name) + instance.status = "error" + instance.reason = f"Snippet {this_snippet} not found" + missing_snippet = True + break + + if not missing_snippet: + # Look for required snippets and check that they are applicable for these + # platforms/boards + for this_snippet in found_snippets: + matched_snippet_board = False + + # If the "appends" key is present with at least one entry then this + # snippet applies to all boards and further platform-specific checks + # are not required + if found_snippets[this_snippet].appends: + continue + + for this_board in found_snippets[this_snippet].board2appends: + if this_board.startswith('/'): + match = re.search(this_board[1:-1], plat.name) + if match is not None: + matched_snippet_board = True + break + elif this_board == plat.name: + matched_snippet_board = True + break + + if matched_snippet_board is False: + instance.add_filter("Snippet not supported", Filters.PLATFORM) + break + # platform_key is a list of unique platform attributes that form a unique key a test # will match against to determine if it should be scheduled to run. A key containing a # field name that the platform does not have will filter the platform. diff --git a/scripts/schemas/twister/testsuite-schema.yaml b/scripts/schemas/twister/testsuite-schema.yaml index 4d67fe71706..116c1a43379 100644 --- a/scripts/schemas/twister/testsuite-schema.yaml +++ b/scripts/schemas/twister/testsuite-schema.yaml @@ -145,6 +145,11 @@ mapping: matching: "all" sequence: - type: str + "required_snippets": + type: seq + required: false + sequence: + - type: str "tags": type: any required: false @@ -243,6 +248,11 @@ mapping: "extra_sections": type: any required: false + "required_snippets": + type: seq + required: false + sequence: + - type: str "filter": type: str required: false diff --git a/scripts/snippets.py b/scripts/snippets.py index 9662f3edcec..78ab896e85b 100644 --- a/scripts/snippets.py +++ b/scripts/snippets.py @@ -238,6 +238,22 @@ def process_snippets(args: argparse.Namespace) -> Snippets: return snippets +def find_snippets_in_roots(requested_snippets, snippet_roots) -> Snippets: + '''Process snippet.yml files under each *snippet_root* + by recursive search. Return a Snippets object describing + the results of the search. + ''' + # This will contain information about all the snippets + # we discover in each snippet_root element. + snippets = Snippets(requested=requested_snippets) + + # Process each path in snippet_root in order, adjusting + # snippets as needed for each one. + for root in snippet_roots: + process_snippets_in(root, snippets) + + return snippets + def process_snippets_in(root_dir: Path, snippets: Snippets) -> None: '''Process snippet.yml files in *root_dir*, updating *snippets* as needed.''' diff --git a/scripts/twister b/scripts/twister index 0f5e622011f..f41349871ed 100755 --- a/scripts/twister +++ b/scripts/twister @@ -44,6 +44,9 @@ pairs: Extra configuration options to be merged with a master prj.conf when building or running the test case. + required_snippets: + Snippets that must be applied for the test case to run. + sysbuild: (default False) If true, build the sample using the sysbuild infrastructure. Filtering will only be enabled for the main project, and is not supported for diff --git a/scripts/west_commands/build.py b/scripts/west_commands/build.py index 65dbe963cd4..bcc5106f8ca 100644 --- a/scripts/west_commands/build.py +++ b/scripts/west_commands/build.py @@ -293,6 +293,7 @@ def _parse_test_item(self, test_item): extra_dtc_overlay_files = [] extra_overlay_confs = [] extra_conf_files = [] + required_snippets = [] for section in [common, item]: if not section: continue @@ -302,7 +303,8 @@ def _parse_test_item(self, test_item): 'extra_configs', 'extra_conf_files', 'extra_overlay_confs', - 'extra_dtc_overlay_files' + 'extra_dtc_overlay_files', + 'required_snippets' ]: extra = section.get(data) if not extra: @@ -325,6 +327,9 @@ def _parse_test_item(self, test_item): elif data == 'extra_dtc_overlay_files': extra_dtc_overlay_files.extend(arg_list) continue + elif data == 'required_snippets': + required_snippets.extend(arg_list) + continue if self.args.cmake_opts: self.args.cmake_opts.extend(args) @@ -343,6 +348,10 @@ def _parse_test_item(self, test_item): if extra_overlay_confs: args.append(f"OVERLAY_CONFIG=\"{';'.join(extra_overlay_confs)}\"") + + if required_snippets: + args.append(f"SNIPPET=\"{';'.join(required_snippets)}\"") + # Build the final argument list args_expanded = ["-D{}".format(a.replace('"', '')) for a in args] From 45e05e2d8f3ffb0b46a0fa055cb5b3ded64e13f7 Mon Sep 17 00:00:00 2001 From: Chaitanya Tata Date: Tue, 5 Sep 2023 01:47:48 +0530 Subject: [PATCH 059/421] [nrf fromtree] twister: handle quotes for configuration options Add support handling quotes for configuration options in extra args by escaping them properly instead of removing the quotes altogether. For other options in extra_args quotes are removes as usual. Add similar support in west build command also. Add a unit test to check this functionality. Signed-off-by: Chaitanya Tata (cherry picked from commit 6b05af6e4389cf10415b7c3bd83c0dd45b10ed26) (cherry picked from commit 81b838d57dc6997c14718c0dc94b778bcd6eeba5) Signed-off-by: Dominik Ermel (cherry picked from commit dbe7b7c5dd073df4c2a5680bab5d4783f79780ef) --- scripts/pylib/twister/twisterlib/runner.py | 10 ++++++++-- scripts/tests/twister/test_runner.py | 5 +++-- scripts/west_commands/build.py | 6 +++++- 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/scripts/pylib/twister/twisterlib/runner.py b/scripts/pylib/twister/twisterlib/runner.py index bbbdb18d05a..ef41084cdd4 100644 --- a/scripts/pylib/twister/twisterlib/runner.py +++ b/scripts/pylib/twister/twisterlib/runner.py @@ -978,9 +978,15 @@ def report_out(self, results): sys.stdout.flush() @staticmethod - def cmake_assemble_args(args, handler, extra_conf_files, extra_overlay_confs, + def cmake_assemble_args(extra_args, handler, extra_conf_files, extra_overlay_confs, extra_dtc_overlay_files, cmake_extra_args, build_dir): + # Retain quotes around config options + config_options = [arg for arg in extra_args if arg.startswith("CONFIG_")] + args = [arg for arg in extra_args if not arg.startswith("CONFIG_")] + + args_expanded = ["-D{}".format(a.replace('"', '\"')) for a in config_options] + if handler.ready: args.extend(handler.args) @@ -1003,7 +1009,7 @@ def cmake_assemble_args(args, handler, extra_conf_files, extra_overlay_confs, args.append("OVERLAY_CONFIG=\"%s\"" % (" ".join(overlays))) # Build the final argument list - args_expanded = ["-D{}".format(a.replace('"', '\"')) for a in cmake_extra_args] + args_expanded.extend(["-D{}".format(a.replace('"', '\"')) for a in cmake_extra_args]) args_expanded.extend(["-D{}".format(a.replace('"', '')) for a in args]) return args_expanded diff --git a/scripts/tests/twister/test_runner.py b/scripts/tests/twister/test_runner.py index 7540da04394..37c02b6d17b 100644 --- a/scripts/tests/twister/test_runner.py +++ b/scripts/tests/twister/test_runner.py @@ -90,7 +90,7 @@ class MockHandler: handler.ready = True assert(ProjectBuilder.cmake_assemble_args( - ["basearg1"], + ["basearg1", "CONFIG_t=\"test\"", "SNIPPET_t=\"test\""], handler, ["a.conf;b.conf", "c.conf"], ["extra_overlay.conf"], @@ -98,8 +98,9 @@ class MockHandler: ["cmake1=foo", "cmake2=bar"], "/builddir/", ) == [ + "-DCONFIG_t=\"test\"", "-Dcmake1=foo", "-Dcmake2=bar", - "-Dbasearg1", + "-Dbasearg1", "-DSNIPPET_t=test", "-Dhandler_arg1", "-Dhandler_arg2", "-DCONF_FILE=a.conf;b.conf;c.conf", "-DDTC_OVERLAY_FILE=x.overlay;y.overlay;z.overlay", diff --git a/scripts/west_commands/build.py b/scripts/west_commands/build.py index bcc5106f8ca..f7a605f4d7f 100644 --- a/scripts/west_commands/build.py +++ b/scripts/west_commands/build.py @@ -317,7 +317,11 @@ def _parse_test_item(self, test_item): if data == 'extra_configs': args = ["-D{}".format(arg.replace('"', '\"')) for arg in arg_list] elif data == 'extra_args': - args = ["-D{}".format(arg.replace('"', '')) for arg in arg_list] + # Retain quotes around config options + config_options = [arg for arg in arg_list if arg.startswith("CONFIG_")] + non_config_options = [arg for arg in arg_list if not arg.startswith("CONFIG_")] + args = ["-D{}".format(a.replace('"', '\"')) for a in config_options] + args.extend(["-D{}".format(arg.replace('"', '')) for arg in non_config_options]) elif data == 'extra_conf_files': extra_conf_files.extend(arg_list) continue From 622ccbce57fab78fd9527f0099207f84a2582459 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Fri, 23 Jun 2023 16:19:25 +0000 Subject: [PATCH 060/421] [nrf fromtree] mgmt/MCUmgr/grp/img: Add support for three image configuration The commit adds support for uploading images to secondary slots of three images. (cherry picked from commit ea6129cd7c21299c8cd65db5722f0a7d7aafaeae) Signed-off-by: Dominik Ermel (cherry picked from commit 0784ebb292ee95a82f12f86c12eef89845ff543e) --- subsys/dfu/Kconfig | 2 +- subsys/mgmt/mcumgr/grp/img_mgmt/Kconfig | 2 +- .../mgmt/mcumgr/grp/img_mgmt/src/img_mgmt.c | 65 +++++++++---------- .../mcumgr/grp/img_mgmt/src/zephyr_img_mgmt.c | 36 ++++++++-- 4 files changed, 63 insertions(+), 42 deletions(-) diff --git a/subsys/dfu/Kconfig b/subsys/dfu/Kconfig index f998b2ef9f2..121fa3964f6 100644 --- a/subsys/dfu/Kconfig +++ b/subsys/dfu/Kconfig @@ -89,7 +89,7 @@ if !MCUBOOT config UPDATEABLE_IMAGE_NUMBER int "Number of updateable images" default 1 - range 1 2 + range 1 3 help If value is set to 2 or greater then, this enables support needed when application is combined with MCUboot multi-image boot. diff --git a/subsys/mgmt/mcumgr/grp/img_mgmt/Kconfig b/subsys/mgmt/mcumgr/grp/img_mgmt/Kconfig index 641e16bd703..81fc57d9238 100644 --- a/subsys/mgmt/mcumgr/grp/img_mgmt/Kconfig +++ b/subsys/mgmt/mcumgr/grp/img_mgmt/Kconfig @@ -46,7 +46,7 @@ endif config MCUMGR_GRP_IMG_UPDATABLE_IMAGE_NUMBER int "Number of supported images" default UPDATEABLE_IMAGE_NUMBER - range 1 2 + range 1 3 help Sets how many application images are supported (pairs of secondary and primary slots). Setting this to 2 requires MCUMGR_TRANSPORT_NETBUF_SIZE to be at least 512b. diff --git a/subsys/mgmt/mcumgr/grp/img_mgmt/src/img_mgmt.c b/subsys/mgmt/mcumgr/grp/img_mgmt/src/img_mgmt.c index b2bb39aca86..305cad41c44 100644 --- a/subsys/mgmt/mcumgr/grp/img_mgmt/src/img_mgmt.c +++ b/subsys/mgmt/mcumgr/grp/img_mgmt/src/img_mgmt.c @@ -59,43 +59,38 @@ BUILD_ASSERT(PM_MCUBOOT_PAD_SIZE == PM_MCUBOOT_SECONDARY_PAD_SIZE); (FIXED_PARTITION_OFFSET(label) == CONFIG_FLASH_LOAD_OFFSET) #endif /* USE_PARTITION_MANAGER */ -#if FIXED_PARTITION_EXISTS(slot0_partition) -#if FIXED_PARTITION_IS_RUNNING_APP_PARTITION(slot0_partition) -#define NUMBER_OF_ACTIVE_IMAGE 0 -#endif -#endif - -#if !defined(NUMBER_OF_ACTIVE_IMAGE) && FIXED_PARTITION_EXISTS(slot0_ns_partition) -#if FIXED_PARTITION_IS_RUNNING_APP_PARTITION(slot0_ns_partition) -#define NUMBER_OF_ACTIVE_IMAGE 0 -#endif -#endif - -#if !defined(NUMBER_OF_ACTIVE_IMAGE) && FIXED_PARTITION_EXISTS(slot1_partition) -#if FIXED_PARTITION_IS_RUNNING_APP_PARTITION(slot1_partition) -#define NUMBER_OF_ACTIVE_IMAGE 0 -#endif -#endif - -#if !defined(NUMBER_OF_ACTIVE_IMAGE) && FIXED_PARTITION_EXISTS(slot2_partition) -#if FIXED_PARTITION_IS_RUNNING_APP_PARTITION(slot2_partition) -#define NUMBER_OF_ACTIVE_IMAGE 1 -#endif -#endif - -#if !defined(NUMBER_OF_ACTIVE_IMAGE) && FIXED_PARTITION_EXISTS(slot3_partition) -#if FIXED_PARTITION_IS_RUNNING_APP_PARTITION(slot3_partition) -#define NUMBER_OF_ACTIVE_IMAGE 1 -#endif +BUILD_ASSERT(sizeof(struct image_header) == IMAGE_HEADER_SIZE, + "struct image_header not required size"); + +#if CONFIG_MCUMGR_GRP_IMG_UPDATABLE_IMAGE_NUMBER >= 2 +#if FIXED_PARTITION_EXISTS(slot0_ns_partition) && \ + FIXED_PARTITION_IS_RUNNING_APP_PARTITION(slot0_ns_partition) +#define ACTIVE_IMAGE_IS 0 +#elif FIXED_PARTITION_EXISTS(slot0_partition) && \ + FIXED_PARTITION_IS_RUNNING_APP_PARTITION(slot0_partition) +#define ACTIVE_IMAGE_IS 0 +#elif FIXED_PARTITION_EXISTS(slot1_partition) && \ + FIXED_PARTITION_IS_RUNNING_APP_PARTITION(slot1_partition) +#define ACTIVE_IMAGE_IS 0 +#elif FIXED_PARTITION_EXISTS(slot2_partition) && \ + FIXED_PARTITION_IS_RUNNING_APP_PARTITION(slot2_partition) +#define ACTIVE_IMAGE_IS 1 +#elif FIXED_PARTITION_EXISTS(slot3_partition) && \ + FIXED_PARTITION_IS_RUNNING_APP_PARTITION(slot3_partition) +#define ACTIVE_IMAGE_IS 1 +#elif FIXED_PARTITION_EXISTS(slot4_partition) && \ + FIXED_PARTITION_IS_RUNNING_APP_PARTITION(slot4_partition) +#define ACTIVE_IMAGE_IS 2 +#elif FIXED_PARTITION_EXISTS(slot5_partition) && \ + FIXED_PARTITION_IS_RUNNING_APP_PARTITION(slot5_partition) +#define ACTIVE_IMAGE_IS 2 +#else +#define ACTIVE_IMAGE_IS 0 #endif - -#ifndef NUMBER_OF_ACTIVE_IMAGE -#error "Unsupported code parition is set as active application partition" +#else +#define ACTIVE_IMAGE_IS 0 #endif -_Static_assert(sizeof(struct image_header) == IMAGE_HEADER_SIZE, - "struct image_header not required size"); - LOG_MODULE_REGISTER(mcumgr_img_grp, CONFIG_MCUMGR_GRP_IMG_LOG_LEVEL); struct img_mgmt_state g_img_mgmt_state; @@ -177,7 +172,7 @@ int img_mgmt_active_slot(int image) int img_mgmt_active_image(void) { - return NUMBER_OF_ACTIVE_IMAGE; + return ACTIVE_IMAGE_IS; } /* diff --git a/subsys/mgmt/mcumgr/grp/img_mgmt/src/zephyr_img_mgmt.c b/subsys/mgmt/mcumgr/grp/img_mgmt/src/zephyr_img_mgmt.c index c3641986fd2..addde1e9a2c 100644 --- a/subsys/mgmt/mcumgr/grp/img_mgmt/src/zephyr_img_mgmt.c +++ b/subsys/mgmt/mcumgr/grp/img_mgmt/src/zephyr_img_mgmt.c @@ -25,12 +25,26 @@ LOG_MODULE_DECLARE(mcumgr_img_grp, CONFIG_MCUMGR_GRP_IMG_LOG_LEVEL); #define SLOT1_PARTITION slot1_partition #define SLOT2_PARTITION slot2_partition #define SLOT3_PARTITION slot3_partition +#define SLOT4_PARTITION slot4_partition +#define SLOT5_PARTITION slot5_partition + +/* SLOT0_PARTITION and SLOT1_PARTITION are not checked because + * there is not conditional code that depends on them. If they do + * not exist compilation will fail, but in case if some of other + * partitions do not exist, code will compile and will not work + * properly. + */ +#if CONFIG_MCUMGR_GRP_IMG_UPDATABLE_IMAGE_NUMBER >= 2 +BUILD_ASSERT(FIXED_PARTITION_EXISTS(SLOT2_PARTITION) && + FIXED_PARTITION_EXISTS(SLOT3_PARTITION), + "Missing partitions?"); +#endif -BUILD_ASSERT(CONFIG_MCUMGR_GRP_IMG_UPDATABLE_IMAGE_NUMBER == 1 || - (CONFIG_MCUMGR_GRP_IMG_UPDATABLE_IMAGE_NUMBER == 2 && - FIXED_PARTITION_EXISTS(SLOT2_PARTITION) && - FIXED_PARTITION_EXISTS(SLOT3_PARTITION)), +#if CONFIG_MCUMGR_GRP_IMG_UPDATABLE_IMAGE_NUMBER == 3 +BUILD_ASSERT(FIXED_PARTITION_EXISTS(SLOT4_PARTITION) && + FIXED_PARTITION_EXISTS(SLOT5_PARTITION), "Missing partitions?"); +#endif /** * Determines if the specified area of flash is completely unwritten. @@ -137,6 +151,18 @@ img_mgmt_flash_area_id(int slot) break; #endif +#if FIXED_PARTITION_EXISTS(SLOT4_PARTITION) + case 4: + fa_id = FIXED_PARTITION_ID(SLOT4_PARTITION); + break; +#endif + +#if FIXED_PARTITION_EXISTS(SLOT5_PARTITION) + case 5: + fa_id = FIXED_PARTITION_ID(SLOT5_PARTITION); + break; +#endif + default: fa_id = -1; break; @@ -194,7 +220,7 @@ static int img_mgmt_get_unused_slot_area_id(int slot) return slot != -1 ? img_mgmt_flash_area_id(slot) : -1; #endif } -#elif CONFIG_MCUMGR_GRP_IMG_UPDATABLE_IMAGE_NUMBER == 2 +#elif CONFIG_MCUMGR_GRP_IMG_UPDATABLE_IMAGE_NUMBER >= 2 static int img_mgmt_get_unused_slot_area_id(int image) { int area_id = -1; From ff771d084177ffb3595bf855fb0fb26cef6c225e Mon Sep 17 00:00:00 2001 From: Kapil Bhatt Date: Wed, 20 Sep 2023 17:57:04 +0530 Subject: [PATCH 061/421] [nrf fromtree] net: l2: wifi: Change arrays to functions The header file contains mixture of functions and static arrays. Replacing static arrays to functions. Initialize functions in C file. Signed-off-by: Kapil Bhatt (cherry picked from commit 4b9f5cc455c1c018c506a94f8b4a5b2fa617e51e) (cherry picked from commit 1db99743a416e7a1eb407392567e5a562ea230ac) Signed-off-by: Dominik Ermel (cherry picked from commit bd51b50482fde641900df44752061b930ab208b9) --- include/zephyr/net/wifi.h | 187 +++-------------------- subsys/net/l2/wifi/wifi_shell.c | 258 +++++++++++++++++++++++++++++--- 2 files changed, 256 insertions(+), 189 deletions(-) diff --git a/include/zephyr/net/wifi.h b/include/zephyr/net/wifi.h index 55bd8d71a3a..294fdc53c5d 100644 --- a/include/zephyr/net/wifi.h +++ b/include/zephyr/net/wifi.h @@ -52,30 +52,7 @@ enum wifi_security_type { }; /** Helper function to get user-friendly security type name. */ -static inline const char *wifi_security_txt(enum wifi_security_type security) -{ - switch (security) { - case WIFI_SECURITY_TYPE_NONE: - return "OPEN"; - case WIFI_SECURITY_TYPE_WEP: - return "WEP"; - case WIFI_SECURITY_TYPE_WPA_PSK: - return "WPA-PSK"; - case WIFI_SECURITY_TYPE_PSK: - return "WPA2-PSK"; - case WIFI_SECURITY_TYPE_PSK_SHA256: - return "WPA2-PSK-SHA256"; - case WIFI_SECURITY_TYPE_SAE: - return "WPA3-SAE"; - case WIFI_SECURITY_TYPE_WAPI: - return "WAPI"; - case WIFI_SECURITY_TYPE_EAP: - return "EAP"; - case WIFI_SECURITY_TYPE_UNKNOWN: - default: - return "UNKNOWN"; - } -} +const char * const wifi_security_txt(enum wifi_security_type security); /** IEEE 802.11w - Management frame protection. */ enum wifi_mfp_options { @@ -92,20 +69,7 @@ enum wifi_mfp_options { }; /** Helper function to get user-friendly MFP name.*/ -static inline const char *wifi_mfp_txt(enum wifi_mfp_options mfp) -{ - switch (mfp) { - case WIFI_MFP_DISABLE: - return "Disable"; - case WIFI_MFP_OPTIONAL: - return "Optional"; - case WIFI_MFP_REQUIRED: - return "Required"; - case WIFI_MFP_UNKNOWN: - default: - return "UNKNOWN"; - } -} +const char * const wifi_mfp_txt(enum wifi_mfp_options mfp); /** * @brief IEEE 802.11 operational frequency bands (not exhaustive). @@ -127,20 +91,7 @@ enum wifi_frequency_bands { }; /** Helper function to get user-friendly frequency band name. */ -static inline const char *wifi_band_txt(enum wifi_frequency_bands band) -{ - switch (band) { - case WIFI_FREQ_BAND_2_4_GHZ: - return "2.4GHz"; - case WIFI_FREQ_BAND_5_GHZ: - return "5GHz"; - case WIFI_FREQ_BAND_6_GHZ: - return "6GHz"; - case WIFI_FREQ_BAND_UNKNOWN: - default: - return "UNKNOWN"; - } -} +const char * const wifi_band_txt(enum wifi_frequency_bands band); #define WIFI_SSID_MAX_LEN 32 #define WIFI_PSK_MIN_LEN 8 @@ -184,34 +135,7 @@ enum wifi_iface_state { }; /** Helper function to get user-friendly interface state name. */ -static inline const char *wifi_state_txt(enum wifi_iface_state state) -{ - switch (state) { - case WIFI_STATE_DISCONNECTED: - return "DISCONNECTED"; - case WIFI_STATE_INACTIVE: - return "INACTIVE"; - case WIFI_STATE_INTERFACE_DISABLED: - return "INTERFACE_DISABLED"; - case WIFI_STATE_SCANNING: - return "SCANNING"; - case WIFI_STATE_AUTHENTICATING: - return "AUTHENTICATING"; - case WIFI_STATE_ASSOCIATING: - return "ASSOCIATING"; - case WIFI_STATE_ASSOCIATED: - return "ASSOCIATED"; - case WIFI_STATE_4WAY_HANDSHAKE: - return "4WAY_HANDSHAKE"; - case WIFI_STATE_GROUP_HANDSHAKE: - return "GROUP_HANDSHAKE"; - case WIFI_STATE_COMPLETED: - return "COMPLETED"; - case WIFI_STATE_UNKNOWN: - default: - return "UNKNOWN"; - } -} +const char * const wifi_state_txt(enum wifi_iface_state state); /** Wi-Fi interface modes. * @@ -237,26 +161,7 @@ enum wifi_iface_mode { }; /** Helper function to get user-friendly interface mode name. */ -static inline const char *wifi_mode_txt(enum wifi_iface_mode mode) -{ - switch (mode) { - case WIFI_MODE_INFRA: - return "STATION"; - case WIFI_MODE_IBSS: - return "ADHOC"; - case WIFI_MODE_AP: - return "ACCESS POINT"; - case WIFI_MODE_P2P_GO: - return "P2P GROUP OWNER"; - case WIFI_MODE_P2P_GROUP_FORMATION: - return "P2P GROUP FORMATION"; - case WIFI_MODE_MESH: - return "MESH"; - case WIFI_MODE_UNKNOWN: - default: - return "UNKNOWN"; - } -} +const char * const wifi_mode_txt(enum wifi_iface_mode mode); /** Wi-Fi link operating modes * @@ -288,32 +193,7 @@ enum wifi_link_mode { }; /** Helper function to get user-friendly link mode name. */ -static inline const char *wifi_link_mode_txt(enum wifi_link_mode link_mode) -{ - switch (link_mode) { - case WIFI_0: - return "WIFI 0 (802.11)"; - case WIFI_1: - return "WIFI 1 (802.11b)"; - case WIFI_2: - return "WIFI 2 (802.11a)"; - case WIFI_3: - return "WIFI 3 (802.11g)"; - case WIFI_4: - return "WIFI 4 (802.11n/HT)"; - case WIFI_5: - return "WIFI 5 (802.11ac/VHT)"; - case WIFI_6: - return "WIFI 6 (802.11ax/HE)"; - case WIFI_6E: - return "WIFI 6E (802.11ax 6GHz/HE)"; - case WIFI_7: - return "WIFI 7 (802.11be/EHT)"; - case WIFI_LINK_MODE_UNKNOWN: - default: - return "UNKNOWN"; - } -} +const char * const wifi_link_mode_txt(enum wifi_link_mode link_mode); /** Wi-Fi scanning types. */ enum wifi_scan_type { @@ -331,12 +211,8 @@ enum wifi_ps { WIFI_PS_ENABLED, }; -/** @cond INTERNAL_HIDDEN */ -static const char * const wifi_ps2str[] = { - [WIFI_PS_DISABLED] = "Power save disabled", - [WIFI_PS_ENABLED] = "Power save enabled", -}; -/** @endcond */ +/** Helper function to get user-friendly ps name. */ +const char * const wifi_ps_txt(enum wifi_ps ps_name); /** Wi-Fi power save modes. */ enum wifi_ps_mode { @@ -349,12 +225,8 @@ enum wifi_ps_mode { WIFI_PS_MODE_WMM, }; -/** @cond INTERNAL_HIDDEN */ -static const char * const wifi_ps_mode2str[] = { - [WIFI_PS_MODE_LEGACY] = "Legacy power save", - [WIFI_PS_MODE_WMM] = "WMM power save", -}; -/** @endcond */ +/** Helper function to get user-friendly ps mode name. */ +const char * const wifi_ps_mode_txt(enum wifi_ps_mode ps_mode); /* Interface index Min and Max values */ #define WIFI_INTERFACE_INDEX_MIN 1 @@ -396,12 +268,8 @@ enum wifi_twt_operation { WIFI_TWT_TEARDOWN, }; -/** @cond INTERNAL_HIDDEN */ -static const char * const wifi_twt_operation2str[] = { - [WIFI_TWT_SETUP] = "TWT setup", - [WIFI_TWT_TEARDOWN] = "TWT teardown", -}; -/** @endcond */ +/** Helper function to get user-friendly twt operation name. */ +const char * const wifi_twt_operation_txt(enum wifi_twt_operation twt_operation); /** Wi-Fi Target Wake Time (TWT) negotiation types. */ enum wifi_twt_negotiation_type { @@ -413,13 +281,8 @@ enum wifi_twt_negotiation_type { WIFI_TWT_WAKE_TBTT }; -/** @cond INTERNAL_HIDDEN */ -static const char * const wifi_twt_negotiation_type2str[] = { - [WIFI_TWT_INDIVIDUAL] = "TWT individual negotiation", - [WIFI_TWT_BROADCAST] = "TWT broadcast negotiation", - [WIFI_TWT_WAKE_TBTT] = "TWT wake TBTT negotiation", -}; -/** @endcond */ +/** Helper function to get user-friendly twt negotiation type name. */ +const char * const wifi_twt_negotiation_type_txt(enum wifi_twt_negotiation_type twt_negotiation); /** Wi-Fi Target Wake Time (TWT) setup commands. */ enum wifi_twt_setup_cmd { @@ -441,18 +304,8 @@ enum wifi_twt_setup_cmd { WIFI_TWT_SETUP_CMD_REJECT, }; -/** @cond INTERNAL_HIDDEN */ -static const char * const wifi_twt_setup_cmd2str[] = { - [WIFI_TWT_SETUP_CMD_REQUEST] = "TWT request", - [WIFI_TWT_SETUP_CMD_SUGGEST] = "TWT suggest", - [WIFI_TWT_SETUP_CMD_DEMAND] = "TWT demand", - [WIFI_TWT_SETUP_CMD_GROUPING] = "TWT grouping", - [WIFI_TWT_SETUP_CMD_ACCEPT] = "TWT accept", - [WIFI_TWT_SETUP_CMD_ALTERNATE] = "TWT alternate", - [WIFI_TWT_SETUP_CMD_DICTATE] = "TWT dictate", - [WIFI_TWT_SETUP_CMD_REJECT] = "TWT reject", -}; -/** @endcond */ +/** Helper function to get user-friendly twt setup cmd name. */ +const char * const wifi_twt_setup_cmd_txt(enum wifi_twt_setup_cmd twt_setup); /** Wi-Fi Target Wake Time (TWT) negotiation status. */ enum wifi_twt_setup_resp_status { @@ -543,12 +396,8 @@ enum wifi_ps_wakeup_mode { WIFI_PS_WAKEUP_MODE_LISTEN_INTERVAL, }; -/** @cond INTERNAL_HIDDEN */ -static const char * const wifi_ps_wakeup_mode2str[] = { - [WIFI_PS_WAKEUP_MODE_DTIM] = "PS wakeup mode DTIM", - [WIFI_PS_WAKEUP_MODE_LISTEN_INTERVAL] = "PS wakeup mode listen interval", -}; -/** @endcond */ +/** Helper function to get user-friendly ps wakeup mode name. */ +const char * const wifi_ps_wakeup_mode_txt(enum wifi_ps_wakeup_mode ps_wakeup_mode); /** Wi-Fi power save error codes. */ enum wifi_config_ps_param_fail_reason { diff --git a/subsys/net/l2/wifi/wifi_shell.c b/subsys/net/l2/wifi/wifi_shell.c index 21b1f551448..74284e56e98 100644 --- a/subsys/net/l2/wifi/wifi_shell.c +++ b/subsys/net/l2/wifi/wifi_shell.c @@ -97,6 +97,224 @@ static bool parse_number(const struct shell *sh, long *param, char *str, long mi return true; } +const char * const wifi_security_txt(enum wifi_security_type security) +{ + switch (security) { + case WIFI_SECURITY_TYPE_NONE: + return "OPEN"; + case WIFI_SECURITY_TYPE_WEP: + return "WEP"; + case WIFI_SECURITY_TYPE_WPA_PSK: + return "WPA-PSK"; + case WIFI_SECURITY_TYPE_PSK: + return "WPA2-PSK"; + case WIFI_SECURITY_TYPE_PSK_SHA256: + return "WPA2-PSK-SHA256"; + case WIFI_SECURITY_TYPE_SAE: + return "WPA3-SAE"; + case WIFI_SECURITY_TYPE_WAPI: + return "WAPI"; + case WIFI_SECURITY_TYPE_EAP: + return "EAP"; + case WIFI_SECURITY_TYPE_UNKNOWN: + default: + return "UNKNOWN"; + } +} + +const char * const wifi_mfp_txt(enum wifi_mfp_options mfp) +{ + switch (mfp) { + case WIFI_MFP_DISABLE: + return "Disable"; + case WIFI_MFP_OPTIONAL: + return "Optional"; + case WIFI_MFP_REQUIRED: + return "Required"; + case WIFI_MFP_UNKNOWN: + default: + return "UNKNOWN"; + } +} + +const char * const wifi_band_txt(enum wifi_frequency_bands band) +{ + switch (band) { + case WIFI_FREQ_BAND_2_4_GHZ: + return "2.4GHz"; + case WIFI_FREQ_BAND_5_GHZ: + return "5GHz"; + case WIFI_FREQ_BAND_6_GHZ: + return "6GHz"; + case WIFI_FREQ_BAND_UNKNOWN: + default: + return "UNKNOWN"; + } +} + +const char * const wifi_state_txt(enum wifi_iface_state state) +{ + switch (state) { + case WIFI_STATE_DISCONNECTED: + return "DISCONNECTED"; + case WIFI_STATE_INACTIVE: + return "INACTIVE"; + case WIFI_STATE_INTERFACE_DISABLED: + return "INTERFACE_DISABLED"; + case WIFI_STATE_SCANNING: + return "SCANNING"; + case WIFI_STATE_AUTHENTICATING: + return "AUTHENTICATING"; + case WIFI_STATE_ASSOCIATING: + return "ASSOCIATING"; + case WIFI_STATE_ASSOCIATED: + return "ASSOCIATED"; + case WIFI_STATE_4WAY_HANDSHAKE: + return "4WAY_HANDSHAKE"; + case WIFI_STATE_GROUP_HANDSHAKE: + return "GROUP_HANDSHAKE"; + case WIFI_STATE_COMPLETED: + return "COMPLETED"; + case WIFI_STATE_UNKNOWN: + default: + return "UNKNOWN"; + } +} + +const char * const wifi_mode_txt(enum wifi_iface_mode mode) +{ + switch (mode) { + case WIFI_MODE_INFRA: + return "STATION"; + case WIFI_MODE_IBSS: + return "ADHOC"; + case WIFI_MODE_AP: + return "ACCESS POINT"; + case WIFI_MODE_P2P_GO: + return "P2P GROUP OWNER"; + case WIFI_MODE_P2P_GROUP_FORMATION: + return "P2P GROUP FORMATION"; + case WIFI_MODE_MESH: + return "MESH"; + case WIFI_MODE_UNKNOWN: + default: + return "UNKNOWN"; + } +} + +const char * const wifi_link_mode_txt(enum wifi_link_mode link_mode) +{ + switch (link_mode) { + case WIFI_0: + return "WIFI 0 (802.11)"; + case WIFI_1: + return "WIFI 1 (802.11b)"; + case WIFI_2: + return "WIFI 2 (802.11a)"; + case WIFI_3: + return "WIFI 3 (802.11g)"; + case WIFI_4: + return "WIFI 4 (802.11n/HT)"; + case WIFI_5: + return "WIFI 5 (802.11ac/VHT)"; + case WIFI_6: + return "WIFI 6 (802.11ax/HE)"; + case WIFI_6E: + return "WIFI 6E (802.11ax 6GHz/HE)"; + case WIFI_7: + return "WIFI 7 (802.11be/EHT)"; + case WIFI_LINK_MODE_UNKNOWN: + default: + return "UNKNOWN"; + } +} + +const char * const wifi_ps_txt(enum wifi_ps ps_name) +{ + switch (ps_name) { + case WIFI_PS_DISABLED: + return "Power save disabled"; + case WIFI_PS_ENABLED: + return "Power save enabled"; + default: + return "UNKNOWN"; + } +} + +const char * const wifi_ps_mode_txt(enum wifi_ps_mode ps_mode) +{ + switch (ps_mode) { + case WIFI_PS_MODE_LEGACY: + return "Legacy power save"; + case WIFI_PS_MODE_WMM: + return "WMM power save"; + default: + return "UNKNOWN"; + } +} + +const char * const wifi_twt_operation_txt(enum wifi_twt_operation twt_operation) +{ + switch (twt_operation) { + case WIFI_TWT_SETUP: + return "TWT setup"; + case WIFI_TWT_TEARDOWN: + return "TWT teardown"; + default: + return "UNKNOWN"; + } +} + +const char * const wifi_twt_negotiation_type_txt(enum wifi_twt_negotiation_type twt_negotiation) +{ + switch (twt_negotiation) { + case WIFI_TWT_INDIVIDUAL: + return "TWT individual negotiation"; + case WIFI_TWT_BROADCAST: + return "TWT broadcast negotiation"; + case WIFI_TWT_WAKE_TBTT: + return "TWT wake TBTT negotiation"; + default: + return "UNKNOWN"; + } +} + +const char * const wifi_twt_setup_cmd_txt(enum wifi_twt_setup_cmd twt_setup) +{ + switch (twt_setup) { + case WIFI_TWT_SETUP_CMD_REQUEST: + return "TWT request"; + case WIFI_TWT_SETUP_CMD_SUGGEST: + return "TWT suggest"; + case WIFI_TWT_SETUP_CMD_DEMAND: + return "TWT demand"; + case WIFI_TWT_SETUP_CMD_GROUPING: + return "TWT grouping"; + case WIFI_TWT_SETUP_CMD_ACCEPT: + return "TWT accept"; + case WIFI_TWT_SETUP_CMD_ALTERNATE: + return "TWT alternate"; + case WIFI_TWT_SETUP_CMD_DICTATE: + return "TWT dictate"; + case WIFI_TWT_SETUP_CMD_REJECT: + return "TWT reject"; + default: + return "UNKNOWN"; + } +} + +const char * const wifi_ps_wakeup_mode_txt(enum wifi_ps_wakeup_mode ps_wakeup_mode) +{ + switch (ps_wakeup_mode) { + case WIFI_PS_WAKEUP_MODE_DTIM: + return "PS wakeup mode DTIM"; + case WIFI_PS_WAKEUP_MODE_LISTEN_INTERVAL: + return "PS wakeup mode listen interval"; + default: + return "UNKNOWN"; + } +} + static void handle_wifi_scan_result(struct net_mgmt_event_callback *cb) { const struct wifi_scan_result *entry = @@ -257,7 +475,7 @@ static void print_twt_params(uint8_t dialog_token, uint8_t flow_id, print(context.sh, SHELL_NORMAL, "TWT flow ID: %d\n", flow_id); print(context.sh, SHELL_NORMAL, "TWT negotiation type: %s\n", - wifi_twt_negotiation_type2str[negotiation_type]); + wifi_twt_negotiation_type_txt(negotiation_type)); print(context.sh, SHELL_NORMAL, "TWT responder: %s\n", responder ? "true" : "false"); print(context.sh, SHELL_NORMAL, "TWT implicit: %s\n", @@ -286,7 +504,7 @@ static void handle_wifi_twt_event(struct net_mgmt_event_callback *cb) if (resp->resp_status == WIFI_TWT_RESP_RECEIVED) { print(context.sh, SHELL_NORMAL, "TWT response: %s\n", - wifi_twt_setup_cmd2str[resp->setup_cmd]); + wifi_twt_setup_cmd_txt(resp->setup_cmd)); print(context.sh, SHELL_NORMAL, "== TWT negotiated parameters ==\n"); print_twt_params(resp->dialog_token, resp->flow_id, @@ -736,10 +954,10 @@ static int cmd_wifi_ps(const struct shell *sh, size_t argc, char *argv[]) } shell_fprintf(sh, SHELL_NORMAL, "PS status: %s\n", - wifi_ps2str[config.ps_params.enabled]); + wifi_ps_txt(config.ps_params.enabled)); if (config.ps_params.enabled) { shell_fprintf(sh, SHELL_NORMAL, "PS mode: %s\n", - wifi_ps_mode2str[config.ps_params.mode]); + wifi_ps_mode_txt(config.ps_params.mode)); } shell_fprintf(sh, SHELL_NORMAL, "PS listen_interval: %d\n", @@ -794,7 +1012,7 @@ static int cmd_wifi_ps(const struct shell *sh, size_t argc, char *argv[]) return -ENOEXEC; } - shell_fprintf(sh, SHELL_NORMAL, "%s\n", wifi_ps2str[params.enabled]); + shell_fprintf(sh, SHELL_NORMAL, "%s\n", wifi_ps_txt(params.enabled)); return 0; } @@ -819,12 +1037,12 @@ static int cmd_wifi_ps_mode(const struct shell *sh, size_t argc, char *argv[]) if (net_mgmt(NET_REQUEST_WIFI_PS, iface, ¶ms, sizeof(params))) { shell_fprintf(sh, SHELL_WARNING, "%s failed Reason : %s\n", - wifi_ps_mode2str[params.mode], + wifi_ps_mode_txt(params.mode), wifi_ps_get_config_err_code_str(params.fail_reason)); return -ENOEXEC; } - shell_fprintf(sh, SHELL_NORMAL, "%s\n", wifi_ps_mode2str[params.mode]); + shell_fprintf(sh, SHELL_NORMAL, "%s\n", wifi_ps_mode_txt(params.mode)); return 0; } @@ -903,15 +1121,15 @@ static int cmd_wifi_twt_setup_quick(const struct shell *sh, size_t argc, if (net_mgmt(NET_REQUEST_WIFI_TWT, iface, ¶ms, sizeof(params))) { shell_fprintf(sh, SHELL_WARNING, "%s with %s failed, reason : %s\n", - wifi_twt_operation2str[params.operation], - wifi_twt_negotiation_type2str[params.negotiation_type], + wifi_twt_operation_txt(params.operation), + wifi_twt_negotiation_type_txt(params.negotiation_type), wifi_twt_get_err_code_str(params.fail_reason)); return -ENOEXEC; } shell_fprintf(sh, SHELL_NORMAL, "TWT operation %s with dg: %d, flow_id: %d requested\n", - wifi_twt_operation2str[params.operation], + wifi_twt_operation_txt(params.operation), params.dialog_token, params.flow_id); return 0; @@ -990,15 +1208,15 @@ static int cmd_wifi_twt_setup(const struct shell *sh, size_t argc, if (net_mgmt(NET_REQUEST_WIFI_TWT, iface, ¶ms, sizeof(params))) { shell_fprintf(sh, SHELL_WARNING, "%s with %s failed. reason : %s\n", - wifi_twt_operation2str[params.operation], - wifi_twt_negotiation_type2str[params.negotiation_type], + wifi_twt_operation_txt(params.operation), + wifi_twt_negotiation_type_txt(params.negotiation_type), wifi_twt_get_err_code_str(params.fail_reason)); return -ENOEXEC; } shell_fprintf(sh, SHELL_NORMAL, "TWT operation %s with dg: %d, flow_id: %d requested\n", - wifi_twt_operation2str[params.operation], + wifi_twt_operation_txt(params.operation), params.dialog_token, params.flow_id); return 0; @@ -1046,15 +1264,15 @@ static int cmd_wifi_twt_teardown(const struct shell *sh, size_t argc, if (net_mgmt(NET_REQUEST_WIFI_TWT, iface, ¶ms, sizeof(params))) { shell_fprintf(sh, SHELL_WARNING, "%s with %s failed, reason : %s\n", - wifi_twt_operation2str[params.operation], - wifi_twt_negotiation_type2str[params.negotiation_type], + wifi_twt_operation_txt(params.operation), + wifi_twt_negotiation_type_txt(params.negotiation_type), wifi_twt_get_err_code_str(params.fail_reason)); return -ENOEXEC; } shell_fprintf(sh, SHELL_NORMAL, "TWT operation %s with dg: %d, flow_id: %d success\n", - wifi_twt_operation2str[params.operation], + wifi_twt_operation_txt(params.operation), params.dialog_token, params.flow_id); return 0; @@ -1073,15 +1291,15 @@ static int cmd_wifi_twt_teardown_all(const struct shell *sh, size_t argc, if (net_mgmt(NET_REQUEST_WIFI_TWT, iface, ¶ms, sizeof(params))) { shell_fprintf(sh, SHELL_WARNING, "%s with %s failed, reason : %s\n", - wifi_twt_operation2str[params.operation], - wifi_twt_negotiation_type2str[params.negotiation_type], + wifi_twt_operation_txt(params.operation), + wifi_twt_negotiation_type_txt(params.negotiation_type), wifi_twt_get_err_code_str(params.fail_reason)); return -ENOEXEC; } shell_fprintf(sh, SHELL_NORMAL, "TWT operation %s all flows success\n", - wifi_twt_operation2str[params.operation]); + wifi_twt_operation_txt(params.operation)); return 0; } @@ -1258,7 +1476,7 @@ static int cmd_wifi_ps_wakeup_mode(const struct shell *sh, size_t argc, char *ar } shell_fprintf(sh, SHELL_NORMAL, "%s\n", - wifi_ps_wakeup_mode2str[params.wakeup_mode]); + wifi_ps_wakeup_mode_txt(params.wakeup_mode)); return 0; } From 4a36c92e39aae11a7736b872dd9f0c8d34235af5 Mon Sep 17 00:00:00 2001 From: Kapil Bhatt Date: Thu, 28 Sep 2023 10:32:02 +0530 Subject: [PATCH 062/421] [nrf fromtree] net: wifi: Move function from shell to mgmt The CONFIG_NET_L2_WIFI_SHELL isn't always enabled. But these functions might still be used, so need to move functions into mgmt. Signed-off-by: Kapil Bhatt (cherry picked from commit 29bbcb1e38f84b505c7fe7e3f7ab4bb3497eea4c) (cherry picked from commit a47925f081693cfef963af4f29b2f9f0ccc80768) Signed-off-by: Dominik Ermel (cherry picked from commit ed131f28ebff3cce80390855dc02cce45d06adc6) --- subsys/net/l2/wifi/wifi_mgmt.c | 218 ++++++++++++++++++++++++++++++++ subsys/net/l2/wifi/wifi_shell.c | 218 -------------------------------- 2 files changed, 218 insertions(+), 218 deletions(-) diff --git a/subsys/net/l2/wifi/wifi_mgmt.c b/subsys/net/l2/wifi/wifi_mgmt.c index 7f0f30dc8c1..65457427bda 100644 --- a/subsys/net/l2/wifi/wifi_mgmt.c +++ b/subsys/net/l2/wifi/wifi_mgmt.c @@ -18,6 +18,224 @@ LOG_MODULE_REGISTER(net_wifi_mgmt, CONFIG_NET_L2_WIFI_MGMT_LOG_LEVEL); #include #endif /* CONFIG_WIFI_NM */ +const char * const wifi_security_txt(enum wifi_security_type security) +{ + switch (security) { + case WIFI_SECURITY_TYPE_NONE: + return "OPEN"; + case WIFI_SECURITY_TYPE_WEP: + return "WEP"; + case WIFI_SECURITY_TYPE_WPA_PSK: + return "WPA-PSK"; + case WIFI_SECURITY_TYPE_PSK: + return "WPA2-PSK"; + case WIFI_SECURITY_TYPE_PSK_SHA256: + return "WPA2-PSK-SHA256"; + case WIFI_SECURITY_TYPE_SAE: + return "WPA3-SAE"; + case WIFI_SECURITY_TYPE_WAPI: + return "WAPI"; + case WIFI_SECURITY_TYPE_EAP: + return "EAP"; + case WIFI_SECURITY_TYPE_UNKNOWN: + default: + return "UNKNOWN"; + } +} + +const char * const wifi_mfp_txt(enum wifi_mfp_options mfp) +{ + switch (mfp) { + case WIFI_MFP_DISABLE: + return "Disable"; + case WIFI_MFP_OPTIONAL: + return "Optional"; + case WIFI_MFP_REQUIRED: + return "Required"; + case WIFI_MFP_UNKNOWN: + default: + return "UNKNOWN"; + } +} + +const char * const wifi_band_txt(enum wifi_frequency_bands band) +{ + switch (band) { + case WIFI_FREQ_BAND_2_4_GHZ: + return "2.4GHz"; + case WIFI_FREQ_BAND_5_GHZ: + return "5GHz"; + case WIFI_FREQ_BAND_6_GHZ: + return "6GHz"; + case WIFI_FREQ_BAND_UNKNOWN: + default: + return "UNKNOWN"; + } +} + +const char * const wifi_state_txt(enum wifi_iface_state state) +{ + switch (state) { + case WIFI_STATE_DISCONNECTED: + return "DISCONNECTED"; + case WIFI_STATE_INACTIVE: + return "INACTIVE"; + case WIFI_STATE_INTERFACE_DISABLED: + return "INTERFACE_DISABLED"; + case WIFI_STATE_SCANNING: + return "SCANNING"; + case WIFI_STATE_AUTHENTICATING: + return "AUTHENTICATING"; + case WIFI_STATE_ASSOCIATING: + return "ASSOCIATING"; + case WIFI_STATE_ASSOCIATED: + return "ASSOCIATED"; + case WIFI_STATE_4WAY_HANDSHAKE: + return "4WAY_HANDSHAKE"; + case WIFI_STATE_GROUP_HANDSHAKE: + return "GROUP_HANDSHAKE"; + case WIFI_STATE_COMPLETED: + return "COMPLETED"; + case WIFI_STATE_UNKNOWN: + default: + return "UNKNOWN"; + } +} + +const char * const wifi_mode_txt(enum wifi_iface_mode mode) +{ + switch (mode) { + case WIFI_MODE_INFRA: + return "STATION"; + case WIFI_MODE_IBSS: + return "ADHOC"; + case WIFI_MODE_AP: + return "ACCESS POINT"; + case WIFI_MODE_P2P_GO: + return "P2P GROUP OWNER"; + case WIFI_MODE_P2P_GROUP_FORMATION: + return "P2P GROUP FORMATION"; + case WIFI_MODE_MESH: + return "MESH"; + case WIFI_MODE_UNKNOWN: + default: + return "UNKNOWN"; + } +} + +const char * const wifi_link_mode_txt(enum wifi_link_mode link_mode) +{ + switch (link_mode) { + case WIFI_0: + return "WIFI 0 (802.11)"; + case WIFI_1: + return "WIFI 1 (802.11b)"; + case WIFI_2: + return "WIFI 2 (802.11a)"; + case WIFI_3: + return "WIFI 3 (802.11g)"; + case WIFI_4: + return "WIFI 4 (802.11n/HT)"; + case WIFI_5: + return "WIFI 5 (802.11ac/VHT)"; + case WIFI_6: + return "WIFI 6 (802.11ax/HE)"; + case WIFI_6E: + return "WIFI 6E (802.11ax 6GHz/HE)"; + case WIFI_7: + return "WIFI 7 (802.11be/EHT)"; + case WIFI_LINK_MODE_UNKNOWN: + default: + return "UNKNOWN"; + } +} + +const char * const wifi_ps_txt(enum wifi_ps ps_name) +{ + switch (ps_name) { + case WIFI_PS_DISABLED: + return "Power save disabled"; + case WIFI_PS_ENABLED: + return "Power save enabled"; + default: + return "UNKNOWN"; + } +} + +const char * const wifi_ps_mode_txt(enum wifi_ps_mode ps_mode) +{ + switch (ps_mode) { + case WIFI_PS_MODE_LEGACY: + return "Legacy power save"; + case WIFI_PS_MODE_WMM: + return "WMM power save"; + default: + return "UNKNOWN"; + } +} + +const char * const wifi_twt_operation_txt(enum wifi_twt_operation twt_operation) +{ + switch (twt_operation) { + case WIFI_TWT_SETUP: + return "TWT setup"; + case WIFI_TWT_TEARDOWN: + return "TWT teardown"; + default: + return "UNKNOWN"; + } +} + +const char * const wifi_twt_negotiation_type_txt(enum wifi_twt_negotiation_type twt_negotiation) +{ + switch (twt_negotiation) { + case WIFI_TWT_INDIVIDUAL: + return "TWT individual negotiation"; + case WIFI_TWT_BROADCAST: + return "TWT broadcast negotiation"; + case WIFI_TWT_WAKE_TBTT: + return "TWT wake TBTT negotiation"; + default: + return "UNKNOWN"; + } +} + +const char * const wifi_twt_setup_cmd_txt(enum wifi_twt_setup_cmd twt_setup) +{ + switch (twt_setup) { + case WIFI_TWT_SETUP_CMD_REQUEST: + return "TWT request"; + case WIFI_TWT_SETUP_CMD_SUGGEST: + return "TWT suggest"; + case WIFI_TWT_SETUP_CMD_DEMAND: + return "TWT demand"; + case WIFI_TWT_SETUP_CMD_GROUPING: + return "TWT grouping"; + case WIFI_TWT_SETUP_CMD_ACCEPT: + return "TWT accept"; + case WIFI_TWT_SETUP_CMD_ALTERNATE: + return "TWT alternate"; + case WIFI_TWT_SETUP_CMD_DICTATE: + return "TWT dictate"; + case WIFI_TWT_SETUP_CMD_REJECT: + return "TWT reject"; + default: + return "UNKNOWN"; + } +} + +const char * const wifi_ps_wakeup_mode_txt(enum wifi_ps_wakeup_mode ps_wakeup_mode) +{ + switch (ps_wakeup_mode) { + case WIFI_PS_WAKEUP_MODE_DTIM: + return "PS wakeup mode DTIM"; + case WIFI_PS_WAKEUP_MODE_LISTEN_INTERVAL: + return "PS wakeup mode listen interval"; + default: + return "UNKNOWN"; + } +} + static const struct wifi_mgmt_ops *const get_wifi_api(struct net_if *iface) { const struct device *dev = net_if_get_device(iface); diff --git a/subsys/net/l2/wifi/wifi_shell.c b/subsys/net/l2/wifi/wifi_shell.c index 74284e56e98..7472d3fa984 100644 --- a/subsys/net/l2/wifi/wifi_shell.c +++ b/subsys/net/l2/wifi/wifi_shell.c @@ -97,224 +97,6 @@ static bool parse_number(const struct shell *sh, long *param, char *str, long mi return true; } -const char * const wifi_security_txt(enum wifi_security_type security) -{ - switch (security) { - case WIFI_SECURITY_TYPE_NONE: - return "OPEN"; - case WIFI_SECURITY_TYPE_WEP: - return "WEP"; - case WIFI_SECURITY_TYPE_WPA_PSK: - return "WPA-PSK"; - case WIFI_SECURITY_TYPE_PSK: - return "WPA2-PSK"; - case WIFI_SECURITY_TYPE_PSK_SHA256: - return "WPA2-PSK-SHA256"; - case WIFI_SECURITY_TYPE_SAE: - return "WPA3-SAE"; - case WIFI_SECURITY_TYPE_WAPI: - return "WAPI"; - case WIFI_SECURITY_TYPE_EAP: - return "EAP"; - case WIFI_SECURITY_TYPE_UNKNOWN: - default: - return "UNKNOWN"; - } -} - -const char * const wifi_mfp_txt(enum wifi_mfp_options mfp) -{ - switch (mfp) { - case WIFI_MFP_DISABLE: - return "Disable"; - case WIFI_MFP_OPTIONAL: - return "Optional"; - case WIFI_MFP_REQUIRED: - return "Required"; - case WIFI_MFP_UNKNOWN: - default: - return "UNKNOWN"; - } -} - -const char * const wifi_band_txt(enum wifi_frequency_bands band) -{ - switch (band) { - case WIFI_FREQ_BAND_2_4_GHZ: - return "2.4GHz"; - case WIFI_FREQ_BAND_5_GHZ: - return "5GHz"; - case WIFI_FREQ_BAND_6_GHZ: - return "6GHz"; - case WIFI_FREQ_BAND_UNKNOWN: - default: - return "UNKNOWN"; - } -} - -const char * const wifi_state_txt(enum wifi_iface_state state) -{ - switch (state) { - case WIFI_STATE_DISCONNECTED: - return "DISCONNECTED"; - case WIFI_STATE_INACTIVE: - return "INACTIVE"; - case WIFI_STATE_INTERFACE_DISABLED: - return "INTERFACE_DISABLED"; - case WIFI_STATE_SCANNING: - return "SCANNING"; - case WIFI_STATE_AUTHENTICATING: - return "AUTHENTICATING"; - case WIFI_STATE_ASSOCIATING: - return "ASSOCIATING"; - case WIFI_STATE_ASSOCIATED: - return "ASSOCIATED"; - case WIFI_STATE_4WAY_HANDSHAKE: - return "4WAY_HANDSHAKE"; - case WIFI_STATE_GROUP_HANDSHAKE: - return "GROUP_HANDSHAKE"; - case WIFI_STATE_COMPLETED: - return "COMPLETED"; - case WIFI_STATE_UNKNOWN: - default: - return "UNKNOWN"; - } -} - -const char * const wifi_mode_txt(enum wifi_iface_mode mode) -{ - switch (mode) { - case WIFI_MODE_INFRA: - return "STATION"; - case WIFI_MODE_IBSS: - return "ADHOC"; - case WIFI_MODE_AP: - return "ACCESS POINT"; - case WIFI_MODE_P2P_GO: - return "P2P GROUP OWNER"; - case WIFI_MODE_P2P_GROUP_FORMATION: - return "P2P GROUP FORMATION"; - case WIFI_MODE_MESH: - return "MESH"; - case WIFI_MODE_UNKNOWN: - default: - return "UNKNOWN"; - } -} - -const char * const wifi_link_mode_txt(enum wifi_link_mode link_mode) -{ - switch (link_mode) { - case WIFI_0: - return "WIFI 0 (802.11)"; - case WIFI_1: - return "WIFI 1 (802.11b)"; - case WIFI_2: - return "WIFI 2 (802.11a)"; - case WIFI_3: - return "WIFI 3 (802.11g)"; - case WIFI_4: - return "WIFI 4 (802.11n/HT)"; - case WIFI_5: - return "WIFI 5 (802.11ac/VHT)"; - case WIFI_6: - return "WIFI 6 (802.11ax/HE)"; - case WIFI_6E: - return "WIFI 6E (802.11ax 6GHz/HE)"; - case WIFI_7: - return "WIFI 7 (802.11be/EHT)"; - case WIFI_LINK_MODE_UNKNOWN: - default: - return "UNKNOWN"; - } -} - -const char * const wifi_ps_txt(enum wifi_ps ps_name) -{ - switch (ps_name) { - case WIFI_PS_DISABLED: - return "Power save disabled"; - case WIFI_PS_ENABLED: - return "Power save enabled"; - default: - return "UNKNOWN"; - } -} - -const char * const wifi_ps_mode_txt(enum wifi_ps_mode ps_mode) -{ - switch (ps_mode) { - case WIFI_PS_MODE_LEGACY: - return "Legacy power save"; - case WIFI_PS_MODE_WMM: - return "WMM power save"; - default: - return "UNKNOWN"; - } -} - -const char * const wifi_twt_operation_txt(enum wifi_twt_operation twt_operation) -{ - switch (twt_operation) { - case WIFI_TWT_SETUP: - return "TWT setup"; - case WIFI_TWT_TEARDOWN: - return "TWT teardown"; - default: - return "UNKNOWN"; - } -} - -const char * const wifi_twt_negotiation_type_txt(enum wifi_twt_negotiation_type twt_negotiation) -{ - switch (twt_negotiation) { - case WIFI_TWT_INDIVIDUAL: - return "TWT individual negotiation"; - case WIFI_TWT_BROADCAST: - return "TWT broadcast negotiation"; - case WIFI_TWT_WAKE_TBTT: - return "TWT wake TBTT negotiation"; - default: - return "UNKNOWN"; - } -} - -const char * const wifi_twt_setup_cmd_txt(enum wifi_twt_setup_cmd twt_setup) -{ - switch (twt_setup) { - case WIFI_TWT_SETUP_CMD_REQUEST: - return "TWT request"; - case WIFI_TWT_SETUP_CMD_SUGGEST: - return "TWT suggest"; - case WIFI_TWT_SETUP_CMD_DEMAND: - return "TWT demand"; - case WIFI_TWT_SETUP_CMD_GROUPING: - return "TWT grouping"; - case WIFI_TWT_SETUP_CMD_ACCEPT: - return "TWT accept"; - case WIFI_TWT_SETUP_CMD_ALTERNATE: - return "TWT alternate"; - case WIFI_TWT_SETUP_CMD_DICTATE: - return "TWT dictate"; - case WIFI_TWT_SETUP_CMD_REJECT: - return "TWT reject"; - default: - return "UNKNOWN"; - } -} - -const char * const wifi_ps_wakeup_mode_txt(enum wifi_ps_wakeup_mode ps_wakeup_mode) -{ - switch (ps_wakeup_mode) { - case WIFI_PS_WAKEUP_MODE_DTIM: - return "PS wakeup mode DTIM"; - case WIFI_PS_WAKEUP_MODE_LISTEN_INTERVAL: - return "PS wakeup mode listen interval"; - default: - return "UNKNOWN"; - } -} - static void handle_wifi_scan_result(struct net_mgmt_event_callback *cb) { const struct wifi_scan_result *entry = From 2069e2a621432e875a488200ef7a4d95285f5864 Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Tue, 5 Sep 2023 12:44:50 +0530 Subject: [PATCH 063/421] [nrf fromtree] Bluetooth: Controller: Fix missing PHY_CODED cond compile Fix missing Coded PHY implementation conditional compile causing compile error when disabling Coded PHY support in SoCs that have radio that support Coded PHY. Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit e8fe144f3a0209569ea661520b65dee20e767c12) Signed-off-by: Dominik Ermel (cherry picked from commit 120b33f965d46bbedbf4e4e08e521fec64f432dc) --- samples/bluetooth/hci_rpmsg/sample.yaml | 10 ++++++++++ .../ll_sw/nordic/hal/nrf5/radio/radio_nrf5_dppi.h | 2 ++ 2 files changed, 12 insertions(+) diff --git a/samples/bluetooth/hci_rpmsg/sample.yaml b/samples/bluetooth/hci_rpmsg/sample.yaml index 3330002a59d..7cecb12be67 100644 --- a/samples/bluetooth/hci_rpmsg/sample.yaml +++ b/samples/bluetooth/hci_rpmsg/sample.yaml @@ -82,6 +82,16 @@ tests: platform_allow: nrf5340dk_nrf5340_cpunet integration_platforms: - nrf5340dk_nrf5340_cpunet + sample.bluetooth.hci_rpmsg.df.no_phy_coded.bt_ll_sw_split: + harness: bluetooth + tags: bluetooth + extra_args: + - CONF_FILE="nrf5340_cpunet_df-bt_ll_sw_split.conf" + - DTC_OVERLAY_FILE="nrf5340_cpunet_df-bt_ll_sw_split.overlay" + - CONFIG_BT_CTLR_PHY_CODED=n + platform_allow: nrf5340dk_nrf5340_cpunet + integration_platforms: + - nrf5340dk_nrf5340_cpunet sample.bluetooth.hci_rpmsg.mesh.bt_ll_sw_split: harness: bluetooth tags: bluetooth diff --git a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5_dppi.h b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5_dppi.h index 085b881d47e..71e5ffa0e6f 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5_dppi.h +++ b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5_dppi.h @@ -582,6 +582,7 @@ static inline void hal_radio_sw_switch_coded_tx_config_set(uint8_t ppi_en, BIT(HAL_SW_SWITCH_TIMER_S8_DISABLE_PPI)); } +#if defined(CONFIG_BT_CTLR_PHY_CODED) && defined(CONFIG_HAS_HW_NRF_RADIO_BLE_CODED) static inline void hal_radio_sw_switch_coded_config_clear(uint8_t ppi_en, uint8_t ppi_dis, uint8_t cc_reg, uint8_t group_index) { @@ -594,6 +595,7 @@ static inline void hal_radio_sw_switch_coded_config_clear(uint8_t ppi_en, HAL_SW_SWITCH_RADIO_ENABLE_PPI_REGISTER_EVT( SW_SWITCH_TIMER_S2_EVTS_COMP(group_index)) = 0; } +#endif /* CONFIG_BT_CTLR_PHY_CODED && CONFIG_HAS_HW_NRF_RADIO_BLE_CODED */ static inline void hal_radio_sw_switch_disable_group_clear(uint8_t ppi_dis, uint8_t cc_reg, uint8_t group_index) From 61e999db7b38eff9939f51860a0a2e2a7fe87138 Mon Sep 17 00:00:00 2001 From: Huifeng Zhang Date: Fri, 8 Sep 2023 13:31:24 +0800 Subject: [PATCH 064/421] [nrf fromtree] tests: net: lib: lwm2m: fix the missing float support The tests `content_json` and `content_plain_test` depend on the float support of libc. After PR##57340, Picolibc would be selected in these two tests and the `PICOLIBC_IO_FLOAT` won't be selected if the platform doesn't select `FPU`. This commit select `CONFIG_PICOLIBC` and `CONFIG_PICOLIBC_IO_FLOAT` for these two tests. Signed-off-by: Huifeng Zhang (cherry picked from commit 5a1a1fe13d88c6429d2cf80975aaea3302441ce1) Signed-off-by: Dominik Ermel (cherry picked from commit fb04730a55116fb950719b81823acc0b41e7f98c) --- tests/net/lib/lwm2m/content_json/prj.conf | 2 ++ tests/net/lib/lwm2m/content_plain_text/prj.conf | 2 ++ 2 files changed, 4 insertions(+) diff --git a/tests/net/lib/lwm2m/content_json/prj.conf b/tests/net/lib/lwm2m/content_json/prj.conf index 3f2cd3e60f2..7ff07df9897 100644 --- a/tests/net/lib/lwm2m/content_json/prj.conf +++ b/tests/net/lib/lwm2m/content_json/prj.conf @@ -9,3 +9,5 @@ CONFIG_LWM2M=y CONFIG_LWM2M_COAP_MAX_MSG_SIZE=512 CONFIG_LWM2M_RW_JSON_SUPPORT=y CONFIG_JSON_LIBRARY=y + +CONFIG_PICOLIBC_IO_FLOAT=y diff --git a/tests/net/lib/lwm2m/content_plain_text/prj.conf b/tests/net/lib/lwm2m/content_plain_text/prj.conf index 6041addad83..877c969958f 100644 --- a/tests/net/lib/lwm2m/content_plain_text/prj.conf +++ b/tests/net/lib/lwm2m/content_plain_text/prj.conf @@ -6,3 +6,5 @@ CONFIG_ZTEST_NEW_API=y CONFIG_ENTROPY_GENERATOR=y CONFIG_TEST_RANDOM_GENERATOR=y CONFIG_LWM2M=y + +CONFIG_PICOLIBC_IO_FLOAT=y From 350e687dd5c75ac574fbea06200b8f02b854a7c7 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Wed, 27 Sep 2023 09:41:10 +0000 Subject: [PATCH 065/421] [nrf noup] test: schedule_api: Use Minimal C library There is no point to use PICOLIB here as it bloats the tests. Signed-off-by: Dominik Ermel (cherry picked from commit a52d1de722821b61f3338d9955015777489bf1e5) --- tests/kernel/sched/schedule_api/prj.conf | 1 + tests/kernel/sched/schedule_api/prj_dumb.conf | 1 + tests/kernel/sched/schedule_api/prj_multiq.conf | 1 + 3 files changed, 3 insertions(+) diff --git a/tests/kernel/sched/schedule_api/prj.conf b/tests/kernel/sched/schedule_api/prj.conf index b24271c4232..4178dc560a9 100644 --- a/tests/kernel/sched/schedule_api/prj.conf +++ b/tests/kernel/sched/schedule_api/prj.conf @@ -8,3 +8,4 @@ CONFIG_MAX_THREAD_BYTES=5 CONFIG_TEST_USERSPACE=y CONFIG_MP_MAX_NUM_CPUS=1 CONFIG_ZTEST_FATAL_HOOK=y +CONFIG_MINIMAL_LIBC=y diff --git a/tests/kernel/sched/schedule_api/prj_dumb.conf b/tests/kernel/sched/schedule_api/prj_dumb.conf index 9d996d2c9fb..5331db2daed 100644 --- a/tests/kernel/sched/schedule_api/prj_dumb.conf +++ b/tests/kernel/sched/schedule_api/prj_dumb.conf @@ -6,3 +6,4 @@ CONFIG_SCHED_DUMB=y CONFIG_MAX_THREAD_BYTES=5 CONFIG_MP_MAX_NUM_CPUS=1 CONFIG_ZTEST_FATAL_HOOK=y +CONFIG_MINIMAL_LIBC=y diff --git a/tests/kernel/sched/schedule_api/prj_multiq.conf b/tests/kernel/sched/schedule_api/prj_multiq.conf index d1074c07585..0c37654fd60 100644 --- a/tests/kernel/sched/schedule_api/prj_multiq.conf +++ b/tests/kernel/sched/schedule_api/prj_multiq.conf @@ -6,3 +6,4 @@ CONFIG_SCHED_MULTIQ=y CONFIG_MAX_THREAD_BYTES=5 CONFIG_MP_MAX_NUM_CPUS=1 CONFIG_ZTEST_FATAL_HOOK=y +CONFIG_MINIMAL_LIBC=y From 7ff9fc19e1337526ed731f643d716ddcc55c9e9a Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Tue, 26 Sep 2023 14:36:51 +0000 Subject: [PATCH 066/421] [nrf fromlist] Bluetooth: Host: Use memcpy instad of strncpy in bt_set_name memcpy makes more sense here. Upstream PR: https://github.com/zephyrproject-rtos/zephyr/pull/63112 Signed-off-by: Dominik Ermel (cherry picked from commit 1866b939dd15ec88d0e78f3a5fa57290bcc0b6db) --- subsys/bluetooth/host/hci_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subsys/bluetooth/host/hci_core.c b/subsys/bluetooth/host/hci_core.c index b3a7e05891a..8e1227c0bf5 100644 --- a/subsys/bluetooth/host/hci_core.c +++ b/subsys/bluetooth/host/hci_core.c @@ -4110,7 +4110,7 @@ int bt_set_name(const char *name) return 0; } - strncpy(bt_dev.name, name, len); + memcpy(bt_dev.name, name, len); bt_dev.name[len] = '\0'; if (IS_ENABLED(CONFIG_BT_SETTINGS)) { From 0985ab67282f633fe616fb499248c225a75cfe24 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mo=C5=84?= Date: Mon, 25 Sep 2023 08:42:00 +0200 Subject: [PATCH 067/421] [nrf fromtree] manifest: hal_nordic: update to prevent USBD bad DMA MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The bad DMA request was observed as SPU FLASHACCERR when building for nrf5340dk_nrf5340_cpuapp_ns target. The bad DMA request would manifest itself as device failing to reconnect after USB cable was reconnected. The issue was especially visible with CDC ACM sample because SET LINE CODING request has 7 bytes payload. (cherry picked from commit c796e1bee2e312ede01f6889539e6fb4bcceb8d4) Signed-off-by: Tomasz Moń (cherry picked from commit c2572c301f24bc9ae799519ea74dcd68a7b085c7) --- west.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/west.yml b/west.yml index 727d6d807ab..b4f874a87c5 100644 --- a/west.yml +++ b/west.yml @@ -183,7 +183,7 @@ manifest: groups: - hal - name: hal_nordic - revision: 9ae7c765985ebdea3d9b98c0d3b154794f0b47cf + revision: 092eb78ed1b1551d8f480019b9c05d7371784578 path: modules/hal/nordic groups: - hal From 6799c02cb60196ac26ebc1c1aeee54ca105f8e75 Mon Sep 17 00:00:00 2001 From: Mateusz Kapala Date: Fri, 1 Sep 2023 16:52:55 +0200 Subject: [PATCH 068/421] [nrf noup] boards: arm: thingy53: Fix MCUBOOT_USB_SUPPORT def Add missing MCUBOOT_USB_SUPPORT Kconfig type to fix doc build. Signed-off-by: Mateusz Kapala (cherry picked from commit fe27a31ba8bee739590183133f54938c2fe87796) --- boards/arm/thingy53_nrf5340/Kconfig.defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/boards/arm/thingy53_nrf5340/Kconfig.defconfig b/boards/arm/thingy53_nrf5340/Kconfig.defconfig index c79eb908c21..ec17fcff34a 100644 --- a/boards/arm/thingy53_nrf5340/Kconfig.defconfig +++ b/boards/arm/thingy53_nrf5340/Kconfig.defconfig @@ -160,6 +160,7 @@ endif # BOARD_SERIAL_BACKEND_CDC_ACM # It is not necessary for nRF Connect SDK to add another instance if MCUBoot # bootloader is built as a child image. config MCUBOOT_USB_SUPPORT + bool default n endif # BOARD_THINGY53_NRF5340_CPUAPP || BOARD_THINGY53_NRF5340_CPUAPP_NS From 2e321f2c6155adc5d32142a5235bd72ea55df2c3 Mon Sep 17 00:00:00 2001 From: Yves Vandervennet Date: Fri, 1 Sep 2023 11:41:36 -0500 Subject: [PATCH 069/421] [nrf fromtree] linkserver: doc: updates for NXP's mimxrt1170 This commit adds the documentation details for the linkserver support on rt1170. Signed-off-by: Yves Vandervennet (cherry picked from commit 1477865a7a1ee6c1a869265d949ab63669dfe597) Signed-off-by: Dominik Ermel (cherry picked from commit 254c933b4e4722cdf0e9a3595f65e7ed4f2e5b17) --- boards/arm/mimxrt1170_evk/doc/index.rst | 102 ++++++++++++++++-------- doc/develop/flash_debug/host-tools.rst | 25 ++++-- doc/develop/flash_debug/probes.rst | 61 ++++++++++++++ 3 files changed, 148 insertions(+), 40 deletions(-) diff --git a/boards/arm/mimxrt1170_evk/doc/index.rst b/boards/arm/mimxrt1170_evk/doc/index.rst index 90f192c3870..51d5053e360 100644 --- a/boards/arm/mimxrt1170_evk/doc/index.rst +++ b/boards/arm/mimxrt1170_evk/doc/index.rst @@ -1,4 +1,4 @@ -.. _mimxrt1170_evk: +.. _mimxrt1170_evk: NXP MIMXRT1170-EVK/EVKB ####################### @@ -9,7 +9,7 @@ Overview The dual core i.MX RT1170 runs on the Cortex-M7 core at 1 GHz and on the Cortex-M4 at 400 MHz. The i.MX RT1170 MCU offers support over a wide temperature range and is qualified for consumer, industrial and automotive markets. Zephyr -supports the initial revision of this EVK, as well as EVK rev B. +supports the initial revision of this EVK, as well as rev EVKB. .. image:: mimxrt1170_evk.jpg :align: center @@ -59,7 +59,7 @@ Hardware - Debug - JTAG 20-pin connector - - OpenSDA with DAPLink + - on-board debugger - Sensor @@ -90,16 +90,17 @@ This platform has the following external memories: | Device | Controller | Status | +====================+============+=====================================+ | W9825G6KH | SEMC | Enabled via device configuration | -| | | data block, which sets up SEMC at | -| | | boot time | +| SDRAM | | data (DCD) block, which sets up | +| | | the SEMC at boot time | +--------------------+------------+-------------------------------------+ -| IS25WP128 | FLEXSPI | Enabled via flash configurationn | -| (RT1170 EVK) | | block, which sets up FLEXSPI at | -| | | boot time. | +| IS25WP128 | FLEXSPI | Enabled via flash configuration | +| QSPI flash | | block (FCB), which sets up the | +| (RT1170 EVK) | | FLEXSPI at boot time. | +--------------------+------------+-------------------------------------+ -| W25Q512NWEIQ | FLEXSPI | Enabled via flash configurationn | -| (RT1170 EVKB) | | block, which sets up FLEXSPI at | -| | | boot time. Supported for XIP only. | +| W25Q512NWEIQ | FLEXSPI | Enabled via flash configuration | +| QSPI flash | | block (FCB), which sets up the | +| (RT1170 EVKB) | | FLEXSPI at boot time. Supported for | +| | | XIP only. | +--------------------+------------+-------------------------------------+ Supported Features @@ -123,6 +124,8 @@ RT1170 EVKB (`mimxrt1170_evkb_cm7/cm4`) +-----------+------------+-------------------------------------+-----------------+-----------------+ | COUNTER | on-chip | gpt | Supported | Supported | +-----------+------------+-------------------------------------+-----------------+-----------------+ +| TIMER | on-chip | gpt | Supported | Supported | ++-----------+------------+-------------------------------------+-----------------+-----------------+ | CAN | on-chip | flexcan | Supported (M7) | Supported (M7) | +-----------+------------+-------------------------------------+-----------------+-----------------+ | SPI | on-chip | spi | Supported (M7) | Supported | @@ -139,11 +142,10 @@ RT1170 EVKB (`mimxrt1170_evkb_cm7/cm4`) +-----------+------------+-------------------------------------+-----------------+-----------------+ | DMA | on-chip | dma | Supported | Supported | +-----------+------------+-------------------------------------+-----------------+-----------------+ -| GPT | on-chip | gpt | Supported | Supported | -+-----------+------------+-------------------------------------+-----------------+-----------------+ | WATCHDOG | on-chip | watchdog | Supported (M7) | Supported (M7) | +-----------+------------+-------------------------------------+-----------------+-----------------+ -| ENET | on-chip | ethernet | Supported (M7) | No support | +| ENET | on-chip | ethernet - 10/100M (ENET_QOS or | Supported (M7) | No support | +| ENET1G | | GigE not supported yet) | | | +-----------+------------+-------------------------------------+-----------------+-----------------+ | SAI | on-chip | i2s | Supported | No support | +-----------+------------+-------------------------------------+-----------------+-----------------+ @@ -165,10 +167,9 @@ RT1170 EVKB (`mimxrt1170_evkb_cm7/cm4`) | SDHC | on-chip | SD host controller | Supported (M7) | Supported (M7) | +-----------+------------+-------------------------------------+-----------------+-----------------+ -The default configuration can be found in the defconfig file: +The default configuration can be found in the defconfig files: ``boards/arm/mimxrt1170_evk/mimxrt1170_evk_cm7_defconfig`` - -Other hardware features are not currently supported by the port. +``boards/arm/mimxrt1170_evk/mimxrt1170_evkb_cm7_defconfig`` Connections and I/Os ==================== @@ -310,33 +311,62 @@ secondary core should be placed into a loop, then a debugger can be attached Configuring a Debug Probe ========================= -A debug probe is used for both flashing and debugging the board. This board is -configured by default to use the :ref:`opensda-daplink-onboard-debug-probe`, -however the :ref:`pyocd-debug-host-tools` do not yet support programming the -external flashes on this board so you must reconfigure the board for one of the -following debug probes instead. +A debug probe is used for both flashing and debugging the board. The on-board +debugger listed below works with the LinkServer runner by default, or can be +reprogrammed with JLink firmware. +- MIMXRT1170-EVKB: :ref:`mcu-link-cmsis-onboard-debug-probe` +- MIMXRT1170-EVK: :ref:`opensda-daplink-onboard-debug-probe` .. _Using J-Link RT1170: Using J-Link --------------------------------- -Install the :ref:`jlink-debug-host-tools` and make sure they are in your search -path. +JLink is the default runner for this board. Install the +:ref:`jlink-debug-host-tools` and make sure they are in your search path. There are two options: the onboard debug circuit can be updated with Segger J-Link firmware, or :ref:`jlink-external-debug-probe` can be attached to the -EVK. See `Using J-Link with MIMXRT1160-EVK or MIMXRT1170-EVK`_ for more details. +EVK. See `Using J-Link with MIMXRT1170-EVKB`_ or +`Using J-Link with MIMXRT1160-EVK or MIMXRT1170-EVK`_ for more details. + +.. _Using LinkServer RT1170: + +Using LinkServer +---------------------------------- + +Known limitations with LinkServer and these boards include: +- ``west debug`` does not yet work correctly, and the application image is not +properly written to the memory. `NXP MCUXpresso for Visual Studio Code`_ +can be used to debug Zephyr applications with LinkServer. +- ``west flash`` will not write images to non-flash locations. The flash +command only works when all data in the image is written to flash memory +regions. + +Install the :ref:`linkserver-debug-host-tools` and make sure they are in your +search path. LinkServer works with the default CMSIS-DAP firmware included in +the on-board debugger. + +Use the ``-r linkserver`` option with West to use the LinkServer runner. + +.. code-block:: console + + west flash -r linkserver + Configuring a Console ===================== -Regardless of your choice in debug probe, we will use the OpenSDA -microcontroller as a usb-to-serial adapter for the serial console. Check that -jumpers J5 and J8 are **on** (they are on by default when boards ship from -the factory) to connect UART signals to the OpenSDA microcontroller. +We will use the on-board debugger +microcontroller as a usb-to-serial adapter for the serial console. The following +jumper settings are default on these boards, and are required to connect the +UART signals to the USB bridge circuit: +- MIMXRT1170-EVKB: JP2 open (default) +- MIMXRT1170-EVK: J31 and J32 shorted (default) -Connect a USB cable from your PC to J11. +Connect a USB cable from your PC to the on-board debugger USB port: +- MIMXRT1170-EVKB: J86 +- MIMXRT1170-EVK: J11 Use the following settings with your serial terminal of choice (minicom, putty, etc.): @@ -351,7 +381,7 @@ Flashing Here is an example for the :ref:`hello_world` application. -Before power on the board, make sure SW1 is set to 0001b +Before powering the board, make sure SW1 is set to 0001b .. zephyr-app-commands:: :zephyr-app: samples/hello_world @@ -364,7 +394,7 @@ see the following message in the terminal: .. code-block:: console - ***** Booting Zephyr OS v2.4.0-xxxx-xxxxxxxxxxxxx ***** + ***** Booting Zephyr OS v3.4.0-xxxx-xxxxxxxxxxxxx ***** Hello World! mimxrt1170_evk_cm7 Debugging @@ -382,7 +412,7 @@ should see the following message in the terminal: .. code-block:: console - ***** Booting Zephyr OS v2.4.0-xxxx-xxxxxxxxxxxxx ***** + ***** Booting Zephyr OS v3.4.0-xxxx-xxxxxxxxxxxxx ***** Hello World! mimxrt1170_evk_cm7 .. _MIMXRT1170-EVK Website: @@ -403,5 +433,11 @@ should see the following message in the terminal: .. _Using J-Link with MIMXRT1160-EVK or MIMXRT1170-EVK: https://community.nxp.com/t5/i-MX-RT-Knowledge-Base/Using-J-Link-with-MIMXRT1160-EVK-or-MIMXRT1170-EVK/ta-p/1529760 +.. _Using J-Link with MIMXRT1170-EVKB: + https://community.nxp.com/t5/i-MX-RT-Knowledge-Base/Using-J-Link-with-MIMXRT1170-EVKB/ta-p/1715138 + .. _AN13264: https://www.nxp.com/docs/en/application-note/AN13264.pdf + +.. _NXP MCUXpresso for Visual Studio Code: + https://www.nxp.com/design/software/development-software/mcuxpresso-software-and-tools-/mcuxpresso-for-visual-studio-code:MCUXPRESSO-VSC diff --git a/doc/develop/flash_debug/host-tools.rst b/doc/develop/flash_debug/host-tools.rst index e93ee618f55..981c89ce686 100644 --- a/doc/develop/flash_debug/host-tools.rst +++ b/doc/develop/flash_debug/host-tools.rst @@ -206,17 +206,20 @@ LinkServer Debug Host Tools Linkserver is a utility for launching and managing GDB servers for NXP debug probes, which also provides a command-line target flash programming capabilities. -Linkserver can be used with NXP MCUXpresso for Visual Studio Code implementation, +Linkserver can be used with the `NXP MCUXpresso for Visual Studio Code`_ implementation, with custom debug configurations based on GNU tools or as part of a headless solution -for continuous integration and test. Linkserver can be used with MCU-Link, LPC-Link2, +for continuous integration and test. LinkServer can be used with MCU-Link, LPC-Link2, LPC11U35-based and OpenSDA based standalone or on-board debug probes from NXP. -The Linkserver installer also includes the firmware update utilities for MCU-Link and -the LPCScrypt utility for use with LPC-Link2. Linkserver can also be installed using -the MCUXpresso Installer. + +NXP recommends installing LinkServer by using NXP's `MCUXpresso Installer`_. +This method will also install the tools supporting the debug probes below, +including NXP's MCU-Link and LPCScrypt tools. LinkServer is compatible with the following debug probes: - :ref:`lpclink2-cmsis-onboard-debug-probe` +- :ref:`mcu-link-cmsis-onboard-debug-probe` +- :ref:`opensda-daplink-onboard-debug-probe` Supported west commands: @@ -234,13 +237,14 @@ Notes: LinkServer probes -2. Use the LinkServer west runner ``--probe`` option to pass the probe index. +2. With multiple debug probes attached to the host, use the +LinkServer west runner ``--probe`` option to pass the probe index. .. code-block:: console west flash --runner=linkserver --probe=3 -3. device specific settings can be overridden with the west runner for LinkServer with +3. Device-specific settings can be overridden with the west runner for LinkServer with the option '--override'. May be used multiple times. The format is dictated by LinkServer, e.g.: @@ -265,6 +269,7 @@ These debug host tools are compatible with the following debug probes: - :ref:`lpclink2-jlink-onboard-debug-probe` - :ref:`opensda-jlink-onboard-debug-probe` +- :ref:`mcu-link-jlink-onboard-debug-probe` - :ref:`jlink-external-debug-probe` - :ref:`stlink-v21-onboard-debug-probe` @@ -405,3 +410,9 @@ To enable Zephyr RTOS awareness follow the steps described in .. _BOSSA official releases: https://github.com/shumatech/BOSSA/releases + +.. _NXP MCUXpresso for Visual Studio Code: + https://www.nxp.com/design/software/development-software/mcuxpresso-software-and-tools-/mcuxpresso-for-visual-studio-code:MCUXPRESSO-VSC + +.. _MCUXpresso Installer: + https://www.nxp.com/lgfiles/updates/mcuxpresso/MCUXpressoInstaller.exe diff --git a/doc/develop/flash_debug/probes.rst b/doc/develop/flash_debug/probes.rst index 78a068d6ac4..83f355aadba 100644 --- a/doc/develop/flash_debug/probes.rst +++ b/doc/develop/flash_debug/probes.rst @@ -58,6 +58,64 @@ onboard debug probe may have limitations, such as lack of support for advanced debuggers or high-speed tracing. You may need to adjust jumpers to prevent the onboard debug probe from interfering with the external debug probe. +.. _mcu-link-cmsis-onboard-debug-probe: + +MCU-Link CMSIS-DAP Onboard Debug Probe +*************************************** + +The CMSIS-DAP debug probes allow debugging from any compatible toolchain, +including IAR EWARM, Keil MDK, NXP’s MCUXpresso IDE and +MCUXpresso extension for VS Code. In addition to debug probe functionality, the +MCU-Link probes may also provide: + +1. SWO trace end point: this virtual device is used by MCUXpresso to retrieve + SWO trace data. See the MCUXpresso IDE documentation for more information. +#. Virtual COM (VCOM) port / UART bridge connected to the target processor +#. USB to UART, SPI and/or I2C interfaces (depending on MCU-Link + type/implementation) +#. Energy measurements of the target MCU + +This debug probe is compatible with the following debug host tools: + +- :ref:`linkserver-debug-host-tools` + +This probe is realized by programming the MCU-Link microcontroller with the +CMSIS-DAP MCU-Link firmware, which is already installed by default. NXP +recommends using NXP's `MCUXpresso Installer`_, which installs both the MCU-Link +host tools plus the :ref:`linkserver-debug-host-tools`. + +1. Put the MCU-Link microcontroller into DFU boot mode by attaching the DFU + jumper, then powering up the board. + +#. Run the ``program_CMSIS`` script, found in the installed MCU-Link ``scripts`` + folder. + +#. Remove the DFU jumper and power cycle the board. + +.. _mcu-link-jlink-onboard-debug-probe: + +MCU-Link JLink Onboard Debug Probe +************************************ + +The MCU-Link J-Link is an onboard debug probe and usb-to-serial adapter +supported on many NXP development boards. + +This debug probe is compatible with the following debug host tools: + +- :ref:`jlink-debug-host-tools` + +These probes do not have JLink firmware installed by default, and must be +updated. NXP recommends using NXP's `MCUXpresso Installer`_, which installs both +the :ref:`jlink-debug-host-tools` plus the MCU-Link host tools. + +1. Put the MCU-Link microcontroller into DFU boot mode by attaching the DFU + jumper, then powering up the board. + +#. Run the ``program_JLINK`` script, found in the installed MCU-Link ``scripts`` + folder. + +#. Remove the DFU jumper and power cycle the board. + .. _lpclink2-cmsis-onboard-debug-probe: LPC-LINK2 CMSIS DAP Onboard Debug Probe @@ -341,3 +399,6 @@ option. For more information about twister and available options, see .. _STM32CubeProgrammer Tool: https://www.st.com/en/development-tools/stm32cubeprog.html + +.. _MCUXpresso Installer: + https://www.nxp.com/lgfiles/updates/mcuxpresso/MCUXpressoInstaller.exe From 3f54ea307c5d2ff2b956ecb191a3bba57e457b63 Mon Sep 17 00:00:00 2001 From: Gerard Marull-Paretas Date: Thu, 7 Sep 2023 12:15:29 +0200 Subject: [PATCH 070/421] [nrf fromtree] boards: arm: (mimx|vmu_)rt1170: fix documentation issues - Remove duplicated labels (not sure why they were not spotted by doc CI?) - Fix titles Signed-off-by: Gerard Marull-Paretas (cherry picked from commit 0371708ba4d067319c4a66f33489ebec8aedd0fc) Signed-off-by: Dominik Ermel (cherry picked from commit 3948fd35bc6feab39bcb31614dec64e43ec9aa01) --- boards/arm/mimxrt1170_evk/doc/index.rst | 8 ++------ boards/arm/vmu_rt1170/doc/index.rst | 4 +--- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/boards/arm/mimxrt1170_evk/doc/index.rst b/boards/arm/mimxrt1170_evk/doc/index.rst index 51d5053e360..1582861ffc9 100644 --- a/boards/arm/mimxrt1170_evk/doc/index.rst +++ b/boards/arm/mimxrt1170_evk/doc/index.rst @@ -317,10 +317,8 @@ reprogrammed with JLink firmware. - MIMXRT1170-EVKB: :ref:`mcu-link-cmsis-onboard-debug-probe` - MIMXRT1170-EVK: :ref:`opensda-daplink-onboard-debug-probe` -.. _Using J-Link RT1170: - Using J-Link ---------------------------------- +------------ JLink is the default runner for this board. Install the :ref:`jlink-debug-host-tools` and make sure they are in your search path. @@ -330,10 +328,8 @@ J-Link firmware, or :ref:`jlink-external-debug-probe` can be attached to the EVK. See `Using J-Link with MIMXRT1170-EVKB`_ or `Using J-Link with MIMXRT1160-EVK or MIMXRT1170-EVK`_ for more details. -.. _Using LinkServer RT1170: - Using LinkServer ----------------------------------- +---------------- Known limitations with LinkServer and these boards include: - ``west debug`` does not yet work correctly, and the application image is not diff --git a/boards/arm/vmu_rt1170/doc/index.rst b/boards/arm/vmu_rt1170/doc/index.rst index 3514bf15893..28d57464b4f 100644 --- a/boards/arm/vmu_rt1170/doc/index.rst +++ b/boards/arm/vmu_rt1170/doc/index.rst @@ -216,10 +216,8 @@ Configuring a Debug Probe A debug probe is used for both flashing and debugging the board. -.. _Using J-Link RT1170: - Using J-Link ---------------------------------- +------------ Install the :ref:`jlink-debug-host-tools` and make sure they are in your search path. From cf88137e48d93f97b16354ce0a41e1323478bbb7 Mon Sep 17 00:00:00 2001 From: Gerard Marull-Paretas Date: Thu, 7 Sep 2023 12:50:06 +0200 Subject: [PATCH 071/421] [nrf fromtree] drivers: gpio: fix optional operations usage Only provide implementations for optional operations if needed. This patch deletes quite a few dummy `pin_interrupt_configure` ops (now optional), and adjusts ifdeffery on some drivers so that optional ops are only provided if they implement real functionality. Signed-off-by: Gerard Marull-Paretas (cherry picked from commit 64968d74024ab4d43de731c1e7c265869c63f2a0) Signed-off-by: Dominik Ermel (cherry picked from commit bc1cd429d26860622fc5eae54f03af59a94231e7) --- drivers/gpio/gpio_ads114s0x.c | 12 ------------ drivers/gpio/gpio_axp192.c | 12 ------------ drivers/gpio/gpio_bd8lb600fs.c | 7 ------- drivers/gpio/gpio_creg_gpio.c | 9 --------- drivers/gpio/gpio_cy8c95xx.c | 9 --------- drivers/gpio/gpio_fxl6408.c | 10 ---------- drivers/gpio/gpio_lmp90xxx.c | 14 -------------- drivers/gpio/gpio_mcp23s17.c | 9 --------- drivers/gpio/gpio_mmio32.c | 13 ------------- drivers/gpio/gpio_neorv32.c | 14 -------------- drivers/gpio/gpio_npm1300.c | 12 ------------ drivers/gpio/gpio_npm6001.c | 14 -------------- drivers/gpio/gpio_nxp_s32.c | 29 +++-------------------------- drivers/gpio/gpio_pca95xx.c | 14 ++------------ drivers/gpio/gpio_sc18im704.c | 12 ------------ drivers/gpio/gpio_sn74hc595.c | 11 ----------- drivers/gpio/gpio_stmpe1600.c | 9 --------- drivers/gpio/gpio_sx1509b.c | 11 +++-------- drivers/gpio/gpio_test.c | 23 ----------------------- drivers/gpio/gpio_xlnx_axi.c | 4 +++- drivers/gpio/gpio_xmc4xxx.c | 15 +++++---------- 21 files changed, 16 insertions(+), 247 deletions(-) diff --git a/drivers/gpio/gpio_ads114s0x.c b/drivers/gpio/gpio_ads114s0x.c index 79383d38154..13f4f7f1266 100644 --- a/drivers/gpio/gpio_ads114s0x.c +++ b/drivers/gpio/gpio_ads114s0x.c @@ -106,17 +106,6 @@ static int gpio_ads114s0x_port_toggle_bits(const struct device *dev, gpio_port_p return ads114s0x_gpio_port_toggle_bits(config->parent, pins); } -static int gpio_ads114s0x_pin_interrupt_configure(const struct device *dev, gpio_pin_t pin, - enum gpio_int_mode mode, enum gpio_int_trig trig) -{ - ARG_UNUSED(dev); - ARG_UNUSED(pin); - ARG_UNUSED(mode); - ARG_UNUSED(trig); - - return -ENOTSUP; -} - static int gpio_ads114s0x_init(const struct device *dev) { const struct gpio_ads114s0x_config *config = dev->config; @@ -135,7 +124,6 @@ static const struct gpio_driver_api gpio_ads114s0x_api = { .port_set_bits_raw = gpio_ads114s0x_port_set_bits_raw, .port_clear_bits_raw = gpio_ads114s0x_port_clear_bits_raw, .port_toggle_bits = gpio_ads114s0x_port_toggle_bits, - .pin_interrupt_configure = gpio_ads114s0x_pin_interrupt_configure, .port_get_raw = gpio_ads114s0x_port_get_raw, }; diff --git a/drivers/gpio/gpio_axp192.c b/drivers/gpio/gpio_axp192.c index ee75fe9b276..95625d99dfe 100644 --- a/drivers/gpio/gpio_axp192.c +++ b/drivers/gpio/gpio_axp192.c @@ -159,17 +159,6 @@ static int gpio_axp192_port_toggle_bits(const struct device *dev, gpio_port_pins return ret; } -static int gpio_axp192_pin_interrupt_configure(const struct device *dev, gpio_pin_t pin, - enum gpio_int_mode mode, enum gpio_int_trig trig) -{ - ARG_UNUSED(dev); - ARG_UNUSED(pin); - ARG_UNUSED(mode); - ARG_UNUSED(trig); - - return -ENOTSUP; -} - #ifdef CONFIG_GPIO_GET_CONFIG static int gpio_axp192_get_config(const struct device *dev, gpio_pin_t pin, gpio_flags_t *out_flags) { @@ -276,7 +265,6 @@ static const struct gpio_driver_api gpio_axp192_api = { .port_set_bits_raw = gpio_axp192_port_set_bits_raw, .port_clear_bits_raw = gpio_axp192_port_clear_bits_raw, .port_toggle_bits = gpio_axp192_port_toggle_bits, - .pin_interrupt_configure = gpio_axp192_pin_interrupt_configure, .manage_callback = gpio_axp192_manage_callback, #ifdef CONFIG_GPIO_GET_DIRECTION .port_get_direction = gpio_axp192_port_get_direction, diff --git a/drivers/gpio/gpio_bd8lb600fs.c b/drivers/gpio/gpio_bd8lb600fs.c index 555a63b91fd..30ae851d90b 100644 --- a/drivers/gpio/gpio_bd8lb600fs.c +++ b/drivers/gpio/gpio_bd8lb600fs.c @@ -193,12 +193,6 @@ static int bd8lb600fs_port_toggle_bits(const struct device *dev, uint32_t mask) return result; } -static int bd8lb600fs_pin_interrupt_configure(const struct device *dev, gpio_pin_t pin, - enum gpio_int_mode mode, enum gpio_int_trig trig) -{ - return -ENOTSUP; -} - static const struct gpio_driver_api api_table = { .pin_configure = bd8lb600fs_pin_configure, .port_get_raw = bd8lb600fs_port_get_raw, @@ -206,7 +200,6 @@ static const struct gpio_driver_api api_table = { .port_set_bits_raw = bd8lb600fs_port_set_bits_raw, .port_clear_bits_raw = bd8lb600fs_port_clear_bits_raw, .port_toggle_bits = bd8lb600fs_port_toggle_bits, - .pin_interrupt_configure = bd8lb600fs_pin_interrupt_configure, }; static int bd8lb600fs_init(const struct device *dev) diff --git a/drivers/gpio/gpio_creg_gpio.c b/drivers/gpio/gpio_creg_gpio.c index 05b09184df9..1b9f4d63a50 100644 --- a/drivers/gpio/gpio_creg_gpio.c +++ b/drivers/gpio/gpio_creg_gpio.c @@ -104,14 +104,6 @@ static int port_toggle_bits(const struct device *dev, return port_write(dev, 0, 0, pins); } -static int pin_interrupt_configure(const struct device *dev, - gpio_pin_t pin, - enum gpio_int_mode mode, - enum gpio_int_trig trig) -{ - return -ENOTSUP; -} - static int pin_config(const struct device *dev, gpio_pin_t pin, gpio_flags_t flags) @@ -163,7 +155,6 @@ static const struct gpio_driver_api api_table = { .port_set_bits_raw = port_set_bits, .port_clear_bits_raw = port_clear_bits, .port_toggle_bits = port_toggle_bits, - .pin_interrupt_configure = pin_interrupt_configure, }; static const struct creg_gpio_config creg_gpio_cfg = { diff --git a/drivers/gpio/gpio_cy8c95xx.c b/drivers/gpio/gpio_cy8c95xx.c index b540a7b96bf..155bfb4988a 100644 --- a/drivers/gpio/gpio_cy8c95xx.c +++ b/drivers/gpio/gpio_cy8c95xx.c @@ -214,14 +214,6 @@ static int port_toggle_bits(const struct device *dev, return port_write(dev, 0, 0, pins); } -static int pin_interrupt_configure(const struct device *dev, - gpio_pin_t pin, - enum gpio_int_mode mode, - enum gpio_int_trig trig) -{ - return -ENOTSUP; -} - /** * @brief Initialization function of CY8C95XX * @@ -277,7 +269,6 @@ static const struct gpio_driver_api api_table = { .port_set_bits_raw = port_set_bits, .port_clear_bits_raw = port_clear_bits, .port_toggle_bits = port_toggle_bits, - .pin_interrupt_configure = pin_interrupt_configure, }; static struct k_sem cy8c95xx_lock = Z_SEM_INITIALIZER(cy8c95xx_lock, 1, 1); diff --git a/drivers/gpio/gpio_fxl6408.c b/drivers/gpio/gpio_fxl6408.c index 164a4396c13..7352390e371 100644 --- a/drivers/gpio/gpio_fxl6408.c +++ b/drivers/gpio/gpio_fxl6408.c @@ -377,15 +377,6 @@ static int gpio_fxl6408_port_toggle_bits(const struct device *dev, return ret; } -static int gpio_fxl6408_pin_interrupt_configure(const struct device *port, - gpio_pin_t pin, - enum gpio_int_mode mode, - enum gpio_int_trig trig) -{ - LOG_DBG("Pin interrupts not supported."); - return -ENOTSUP; -} - int gpio_fxl6408_init(const struct device *dev) { struct gpio_fxl6408_drv_data *const drv_data = @@ -409,7 +400,6 @@ static const struct gpio_driver_api gpio_fxl_driver = { .port_set_bits_raw = gpio_fxl6408_port_set_bits_raw, .port_clear_bits_raw = gpio_fxl6408_port_clear_bits_raw, .port_toggle_bits = gpio_fxl6408_port_toggle_bits, - .pin_interrupt_configure = gpio_fxl6408_pin_interrupt_configure }; #define GPIO_FXL6408_DEVICE_INSTANCE(inst) \ diff --git a/drivers/gpio/gpio_lmp90xxx.c b/drivers/gpio/gpio_lmp90xxx.c index 1bd99d88cf2..2514ef35211 100644 --- a/drivers/gpio/gpio_lmp90xxx.c +++ b/drivers/gpio/gpio_lmp90xxx.c @@ -122,19 +122,6 @@ static int gpio_lmp90xxx_port_toggle_bits(const struct device *dev, return lmp90xxx_gpio_port_toggle_bits(config->parent, pins); } -static int gpio_lmp90xxx_pin_interrupt_configure(const struct device *dev, - gpio_pin_t pin, - enum gpio_int_mode mode, - enum gpio_int_trig trig) -{ - ARG_UNUSED(dev); - ARG_UNUSED(pin); - ARG_UNUSED(mode); - ARG_UNUSED(trig); - - return -ENOTSUP; -} - static int gpio_lmp90xxx_init(const struct device *dev) { const struct gpio_lmp90xxx_config *config = dev->config; @@ -154,7 +141,6 @@ static const struct gpio_driver_api gpio_lmp90xxx_api = { .port_set_bits_raw = gpio_lmp90xxx_port_set_bits_raw, .port_clear_bits_raw = gpio_lmp90xxx_port_clear_bits_raw, .port_toggle_bits = gpio_lmp90xxx_port_toggle_bits, - .pin_interrupt_configure = gpio_lmp90xxx_pin_interrupt_configure, .port_get_raw = gpio_lmp90xxx_port_get_raw, }; diff --git a/drivers/gpio/gpio_mcp23s17.c b/drivers/gpio/gpio_mcp23s17.c index 96a266fdf6d..4849c3a02fe 100644 --- a/drivers/gpio/gpio_mcp23s17.c +++ b/drivers/gpio/gpio_mcp23s17.c @@ -340,14 +340,6 @@ static int mcp23s17_port_toggle_bits(const struct device *dev, uint32_t mask) return ret; } -static int mcp23s17_pin_interrupt_configure(const struct device *dev, - gpio_pin_t pin, - enum gpio_int_mode mode, - enum gpio_int_trig trig) -{ - return -ENOTSUP; -} - static const struct gpio_driver_api api_table = { .pin_configure = mcp23s17_config, .port_get_raw = mcp23s17_port_get_raw, @@ -355,7 +347,6 @@ static const struct gpio_driver_api api_table = { .port_set_bits_raw = mcp23s17_port_set_bits_raw, .port_clear_bits_raw = mcp23s17_port_clear_bits_raw, .port_toggle_bits = mcp23s17_port_toggle_bits, - .pin_interrupt_configure = mcp23s17_pin_interrupt_configure, }; static int mcp23s17_init(const struct device *dev) diff --git a/drivers/gpio/gpio_mmio32.c b/drivers/gpio/gpio_mmio32.c index e9e58373b5b..0fe5e9fedd8 100644 --- a/drivers/gpio/gpio_mmio32.c +++ b/drivers/gpio/gpio_mmio32.c @@ -147,18 +147,6 @@ static int gpio_mmio32_port_toggle_bits(const struct device *dev, return 0; } -static int gpio_mmio32_pin_interrupt_configure(const struct device *dev, - gpio_pin_t pin, - enum gpio_int_mode mode, - enum gpio_int_trig trig) -{ - if (mode != GPIO_INT_MODE_DISABLED) { - return -ENOTSUP; - } - - return 0; -} - const struct gpio_driver_api gpio_mmio32_api = { .pin_configure = gpio_mmio32_config, .port_get_raw = gpio_mmio32_port_get_raw, @@ -166,7 +154,6 @@ const struct gpio_driver_api gpio_mmio32_api = { .port_set_bits_raw = gpio_mmio32_port_set_bits_raw, .port_clear_bits_raw = gpio_mmio32_port_clear_bits_raw, .port_toggle_bits = gpio_mmio32_port_toggle_bits, - .pin_interrupt_configure = gpio_mmio32_pin_interrupt_configure, }; int gpio_mmio32_init(const struct device *dev) diff --git a/drivers/gpio/gpio_neorv32.c b/drivers/gpio/gpio_neorv32.c index b448962bde7..b14c51c1471 100644 --- a/drivers/gpio/gpio_neorv32.c +++ b/drivers/gpio/gpio_neorv32.c @@ -151,19 +151,6 @@ static int neorv32_gpio_port_toggle_bits(const struct device *dev, return 0; } -static int neorv32_gpio_pin_interrupt_configure(const struct device *dev, - gpio_pin_t pin, - enum gpio_int_mode mode, - enum gpio_int_trig trig) -{ - ARG_UNUSED(dev); - ARG_UNUSED(pin); - ARG_UNUSED(mode); - ARG_UNUSED(trig); - - return -ENOTSUP; -} - static int neorv32_gpio_manage_callback(const struct device *dev, struct gpio_callback *cb, bool set) @@ -215,7 +202,6 @@ static const struct gpio_driver_api neorv32_gpio_driver_api = { .port_set_bits_raw = neorv32_gpio_port_set_bits_raw, .port_clear_bits_raw = neorv32_gpio_port_clear_bits_raw, .port_toggle_bits = neorv32_gpio_port_toggle_bits, - .pin_interrupt_configure = neorv32_gpio_pin_interrupt_configure, .manage_callback = neorv32_gpio_manage_callback, .get_pending_int = neorv32_gpio_get_pending_int, }; diff --git a/drivers/gpio/gpio_npm1300.c b/drivers/gpio/gpio_npm1300.c index 37e7f99c936..65c3cdd6fda 100644 --- a/drivers/gpio/gpio_npm1300.c +++ b/drivers/gpio/gpio_npm1300.c @@ -185,17 +185,6 @@ static int gpio_npm1300_port_toggle_bits(const struct device *dev, gpio_port_pin return gpio_npm1300_port_set_masked_raw(dev, pins, ~value); } -static int gpio_npm1300_pin_interrupt_configure(const struct device *dev, gpio_pin_t pin, - enum gpio_int_mode mode, enum gpio_int_trig trig) -{ - ARG_UNUSED(dev); - ARG_UNUSED(pin); - ARG_UNUSED(mode); - ARG_UNUSED(trig); - - return -ENOTSUP; -} - static const struct gpio_driver_api gpio_npm1300_api = { .pin_configure = gpio_npm1300_configure, .port_get_raw = gpio_npm1300_port_get_raw, @@ -203,7 +192,6 @@ static const struct gpio_driver_api gpio_npm1300_api = { .port_set_bits_raw = gpio_npm1300_port_set_bits_raw, .port_clear_bits_raw = gpio_npm1300_port_clear_bits_raw, .port_toggle_bits = gpio_npm1300_port_toggle_bits, - .pin_interrupt_configure = gpio_npm1300_pin_interrupt_configure, }; static int gpio_npm1300_init(const struct device *dev) diff --git a/drivers/gpio/gpio_npm6001.c b/drivers/gpio/gpio_npm6001.c index 98bd4db49e0..f722c4275d6 100644 --- a/drivers/gpio/gpio_npm6001.c +++ b/drivers/gpio/gpio_npm6001.c @@ -192,19 +192,6 @@ static int gpio_npm6001_port_toggle_bits(const struct device *dev, ~val & NPM6001_PIN_MSK); } -static int gpio_npm6001_pin_interrupt_configure(const struct device *dev, - gpio_pin_t pin, - enum gpio_int_mode mode, - enum gpio_int_trig trig) -{ - ARG_UNUSED(dev); - ARG_UNUSED(pin); - ARG_UNUSED(mode); - ARG_UNUSED(trig); - - return -ENOTSUP; -} - static const struct gpio_driver_api gpio_npm6001_api = { .pin_configure = gpio_npm6001_configure, .port_get_raw = gpio_npm6001_port_get_raw, @@ -212,7 +199,6 @@ static const struct gpio_driver_api gpio_npm6001_api = { .port_set_bits_raw = gpio_npm6001_port_set_bits_raw, .port_clear_bits_raw = gpio_npm6001_port_clear_bits_raw, .port_toggle_bits = gpio_npm6001_port_toggle_bits, - .pin_interrupt_configure = gpio_npm6001_pin_interrupt_configure, }; static int gpio_npm6001_init(const struct device *dev) diff --git a/drivers/gpio/gpio_nxp_s32.c b/drivers/gpio/gpio_nxp_s32.c index 3bdf9f4599d..de5dbd39dd7 100644 --- a/drivers/gpio/gpio_nxp_s32.c +++ b/drivers/gpio/gpio_nxp_s32.c @@ -205,14 +205,12 @@ static void nxp_s32_gpio_isr(uint8_t pin, void *arg) gpio_fire_callbacks(&data->callbacks, dev, BIT(pin)); } -#endif /* CONFIG_NXP_S32_EIRQ */ static int nxp_s32_gpio_pin_interrupt_configure(const struct device *dev, gpio_pin_t pin, enum gpio_int_mode mode, enum gpio_int_trig trig) { -#ifdef CONFIG_NXP_S32_EIRQ const struct gpio_nxp_s32_config *config = dev->config; const struct eirq_nxp_s32_info *eirq_info = config->eirq_info; @@ -255,35 +253,18 @@ static int nxp_s32_gpio_pin_interrupt_configure(const struct device *dev, } return 0; -#else - ARG_UNUSED(dev); - ARG_UNUSED(pin); - ARG_UNUSED(mode); - ARG_UNUSED(trig); - - return -ENOTSUP; -#endif } static int nxp_s32_gpio_manage_callback(const struct device *dev, struct gpio_callback *cb, bool set) { -#ifdef CONFIG_NXP_S32_EIRQ struct gpio_nxp_s32_data *data = dev->data; return gpio_manage_callback(&data->callbacks, cb, set); -#else - ARG_UNUSED(dev); - ARG_UNUSED(cb); - ARG_UNUSED(set); - - return -ENOTSUP; -#endif } static uint32_t nxp_s32_gpio_get_pending_int(const struct device *dev) { -#ifdef CONFIG_NXP_S32_EIRQ const struct gpio_nxp_s32_config *config = dev->config; const struct eirq_nxp_s32_info *eirq_info = config->eirq_info; @@ -300,14 +281,8 @@ static uint32_t nxp_s32_gpio_get_pending_int(const struct device *dev) * that GPIO port belongs to */ return eirq_nxp_s32_get_pending(eirq_info->eirq_dev); - -#else - ARG_UNUSED(dev); - - return -ENOTSUP; -#endif } - +#endif /* CONFIG_NXP_S32_EIRQ */ #ifdef CONFIG_GPIO_GET_CONFIG static int nxp_s32_gpio_pin_get_config(const struct device *dev, @@ -400,9 +375,11 @@ static const struct gpio_driver_api gpio_nxp_s32_driver_api = { .port_set_bits_raw = nxp_s32_gpio_port_set_bits_raw, .port_clear_bits_raw = nxp_s32_gpio_port_clear_bits_raw, .port_toggle_bits = nxp_s32_gpio_port_toggle_bits, +#ifdef CONFIG_NXP_S32_EIRQ .pin_interrupt_configure = nxp_s32_gpio_pin_interrupt_configure, .manage_callback = nxp_s32_gpio_manage_callback, .get_pending_int = nxp_s32_gpio_get_pending_int, +#endif #ifdef CONFIG_GPIO_GET_CONFIG .pin_get_config = nxp_s32_gpio_pin_get_config, #endif diff --git a/drivers/gpio/gpio_pca95xx.c b/drivers/gpio/gpio_pca95xx.c index 66b21fd5b88..f8489128332 100644 --- a/drivers/gpio/gpio_pca95xx.c +++ b/drivers/gpio/gpio_pca95xx.c @@ -644,7 +644,6 @@ static void gpio_pca95xx_interrupt_callback(const struct device *dev, /* Cannot read PCA95xx registers from ISR context, queue worker */ k_work_submit(&drv_data->interrupt_worker); } -#endif /* CONFIG_GPIO_PCA95XX_INTERRUPT */ static int gpio_pca95xx_pin_interrupt_configure(const struct device *dev, gpio_pin_t pin, @@ -652,13 +651,6 @@ static int gpio_pca95xx_pin_interrupt_configure(const struct device *dev, enum gpio_int_trig trig) { int ret = 0; - - if (!IS_ENABLED(CONFIG_GPIO_PCA95XX_INTERRUPT) - && (mode != GPIO_INT_MODE_DISABLED)) { - return -ENOTSUP; - } - -#ifdef CONFIG_GPIO_PCA95XX_INTERRUPT const struct gpio_pca95xx_config * const config = dev->config; struct gpio_pca95xx_drv_data * const drv_data = (struct gpio_pca95xx_drv_data * const)dev->data; @@ -742,11 +734,9 @@ static int gpio_pca95xx_pin_interrupt_configure(const struct device *dev, err: k_sem_give(&drv_data->lock); -#endif /* CONFIG_GPIO_PCA95XX_INTERRUPT */ return ret; } -#ifdef CONFIG_GPIO_PCA95XX_INTERRUPT static int gpio_pca95xx_manage_callback(const struct device *dev, struct gpio_callback *callback, bool set) @@ -766,7 +756,7 @@ static int gpio_pca95xx_manage_callback(const struct device *dev, k_sem_give(&drv_data->lock); return 0; } -#endif +#endif /* CONFIG_GPIO_PCA95XX_INTERRUPT */ static const struct gpio_driver_api gpio_pca95xx_drv_api_funcs = { .pin_configure = gpio_pca95xx_config, @@ -775,8 +765,8 @@ static const struct gpio_driver_api gpio_pca95xx_drv_api_funcs = { .port_set_bits_raw = gpio_pca95xx_port_set_bits_raw, .port_clear_bits_raw = gpio_pca95xx_port_clear_bits_raw, .port_toggle_bits = gpio_pca95xx_port_toggle_bits, - .pin_interrupt_configure = gpio_pca95xx_pin_interrupt_configure, #ifdef CONFIG_GPIO_PCA95XX_INTERRUPT + .pin_interrupt_configure = gpio_pca95xx_pin_interrupt_configure, .manage_callback = gpio_pca95xx_manage_callback, #endif }; diff --git a/drivers/gpio/gpio_sc18im704.c b/drivers/gpio/gpio_sc18im704.c index 96fd56cadb6..c45e9d51a60 100644 --- a/drivers/gpio/gpio_sc18im704.c +++ b/drivers/gpio/gpio_sc18im704.c @@ -239,17 +239,6 @@ static int gpio_sc18im_port_toggle_bits(const struct device *port, gpio_port_pin return gpio_sc18im_port_set_raw(port, 0, 0, (uint8_t)pins); } -static int gpio_sc18im_pin_interrupt_configure(const struct device *port, gpio_pin_t pin, - enum gpio_int_mode mode, enum gpio_int_trig trig) -{ - ARG_UNUSED(port); - ARG_UNUSED(pin); - ARG_UNUSED(mode); - ARG_UNUSED(trig); - - return -ENOTSUP; -} - static int gpio_sc18im_init(const struct device *dev) { const struct gpio_sc18im_config *cfg = dev->config; @@ -272,7 +261,6 @@ static const struct gpio_driver_api gpio_sc18im_driver_api = { .port_set_bits_raw = gpio_sc18im_port_set_bits_raw, .port_clear_bits_raw = gpio_sc18im_port_clear_bits_raw, .port_toggle_bits = gpio_sc18im_port_toggle_bits, - .pin_interrupt_configure = gpio_sc18im_pin_interrupt_configure, }; #define CHECK_COMPAT(node) \ diff --git a/drivers/gpio/gpio_sn74hc595.c b/drivers/gpio/gpio_sn74hc595.c index 38f5de94d38..16eb35bb690 100644 --- a/drivers/gpio/gpio_sn74hc595.c +++ b/drivers/gpio/gpio_sn74hc595.c @@ -134,16 +134,6 @@ static int gpio_sn74hc595_port_toggle_bits(const struct device *dev, uint32_t ma return ret; } -static int gpio_sn74hc595_pin_interrupt_configure(const struct device *dev, gpio_pin_t pin, - enum gpio_int_mode mode, enum gpio_int_trig trig) -{ - ARG_UNUSED(dev); - ARG_UNUSED(pin); - ARG_UNUSED(mode); - ARG_UNUSED(trig); - return -ENOTSUP; -} - static const struct gpio_driver_api gpio_sn74hc595_drv_api_funcs = { .pin_configure = gpio_sn74hc595_config, .port_get_raw = gpio_sn74hc595_port_get_raw, @@ -151,7 +141,6 @@ static const struct gpio_driver_api gpio_sn74hc595_drv_api_funcs = { .port_set_bits_raw = gpio_sn74hc595_port_set_bits_raw, .port_clear_bits_raw = gpio_sn74hc595_port_clear_bits_raw, .port_toggle_bits = gpio_sn74hc595_port_toggle_bits, - .pin_interrupt_configure = gpio_sn74hc595_pin_interrupt_configure, }; /** diff --git a/drivers/gpio/gpio_stmpe1600.c b/drivers/gpio/gpio_stmpe1600.c index 518b41c7c57..2331fdf9fed 100644 --- a/drivers/gpio/gpio_stmpe1600.c +++ b/drivers/gpio/gpio_stmpe1600.c @@ -249,14 +249,6 @@ static int stmpe1600_port_toggle_bits(const struct device *dev, uint32_t mask) return ret; } -static int stmpe1600_pin_interrupt_configure(const struct device *dev, - gpio_pin_t pin, - enum gpio_int_mode mode, - enum gpio_int_trig trig) -{ - return -ENOTSUP; -} - static int stmpe1600_init(const struct device *dev) { const struct stmpe1600_config *const config = dev->config; @@ -300,7 +292,6 @@ static const struct gpio_driver_api stmpe1600_drv_api = { .port_set_bits_raw = stmpe1600_port_set_bits_raw, .port_clear_bits_raw = stmpe1600_port_clear_bits_raw, .port_toggle_bits = stmpe1600_port_toggle_bits, - .pin_interrupt_configure = stmpe1600_pin_interrupt_configure, }; #define STMPE1600_INIT(inst) \ diff --git a/drivers/gpio/gpio_sx1509b.c b/drivers/gpio/gpio_sx1509b.c index c62f803e307..b8ecdf4d772 100644 --- a/drivers/gpio/gpio_sx1509b.c +++ b/drivers/gpio/gpio_sx1509b.c @@ -468,6 +468,7 @@ static int port_toggle_bits(const struct device *dev, return port_write(dev, 0, 0, pins); } +#ifdef CONFIG_GPIO_SX1509B_INTERRUPT static int pin_interrupt_configure(const struct device *dev, gpio_pin_t pin, enum gpio_int_mode mode, @@ -475,12 +476,6 @@ static int pin_interrupt_configure(const struct device *dev, { int rc = 0; - if (!IS_ENABLED(CONFIG_GPIO_SX1509B_INTERRUPT) - && (mode != GPIO_INT_MODE_DISABLED)) { - return -ENOTSUP; - } - -#ifdef CONFIG_GPIO_SX1509B_INTERRUPT /* Device does not support level-triggered interrupts. */ if (mode == GPIO_INT_MODE_LEVEL) { return -ENOTSUP; @@ -531,10 +526,10 @@ static int pin_interrupt_configure(const struct device *dev, rc = i2c_write_dt(&cfg->bus, &irq_buf.reg, sizeof(irq_buf)); k_sem_give(&drv_data->lock); -#endif /* CONFIG_GPIO_SX1509B_INTERRUPT */ return rc; } +#endif /* CONFIG_GPIO_SX1509B_INTERRUPT */ /** * @brief Initialization function of SX1509B @@ -647,8 +642,8 @@ static const struct gpio_driver_api api_table = { .port_set_bits_raw = port_set_bits, .port_clear_bits_raw = port_clear_bits, .port_toggle_bits = port_toggle_bits, - .pin_interrupt_configure = pin_interrupt_configure, #ifdef CONFIG_GPIO_SX1509B_INTERRUPT + .pin_interrupt_configure = pin_interrupt_configure, .manage_callback = gpio_sx1509b_manage_callback, #endif }; diff --git a/drivers/gpio/gpio_test.c b/drivers/gpio/gpio_test.c index 192028acac0..3befab37fc2 100644 --- a/drivers/gpio/gpio_test.c +++ b/drivers/gpio/gpio_test.c @@ -63,26 +63,6 @@ static int vnd_gpio_port_toggle_bits(const struct device *port, return -ENOTSUP; } -static int vnd_gpio_pin_interrupt_configure(const struct device *port, - gpio_pin_t pin, - enum gpio_int_mode mode, - enum gpio_int_trig trig) -{ - return -ENOTSUP; -} - -static int vnd_gpio_manage_callback(const struct device *port, - struct gpio_callback *cb, - bool set) -{ - return -ENOTSUP; -} - -static uint32_t vnd_gpio_get_pending_int(const struct device *dev) -{ - return 0; -} - static const struct gpio_driver_api vnd_gpio_api = { .pin_configure = vnd_gpio_pin_configure, .port_get_raw = vnd_gpio_port_get_raw, @@ -90,9 +70,6 @@ static const struct gpio_driver_api vnd_gpio_api = { .port_set_bits_raw = vnd_gpio_port_set_bits_raw, .port_clear_bits_raw = vnd_gpio_port_clear_bits_raw, .port_toggle_bits = vnd_gpio_port_toggle_bits, - .pin_interrupt_configure = vnd_gpio_pin_interrupt_configure, - .manage_callback = vnd_gpio_manage_callback, - .get_pending_int = vnd_gpio_get_pending_int }; #define VND_GPIO_INIT(n) \ diff --git a/drivers/gpio/gpio_xlnx_axi.c b/drivers/gpio/gpio_xlnx_axi.c index 99e9e350aa2..f070e691e5d 100644 --- a/drivers/gpio/gpio_xlnx_axi.c +++ b/drivers/gpio/gpio_xlnx_axi.c @@ -198,6 +198,7 @@ static int gpio_xlnx_axi_port_toggle_bits(const struct device *dev, gpio_port_pi return 0; } +#if DT_ANY_INST_HAS_PROP_STATUS_OKAY(interrupts) /** * Enables interrupts for the given pins on the channel * The axi gpio can only enable interrupts for an entire port, so we need to track @@ -206,7 +207,6 @@ static int gpio_xlnx_axi_port_toggle_bits(const struct device *dev, gpio_port_pi static int gpio_xlnx_axi_pin_interrupt_configure(const struct device *dev, gpio_pin_t pin, enum gpio_int_mode mode, enum gpio_int_trig trig) { -#if DT_ANY_INST_HAS_PROP_STATUS_OKAY(interrupts) const struct gpio_xlnx_axi_config *config = dev->config; struct gpio_xlnx_axi_data *data = dev->data; const uint32_t pin_mask = BIT(pin); @@ -390,9 +390,11 @@ static const struct gpio_driver_api gpio_xlnx_axi_driver_api = { .port_set_bits_raw = gpio_xlnx_axi_port_set_bits_raw, .port_clear_bits_raw = gpio_xlnx_axi_port_clear_bits_raw, .port_toggle_bits = gpio_xlnx_axi_port_toggle_bits, +#if DT_ANY_INST_HAS_PROP_STATUS_OKAY(interrupts) .pin_interrupt_configure = gpio_xlnx_axi_pin_interrupt_configure, .manage_callback = gpio_xlnx_axi_manage_callback, .get_pending_int = gpio_xlnx_axi_get_pending_int, +#endif }; #define GPIO_XLNX_AXI_GPIO2_HAS_COMPAT_STATUS_OKAY(n) \ diff --git a/drivers/gpio/gpio_xmc4xxx.c b/drivers/gpio/gpio_xmc4xxx.c index 29462308481..d90f68d3b32 100644 --- a/drivers/gpio/gpio_xmc4xxx.c +++ b/drivers/gpio/gpio_xmc4xxx.c @@ -117,10 +117,10 @@ static void gpio_xmc4xxx_isr(const struct device *dev, int pin) } #endif +#ifdef CONFIG_XMC4XXX_INTC static int gpio_xmc4xxx_pin_interrupt_configure(const struct device *dev, gpio_pin_t pin, enum gpio_int_mode mode, enum gpio_int_trig trig) { -#if defined(CONFIG_XMC4XXX_INTC) const struct gpio_xmc4xxx_config *config = dev->config; int port_id = PORT_TO_PORT_ID(config->port); @@ -132,15 +132,8 @@ static int gpio_xmc4xxx_pin_interrupt_configure(const struct device *dev, gpio_p } else { return -EINVAL; } -#else - ARG_UNUSED(dev); - ARG_UNUSED(pin); - ARG_UNUSED(mode); - ARG_UNUSED(trig); - - return -ENOTSUP; -#endif } +#endif static int gpio_xmc4xxx_get_raw(const struct device *dev, gpio_port_value_t *value) { @@ -215,8 +208,10 @@ static const struct gpio_driver_api gpio_xmc4xxx_driver_api = { .port_set_bits_raw = gpio_xmc4xxx_set_bits_raw, .port_clear_bits_raw = gpio_xmc4xxx_clear_bits_raw, .port_toggle_bits = gpio_xmc4xxx_toggle_bits, +#ifdef CONFIG_XMC4XXX_INTC .pin_interrupt_configure = gpio_xmc4xxx_pin_interrupt_configure, - .manage_callback = IS_ENABLED(CONFIG_XMC4XXX_INTC) ? gpio_xmc4xxx_manage_callback : NULL, + .manage_callback = gpio_xmc4xxx_manage_callback, +#endif }; #define GPIO_XMC4XXX_INIT(index) \ From 1cba00a409f64a96f3a0c75bd3cb15c146829077 Mon Sep 17 00:00:00 2001 From: Marek Pieta Date: Tue, 5 Sep 2023 12:28:45 +0200 Subject: [PATCH 072/421] [nrf fromtree] drivers: gpio_nrfx: Allow to disable interrupt support Change introduces a new configuration option that can be used to disable GPIO interrupt support to reduce memory footprint. Signed-off-by: Marek Pieta (cherry picked from commit 44c723e65d659a222b8744eba97a62335962d197) Signed-off-by: Dominik Ermel (cherry picked from commit 0a55c2ea2679237081b6b777fe8fcb71db5894ba) --- drivers/gpio/Kconfig.nrfx | 11 +++++++++- drivers/gpio/gpio_nrfx.c | 42 +++++++++++++++++++++++++-------------- 2 files changed, 37 insertions(+), 16 deletions(-) diff --git a/drivers/gpio/Kconfig.nrfx b/drivers/gpio/Kconfig.nrfx index 6757b6b12e9..356c43cb5fa 100644 --- a/drivers/gpio/Kconfig.nrfx +++ b/drivers/gpio/Kconfig.nrfx @@ -1,10 +1,19 @@ # Copyright (c) 2018 Nordic Semiconductor ASA # SPDX-License-Identifier: Apache-2.0 -config GPIO_NRFX +menuconfig GPIO_NRFX bool "nRF GPIO driver" default y depends on DT_HAS_NORDIC_NRF_GPIO_ENABLED select NRFX_GPIOTE help Enable GPIO driver for nRF line of MCUs. + +config GPIO_NRFX_INTERRUPT + bool "Interrupt support" + depends on GPIO_NRFX + default y + help + The option can be used to disable the GPIO interrupt support to + significantly reduce memory footprint in case of application that does + not need GPIO interrupts. diff --git a/drivers/gpio/gpio_nrfx.c b/drivers/gpio/gpio_nrfx.c index 1683b8b2cea..0aa282dda37 100644 --- a/drivers/gpio/gpio_nrfx.c +++ b/drivers/gpio/gpio_nrfx.c @@ -85,17 +85,19 @@ static nrf_gpio_pin_pull_t get_pull(gpio_flags_t flags) static int gpio_nrfx_pin_configure(const struct device *port, gpio_pin_t pin, gpio_flags_t flags) { - nrfx_err_t err; + nrfx_err_t err = NRFX_SUCCESS; uint8_t ch; - bool free_ch; + bool free_ch = false; const struct gpio_nrfx_cfg *cfg = get_port_cfg(port); nrfx_gpiote_pin_t abs_pin = NRF_GPIO_PIN_MAP(cfg->port_num, pin); /* Get the GPIOTE channel associated with this pin, if any. It needs * to be freed when the pin is reconfigured or disconnected. */ - err = nrfx_gpiote_channel_get(abs_pin, &ch); - free_ch = (err == NRFX_SUCCESS); + if (IS_ENABLED(CONFIG_GPIO_NRFX_INTERRUPT)) { + err = nrfx_gpiote_channel_get(abs_pin, &ch); + free_ch = (err == NRFX_SUCCESS); + } if ((flags & (GPIO_INPUT | GPIO_OUTPUT)) == GPIO_DISCONNECTED) { /* Ignore the error code. The pin may not have been used. */ @@ -109,19 +111,21 @@ static int gpio_nrfx_pin_configure(const struct device *port, gpio_pin_t pin, return 0; } - nrfx_gpiote_trigger_config_t trigger_config = { - .trigger = NRFX_GPIOTE_TRIGGER_NONE - }; + if (IS_ENABLED(CONFIG_GPIO_NRFX_INTERRUPT)) { + nrfx_gpiote_trigger_config_t trigger_config = { + .trigger = NRFX_GPIOTE_TRIGGER_NONE + }; - /* Remove previously configured trigger when pin is reconfigured. */ - err = nrfx_gpiote_input_configure(abs_pin, NULL, &trigger_config, NULL); - if (err != NRFX_SUCCESS) { - return -EINVAL; - } + /* Remove previously configured trigger when pin is reconfigured. */ + err = nrfx_gpiote_input_configure(abs_pin, NULL, &trigger_config, NULL); + if (err != NRFX_SUCCESS) { + return -EINVAL; + } - if (free_ch) { - err = nrfx_gpiote_channel_free(ch); - __ASSERT_NO_MSG(err == NRFX_SUCCESS); + if (free_ch) { + err = nrfx_gpiote_channel_free(ch); + __ASSERT_NO_MSG(err == NRFX_SUCCESS); + } } if (flags & GPIO_OUTPUT) { @@ -219,6 +223,7 @@ static int gpio_nrfx_port_toggle_bits(const struct device *port, return 0; } +#ifdef CONFIG_GPIO_NRFX_INTERRUPT static nrfx_gpiote_trigger_t get_trigger(enum gpio_int_mode mode, enum gpio_int_trig trig) { @@ -285,6 +290,7 @@ static int gpio_nrfx_manage_callback(const struct device *port, return gpio_manage_callback(&get_port_data(port)->callbacks, callback, set); } +#endif /* CONFIG_GPIO_NRFX_INTERRUPT */ #ifdef CONFIG_GPIO_GET_DIRECTION static int gpio_nrfx_port_get_direction(const struct device *port, @@ -322,6 +328,7 @@ static int gpio_nrfx_port_get_direction(const struct device *port, } #endif /* CONFIG_GPIO_GET_DIRECTION */ +#ifdef CONFIG_GPIO_NRFX_INTERRUPT /* Get port device from port id. */ static const struct device *get_dev(uint32_t port_id) { @@ -358,6 +365,7 @@ static void nrfx_gpio_handler(nrfx_gpiote_pin_t abs_pin, gpio_fire_callbacks(list, port, BIT(pin)); } +#endif /* CONFIG_GPIO_NRFX_INTERRUPT */ #define GPIOTE_NODE DT_INST(0, nordic_nrf_gpiote) @@ -374,10 +382,12 @@ static int gpio_nrfx_init(const struct device *port) return -EIO; } +#ifdef CONFIG_GPIO_NRFX_INTERRUPT nrfx_gpiote_global_callback_set(nrfx_gpio_handler, NULL); IRQ_CONNECT(DT_IRQN(GPIOTE_NODE), DT_IRQ(GPIOTE_NODE, priority), nrfx_isr, nrfx_gpiote_irq_handler, 0); +#endif /* CONFIG_GPIO_NRFX_INTERRUPT */ return 0; } @@ -389,8 +399,10 @@ static const struct gpio_driver_api gpio_nrfx_drv_api_funcs = { .port_set_bits_raw = gpio_nrfx_port_set_bits_raw, .port_clear_bits_raw = gpio_nrfx_port_clear_bits_raw, .port_toggle_bits = gpio_nrfx_port_toggle_bits, +#ifdef CONFIG_GPIO_NRFX_INTERRUPT .pin_interrupt_configure = gpio_nrfx_pin_interrupt_configure, .manage_callback = gpio_nrfx_manage_callback, +#endif #ifdef CONFIG_GPIO_GET_DIRECTION .port_get_direction = gpio_nrfx_port_get_direction, #endif From 9aa9bb98607f6f7232adedb5e7e15f7663f58498 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Wed, 13 Sep 2023 15:13:48 +0000 Subject: [PATCH 073/421] [nrf fromtree] net: Fix usage of strncpy in net_if_get_name and net_if_set_name Replaced with memcpy. (cherry picked from commit 47396e18e12ae859b9858cb439e531a5611255b8) Signed-off-by: Dominik Ermel (cherry picked from commit ee35c807af0d2253acdecaccec3d5ecebc2db195) --- subsys/net/ip/net_if.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/subsys/net/ip/net_if.c b/subsys/net/ip/net_if.c index e6e3512e4b2..828e48ecf78 100644 --- a/subsys/net/ip/net_if.c +++ b/subsys/net/ip/net_if.c @@ -4747,7 +4747,8 @@ int net_if_get_name(struct net_if *iface, char *buf, int len) return -ERANGE; } - strncpy(buf, net_if_get_config(iface)->name, name_len); + /* Copy string and null terminator */ + memcpy(buf, net_if_get_config(iface)->name, name_len + 1); return name_len; #else @@ -4769,7 +4770,8 @@ int net_if_set_name(struct net_if *iface, const char *buf) return -ENAMETOOLONG; } - strncpy(net_if_get_config(iface)->name, buf, name_len); + /* Copy string and null terminator */ + memcpy(net_if_get_config(iface)->name, buf, name_len + 1); return 0; #else From b0cfad5a121d46969e682eb77ea91b1a2720960d Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Tue, 29 Aug 2023 07:44:54 +0100 Subject: [PATCH 074/421] [nrf fromtree] mgmt: mcumgr: Split mgmt defines to new file This splits defines to a separate file, which are commonly needed by out-of-tree projects whereby the full MCUmgr include cannot be used due to undefined types being used. Signed-off-by: Jamie McCrae (cherry picked from commit a15752c79cba648541b87fd54d58379daa61c6db) Signed-off-by: Dominik Ermel (cherry picked from commit a6007b6804cf6db979d46954072f1f21691785a6) --- include/zephyr/mgmt/mcumgr/mgmt/mgmt.h | 119 +------------- .../zephyr/mgmt/mcumgr/mgmt/mgmt_defines.h | 150 ++++++++++++++++++ 2 files changed, 151 insertions(+), 118 deletions(-) create mode 100644 include/zephyr/mgmt/mcumgr/mgmt/mgmt_defines.h diff --git a/include/zephyr/mgmt/mcumgr/mgmt/mgmt.h b/include/zephyr/mgmt/mcumgr/mgmt/mgmt.h index eb9ecfcf2a9..e681ea2b939 100644 --- a/include/zephyr/mgmt/mcumgr/mgmt/mgmt.h +++ b/include/zephyr/mgmt/mcumgr/mgmt/mgmt.h @@ -11,6 +11,7 @@ #include #include #include +#include #ifdef __cplusplus extern "C" { @@ -23,124 +24,6 @@ extern "C" { * @{ */ -/** - * Used at end of MCUmgr handlers to return an error if the message size limit was reached, - * or OK if it was not - */ -#define MGMT_RETURN_CHECK(ok) ok ? MGMT_ERR_EOK : MGMT_ERR_EMSGSIZE - -/** Opcodes; encoded in first byte of header. */ -enum mcumgr_op_t { - /** Read op-code */ - MGMT_OP_READ = 0, - - /** Read response op-code */ - MGMT_OP_READ_RSP, - - /** Write op-code */ - MGMT_OP_WRITE, - - /** Write response op-code */ - MGMT_OP_WRITE_RSP, -}; - -/** - * MCUmgr groups. The first 64 groups are reserved for system level mcumgr - * commands. Per-user commands are then defined after group 64. - */ -enum mcumgr_group_t { - /** OS (operating system) group */ - MGMT_GROUP_ID_OS = 0, - - /** Image management group, used for uploading firmware images */ - MGMT_GROUP_ID_IMAGE, - - /** Statistic management group, used for retieving statistics */ - MGMT_GROUP_ID_STAT, - - /** Settings management (config) group, used for reading/writing settings */ - MGMT_GROUP_ID_SETTINGS, - - /** Log management group (unused) */ - MGMT_GROUP_ID_LOG, - - /** Crash group (unused) */ - MGMT_GROUP_ID_CRASH, - - /** Split image management group (unused) */ - MGMT_GROUP_ID_SPLIT, - - /** Run group (unused) */ - MGMT_GROUP_ID_RUN, - - /** FS (file system) group, used for performing file IO operations */ - MGMT_GROUP_ID_FS, - - /** Shell management group, used for executing shell commands */ - MGMT_GROUP_ID_SHELL, - - /** User groups defined from 64 onwards */ - MGMT_GROUP_ID_PERUSER = 64, - - /** Zephyr-specific groups decrease from PERUSER to avoid collision with upstream and - * user-defined groups. - * Zephyr-specific: Basic group - */ - ZEPHYR_MGMT_GRP_BASIC = (MGMT_GROUP_ID_PERUSER - 1), -}; - -/** - * MCUmgr error codes. - */ -enum mcumgr_err_t { - /** No error (success). */ - MGMT_ERR_EOK = 0, - - /** Unknown error. */ - MGMT_ERR_EUNKNOWN, - - /** Insufficient memory (likely not enough space for CBOR object). */ - MGMT_ERR_ENOMEM, - - /** Error in input value. */ - MGMT_ERR_EINVAL, - - /** Operation timed out. */ - MGMT_ERR_ETIMEOUT, - - /** No such file/entry. */ - MGMT_ERR_ENOENT, - - /** Current state disallows command. */ - MGMT_ERR_EBADSTATE, - - /** Response too large. */ - MGMT_ERR_EMSGSIZE, - - /** Command not supported. */ - MGMT_ERR_ENOTSUP, - - /** Corrupt */ - MGMT_ERR_ECORRUPT, - - /** Command blocked by processing of other command */ - MGMT_ERR_EBUSY, - - /** Access to specific function, command or resource denied */ - MGMT_ERR_EACCESSDENIED, - - /** Requested SMP MCUmgr protocol version is not supported (too old) */ - MGMT_ERR_UNSUPPORTED_TOO_OLD, - - /** Requested SMP MCUmgr protocol version is not supported (too new) */ - MGMT_ERR_UNSUPPORTED_TOO_NEW, - - /** User errors defined from 256 onwards */ - MGMT_ERR_EPERUSER = 256 -}; - -#define MGMT_HDR_SIZE 8 - /** @typedef mgmt_alloc_rsp_fn * @brief Allocates a buffer suitable for holding a response. * diff --git a/include/zephyr/mgmt/mcumgr/mgmt/mgmt_defines.h b/include/zephyr/mgmt/mcumgr/mgmt/mgmt_defines.h new file mode 100644 index 00000000000..2f33b6d22a1 --- /dev/null +++ b/include/zephyr/mgmt/mcumgr/mgmt/mgmt_defines.h @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2018-2021 mcumgr authors + * Copyright (c) 2022-2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef H_MGMT_MGMT_DEFINES_ +#define H_MGMT_MGMT_DEFINES_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief MCUmgr mgmt API + * @defgroup mcumgr_mgmt_api MCUmgr mgmt API + * @ingroup mcumgr + * @{ + */ + +/** + * Used at end of MCUmgr handlers to return an error if the message size limit was reached, + * or OK if it was not + */ +#define MGMT_RETURN_CHECK(ok) ok ? MGMT_ERR_EOK : MGMT_ERR_EMSGSIZE + +/** Opcodes; encoded in first byte of header. */ +enum mcumgr_op_t { + /** Read op-code */ + MGMT_OP_READ = 0, + + /** Read response op-code */ + MGMT_OP_READ_RSP, + + /** Write op-code */ + MGMT_OP_WRITE, + + /** Write response op-code */ + MGMT_OP_WRITE_RSP, +}; + +/** + * MCUmgr groups. The first 64 groups are reserved for system level mcumgr + * commands. Per-user commands are then defined after group 64. + */ +enum mcumgr_group_t { + /** OS (operating system) group */ + MGMT_GROUP_ID_OS = 0, + + /** Image management group, used for uploading firmware images */ + MGMT_GROUP_ID_IMAGE, + + /** Statistic management group, used for retieving statistics */ + MGMT_GROUP_ID_STAT, + + /** Settings management (config) group, used for reading/writing settings */ + MGMT_GROUP_ID_SETTINGS, + + /** Log management group (unused) */ + MGMT_GROUP_ID_LOG, + + /** Crash group (unused) */ + MGMT_GROUP_ID_CRASH, + + /** Split image management group (unused) */ + MGMT_GROUP_ID_SPLIT, + + /** Run group (unused) */ + MGMT_GROUP_ID_RUN, + + /** FS (file system) group, used for performing file IO operations */ + MGMT_GROUP_ID_FS, + + /** Shell management group, used for executing shell commands */ + MGMT_GROUP_ID_SHELL, + + /** User groups defined from 64 onwards */ + MGMT_GROUP_ID_PERUSER = 64, + + /** Zephyr-specific groups decrease from PERUSER to avoid collision with upstream and + * user-defined groups. + * Zephyr-specific: Basic group + */ + ZEPHYR_MGMT_GRP_BASIC = (MGMT_GROUP_ID_PERUSER - 1), +}; + +/** + * MCUmgr error codes. + */ +enum mcumgr_err_t { + /** No error (success). */ + MGMT_ERR_EOK = 0, + + /** Unknown error. */ + MGMT_ERR_EUNKNOWN, + + /** Insufficient memory (likely not enough space for CBOR object). */ + MGMT_ERR_ENOMEM, + + /** Error in input value. */ + MGMT_ERR_EINVAL, + + /** Operation timed out. */ + MGMT_ERR_ETIMEOUT, + + /** No such file/entry. */ + MGMT_ERR_ENOENT, + + /** Current state disallows command. */ + MGMT_ERR_EBADSTATE, + + /** Response too large. */ + MGMT_ERR_EMSGSIZE, + + /** Command not supported. */ + MGMT_ERR_ENOTSUP, + + /** Corrupt */ + MGMT_ERR_ECORRUPT, + + /** Command blocked by processing of other command */ + MGMT_ERR_EBUSY, + + /** Access to specific function, command or resource denied */ + MGMT_ERR_EACCESSDENIED, + + /** Requested SMP MCUmgr protocol version is not supported (too old) */ + MGMT_ERR_UNSUPPORTED_TOO_OLD, + + /** Requested SMP MCUmgr protocol version is not supported (too new) */ + MGMT_ERR_UNSUPPORTED_TOO_NEW, + + /** User errors defined from 256 onwards */ + MGMT_ERR_EPERUSER = 256 +}; + +#define MGMT_HDR_SIZE 8 + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* MGMT_MGMT_DEFINES_H_ */ From c606de126612153b2c036b730d66ec622c88aec9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eivind=20J=C3=B8lsgard?= Date: Wed, 20 Sep 2023 10:16:50 +0200 Subject: [PATCH 075/421] [nrf fromtree] drivers: serial: uart_nrfx_uarte: coexisting async and interrupt API MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit fixes an issue with the nrfx uarte driver to allow the async and interrupt driven UART APIs to coexist on different uart instances. As both APIs cannot be used simultaneously for a given instance, there is no need to handle CONFIG_UART_EXCLUSIVE_API_CALLBACKS in this driver. Signed-off-by: Eivind Jølsgard (cherry picked from commit 66069b3b397dbd68fe47ab54579501b9fc365425) Signed-off-by: Dominik Ermel (cherry picked from commit 1c5e17f1ea603f2bea44c9d0d49817d293f6f45b) --- drivers/serial/uart_nrfx_uarte.c | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/drivers/serial/uart_nrfx_uarte.c b/drivers/serial/uart_nrfx_uarte.c index bdafe6c7d4c..017efa6a2e5 100644 --- a/drivers/serial/uart_nrfx_uarte.c +++ b/drivers/serial/uart_nrfx_uarte.c @@ -937,11 +937,6 @@ static int uarte_nrfx_callback_set(const struct device *dev, data->async->user_callback = callback; data->async->user_data = user_data; -#if defined(CONFIG_UART_EXCLUSIVE_API_CALLBACKS) && defined(UARTE_INTERRUPT_DRIVEN) - data->int_driven->cb = NULL; - data->int_driven->cb_data = NULL; -#endif - return 0; } @@ -1680,11 +1675,6 @@ static void uarte_nrfx_irq_callback_set(const struct device *dev, data->int_driven->cb = cb; data->int_driven->cb_data = cb_data; - -#if defined(UARTE_ANY_ASYNC) && defined(CONFIG_UART_EXCLUSIVE_API_CALLBACKS) - data->async->user_callback = NULL; - data->async->user_data = NULL; -#endif } #endif /* UARTE_INTERRUPT_DRIVEN */ From 83e1ffa903da471f7d065edfeb59c990b695ae25 Mon Sep 17 00:00:00 2001 From: Emil Gydesen Date: Tue, 12 Sep 2023 23:28:34 +0200 Subject: [PATCH 076/421] [nrf fromtree] tests: Bluetooth: Audio: Modify bsim tests to use bt_le_scan_cb_register Update the tests to use bt_le_scan_cb_register and the "new" scan callback, as that is better suited to handle extended advertising. Signed-off-by: Emil Gydesen (cherry picked from commit 9064170cf85c8ac71961ff01c018cadc03d742d7) Signed-off-by: Dominik Ermel (cherry picked from commit ea578d4eb182174fcd5c5ca6b29265249beaa83e) --- .../audio/src/bap_broadcast_assistant_test.c | 3 ++- .../audio/src/bap_unicast_client_test.c | 17 ++++++++++++++++- tests/bsim/bluetooth/audio/src/common.c | 19 +++++++++++-------- tests/bsim/bluetooth/audio/src/common.h | 3 +-- .../bluetooth/audio/src/has_client_test.c | 4 +++- .../bluetooth/audio/src/ias_client_test.c | 4 +++- tests/bsim/bluetooth/audio/src/mcc_test.c | 4 +++- .../audio/src/media_controller_test.c | 4 +++- .../bluetooth/audio/src/micp_mic_ctlr_test.c | 4 +++- .../audio/src/pacs_notify_client_test.c | 6 ++++-- tests/bsim/bluetooth/audio/src/tbs_test.c | 3 ++- .../bluetooth/audio/src/vcp_vol_ctlr_test.c | 3 ++- 12 files changed, 53 insertions(+), 21 deletions(-) diff --git a/tests/bsim/bluetooth/audio/src/bap_broadcast_assistant_test.c b/tests/bsim/bluetooth/audio/src/bap_broadcast_assistant_test.c index 381810d68db..9964bd29c0a 100644 --- a/tests/bsim/bluetooth/audio/src/bap_broadcast_assistant_test.c +++ b/tests/bsim/bluetooth/audio/src/bap_broadcast_assistant_test.c @@ -490,9 +490,10 @@ static int common_init(void) bt_gatt_cb_register(&gatt_callbacks); bt_bap_broadcast_assistant_register_cb(&broadcast_assistant_cbs); bt_le_per_adv_sync_cb_register(&sync_callbacks); + bt_le_scan_cb_register(&common_scan_cb); printk("Starting scan\n"); - err = bt_le_scan_start(BT_LE_SCAN_PASSIVE, device_found); + err = bt_le_scan_start(BT_LE_SCAN_PASSIVE, NULL); if (err != 0) { FAIL("Scanning failed to start (err %d)\n", err); return err; diff --git a/tests/bsim/bluetooth/audio/src/bap_unicast_client_test.c b/tests/bsim/bluetooth/audio/src/bap_unicast_client_test.c index e31c092684a..72aa1cfcd96 100644 --- a/tests/bsim/bluetooth/audio/src/bap_unicast_client_test.c +++ b/tests/bsim/bluetooth/audio/src/bap_unicast_client_test.c @@ -320,6 +320,7 @@ static void init(void) g_streams[i].ops = &stream_ops; } + bt_le_scan_cb_register(&common_scan_cb); bt_gatt_cb_register(&gatt_callbacks); err = bt_bap_unicast_client_register_cb(&unicast_client_cbs); @@ -333,7 +334,7 @@ static void scan_and_connect(void) { int err; - err = bt_le_scan_start(BT_LE_SCAN_PASSIVE, device_found); + err = bt_le_scan_start(BT_LE_SCAN_PASSIVE, NULL); if (err != 0) { FAIL("Scanning failed to start (err %d)\n", err); return; @@ -343,6 +344,19 @@ static void scan_and_connect(void) WAIT_FOR_FLAG(flag_connected); } +static void disconnect_acl(void) +{ + int err; + + err = bt_conn_disconnect(default_conn, BT_HCI_ERR_REMOTE_USER_TERM_CONN); + if (err != 0) { + FAIL("Failed to disconnect (err %d)\n", err); + return; + } + + WAIT_FOR_UNSET_FLAG(flag_connected); +} + static void exchange_mtu(void) { WAIT_FOR_FLAG(flag_mtu_exchanged); @@ -748,6 +762,7 @@ static void test_main(void) unicast_group = NULL; } + disconnect_acl(); PASS("Unicast client passed\n"); } diff --git a/tests/bsim/bluetooth/audio/src/common.c b/tests/bsim/bluetooth/audio/src/common.c index 30758e01732..90a8cb98efa 100644 --- a/tests/bsim/bluetooth/audio/src/common.c +++ b/tests/bsim/bluetooth/audio/src/common.c @@ -16,8 +16,7 @@ const struct bt_data ad[AD_SIZE] = { BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)) }; -void device_found(const bt_addr_le_t *addr, int8_t rssi, uint8_t type, - struct net_buf_simple *ad) +static void device_found(const struct bt_le_scan_recv_info *info, struct net_buf_simple *ad) { char addr_str[BT_ADDR_LE_STR_LEN]; int err; @@ -27,15 +26,15 @@ void device_found(const bt_addr_le_t *addr, int8_t rssi, uint8_t type, } /* We're only interested in connectable events */ - if (type != BT_HCI_ADV_IND && type != BT_HCI_ADV_DIRECT_IND) { + if ((info->adv_props & BT_GAP_ADV_PROP_CONNECTABLE) == 0) { return; } - bt_addr_le_to_str(addr, addr_str, sizeof(addr_str)); - printk("Device found: %s (RSSI %d)\n", addr_str, rssi); + bt_addr_le_to_str(info->addr, addr_str, sizeof(addr_str)); + printk("Device found: %s (RSSI %d)\n", addr_str, info->rssi); /* connect only to devices in close proximity */ - if (rssi < -70) { + if (info->rssi < -70) { FAIL("RSSI too low"); return; } @@ -46,13 +45,17 @@ void device_found(const bt_addr_le_t *addr, int8_t rssi, uint8_t type, return; } - err = bt_conn_le_create(addr, BT_CONN_LE_CREATE_CONN, - BT_LE_CONN_PARAM_DEFAULT, &default_conn); + err = bt_conn_le_create(info->addr, BT_CONN_LE_CREATE_CONN, BT_LE_CONN_PARAM_DEFAULT, + &default_conn); if (err) { FAIL("Could not connect to peer: %d", err); } } +struct bt_le_scan_cb common_scan_cb = { + .recv = device_found, +}; + static void connected(struct bt_conn *conn, uint8_t err) { char addr[BT_ADDR_LE_STR_LEN]; diff --git a/tests/bsim/bluetooth/audio/src/common.h b/tests/bsim/bluetooth/audio/src/common.h index 917a024b724..14d6dbbc092 100644 --- a/tests/bsim/bluetooth/audio/src/common.h +++ b/tests/bsim/bluetooth/audio/src/common.h @@ -65,13 +65,12 @@ #define SYNC_RETRY_COUNT 6 /* similar to retries for connections */ #define PA_SYNC_SKIP 5 +extern struct bt_le_scan_cb common_scan_cb; extern const struct bt_data ad[AD_SIZE]; extern struct bt_conn *default_conn; extern atomic_t flag_connected; extern atomic_t flag_conn_updated; -void device_found(const bt_addr_le_t *addr, int8_t rssi, uint8_t type, - struct net_buf_simple *ad); void disconnected(struct bt_conn *conn, uint8_t reason); void test_tick(bs_time_t HW_device_time); void test_init(void); diff --git a/tests/bsim/bluetooth/audio/src/has_client_test.c b/tests/bsim/bluetooth/audio/src/has_client_test.c index 9d63463e0ce..6690c6b032e 100644 --- a/tests/bsim/bluetooth/audio/src/has_client_test.c +++ b/tests/bsim/bluetooth/audio/src/has_client_test.c @@ -157,7 +157,9 @@ static void test_main(void) return; } - err = bt_le_scan_start(BT_LE_SCAN_PASSIVE, device_found); + bt_le_scan_cb_register(&common_scan_cb); + + err = bt_le_scan_start(BT_LE_SCAN_PASSIVE, NULL); if (err < 0) { FAIL("Scanning failed to start (err %d)\n", err); return; diff --git a/tests/bsim/bluetooth/audio/src/ias_client_test.c b/tests/bsim/bluetooth/audio/src/ias_client_test.c index 2c5dbd40bd0..7c24b1a172a 100644 --- a/tests/bsim/bluetooth/audio/src/ias_client_test.c +++ b/tests/bsim/bluetooth/audio/src/ias_client_test.c @@ -83,7 +83,9 @@ static void test_main(void) return; } - err = bt_le_scan_start(BT_LE_SCAN_PASSIVE, device_found); + bt_le_scan_cb_register(&common_scan_cb); + + err = bt_le_scan_start(BT_LE_SCAN_PASSIVE, NULL); if (err < 0) { FAIL("Scanning failed to start (err %d)\n", err); return; diff --git a/tests/bsim/bluetooth/audio/src/mcc_test.c b/tests/bsim/bluetooth/audio/src/mcc_test.c index 8a32e33bf16..9e8cd95806b 100644 --- a/tests/bsim/bluetooth/audio/src/mcc_test.c +++ b/tests/bsim/bluetooth/audio/src/mcc_test.c @@ -2396,6 +2396,8 @@ void test_main(void) printk("Bluetooth initialized\n"); + bt_le_scan_cb_register(&common_scan_cb); + /* Initialize MCC ********************************************/ err = do_mcc_init(); if (err != 0) { @@ -2414,7 +2416,7 @@ void test_main(void) printk("\n########### Running iteration #%u\n\n", i); UNSET_FLAG(flag_connected); - err = bt_le_scan_start(BT_LE_SCAN_PASSIVE, device_found); + err = bt_le_scan_start(BT_LE_SCAN_PASSIVE, NULL); if (err != 0) { FAIL("Failed to start scanning (err %d\n)", err); } else { diff --git a/tests/bsim/bluetooth/audio/src/media_controller_test.c b/tests/bsim/bluetooth/audio/src/media_controller_test.c index 9c1df656fd1..ad91cffb939 100644 --- a/tests/bsim/bluetooth/audio/src/media_controller_test.c +++ b/tests/bsim/bluetooth/audio/src/media_controller_test.c @@ -1585,6 +1585,8 @@ void initialize_bluetooth(void) WAIT_FOR_FLAG(ble_is_initialized); printk("Bluetooth initialized\n"); + + bt_le_scan_cb_register(&common_scan_cb); } void scan_and_connect(void) @@ -1592,7 +1594,7 @@ void scan_and_connect(void) char addr[BT_ADDR_LE_STR_LEN]; int err; - err = bt_le_scan_start(BT_LE_SCAN_PASSIVE, device_found); + err = bt_le_scan_start(BT_LE_SCAN_PASSIVE, NULL); if (err) { FAIL("Failed to start scanning (err %d\n)", err); return; diff --git a/tests/bsim/bluetooth/audio/src/micp_mic_ctlr_test.c b/tests/bsim/bluetooth/audio/src/micp_mic_ctlr_test.c index 1074c8c2cef..5cefd31d099 100644 --- a/tests/bsim/bluetooth/audio/src/micp_mic_ctlr_test.c +++ b/tests/bsim/bluetooth/audio/src/micp_mic_ctlr_test.c @@ -357,11 +357,13 @@ static void test_main(void) return; } + bt_le_scan_cb_register(&common_scan_cb); + bt_micp_mic_ctlr_cb_register(&micp_mic_ctlr_cbs); WAIT_FOR_COND(g_bt_init); - err = bt_le_scan_start(BT_LE_SCAN_PASSIVE, device_found); + err = bt_le_scan_start(BT_LE_SCAN_PASSIVE, NULL); if (err != 0) { FAIL("Scanning failed to start (err %d)\n", err); return; diff --git a/tests/bsim/bluetooth/audio/src/pacs_notify_client_test.c b/tests/bsim/bluetooth/audio/src/pacs_notify_client_test.c index 7cbe5feaa22..9910f6f2c8c 100644 --- a/tests/bsim/bluetooth/audio/src/pacs_notify_client_test.c +++ b/tests/bsim/bluetooth/audio/src/pacs_notify_client_test.c @@ -490,8 +490,10 @@ static void test_main(void) return; } + bt_le_scan_cb_register(&common_scan_cb); + printk("Starting scan\n"); - err = bt_le_scan_start(BT_LE_SCAN_PASSIVE, device_found); + err = bt_le_scan_start(BT_LE_SCAN_PASSIVE, NULL); if (err != 0) { FAIL("Could not start scanning (err %d)\n", err); return; @@ -536,7 +538,7 @@ static void test_main(void) WAIT_FOR_UNSET_FLAG(flag_connected); printk("Starting scan\n"); - err = bt_le_scan_start(BT_LE_SCAN_PASSIVE, device_found); + err = bt_le_scan_start(BT_LE_SCAN_PASSIVE, NULL); if (err != 0) { FAIL("Could not start scanning (err %d)\n", err); return; diff --git a/tests/bsim/bluetooth/audio/src/tbs_test.c b/tests/bsim/bluetooth/audio/src/tbs_test.c index b20dca26608..a1bf1e035c0 100644 --- a/tests/bsim/bluetooth/audio/src/tbs_test.c +++ b/tests/bsim/bluetooth/audio/src/tbs_test.c @@ -331,9 +331,10 @@ static void test_main(void) printk("Audio Client: Bluetooth initialized\n"); bt_conn_cb_register(&conn_callbacks); + bt_le_scan_cb_register(&common_scan_cb); bt_tbs_register_cb(&tbs_cbs); - err = bt_le_scan_start(BT_LE_SCAN_PASSIVE, device_found); + err = bt_le_scan_start(BT_LE_SCAN_PASSIVE, NULL); if (err != 0) { FAIL("Scanning failed to start (err %d)\n", err); return; diff --git a/tests/bsim/bluetooth/audio/src/vcp_vol_ctlr_test.c b/tests/bsim/bluetooth/audio/src/vcp_vol_ctlr_test.c index 52ba2f072ab..77feaa4bfb5 100644 --- a/tests/bsim/bluetooth/audio/src/vcp_vol_ctlr_test.c +++ b/tests/bsim/bluetooth/audio/src/vcp_vol_ctlr_test.c @@ -1153,9 +1153,10 @@ static void test_main(void) return; } + bt_le_scan_cb_register(&common_scan_cb); test_cb_register(); - err = bt_le_scan_start(BT_LE_SCAN_PASSIVE, device_found); + err = bt_le_scan_start(BT_LE_SCAN_PASSIVE, NULL); if (err != 0) { FAIL("Scanning failed to start (err %d)\n", err); return; From 44ae4b554d43483324be575a189a4640a98437b6 Mon Sep 17 00:00:00 2001 From: Emil Gydesen Date: Wed, 13 Sep 2023 16:58:54 +0200 Subject: [PATCH 077/421] [nrf fromtree] tests: bsim: Bluetooth: Add BAP unicast disconnect test The purpose of this test is to verify that the stack has the correct behavior if the ACL disconnects while one or more streams are in the streaming state. The main point it validates is that unicast server device can restart advertising using a simple k_work in the disconnected callback. The number of connections supported by the test suite has also been reduced to 3, to avoid some seen issues with scheduling when CONFIG_BT_MAX_CONN=5. A part of implementing the test for this purpose, the unicast client and unicast server have been extended to also advertise and scan for proper ASCS advertising data. Signed-off-by: Emil Gydesen (cherry picked from commit 01f7d108f3d1982549535f6fe4c7096b188cb3ed) Signed-off-by: Dominik Ermel (cherry picked from commit be34d58d76f42791990927f628beef1623a6cd54) --- tests/bsim/bluetooth/audio/prj.conf | 5 +- .../audio/src/bap_unicast_client_test.c | 149 ++++++++++++- .../audio/src/bap_unicast_server_test.c | 201 +++++++++++++----- .../bap_unicast_audio_acl_disconnect.sh | 27 +++ 4 files changed, 328 insertions(+), 54 deletions(-) create mode 100755 tests/bsim/bluetooth/audio/test_scripts/bap_unicast_audio_acl_disconnect.sh diff --git a/tests/bsim/bluetooth/audio/prj.conf b/tests/bsim/bluetooth/audio/prj.conf index 2077143452b..8f2d6a585a9 100644 --- a/tests/bsim/bluetooth/audio/prj.conf +++ b/tests/bsim/bluetooth/audio/prj.conf @@ -9,8 +9,9 @@ CONFIG_BT_DEVICE_NAME="bsim_test_audio" # TBS Client may require up to 12 buffers CONFIG_BT_L2CAP_TX_BUF_COUNT=12 CONFIG_BT_ATT_PREPARE_COUNT=5 -CONFIG_BT_MAX_CONN=5 -CONFIG_BT_MAX_PAIRED=5 +CONFIG_BT_MAX_CONN=3 +CONFIG_BT_MAX_PAIRED=3 +CONFIG_BT_EXT_ADV_MAX_ADV_SET=3 CONFIG_BT_GATT_DYNAMIC_DB=y CONFIG_BT_SMP=y CONFIG_BT_L2CAP_TX_MTU=100 diff --git a/tests/bsim/bluetooth/audio/src/bap_unicast_client_test.c b/tests/bsim/bluetooth/audio/src/bap_unicast_client_test.c index 72aa1cfcd96..3fbd70458b9 100644 --- a/tests/bsim/bluetooth/audio/src/bap_unicast_client_test.c +++ b/tests/bsim/bluetooth/audio/src/bap_unicast_client_test.c @@ -306,6 +306,92 @@ static struct bt_gatt_cb gatt_callbacks = { .att_mtu_updated = att_mtu_updated, }; +static bool parse_ascs_ad_data(struct bt_data *data, void *user_data) +{ + const struct bt_le_scan_recv_info *info = user_data; + uint16_t available_source_context; + uint16_t available_sink_context; + struct net_buf_simple net_buf; + struct bt_uuid_16 adv_uuid; + uint8_t announcement_type; + void *uuid; + int err; + + const size_t min_data_len = BT_UUID_SIZE_16 + sizeof(announcement_type) + + sizeof(available_sink_context) + + sizeof(available_source_context); + + if (data->type != BT_DATA_SVC_DATA16) { + return true; + } + + if (data->data_len < min_data_len) { + + return true; + } + + net_buf_simple_init_with_data(&net_buf, (void *)data->data, data->data_len); + + uuid = net_buf_simple_pull_mem(&net_buf, BT_UUID_SIZE_16); + if (!bt_uuid_create(&adv_uuid.uuid, uuid, BT_UUID_SIZE_16)) { + return true; + } + + if (bt_uuid_cmp(&adv_uuid.uuid, BT_UUID_ASCS)) { + return true; + } + + announcement_type = net_buf_simple_pull_u8(&net_buf); + available_sink_context = net_buf_simple_pull_le16(&net_buf); + available_source_context = net_buf_simple_pull_le16(&net_buf); + + printk("Found ASCS with announcement type 0x%02X, sink ctx 0x%04X, source ctx 0x%04X\n", + announcement_type, available_sink_context, available_source_context); + + printk("Stopping scan\n"); + if (bt_le_scan_stop()) { + FAIL("Could not stop scan"); + return false; + } + + err = bt_conn_le_create(info->addr, BT_CONN_LE_CREATE_CONN, BT_LE_CONN_PARAM_DEFAULT, + &default_conn); + if (err) { + FAIL("Could not connect to peer: %d", err); + return false; + } + + /* Stop parsing */ + return false; +} + +static void broadcast_scan_recv(const struct bt_le_scan_recv_info *info, struct net_buf_simple *ad) +{ + char addr_str[BT_ADDR_LE_STR_LEN]; + + if (default_conn) { + return; + } + + /* We're only interested in connectable events */ + if ((info->adv_props & BT_GAP_ADV_PROP_CONNECTABLE) == 0) { + return; + } + /* connect only to devices in close proximity */ + if (info->rssi < -70) { + return; + } + + bt_addr_le_to_str(info->addr, addr_str, sizeof(addr_str)); + printk("Device found: %s (RSSI %d)\n", addr_str, info->rssi); + + bt_data_parse(ad, parse_ascs_ad_data, (void *)info); +} + +static struct bt_le_scan_cb bap_scan_cb = { + .recv = broadcast_scan_recv, +}; + static void init(void) { int err; @@ -320,7 +406,7 @@ static void init(void) g_streams[i].ops = &stream_ops; } - bt_le_scan_cb_register(&common_scan_cb); + bt_le_scan_cb_register(&bap_scan_cb); bt_gatt_cb_register(&gatt_callbacks); err = bt_bap_unicast_client_register_cb(&unicast_client_cbs); @@ -767,14 +853,71 @@ static void test_main(void) PASS("Unicast client passed\n"); } +static void test_main_acl_disconnect(void) +{ + struct bt_bap_unicast_group *unicast_group; + size_t stream_cnt; + + init(); + + scan_and_connect(); + + exchange_mtu(); + + discover_sinks(); + + discover_sources(); + + /* Run the stream setup multiple time to ensure states are properly + * set and reset + */ + + printk("Creating unicast group\n"); + stream_cnt = create_unicast_group(&unicast_group); + + printk("Codec configuring streams\n"); + codec_configure_streams(stream_cnt); + + printk("QoS configuring streams\n"); + qos_configure_streams(unicast_group, stream_cnt); + + printk("Enabling streams\n"); + enable_streams(stream_cnt); + + printk("Metadata update streams\n"); + metadata_update_streams(stream_cnt); + + printk("Starting streams\n"); + start_streams(); + + disconnect_acl(); + + printk("Deleting unicast group\n"); + delete_unicast_group(unicast_group); + unicast_group = NULL; + + /* Reconnect */ + scan_and_connect(); + + disconnect_acl(); + + PASS("Unicast client ACL disconnect passed\n"); +} + static const struct bst_test_instance test_unicast_client[] = { { .test_id = "unicast_client", .test_post_init_f = test_init, .test_tick_f = test_tick, - .test_main_f = test_main + .test_main_f = test_main, + }, + { + .test_id = "unicast_client_acl_disconnect", + .test_post_init_f = test_init, + .test_tick_f = test_tick, + .test_main_f = test_main_acl_disconnect, }, - BSTEST_END_MARKER + BSTEST_END_MARKER, }; struct bst_test_list *test_unicast_client_install(struct bst_test_list *tests) diff --git a/tests/bsim/bluetooth/audio/src/bap_unicast_server_test.c b/tests/bsim/bluetooth/audio/src/bap_unicast_server_test.c index c302ec320ab..58acdc1726c 100644 --- a/tests/bsim/bluetooth/audio/src/bap_unicast_server_test.c +++ b/tests/bsim/bluetooth/audio/src/bap_unicast_server_test.c @@ -48,11 +48,20 @@ static struct bt_bap_stream streams[CONFIG_BT_ASCS_ASE_SNK_COUNT + CONFIG_BT_ASC static const struct bt_audio_codec_qos_pref qos_pref = BT_AUDIO_CODEC_QOS_PREF(true, BT_GAP_LE_PHY_2M, 0x02, 10, 40000, 40000, 40000, 40000); -/* TODO: Expand with BAP data */ +static uint8_t unicast_server_addata[] = { + BT_UUID_16_ENCODE(BT_UUID_ASCS_VAL), /* ASCS UUID */ + BT_AUDIO_UNICAST_ANNOUNCEMENT_TARGETED, /* Target Announcement */ + BT_BYTES_LIST_LE16(PREF_CONTEXT), + BT_BYTES_LIST_LE16(PREF_CONTEXT), + 0x00, /* Metadata length */ +}; + static const struct bt_data unicast_server_ad[] = { BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)), BT_DATA_BYTES(BT_DATA_UUID16_ALL, BT_UUID_16_ENCODE(BT_UUID_ASCS_VAL)), + BT_DATA(BT_DATA_SVC_DATA16, unicast_server_addata, ARRAY_SIZE(unicast_server_addata)), }; +static struct bt_le_ext_adv *ext_adv; CREATE_FLAG(flag_stream_configured); @@ -230,47 +239,6 @@ static struct bt_bap_stream_ops stream_ops = { .recv = stream_recv }; -static void init(void) -{ - static struct bt_pacs_cap cap = { - .codec_cap = &lc3_codec_cap, - }; - int err; - - err = bt_enable(NULL); - if (err != 0) { - FAIL("Bluetooth enable failed (err %d)\n", err); - return; - } - - printk("Bluetooth initialized\n"); - - bt_bap_unicast_server_register_cb(&unicast_server_cb); - - err = bt_pacs_cap_register(BT_AUDIO_DIR_SINK, &cap); - if (err != 0) { - FAIL("Failed to register capabilities: %d", err); - return; - } - - err = bt_pacs_cap_register(BT_AUDIO_DIR_SOURCE, &cap); - if (err != 0) { - FAIL("Failed to register capabilities: %d", err); - return; - } - - for (size_t i = 0; i < ARRAY_SIZE(streams); i++) { - bt_bap_stream_cb_register(&streams[i], &stream_ops); - } - - err = bt_le_adv_start(BT_LE_ADV_CONN_NAME, unicast_server_ad, ARRAY_SIZE(unicast_server_ad), - NULL, 0); - if (err != 0) { - FAIL("Advertising failed to start (err %d)\n", err); - return; - } -} - static void set_location(void) { int err; @@ -332,25 +300,160 @@ static void set_available_contexts(void) printk("Available contexts successfully set\n"); } -static void test_main(void) +static void init(void) { - init(); + static struct bt_pacs_cap cap = { + .codec_cap = &lc3_codec_cap, + }; + int err; + + err = bt_enable(NULL); + if (err != 0) { + FAIL("Bluetooth enable failed (err %d)\n", err); + return; + } + + printk("Bluetooth initialized\n"); + + bt_bap_unicast_server_register_cb(&unicast_server_cb); + + err = bt_pacs_cap_register(BT_AUDIO_DIR_SINK, &cap); + if (err != 0) { + FAIL("Failed to register capabilities: %d", err); + return; + } + + err = bt_pacs_cap_register(BT_AUDIO_DIR_SOURCE, &cap); + if (err != 0) { + FAIL("Failed to register capabilities: %d", err); + return; + } set_location(); set_available_contexts(); + for (size_t i = 0; i < ARRAY_SIZE(streams); i++) { + bt_bap_stream_cb_register(&streams[i], &stream_ops); + } + + /* Create a non-connectable non-scannable advertising set */ + err = bt_le_ext_adv_create(BT_LE_EXT_ADV_CONN_NAME, NULL, &ext_adv); + if (err != 0) { + FAIL("Failed to create advertising set (err %d)\n", err); + return; + } + + err = bt_le_ext_adv_set_data(ext_adv, unicast_server_ad, ARRAY_SIZE(unicast_server_ad), + NULL, 0); + if (err != 0) { + FAIL("Failed to set advertising data (err %d)\n", err); + return; + } + + err = bt_le_ext_adv_start(ext_adv, BT_LE_EXT_ADV_START_DEFAULT); + if (err != 0) { + FAIL("Failed to start advertising set (err %d)\n", err); + return; + } + printk("Advertising started\n"); +} + +static void test_main(void) +{ + init(); + /* TODO: When babblesim supports ISO, wait for audio stream to pass */ WAIT_FOR_FLAG(flag_connected); WAIT_FOR_FLAG(flag_stream_configured); + + WAIT_FOR_UNSET_FLAG(flag_connected); + PASS("Unicast server passed\n"); } -static const struct bst_test_instance test_unicast_server[] = {{.test_id = "unicast_server", - .test_post_init_f = test_init, - .test_tick_f = test_tick, - .test_main_f = test_main}, - BSTEST_END_MARKER}; +static void restart_adv_cb(struct k_work *work) +{ + int err; + + printk("Restarting ext_adv after disconnect\n"); + + err = bt_le_ext_adv_start(ext_adv, BT_LE_EXT_ADV_START_DEFAULT); + if (err != 0) { + FAIL("Failed to start advertising set (err %d)\n", err); + return; + } +} + +static K_WORK_DEFINE(restart_adv_work, restart_adv_cb); + +static void acl_disconnected(struct bt_conn *conn, uint8_t reason) +{ + if (conn != default_conn) { + return; + } + + k_work_submit(&restart_adv_work); +} + +static void test_main_acl_disconnect(void) +{ + struct bt_le_ext_adv *dummy_ext_adv[CONFIG_BT_MAX_CONN - 1]; + static struct bt_conn_cb conn_callbacks = { + .disconnected = acl_disconnected, + }; + + init(); + + /* Create CONFIG_BT_MAX_CONN - 1 dummy advertising sets, to ensure that we only have 1 free + * connection when attempting to restart advertising, which should ensure that the + * bt_conn object is properly unref'ed by the stack + */ + for (size_t i = 0U; i < ARRAY_SIZE(dummy_ext_adv); i++) { + const struct bt_le_adv_param param = BT_LE_ADV_PARAM_INIT( + (BT_LE_ADV_OPT_EXT_ADV | BT_LE_ADV_OPT_CONNECTABLE), + BT_GAP_ADV_SLOW_INT_MAX, BT_GAP_ADV_SLOW_INT_MAX, NULL); + int err; + + err = bt_le_ext_adv_create(¶m, NULL, &dummy_ext_adv[i]); + if (err != 0) { + FAIL("Failed to create advertising set[%zu] (err %d)\n", i, err); + return; + } + + err = bt_le_ext_adv_start(dummy_ext_adv[i], BT_LE_EXT_ADV_START_DEFAULT); + if (err != 0) { + FAIL("Failed to start advertising set[%zu] (err %d)\n", i, err); + return; + } + } + + bt_conn_cb_register(&conn_callbacks); + + WAIT_FOR_FLAG(flag_connected); + WAIT_FOR_FLAG(flag_stream_configured); + + /* The client will reconnect */ + WAIT_FOR_UNSET_FLAG(flag_connected); + WAIT_FOR_FLAG(flag_connected); + PASS("Unicast server ACL disconnect passed\n"); +} + +static const struct bst_test_instance test_unicast_server[] = { + { + .test_id = "unicast_server", + .test_post_init_f = test_init, + .test_tick_f = test_tick, + .test_main_f = test_main, + }, + { + .test_id = "unicast_server_acl_disconnect", + .test_post_init_f = test_init, + .test_tick_f = test_tick, + .test_main_f = test_main_acl_disconnect, + }, + BSTEST_END_MARKER, +}; struct bst_test_list *test_unicast_server_install(struct bst_test_list *tests) { diff --git a/tests/bsim/bluetooth/audio/test_scripts/bap_unicast_audio_acl_disconnect.sh b/tests/bsim/bluetooth/audio/test_scripts/bap_unicast_audio_acl_disconnect.sh new file mode 100755 index 00000000000..875a2b752dc --- /dev/null +++ b/tests/bsim/bluetooth/audio/test_scripts/bap_unicast_audio_acl_disconnect.sh @@ -0,0 +1,27 @@ +#!/usr/bin/env bash +# +# Copyright (c) 2023 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: Apache-2.0 + +SIMULATION_ID="unicast_audio_acl_disconnect" +VERBOSITY_LEVEL=2 +EXECUTE_TIMEOUT=20 + +source ${ZEPHYR_BASE}/tests/bsim/sh_common.source + +cd ${BSIM_OUT_PATH}/bin + +printf "\n\n======== Unicast Audio ACL Disconnect test =========\n\n" + +Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \ + -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=0 -testid=unicast_client_acl_disconnect -rs=23 + +Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \ + -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=1 -testid=unicast_server_acl_disconnect -rs=28 + +# Simulation time should be larger than the WAIT_TIME in common.h +Execute ./bs_2G4_phy_v1 -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} \ + -D=2 -sim_length=60e6 $@ + +wait_for_background_jobs From 71c7ace4d8da9c5e88b729e3f1dabde5f330f184 Mon Sep 17 00:00:00 2001 From: Emil Gydesen Date: Wed, 13 Sep 2023 17:02:45 +0200 Subject: [PATCH 078/421] [nrf fromtree] Bluetooth: ASCS: Modify the ACL disconnect behavior Instead of calling ase_release for each ASE in the ACL disconnected callback, we now call the state_transition_work_handler directly. This is to ensure that when the disconnected callback returns, the bt_conn object has been properly unref'ed in a timely manner. Signed-off-by: Emil Gydesen (cherry picked from commit c3c83c7049337f2ab1b6889ad83cb922457a3185) Signed-off-by: Dominik Ermel (cherry picked from commit df75d0300edec2fd1935fb5f7103b9e30f8e2942) --- subsys/bluetooth/audio/ascs.c | 14 +++++++++++++- tests/bluetooth/audio/ascs/src/main.c | 4 ---- tests/bluetooth/audio/mocks/src/kernel.c | 7 +++++++ 3 files changed, 20 insertions(+), 5 deletions(-) diff --git a/subsys/bluetooth/audio/ascs.c b/subsys/bluetooth/audio/ascs.c index 9b45754fe90..d85a90ec77a 100644 --- a/subsys/bluetooth/audio/ascs.c +++ b/subsys/bluetooth/audio/ascs.c @@ -119,6 +119,8 @@ static void ase_free(struct bt_ascs_ase *ase) bt_conn_unref(ase->conn); ase->conn = NULL; + + (void)k_work_cancel(&ase->state_transition_work); } static void ase_status_changed(struct bt_ascs_ase *ase, uint8_t state) @@ -1094,7 +1096,17 @@ static void disconnected(struct bt_conn *conn, uint8_t reason) } if (ase->ep.status.state != BT_BAP_EP_STATE_IDLE) { - ase_release(ase, reason, BT_BAP_ASCS_RSP_NULL); + /* We must set the state to idle when the ACL is disconnected immediately, + * as when the ACL disconnect callbacks have been called, the application + * should expect there to be only a single reference to the bt_conn pointer + * from the stack. + * We trigger the work handler directly rather than e.g. calling + * ase_set_state_idle to trigger "regular" state change behavior (such) as + * calling stream->stopped when leaving the streaming state. + */ + ase->ep.reason = reason; + ase->state_pending = BT_BAP_EP_STATE_IDLE; + state_transition_work_handler(&ase->state_transition_work); /* At this point, `ase` object have been free'd */ } } diff --git a/tests/bluetooth/audio/ascs/src/main.c b/tests/bluetooth/audio/ascs/src/main.c index b0bc7f88150..126c82d63bb 100644 --- a/tests/bluetooth/audio/ascs/src/main.c +++ b/tests/bluetooth/audio/ascs/src/main.c @@ -250,7 +250,6 @@ ZTEST_F(ascs_test_suite, test_release_ase_on_acl_disconnection_client_terminates mock_bt_iso_disconnected(chan, BT_HCI_ERR_REMOTE_USER_TERM_CONN); /* Expected to notify the upper layers */ - expect_bt_bap_unicast_server_cb_release_called_once(stream); expect_bt_bap_stream_ops_released_called_once(stream); bt_bap_unicast_server_unregister_cb(&mock_bap_unicast_server_cb); @@ -288,7 +287,6 @@ ZTEST_F(ascs_test_suite, test_release_ase_on_acl_disconnection_server_terminates k_sleep(K_MSEC(CONFIG_BT_ASCS_ISO_DISCONNECT_DELAY)); /* Expected to notify the upper layers */ - expect_bt_bap_unicast_server_cb_release_called_once(stream); expect_bt_bap_stream_ops_released_called_once(stream); bt_bap_unicast_server_unregister_cb(&mock_bap_unicast_server_cb); @@ -351,7 +349,6 @@ ZTEST_F(ascs_test_suite, test_release_stream_pair_on_acl_disconnection_client_te const struct bt_bap_stream *streams[2] = { &snk_stream, &src_stream }; expect_bt_bap_stream_ops_released_called_twice(streams); - expect_bt_bap_unicast_server_cb_release_called_twice(streams); bt_bap_unicast_server_unregister_cb(&mock_bap_unicast_server_cb); } @@ -413,7 +410,6 @@ ZTEST_F(ascs_test_suite, test_release_stream_pair_on_acl_disconnection_server_te const struct bt_bap_stream *streams[2] = { &snk_stream, &src_stream }; expect_bt_bap_stream_ops_released_called_twice(streams); - expect_bt_bap_unicast_server_cb_release_called_twice(streams); bt_bap_unicast_server_unregister_cb(&mock_bap_unicast_server_cb); } diff --git a/tests/bluetooth/audio/mocks/src/kernel.c b/tests/bluetooth/audio/mocks/src/kernel.c index ce9dcab5d3a..03dc2cf582d 100644 --- a/tests/bluetooth/audio/mocks/src/kernel.c +++ b/tests/bluetooth/audio/mocks/src/kernel.c @@ -56,6 +56,13 @@ int k_work_cancel_delayable(struct k_work_delayable *dwork) return 0; } +int k_work_cancel(struct k_work *work) +{ + (void)sys_slist_find_and_remove(&work_pending, &work->node); + + return 0; +} + void k_work_init(struct k_work *work, k_work_handler_t handler) { work->handler = handler; From 5bb619da835338caa595cdfb90453e8f833effaa Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Thu, 21 Sep 2023 18:51:32 +0000 Subject: [PATCH 079/421] [nrf noup] modules: mbedtls: Use psa_util.c only with non-nRF Adds the psa_util.c conditionally, where needed. Signed-off-by: Dominik Ermel (cherry picked from commit edf807fd47cd6c3ab71c020363888fe73f2cc776) --- modules/mbedtls/CMakeLists.txt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/modules/mbedtls/CMakeLists.txt b/modules/mbedtls/CMakeLists.txt index f061605c027..c1c8e076b83 100644 --- a/modules/mbedtls/CMakeLists.txt +++ b/modules/mbedtls/CMakeLists.txt @@ -76,7 +76,6 @@ zephyr_interface_library_named(mbedTLS) ${ZEPHYR_CURRENT_MODULE_DIR}/library/mps_reader.c ${ZEPHYR_CURRENT_MODULE_DIR}/library/mps_trace.c ${ZEPHYR_CURRENT_MODULE_DIR}/library/poly1305.c - ${ZEPHYR_CURRENT_MODULE_DIR}/library/psa_util.c ${ZEPHYR_CURRENT_MODULE_DIR}/library/ripemd160.c ${ZEPHYR_CURRENT_MODULE_DIR}/library/rsa_alt_helpers.c ${ZEPHYR_CURRENT_MODULE_DIR}/library/rsa.c @@ -89,6 +88,10 @@ zephyr_interface_library_named(mbedTLS) zephyr_init.c ) + if (NOT DEFINED ZEPHYR_NRF_MODULE_DIR) + list(APPEND mbedtls_base_src ${ZEPHYR_CURRENT_MODULE_DIR}/library/psa_util.c) + endif() + zephyr_library_sources(${mbedtls_base_src}) zephyr_library_sources_ifdef(CONFIG_MBEDTLS_DEBUG debug.c) From 0b79df6d821b2f77d65f80c5fe411ec15b273768 Mon Sep 17 00:00:00 2001 From: Florian Grandel Date: Fri, 11 Aug 2023 16:50:28 +0200 Subject: [PATCH 080/421] [nrf fromtree] modules: openthread: radio: OT now uses standard TX timestamp Synchronizes with the new upstream RX/TX timestamp definition in OpenThread based on the standard's SFD. This change is synchronized with the upstream OpenThread implementation via west.yml. Signed-off-by: Florian Grandel (cherry picked from commit e2005b6e48d3b578f83fdfaaff547d1f8082ce35) Signed-off-by: Maciej Baczmanski (cherry picked from commit d62a2c576ac0a2bd164b355cbd95aa00ede869c5) --- modules/openthread/CMakeLists.txt | 12 ++++++++++++ modules/openthread/Kconfig.features | 13 +++++++++++++ modules/openthread/platform/radio.c | 4 +--- tests/subsys/openthread/radio_test.c | 10 ++++------ west.yml | 2 +- 5 files changed, 31 insertions(+), 10 deletions(-) diff --git a/modules/openthread/CMakeLists.txt b/modules/openthread/CMakeLists.txt index 67acbe00dec..826d9b31590 100644 --- a/modules/openthread/CMakeLists.txt +++ b/modules/openthread/CMakeLists.txt @@ -154,6 +154,12 @@ else() set(OT_DATASET_UPDATER OFF CACHE BOOL "Enable Dataset updater" FORCE) endif() +if(CONFIG_OPENTHREAD_DEVICE_PROP_LEADER_WEIGHT) + set(OT_DEVICE_PROP_LEADER_WEIGHT ON CACHE BOOL "Enable device props for leader weight" FORCE) +else() + set(OT_DEVICE_PROP_LEADER_WEIGHT OFF CACHE BOOL "Enable device props for leader weight" FORCE) +endif() + if(CONFIG_OPENTHREAD_DHCP6_CLIENT) set(OT_DHCP6_CLIENT ON CACHE BOOL "Enable DHCPv6 Client" FORCE) else() @@ -274,6 +280,12 @@ else() set(OT_LINK_METRICS_INITIATOR OFF CACHE BOOL "Enable Link Metrics initiator for Thread 1.2" FORCE) endif() +if(CONFIG_OPENTHREAD_LINK_METRICS_MANAGER) + set(OT_LINK_METRICS_MANAGER ON CACHE BOOL "Enable Link Metrics manager for Thread 1.2" FORCE) +else() + set(OT_LINK_METRICS_MANAGER OFF CACHE BOOL "Enable Link Metrics manager for Thread 1.2" FORCE) +endif() + if(CONFIG_OPENTHREAD_LINK_METRICS_SUBJECT) set(OT_LINK_METRICS_SUBJECT ON CACHE BOOL "Enable Link Metrics subject for Thread 1.2" FORCE) else() diff --git a/modules/openthread/Kconfig.features b/modules/openthread/Kconfig.features index 61b0efc921b..87c220944a4 100644 --- a/modules/openthread/Kconfig.features +++ b/modules/openthread/Kconfig.features @@ -92,6 +92,16 @@ config OPENTHREAD_CSL_RECEIVER help Enable CSL Receiver support for Thread 1.2 +config OPENTHREAD_DEVICE_PROP_LEADER_WEIGHT + bool "Device props for leader weight" + default n if (OPENTHREAD_THREAD_VERSION_1_1 || \ + OPENTHREAD_THREAD_VERSION_1_2 || \ + OPENTHREAD_THREAD_VERSION_1_3) + default y + help + Enable the device properties which are then used to determine and set + the Leader Weight. + config OPENTHREAD_DATASET_UPDATER bool "Dataset updater" @@ -165,6 +175,9 @@ config OPENTHREAD_LEGACY config OPENTHREAD_LINK_METRICS_INITIATOR bool "Link Metrics initiator" +config OPENTHREAD_LINK_METRICS_MANAGER + bool "Link Metrics manager" + config OPENTHREAD_LINK_METRICS_SUBJECT bool "Link Metrics subject" diff --git a/modules/openthread/platform/radio.c b/modules/openthread/platform/radio.c index 94b79ddfed6..9d50e445714 100644 --- a/modules/openthread/platform/radio.c +++ b/modules/openthread/platform/radio.c @@ -58,8 +58,6 @@ LOG_MODULE_REGISTER(LOG_MODULE_NAME, CONFIG_OPENTHREAD_L2_LOG_LEVEL); #define CHANNEL_COUNT OT_RADIO_2P4GHZ_OQPSK_CHANNEL_MAX - OT_RADIO_2P4GHZ_OQPSK_CHANNEL_MIN + 1 -#define PHY_SHR_DURATION 160 /* duration of SHR in us */ - enum pending_events { PENDING_EVENT_FRAME_TO_SEND, /* There is a tx frame to send */ PENDING_EVENT_FRAME_RECEIVED, /* Radio has received new frame */ @@ -397,7 +395,7 @@ void transmit_message(struct k_work *tx_job) (sTransmitFrame.mInfo.mTxInfo.mTxDelay != 0)) { #if defined(CONFIG_NET_PKT_TXTIME) uint32_t tx_at = sTransmitFrame.mInfo.mTxInfo.mTxDelayBaseTime + - sTransmitFrame.mInfo.mTxInfo.mTxDelay + PHY_SHR_DURATION; + sTransmitFrame.mInfo.mTxInfo.mTxDelay; struct net_ptp_time timestamp = ns_to_net_ptp_time(convert_32bit_us_wrapped_to_64bit_ns(tx_at)); net_pkt_set_timestamp(tx_pkt, ×tamp); diff --git a/tests/subsys/openthread/radio_test.c b/tests/subsys/openthread/radio_test.c index fb6c8755039..87a7013a0d5 100644 --- a/tests/subsys/openthread/radio_test.c +++ b/tests/subsys/openthread/radio_test.c @@ -30,8 +30,6 @@ DEFINE_FFF_GLOBALS; #define FRAME_TYPE_MASK 0x07 #define FRAME_TYPE_ACK 0x02 -#define PHY_SHR_DURATION 160 - K_SEM_DEFINE(ot_sem, 0, 1); /** @@ -295,10 +293,10 @@ ZTEST(openthread_radio, test_tx_test) get_time_mock_fake.return_val = (int64_t)UINT32_MAX * NSEC_PER_USEC + 1000; frm->mInfo.mTxInfo.mTxDelayBaseTime = 3U; frm->mInfo.mTxInfo.mTxDelay = 5U; - expected_target_time = get_time_mock_fake.return_val + - (frm->mInfo.mTxInfo.mTxDelayBaseTime + - frm->mInfo.mTxInfo.mTxDelay + PHY_SHR_DURATION) * - NSEC_PER_USEC; + expected_target_time = + get_time_mock_fake.return_val + + (frm->mInfo.mTxInfo.mTxDelayBaseTime + frm->mInfo.mTxInfo.mTxDelay) * + NSEC_PER_USEC; } /* ACKed frame */ diff --git a/west.yml b/west.yml index b4f874a87c5..bed3b47cfe5 100644 --- a/west.yml +++ b/west.yml @@ -303,7 +303,7 @@ manifest: revision: 42b7c577714b8f22ce82a901e19c1814af4609a8 path: modules/lib/open-amp - name: openthread - revision: f7690fe7e9d638341921808cba6a3e695ec0131e + revision: d62167ee34b091e7025c9ec2820aae71e17a3944 path: modules/lib/openthread - name: picolibc path: modules/lib/picolibc From 9df3b459e3b507bccc1cbedc43617fdd56b98c93 Mon Sep 17 00:00:00 2001 From: Vivekananda Uppunda Date: Mon, 2 Oct 2023 07:19:05 +0530 Subject: [PATCH 081/421] [nrf fromtree] net: l2: wifi: Fix Wi-Fi mode get command bug The mode command operation has to be set to WIFI_MGMT_GET when the option -g is provided. It was mistakenly set to true. Correcting the same This PR fixes #63424 and sets the proper value for the get command Signed-off-by: Vivekananda Uppunda (cherry picked from commit b0c96580298ac47715fdb1d1ba5ede766676d643) (cherry picked from commit 06088342cb531ee470c7f64c8c7c0e10d75de8fc) --- subsys/net/l2/wifi/wifi_shell.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subsys/net/l2/wifi/wifi_shell.c b/subsys/net/l2/wifi/wifi_shell.c index 7472d3fa984..592ac50cd8e 100644 --- a/subsys/net/l2/wifi/wifi_shell.c +++ b/subsys/net/l2/wifi/wifi_shell.c @@ -1302,7 +1302,7 @@ void parse_mode_args_to_params(const struct shell *sh, int argc, mode->mode |= WIFI_SOFTAP_MODE; break; case 'g': - mode->oper = true; + mode->oper = WIFI_MGMT_GET; break; case 'i': mode->if_index = (uint8_t)atoi(optarg); From 1b5ab89ed6d031cea80269cb38a512800e46fb59 Mon Sep 17 00:00:00 2001 From: Al Semjonovs Date: Thu, 14 Sep 2023 10:56:46 -0600 Subject: [PATCH 082/421] [nrf fromtree] logging: Unused arg in log_msg_get_tid Resolve unused arg compiler error Signed-off-by: Al Semjonovs (cherry picked from commit b1b4932373c6a9b2665432b68df520223243886f) Signed-off-by: Kacper Radoszewski (cherry picked from commit 47f8b98ba0efe5fee10fcc3ed08842ba2e83fd55) --- include/zephyr/logging/log_msg.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/zephyr/logging/log_msg.h b/include/zephyr/logging/log_msg.h index 4eee566bdc5..0279fb0d2cd 100644 --- a/include/zephyr/logging/log_msg.h +++ b/include/zephyr/logging/log_msg.h @@ -669,6 +669,7 @@ static inline void *log_msg_get_tid(struct log_msg *msg) #if CONFIG_LOG_THREAD_ID_PREFIX return msg->hdr.tid; #else + ARG_UNUSED(msg); return NULL; #endif } From 3d2da670428f177fdbe761db49783cdff83503ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Chru=C5=9Bci=C5=84ski?= Date: Fri, 23 Jun 2023 09:06:51 +0200 Subject: [PATCH 083/421] [nrf fromtree] nrf53: Add RTC pretick MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add RTC pretick option that triggers HW activity one tick before and RTC event that leads to the interrupt. Option is active only on nrf53 network core. Signed-off-by: Krzysztof Chruściński (cherry picked from commit 31eaffdf0552ee967b371644869223d9e901de00) (cherry picked from commit da8a9678540b2649c75cd816355aa4b04a01e08f) --- drivers/timer/nrf_rtc_timer.c | 17 ++- soc/arm/nordic_nrf/nrf53/Kconfig.soc | 21 ++++ soc/arm/nordic_nrf/nrf53/soc.c | 164 +++++++++++++++++++++++++++ 3 files changed, 201 insertions(+), 1 deletion(-) diff --git a/drivers/timer/nrf_rtc_timer.c b/drivers/timer/nrf_rtc_timer.c index 4410529608b..e8ba5bd42a5 100644 --- a/drivers/timer/nrf_rtc_timer.c +++ b/drivers/timer/nrf_rtc_timer.c @@ -25,6 +25,11 @@ #define RTC_LABEL rtc1 #define RTC_CH_COUNT RTC1_CC_NUM +#define RTC_PRETICK (IS_ENABLED(CONFIG_SOC_NRF53_RTC_PRETICK) && \ + IS_ENABLED(CONFIG_SOC_NRF5340_CPUNET)) + +BUILD_ASSERT(!RTC_PRETICK || !(RTC_PRETICK && (CONFIG_NRF_RTC_TIMER_USER_CHAN_COUNT > 0)), + "Cannot use user channels when RTC pretick is used"); BUILD_ASSERT(CHAN_COUNT <= RTC_CH_COUNT, "Not enough compare channels"); /* Ensure that counter driver for RTC1 is not enabled. */ BUILD_ASSERT(DT_NODE_HAS_STATUS(DT_NODELABEL(RTC_LABEL), disabled), @@ -44,6 +49,9 @@ BUILD_ASSERT(DT_NODE_HAS_STATUS(DT_NODELABEL(RTC_LABEL), disabled), #define ANCHOR_RANGE_END (7 * COUNTER_SPAN / 8) #define TARGET_TIME_INVALID (UINT64_MAX) +extern void rtc_pretick_rtc1_cc0_set_hook(uint32_t val); +extern void rtc_pretick_rtc1_isr_hook(void); + static volatile uint32_t overflow_cnt; static volatile uint64_t anchor; static uint64_t last_count; @@ -260,7 +268,7 @@ static int set_alarm(int32_t chan, uint32_t req_cc, bool exact) * This never happens when the written value is N+3. Use 3 cycles as * the nearest possible scheduling then. */ - enum { MIN_CYCLES_FROM_NOW = 3 }; + enum { MIN_CYCLES_FROM_NOW = RTC_PRETICK ? 4 : 3 }; uint32_t cc_val = req_cc; uint32_t cc_inc = MIN_CYCLES_FROM_NOW; @@ -277,6 +285,9 @@ static int set_alarm(int32_t chan, uint32_t req_cc, bool exact) for (;;) { uint32_t now; + if (RTC_PRETICK) { + rtc_pretick_rtc1_cc0_set_hook(cc_val); + } set_comparator(chan, cc_val); /* Enable event routing after the required CC value was set. * Even though the above operation may get repeated (see below), @@ -559,6 +570,10 @@ void rtc_nrf_isr(const void *arg) { ARG_UNUSED(arg); + if (RTC_PRETICK) { + rtc_pretick_rtc1_isr_hook(); + } + if (nrf_rtc_int_enable_check(RTC, NRF_RTC_INT_OVERFLOW_MASK) && nrf_rtc_event_check(RTC, NRF_RTC_EVENT_OVERFLOW)) { nrf_rtc_event_clear(RTC, NRF_RTC_EVENT_OVERFLOW); diff --git a/soc/arm/nordic_nrf/nrf53/Kconfig.soc b/soc/arm/nordic_nrf/nrf53/Kconfig.soc index 122c36988e5..b84985d57eb 100644 --- a/soc/arm/nordic_nrf/nrf53/Kconfig.soc +++ b/soc/arm/nordic_nrf/nrf53/Kconfig.soc @@ -10,11 +10,13 @@ config SOC_NRF5340_CPUAPP select CPU_HAS_FPU select ARMV8_M_DSP select HAS_POWEROFF + imply SOC_NRF53_RTC_PRETICK config SOC_NRF5340_CPUNET bool select ARM_ON_EXIT_CPU_IDLE imply SOC_NRF53_ANOMALY_160_WORKAROUND_NEEDED + imply SOC_NRF53_RTC_PRETICK choice prompt "nRF53x MCU Selection" @@ -47,6 +49,25 @@ config SOC_NRF53_ANOMALY_160_WORKAROUND depends on SYS_CLOCK_EXISTS select ARM_ON_ENTER_CPU_IDLE_HOOK +config SOC_NRF53_RTC_PRETICK + bool + depends on !NRF_802154_RADIO_DRIVER + select NRFX_DPPI + +if SOC_NRF53_RTC_PRETICK + +config SOC_NRF53_RTC_PRETICK_IPC_CH_FROM_NET + int "IPC 0 channel for RTC pretick" + range 0 15 + default 10 + +config SOC_NRF53_RTC_PRETICK_IPC_CH_TO_NET + int "IPC 1 channel for RTC pretick" + range 0 15 + default 11 + +endif + if SOC_NRF5340_CPUAPP config SOC_DCDC_NRF53X_APP diff --git a/soc/arm/nordic_nrf/nrf53/soc.c b/soc/arm/nordic_nrf/nrf53/soc.c index 6552f9d4bb1..50f00932be9 100644 --- a/soc/arm/nordic_nrf/nrf53/soc.c +++ b/soc/arm/nordic_nrf/nrf53/soc.c @@ -18,6 +18,8 @@ #include #include #include +#include +#include #if defined(CONFIG_SOC_NRF5340_CPUAPP) #include #include @@ -31,6 +33,8 @@ #if defined(CONFIG_PM_S2RAM) #include #endif +#include +#include #include #include @@ -38,6 +42,9 @@ #define PIN_XL1 0 #define PIN_XL2 1 +#define RTC1_PRETICK_CC_CHAN 1 +#define RTC1_PRETICK_OVERFLOW_CHAN 2 + #if defined(CONFIG_SOC_NRF_GPIO_FORWARDER_FOR_NRF5340) #define GPIOS_PSEL_BY_IDX(node_id, prop, idx) \ NRF_DT_GPIOS_TO_PSEL_BY_IDX(node_id, prop, idx), @@ -137,11 +144,164 @@ bool z_arm_on_enter_cpu_idle(void) suppress_message = true; } #endif +#if defined(CONFIG_SOC_NRF53_RTC_PRETICK) && defined(CONFIG_SOC_NRF5340_CPUNET) + if (ok_to_sleep) { + NRF_IPC->PUBLISH_RECEIVE[CONFIG_SOC_NRF53_RTC_PRETICK_IPC_CH_TO_NET] |= + IPC_PUBLISH_RECEIVE_EN_Msk; + if (!nrf_rtc_event_check(NRF_RTC0, NRF_RTC_CHANNEL_EVENT_ADDR(3)) && + !nrf_rtc_event_check(NRF_RTC1, NRF_RTC_CHANNEL_EVENT_ADDR(RTC1_PRETICK_CC_CHAN)) && + !nrf_rtc_event_check(NRF_RTC1, NRF_RTC_CHANNEL_EVENT_ADDR(RTC1_PRETICK_OVERFLOW_CHAN))) { + NRF_WDT->TASKS_STOP = 1; + /* Check if any event did not occur after we checked for + * stopping condition. If yes, we might have stopped WDT + * when it should be running. Restart it. + */ + if (nrf_rtc_event_check(NRF_RTC0, NRF_RTC_CHANNEL_EVENT_ADDR(3)) || + nrf_rtc_event_check(NRF_RTC1, NRF_RTC_CHANNEL_EVENT_ADDR(RTC1_PRETICK_CC_CHAN)) || + nrf_rtc_event_check(NRF_RTC1, NRF_RTC_CHANNEL_EVENT_ADDR(RTC1_PRETICK_OVERFLOW_CHAN))) { + NRF_WDT->TASKS_START = 1; + } + } + } +#endif return ok_to_sleep; } #endif /* CONFIG_SOC_NRF53_ANOMALY_160_WORKAROUND */ +#if CONFIG_SOC_NRF53_RTC_PRETICK +#ifdef CONFIG_SOC_NRF5340_CPUAPP +/* RTC pretick - application core part. */ +static int rtc_pretick_cpuapp_init(void) +{ + uint8_t ch; + nrfx_err_t err; + nrf_ipc_event_t ipc_event = + nrf_ipc_receive_event_get(CONFIG_SOC_NRF53_RTC_PRETICK_IPC_CH_FROM_NET); + nrf_ipc_task_t ipc_task = + nrf_ipc_send_task_get(CONFIG_SOC_NRF53_RTC_PRETICK_IPC_CH_TO_NET); + uint32_t task_ipc = nrf_ipc_task_address_get(NRF_IPC, ipc_task); + uint32_t evt_ipc = nrf_ipc_event_address_get(NRF_IPC, ipc_event); + + err = nrfx_gppi_channel_alloc(&ch); + if (err != NRFX_SUCCESS) { + return -ENOMEM; + } + + nrf_ipc_receive_config_set(NRF_IPC, CONFIG_SOC_NRF53_RTC_PRETICK_IPC_CH_FROM_NET, + BIT(CONFIG_SOC_NRF53_RTC_PRETICK_IPC_CH_FROM_NET)); + nrf_ipc_send_config_set(NRF_IPC, CONFIG_SOC_NRF53_RTC_PRETICK_IPC_CH_TO_NET, + BIT(CONFIG_SOC_NRF53_RTC_PRETICK_IPC_CH_TO_NET)); + + nrfx_gppi_task_endpoint_setup(ch, task_ipc); + nrfx_gppi_event_endpoint_setup(ch, evt_ipc); + nrfx_gppi_channels_enable(BIT(ch)); + + return 0; +} +#else /* CONFIG_SOC_NRF5340_CPUNET */ + +static void rtc_pretick_rtc_isr_hook(void) +{ + NRF_IPC->PUBLISH_RECEIVE[CONFIG_SOC_NRF53_RTC_PRETICK_IPC_CH_TO_NET] &= + ~IPC_PUBLISH_RECEIVE_EN_Msk; +} + +void rtc_pretick_rtc0_isr_hook(void) +{ + rtc_pretick_rtc_isr_hook(); +} + +void rtc_pretick_rtc1_cc0_set_hook(uint32_t val) +{ + nrf_rtc_cc_set(NRF_RTC1, RTC1_PRETICK_CC_CHAN, val - 1); +} + +void rtc_pretick_rtc1_isr_hook(void) +{ + rtc_pretick_rtc_isr_hook(); + + if (nrf_rtc_event_check(NRF_RTC1, NRF_RTC_EVENT_OVERFLOW)) { + if (IS_ENABLED(CONFIG_SOC_NRF53_RTC_PRETICK)) { + nrf_rtc_event_clear(NRF_RTC1, + NRF_RTC_CHANNEL_EVENT_ADDR(RTC1_PRETICK_OVERFLOW_CHAN)); + } + } + if (nrf_rtc_event_check(NRF_RTC1, NRF_RTC_EVENT_COMPARE_0)) { + if (IS_ENABLED(CONFIG_SOC_NRF53_RTC_PRETICK)) { + nrf_rtc_event_clear(NRF_RTC1, NRF_RTC_CHANNEL_EVENT_ADDR(RTC1_PRETICK_CC_CHAN)); + } + } +} + +static int rtc_pretick_cpunet_init(void) +{ + uint8_t ppi_ch; + nrf_ipc_task_t ipc_task = + nrf_ipc_send_task_get(CONFIG_SOC_NRF53_RTC_PRETICK_IPC_CH_FROM_NET); + nrf_ipc_event_t ipc_event = + nrf_ipc_receive_event_get(CONFIG_SOC_NRF53_RTC_PRETICK_IPC_CH_TO_NET); + uint32_t task_ipc = nrf_ipc_task_address_get(NRF_IPC, ipc_task); + uint32_t evt_ipc = nrf_ipc_event_address_get(NRF_IPC, ipc_event); + uint32_t task_wdt = nrf_wdt_task_address_get(NRF_WDT, NRF_WDT_TASK_START); + uint32_t evt_mpsl_cc = nrf_rtc_event_address_get(NRF_RTC0, NRF_RTC_EVENT_COMPARE_3); + uint32_t evt_cc = nrf_rtc_event_address_get(NRF_RTC1, + NRF_RTC_CHANNEL_EVENT_ADDR(RTC1_PRETICK_CC_CHAN)); + uint32_t evt_overflow = nrf_rtc_event_address_get(NRF_RTC1, + NRF_RTC_CHANNEL_EVENT_ADDR(RTC1_PRETICK_OVERFLOW_CHAN)); + + /* Configure Watchdog to allow stopping. */ + nrf_wdt_behaviour_set(NRF_WDT, WDT_CONFIG_STOPEN_Msk | BIT(4)); + *((volatile uint32_t *)0x41203120) = 0x14; + + /* Configure IPC */ + nrf_ipc_receive_config_set(NRF_IPC, CONFIG_SOC_NRF53_RTC_PRETICK_IPC_CH_TO_NET, + BIT(CONFIG_SOC_NRF53_RTC_PRETICK_IPC_CH_TO_NET)); + nrf_ipc_send_config_set(NRF_IPC, CONFIG_SOC_NRF53_RTC_PRETICK_IPC_CH_FROM_NET, + BIT(CONFIG_SOC_NRF53_RTC_PRETICK_IPC_CH_FROM_NET)); + + /* Allocate PPI channel for RTC Compare event publishers that starts WDT. */ + nrfx_err_t err = nrfx_gppi_channel_alloc(&ppi_ch); + + if (err != NRFX_SUCCESS) { + return -ENOMEM; + } + + /* Setup a PPI connection between RTC "pretick" events and IPC task. */ + if (IS_ENABLED(CONFIG_BT_LL_SOFTDEVICE)) { + nrfx_gppi_event_endpoint_setup(ppi_ch, evt_mpsl_cc); + } + nrfx_gppi_event_endpoint_setup(ppi_ch, evt_cc); + nrfx_gppi_event_endpoint_setup(ppi_ch, evt_overflow); + nrfx_gppi_task_endpoint_setup(ppi_ch, task_ipc); + nrfx_gppi_event_endpoint_setup(ppi_ch, evt_ipc); + nrfx_gppi_task_endpoint_setup(ppi_ch, task_wdt); + nrfx_gppi_channels_enable(BIT(ppi_ch)); + + nrf_rtc_event_enable(NRF_RTC1, NRF_RTC_CHANNEL_INT_MASK(RTC1_PRETICK_CC_CHAN)); + nrf_rtc_event_enable(NRF_RTC1, NRF_RTC_CHANNEL_INT_MASK(RTC1_PRETICK_OVERFLOW_CHAN)); + + nrf_rtc_event_clear(NRF_RTC1, NRF_RTC_CHANNEL_EVENT_ADDR(RTC1_PRETICK_CC_CHAN)); + nrf_rtc_event_clear(NRF_RTC1, NRF_RTC_CHANNEL_EVENT_ADDR(RTC1_PRETICK_OVERFLOW_CHAN)); + /* Set event 1 tick before overflow. */ + nrf_rtc_cc_set(NRF_RTC1, RTC1_PRETICK_OVERFLOW_CHAN, 0x00FFFFFF); + + return 0; +} +#endif /* CONFIG_SOC_NRF5340_CPUNET */ + +static int rtc_pretick_init(void) +{ + ARG_UNUSED(unused); +#ifdef CONFIG_SOC_NRF5340_CPUAPP + return rtc_pretick_cpuapp_init(); +#else + return rtc_pretick_cpunet_init(); +#endif +} +#endif /* CONFIG_SOC_NRF53_RTC_PRETICK */ + + static int nordicsemi_nrf53_init(void) { #if defined(CONFIG_SOC_NRF5340_CPUAPP) && defined(CONFIG_NRF_ENABLE_CACHE) @@ -242,3 +402,7 @@ void arch_busy_wait(uint32_t time_us) } SYS_INIT(nordicsemi_nrf53_init, PRE_KERNEL_1, 0); + +#ifdef CONFIG_SOC_NRF53_RTC_PRETICK +SYS_INIT(rtc_pretick_init, POST_KERNEL, 0); +#endif From b2a1ffbe848082f67c50e094dc065d6d17f5dcc6 Mon Sep 17 00:00:00 2001 From: Andrzej Kuros Date: Tue, 26 Sep 2023 14:28:36 +0200 Subject: [PATCH 084/421] [nrf fromtree] arch: arm: aarch32: Introduce z_arm_on_enter_cpu_idle_prepare() hook MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Introduce an optional hook to be called when the CPU is made idle. If needed, this hook can be used to prepare data for upcoming call to z_arm_on_enter_cpu_idle(). The main difference is that z_arm_on_enter_cpu_idle_prepare() hook is called before interrupts are disabled. Signed-off-by: Andrzej Kuroś (cherry picked from commit 3d89d58cb87843470a6b57b5a5b56b7e29b0d84f) (cherry picked from commit b0c6d4f7c17b232ea688d1621e5162582380b73a) --- arch/arm/Kconfig | 10 ++++++++++ arch/arm/core/aarch32/cpu_idle.S | 25 ++++++++++++++++++++----- include/zephyr/arch/arm/aarch32/misc.h | 9 +++++++++ 3 files changed, 39 insertions(+), 5 deletions(-) diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index e17cf3f9b31..ef9a20d0cc9 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -53,6 +53,16 @@ config ARM_ON_ENTER_CPU_IDLE_HOOK If needed, this hook can be used to prevent the CPU from actually entering sleep by skipping the WFE/WFI instruction. +config ARM_ON_ENTER_CPU_IDLE_PREPARE_HOOK + bool + help + Enables a hook (z_arm_on_enter_cpu_idle_prepare()) that is called when + the CPU is made idle (by k_cpu_idle() or k_cpu_atomic_idle()). + If needed, this hook can prepare data to upcoming call to + z_arm_on_enter_cpu_idle(). The z_arm_on_enter_cpu_idle_prepare differs + from z_arm_on_enter_cpu_idle because it is called before interrupts are + disabled. + config ARM_ON_EXIT_CPU_IDLE bool help diff --git a/arch/arm/core/aarch32/cpu_idle.S b/arch/arm/core/aarch32/cpu_idle.S index 8164959ab29..95e37917180 100644 --- a/arch/arm/core/aarch32/cpu_idle.S +++ b/arch/arm/core/aarch32/cpu_idle.S @@ -85,16 +85,24 @@ _skip_\@: .endm SECTION_FUNC(TEXT, arch_cpu_idle) -#ifdef CONFIG_TRACING +#if defined(CONFIG_TRACING) || \ + defined(CONFIG_ARM_ON_ENTER_CPU_IDLE_PREPARE_HOOK) push {r0, lr} + +#ifdef CONFIG_TRACING bl sys_trace_idle +#endif +#ifdef CONFIG_ARM_ON_ENTER_CPU_IDLE_PREPARE_HOOK + bl z_arm_on_enter_cpu_idle_prepare +#endif + #if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE) pop {r0, r1} mov lr, r1 #else pop {r0, lr} #endif /* CONFIG_ARMV6_M_ARMV8_M_BASELINE */ -#endif /* CONFIG_TRACING */ +#endif #if defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE) /* @@ -138,17 +146,24 @@ SECTION_FUNC(TEXT, arch_cpu_idle) bx lr SECTION_FUNC(TEXT, arch_cpu_atomic_idle) -#ifdef CONFIG_TRACING +#if defined(CONFIG_TRACING) || \ + defined(CONFIG_ARM_ON_ENTER_CPU_IDLE_PREPARE_HOOK) push {r0, lr} + +#ifdef CONFIG_TRACING bl sys_trace_idle +#endif +#ifdef CONFIG_ARM_ON_ENTER_CPU_IDLE_PREPARE_HOOK + bl z_arm_on_enter_cpu_idle_prepare +#endif + #if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE) pop {r0, r1} mov lr, r1 #else pop {r0, lr} #endif /* CONFIG_ARMV6_M_ARMV8_M_BASELINE */ -#endif /* CONFIG_TRACING */ - +#endif /* * Lock PRIMASK while sleeping: wfe will still get interrupted by * incoming interrupts but the CPU will not service them right away. diff --git a/include/zephyr/arch/arm/aarch32/misc.h b/include/zephyr/arch/arm/aarch32/misc.h index 24ed69f663c..ab67a35e94c 100644 --- a/include/zephyr/arch/arm/aarch32/misc.h +++ b/include/zephyr/arch/arm/aarch32/misc.h @@ -51,6 +51,15 @@ extern bool z_arm_thread_is_in_user_mode(void); bool z_arm_on_enter_cpu_idle(void); #endif +#if defined(CONFIG_ARM_ON_ENTER_CPU_IDLE_PREPARE_HOOK) +/* Prototype of a hook that can be enabled to be called every time the CPU is + * made idle (the calls will be done from k_cpu_idle() and k_cpu_atomic_idle()). + * The function is called before interrupts are disabled and can prepare to + * upcoming call to z_arm_on_enter_cpu_idle. + */ +void z_arm_on_enter_cpu_idle_prepare(void); +#endif + #endif #ifdef __cplusplus From 0704fb1e49aef4c6d9f892b0d46c771f0081e360 Mon Sep 17 00:00:00 2001 From: Andrzej Kuros Date: Mon, 18 Sep 2023 10:06:22 +0200 Subject: [PATCH 085/421] [nrf fromtree] nrf53: RTC pretick allows user channels and require just one CC MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The nrf53 pretick can be used with non-zero `NRF_RTC_TIMER_USER_CHAN_COUNT` Kconfig option. The nrf53 pretick requires just one RTC1 CC channel. The nrf53 pretick handles also RTC1 and RTC0 both CCs and OVERFLOW events by examination of events scheduled on them. The pretick is set based on number of ticks to the closest event scheduled that can trigger an interrupt. Because the operation in `z_arm_on_enter_cpu_idle` hook would take too much time with interrupts disabled, the `z_arm_on_enter_cpu_idle_prepare` hook enabled by Kconfig option `ARM_ON_ENTER_CPU_IDLE_PREPARE_HOOK` is used. It performs RTC0 and RTC1 examination, and sets pretick without interrupts being blocked. The LDREX/STREX are leveraged to detect if exception took place between start of `z_arm_on_enter_cpu_idle_prepare` and `z_arm_on_enter_cpu_idle`. If exception has not been taken, the pretick calculation can be trusted because source data could not changed and too much time could not pass. Otherwise the sleep attempt is disallowed, the idle will loop again and try later. Prompt for `SOC_NRF53_RTC_PRETICK` Kconfig option allows to control this option by an user and turn the feature off if necessary. Signed-off-by: Andrzej Kuroś (cherry picked from commit e03d5d4c6dd5d08b0126153203b6dd0331f47507) (cherry picked from commit 835b92d5782fe40b729f8927baba1930ebd92ddb) --- drivers/timer/nrf_rtc_timer.c | 18 +- soc/arm/nordic_nrf/nrf53/Kconfig.soc | 9 +- soc/arm/nordic_nrf/nrf53/soc.c | 274 ++++++++++++++++++++++----- 3 files changed, 239 insertions(+), 62 deletions(-) diff --git a/drivers/timer/nrf_rtc_timer.c b/drivers/timer/nrf_rtc_timer.c index e8ba5bd42a5..9241c5b7a10 100644 --- a/drivers/timer/nrf_rtc_timer.c +++ b/drivers/timer/nrf_rtc_timer.c @@ -17,20 +17,18 @@ #include #include +#define RTC_PRETICK (IS_ENABLED(CONFIG_SOC_NRF53_RTC_PRETICK) && \ + IS_ENABLED(CONFIG_SOC_NRF5340_CPUNET)) + #define EXT_CHAN_COUNT CONFIG_NRF_RTC_TIMER_USER_CHAN_COUNT #define CHAN_COUNT (EXT_CHAN_COUNT + 1) #define RTC NRF_RTC1 #define RTC_IRQn NRFX_IRQ_NUMBER_GET(RTC) #define RTC_LABEL rtc1 -#define RTC_CH_COUNT RTC1_CC_NUM +#define CHAN_COUNT_MAX (RTC1_CC_NUM - (RTC_PRETICK ? 1 : 0)) -#define RTC_PRETICK (IS_ENABLED(CONFIG_SOC_NRF53_RTC_PRETICK) && \ - IS_ENABLED(CONFIG_SOC_NRF5340_CPUNET)) - -BUILD_ASSERT(!RTC_PRETICK || !(RTC_PRETICK && (CONFIG_NRF_RTC_TIMER_USER_CHAN_COUNT > 0)), - "Cannot use user channels when RTC pretick is used"); -BUILD_ASSERT(CHAN_COUNT <= RTC_CH_COUNT, "Not enough compare channels"); +BUILD_ASSERT(CHAN_COUNT <= CHAN_COUNT_MAX, "Not enough compare channels"); /* Ensure that counter driver for RTC1 is not enabled. */ BUILD_ASSERT(DT_NODE_HAS_STATUS(DT_NODELABEL(RTC_LABEL), disabled), "Counter for RTC1 must be disabled"); @@ -49,7 +47,6 @@ BUILD_ASSERT(DT_NODE_HAS_STATUS(DT_NODELABEL(RTC_LABEL), disabled), #define ANCHOR_RANGE_END (7 * COUNTER_SPAN / 8) #define TARGET_TIME_INVALID (UINT64_MAX) -extern void rtc_pretick_rtc1_cc0_set_hook(uint32_t val); extern void rtc_pretick_rtc1_isr_hook(void); static volatile uint32_t overflow_cnt; @@ -268,7 +265,7 @@ static int set_alarm(int32_t chan, uint32_t req_cc, bool exact) * This never happens when the written value is N+3. Use 3 cycles as * the nearest possible scheduling then. */ - enum { MIN_CYCLES_FROM_NOW = RTC_PRETICK ? 4 : 3 }; + enum { MIN_CYCLES_FROM_NOW = 3 }; uint32_t cc_val = req_cc; uint32_t cc_inc = MIN_CYCLES_FROM_NOW; @@ -285,9 +282,6 @@ static int set_alarm(int32_t chan, uint32_t req_cc, bool exact) for (;;) { uint32_t now; - if (RTC_PRETICK) { - rtc_pretick_rtc1_cc0_set_hook(cc_val); - } set_comparator(chan, cc_val); /* Enable event routing after the required CC value was set. * Even though the above operation may get repeated (see below), diff --git a/soc/arm/nordic_nrf/nrf53/Kconfig.soc b/soc/arm/nordic_nrf/nrf53/Kconfig.soc index b84985d57eb..9bb4caf2bb9 100644 --- a/soc/arm/nordic_nrf/nrf53/Kconfig.soc +++ b/soc/arm/nordic_nrf/nrf53/Kconfig.soc @@ -16,7 +16,7 @@ config SOC_NRF5340_CPUNET bool select ARM_ON_EXIT_CPU_IDLE imply SOC_NRF53_ANOMALY_160_WORKAROUND_NEEDED - imply SOC_NRF53_RTC_PRETICK + imply SOC_NRF53_RTC_PRETICK if !WDT_NRFX choice prompt "nRF53x MCU Selection" @@ -50,9 +50,14 @@ config SOC_NRF53_ANOMALY_160_WORKAROUND select ARM_ON_ENTER_CPU_IDLE_HOOK config SOC_NRF53_RTC_PRETICK - bool + bool "Pre-tick workaround for nRF5340 anomaly 165" depends on !NRF_802154_RADIO_DRIVER select NRFX_DPPI + select ARM_ON_ENTER_CPU_IDLE_HOOK if SOC_NRF5340_CPUNET + select ARM_ON_ENTER_CPU_IDLE_PREPARE_HOOK if SOC_NRF5340_CPUNET + help + Indicates that the pre-tick workaround for the anomaly 165 that affects + the nRF5340 SoC should be applied. if SOC_NRF53_RTC_PRETICK diff --git a/soc/arm/nordic_nrf/nrf53/soc.c b/soc/arm/nordic_nrf/nrf53/soc.c index 50f00932be9..aa93dfd4b54 100644 --- a/soc/arm/nordic_nrf/nrf53/soc.c +++ b/soc/arm/nordic_nrf/nrf53/soc.c @@ -14,6 +14,7 @@ #include #include +#include #include #include #include @@ -42,8 +43,11 @@ #define PIN_XL1 0 #define PIN_XL2 1 -#define RTC1_PRETICK_CC_CHAN 1 -#define RTC1_PRETICK_OVERFLOW_CHAN 2 +#define RTC1_PRETICK_CC_CHAN (RTC1_CC_NUM - 1) + +/* Mask of CC channels capable of generating interrupts, see nrf_rtc_timer.c */ +#define RTC1_PRETICK_SELECTED_CC_MASK BIT_MASK(CONFIG_NRF_RTC_TIMER_USER_CHAN_COUNT + 1U) +#define RTC0_PRETICK_SELECTED_CC_MASK BIT_MASK(NRF_RTC_CC_COUNT_MAX) #if defined(CONFIG_SOC_NRF_GPIO_FORWARDER_FOR_NRF5340) #define GPIOS_PSEL_BY_IDX(node_id, prop, idx) \ @@ -130,39 +134,240 @@ static bool nrf53_anomaly_160_check(void) return true; } -bool z_arm_on_enter_cpu_idle(void) +#if defined(CONFIG_SOC_NRF53_RTC_PRETICK) && defined(CONFIG_SOC_NRF5340_CPUNET) + +BUILD_ASSERT(!IS_ENABLED(CONFIG_WDT_NRFX), + "For CONFIG_SOC_NRF53_RTC_PRETICK watchdog is used internally for the pre-tick workaround on nRF5340 cpunet. Application cannot use the watchdog."); + +static inline uint32_t rtc_counter_sub(uint32_t a, uint32_t b) { - bool ok_to_sleep = nrf53_anomaly_160_check(); + return (a - b) & NRF_RTC_COUNTER_MAX; +} -#if (LOG_LEVEL >= LOG_LEVEL_DBG) - static bool suppress_message; +static bool rtc_ticks_to_next_event_get(NRF_RTC_Type *rtc, uint32_t selected_cc_mask, uint32_t cntr, + uint32_t *ticks_to_next_event) +{ + bool result = false; - if (ok_to_sleep) { - suppress_message = false; - } else if (!suppress_message) { - LOG_DBG("Anomaly 160 trigger conditions detected."); - suppress_message = true; + /* Let's preload register to speed-up. */ + uint32_t reg_intenset = rtc->INTENSET; + + /* Note: TICK event not handled. */ + + if (reg_intenset & NRF_RTC_INT_OVERFLOW_MASK) { + /* Overflow can generate an interrupt. */ + *ticks_to_next_event = NRF_RTC_COUNTER_MAX + 1U - cntr; + result = true; } -#endif -#if defined(CONFIG_SOC_NRF53_RTC_PRETICK) && defined(CONFIG_SOC_NRF5340_CPUNET) + + for (uint32_t chan = 0; chan < NRF_RTC_CC_COUNT_MAX; chan++) { + if ((selected_cc_mask & (1U << chan)) && + (reg_intenset & NRF_RTC_CHANNEL_INT_MASK(chan))) { + /* The CC is in selected mask and is can generate an interrupt. */ + uint32_t cc = nrf_rtc_cc_get(rtc, chan); + uint32_t ticks_to_fire = rtc_counter_sub(cc, cntr); + + if (ticks_to_fire == 0U) { + /* When ticks_to_fire == 0, the event should have been just + * generated the interrupt can be already handled or be pending. + * However the next event is expected to be after counter wraps. + */ + ticks_to_fire = NRF_RTC_COUNTER_MAX + 1U; + } + + if (!result) { + *ticks_to_next_event = ticks_to_fire; + result = true; + } else if (ticks_to_fire < *ticks_to_next_event) { + *ticks_to_next_event = ticks_to_fire; + result = true; + } else { + /* CC that fires no earlier than already found. */ + } + } + } + + return result; +} + +static void rtc_counter_synchronized_get(NRF_RTC_Type *rtc_a, NRF_RTC_Type *rtc_b, + uint32_t *counter_a, uint32_t *counter_b) +{ + do { + *counter_a = nrf_rtc_counter_get(rtc_a); + barrier_dmem_fence_full(); + *counter_b = nrf_rtc_counter_get(rtc_b); + barrier_dmem_fence_full(); + } while (*counter_a != nrf_rtc_counter_get(rtc_a)); +} + +static uint8_t cpu_idle_prepare_monitor_dummy; +static bool cpu_idle_prepare_allows_sleep; + +static void cpu_idle_prepare_monitor_begin(void) +{ + __LDREXB(&cpu_idle_prepare_monitor_dummy); +} + +/* Returns 0 if no exception preempted since the last call to cpu_idle_prepare_monitor_begin. */ +static bool cpu_idle_prepare_monitor_end(void) +{ + /* The value stored is irrelevant. If any exception took place after + * cpu_idle_prepare_monitor_begin, the the local monitor is cleared and + * the store fails returning 1. + * See Arm v8-M Architecture Reference Manual: + * Chapter B9.2 The local monitors + * Chapter B9.4 Exclusive access instructions and the monitors + * See Arm Cortex-M33 Processor Technical Reference Manual + * Chapter 3.5 Exclusive monitor + */ + return __STREXB(0U, &cpu_idle_prepare_monitor_dummy); +} + +void z_arm_on_enter_cpu_idle_prepare(void) +{ + bool ok_to_sleep = true; + + cpu_idle_prepare_monitor_begin(); + + uint32_t rtc_counter = 0U; + uint32_t rtc_ticks_to_next_event = 0U; + uint32_t rtc0_counter = 0U; + uint32_t rtc0_ticks_to_next_event = 0U; + + rtc_counter_synchronized_get(NRF_RTC1, NRF_RTC0, &rtc_counter, &rtc0_counter); + + bool rtc_scheduled = rtc_ticks_to_next_event_get(NRF_RTC1, RTC1_PRETICK_SELECTED_CC_MASK, + rtc_counter, &rtc_ticks_to_next_event); + + if (rtc_ticks_to_next_event_get(NRF_RTC0, RTC0_PRETICK_SELECTED_CC_MASK, rtc0_counter, + &rtc0_ticks_to_next_event)) { + /* An event is scheduled on RTC0. */ + if (!rtc_scheduled) { + rtc_ticks_to_next_event = rtc0_ticks_to_next_event; + rtc_scheduled = true; + } else if (rtc0_ticks_to_next_event < rtc_ticks_to_next_event) { + rtc_ticks_to_next_event = rtc0_ticks_to_next_event; + } else { + /* Event on RTC0 will not happen earlier than already found. */ + } + } + + if (rtc_scheduled) { + static bool rtc_pretick_cc_set_on_time; + /* The pretick should happen 1 tick before the earliest scheduled event + * that can trigger an interrupt. + */ + uint32_t rtc_pretick_cc_val = (rtc_counter + rtc_ticks_to_next_event - 1U) + & NRF_RTC_COUNTER_MAX; + + if (rtc_pretick_cc_val != nrf_rtc_cc_get(NRF_RTC1, RTC1_PRETICK_CC_CHAN)) { + /* The CC for pretick needs to be updated. */ + nrf_rtc_cc_set(NRF_RTC1, RTC1_PRETICK_CC_CHAN, rtc_pretick_cc_val); + + if (rtc_ticks_to_next_event >= NRF_RTC_COUNTER_MAX/2) { + /* Pretick is scheduled so far in the future, assumed on time. */ + rtc_pretick_cc_set_on_time = true; + } else { + /* Let's check if we updated CC on time, so that the CC can + * take effect. + */ + barrier_dmem_fence_full(); + rtc_counter = nrf_rtc_counter_get(NRF_RTC1); + uint32_t pretick_cc_to_counter = + rtc_counter_sub(rtc_pretick_cc_val, rtc_counter); + + if ((pretick_cc_to_counter < 3) || + (pretick_cc_to_counter >= NRF_RTC_COUNTER_MAX/2)) { + /* The COUNTER value is close enough to the expected + * pretick CC or has just expired, so the pretick event + * generation is not guaranteed. + */ + rtc_pretick_cc_set_on_time = false; + } else { + /* The written rtc_pretick_cc is guaranteed to to trigger + * compare event. + */ + rtc_pretick_cc_set_on_time = true; + } + } + } else { + /* The CC for pretick doesn't need to be updated, however + * rtc_pretick_cc_set_on_time still holds if we managed to set it on time. + */ + } + + /* If the CC for pretick is set on time, so the pretick CC event can be reliably + * generated then allow to sleep. Otherwise (the CC for pretick cannot be reliably + * generated, because CC was set very short to it's fire time) sleep not at all. + */ + ok_to_sleep = rtc_pretick_cc_set_on_time; + } else { + /* No events on any RTC timers are scheduled. */ + } + if (ok_to_sleep) { NRF_IPC->PUBLISH_RECEIVE[CONFIG_SOC_NRF53_RTC_PRETICK_IPC_CH_TO_NET] |= IPC_PUBLISH_RECEIVE_EN_Msk; - if (!nrf_rtc_event_check(NRF_RTC0, NRF_RTC_CHANNEL_EVENT_ADDR(3)) && - !nrf_rtc_event_check(NRF_RTC1, NRF_RTC_CHANNEL_EVENT_ADDR(RTC1_PRETICK_CC_CHAN)) && - !nrf_rtc_event_check(NRF_RTC1, NRF_RTC_CHANNEL_EVENT_ADDR(RTC1_PRETICK_OVERFLOW_CHAN))) { + if (!nrf_rtc_event_check(NRF_RTC1, + NRF_RTC_CHANNEL_EVENT_ADDR(RTC1_PRETICK_CC_CHAN))) { NRF_WDT->TASKS_STOP = 1; /* Check if any event did not occur after we checked for * stopping condition. If yes, we might have stopped WDT * when it should be running. Restart it. */ - if (nrf_rtc_event_check(NRF_RTC0, NRF_RTC_CHANNEL_EVENT_ADDR(3)) || - nrf_rtc_event_check(NRF_RTC1, NRF_RTC_CHANNEL_EVENT_ADDR(RTC1_PRETICK_CC_CHAN)) || - nrf_rtc_event_check(NRF_RTC1, NRF_RTC_CHANNEL_EVENT_ADDR(RTC1_PRETICK_OVERFLOW_CHAN))) { + if (nrf_rtc_event_check(NRF_RTC1, + NRF_RTC_CHANNEL_EVENT_ADDR(RTC1_PRETICK_CC_CHAN))) { NRF_WDT->TASKS_START = 1; } } } + + cpu_idle_prepare_allows_sleep = ok_to_sleep; +} +#endif /* CONFIG_SOC_NRF53_RTC_PRETICK && CONFIG_SOC_NRF5340_CPUNET */ + +bool z_arm_on_enter_cpu_idle(void) +{ + bool ok_to_sleep = true; + +#if defined(CONFIG_SOC_NRF53_RTC_PRETICK) && defined(CONFIG_SOC_NRF5340_CPUNET) + if (cpu_idle_prepare_monitor_end() == 0) { + /* No exception happened since cpu_idle_prepare_monitor_begin. + * We can trust the outcome of. z_arm_on_enter_cpu_idle_prepare + */ + ok_to_sleep = cpu_idle_prepare_allows_sleep; + } else { + /* Exception happened since cpu_idle_prepare_monitor_begin. + * The values which z_arm_on_enter_cpu_idle_prepare could be changed + * by the exception, so we can not trust to it's outcome. + * Do not sleep at all, let's try in the next iteration of idle loop. + */ + ok_to_sleep = false; + } +#endif + + if (ok_to_sleep) { + ok_to_sleep = nrf53_anomaly_160_check(); + +#if (LOG_LEVEL >= LOG_LEVEL_DBG) + static bool suppress_message; + + if (ok_to_sleep) { + suppress_message = false; + } else if (!suppress_message) { + LOG_DBG("Anomaly 160 trigger conditions detected."); + suppress_message = true; + } +#endif + } + +#if defined(CONFIG_SOC_NRF53_RTC_PRETICK) && defined(CONFIG_SOC_NRF5340_CPUNET) + if (!ok_to_sleep) { + NRF_IPC->PUBLISH_RECEIVE[CONFIG_SOC_NRF53_RTC_PRETICK_IPC_CH_TO_NET] &= + ~IPC_PUBLISH_RECEIVE_EN_Msk; + NRF_WDT->TASKS_STOP = 1; + } #endif return ok_to_sleep; @@ -212,25 +417,12 @@ void rtc_pretick_rtc0_isr_hook(void) rtc_pretick_rtc_isr_hook(); } -void rtc_pretick_rtc1_cc0_set_hook(uint32_t val) -{ - nrf_rtc_cc_set(NRF_RTC1, RTC1_PRETICK_CC_CHAN, val - 1); -} - void rtc_pretick_rtc1_isr_hook(void) { rtc_pretick_rtc_isr_hook(); - if (nrf_rtc_event_check(NRF_RTC1, NRF_RTC_EVENT_OVERFLOW)) { - if (IS_ENABLED(CONFIG_SOC_NRF53_RTC_PRETICK)) { - nrf_rtc_event_clear(NRF_RTC1, - NRF_RTC_CHANNEL_EVENT_ADDR(RTC1_PRETICK_OVERFLOW_CHAN)); - } - } - if (nrf_rtc_event_check(NRF_RTC1, NRF_RTC_EVENT_COMPARE_0)) { - if (IS_ENABLED(CONFIG_SOC_NRF53_RTC_PRETICK)) { - nrf_rtc_event_clear(NRF_RTC1, NRF_RTC_CHANNEL_EVENT_ADDR(RTC1_PRETICK_CC_CHAN)); - } + if (IS_ENABLED(CONFIG_SOC_NRF53_RTC_PRETICK)) { + nrf_rtc_event_clear(NRF_RTC1, NRF_RTC_CHANNEL_EVENT_ADDR(RTC1_PRETICK_CC_CHAN)); } } @@ -244,11 +436,8 @@ static int rtc_pretick_cpunet_init(void) uint32_t task_ipc = nrf_ipc_task_address_get(NRF_IPC, ipc_task); uint32_t evt_ipc = nrf_ipc_event_address_get(NRF_IPC, ipc_event); uint32_t task_wdt = nrf_wdt_task_address_get(NRF_WDT, NRF_WDT_TASK_START); - uint32_t evt_mpsl_cc = nrf_rtc_event_address_get(NRF_RTC0, NRF_RTC_EVENT_COMPARE_3); uint32_t evt_cc = nrf_rtc_event_address_get(NRF_RTC1, NRF_RTC_CHANNEL_EVENT_ADDR(RTC1_PRETICK_CC_CHAN)); - uint32_t evt_overflow = nrf_rtc_event_address_get(NRF_RTC1, - NRF_RTC_CHANNEL_EVENT_ADDR(RTC1_PRETICK_OVERFLOW_CHAN)); /* Configure Watchdog to allow stopping. */ nrf_wdt_behaviour_set(NRF_WDT, WDT_CONFIG_STOPEN_Msk | BIT(4)); @@ -267,24 +456,14 @@ static int rtc_pretick_cpunet_init(void) return -ENOMEM; } - /* Setup a PPI connection between RTC "pretick" events and IPC task. */ - if (IS_ENABLED(CONFIG_BT_LL_SOFTDEVICE)) { - nrfx_gppi_event_endpoint_setup(ppi_ch, evt_mpsl_cc); - } nrfx_gppi_event_endpoint_setup(ppi_ch, evt_cc); - nrfx_gppi_event_endpoint_setup(ppi_ch, evt_overflow); nrfx_gppi_task_endpoint_setup(ppi_ch, task_ipc); nrfx_gppi_event_endpoint_setup(ppi_ch, evt_ipc); nrfx_gppi_task_endpoint_setup(ppi_ch, task_wdt); nrfx_gppi_channels_enable(BIT(ppi_ch)); nrf_rtc_event_enable(NRF_RTC1, NRF_RTC_CHANNEL_INT_MASK(RTC1_PRETICK_CC_CHAN)); - nrf_rtc_event_enable(NRF_RTC1, NRF_RTC_CHANNEL_INT_MASK(RTC1_PRETICK_OVERFLOW_CHAN)); - nrf_rtc_event_clear(NRF_RTC1, NRF_RTC_CHANNEL_EVENT_ADDR(RTC1_PRETICK_CC_CHAN)); - nrf_rtc_event_clear(NRF_RTC1, NRF_RTC_CHANNEL_EVENT_ADDR(RTC1_PRETICK_OVERFLOW_CHAN)); - /* Set event 1 tick before overflow. */ - nrf_rtc_cc_set(NRF_RTC1, RTC1_PRETICK_OVERFLOW_CHAN, 0x00FFFFFF); return 0; } @@ -292,7 +471,6 @@ static int rtc_pretick_cpunet_init(void) static int rtc_pretick_init(void) { - ARG_UNUSED(unused); #ifdef CONFIG_SOC_NRF5340_CPUAPP return rtc_pretick_cpuapp_init(); #else From d4e8b1eeae72a627d38c3cf08736dfe436efdac5 Mon Sep 17 00:00:00 2001 From: Andrzej Kuros Date: Mon, 25 Sep 2023 11:51:15 +0200 Subject: [PATCH 086/421] [nrf fromtree] nrf53: pretick with NRF_802154_RADIO_DRIVER MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The `SOC_NRF53_RTC_PRETICK` option is now allowed to be used with `NRF_802154_RADIO_DRIVER`. Signed-off-by: Andrzej Kuroś (cherry picked from commit d44e96e486ae442d523c3b88ba1ec39b6d5891bd) (cherry picked from commit 01d3f9bba6f9f36374014915e9afbb4cb28d232c) --- drivers/timer/Kconfig.nrf_rtc | 1 + soc/arm/nordic_nrf/nrf53/Kconfig.soc | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/timer/Kconfig.nrf_rtc b/drivers/timer/Kconfig.nrf_rtc index cda05d4dabe..acb6f123afe 100644 --- a/drivers/timer/Kconfig.nrf_rtc +++ b/drivers/timer/Kconfig.nrf_rtc @@ -19,6 +19,7 @@ if NRF_RTC_TIMER config NRF_RTC_TIMER_USER_CHAN_COUNT int "Additional channels that can be used" + default 2 if NRF_802154_RADIO_DRIVER && SOC_NRF5340_CPUNET default 3 if NRF_802154_RADIO_DRIVER default 0 help diff --git a/soc/arm/nordic_nrf/nrf53/Kconfig.soc b/soc/arm/nordic_nrf/nrf53/Kconfig.soc index 9bb4caf2bb9..2ad4a7add66 100644 --- a/soc/arm/nordic_nrf/nrf53/Kconfig.soc +++ b/soc/arm/nordic_nrf/nrf53/Kconfig.soc @@ -51,7 +51,6 @@ config SOC_NRF53_ANOMALY_160_WORKAROUND config SOC_NRF53_RTC_PRETICK bool "Pre-tick workaround for nRF5340 anomaly 165" - depends on !NRF_802154_RADIO_DRIVER select NRFX_DPPI select ARM_ON_ENTER_CPU_IDLE_HOOK if SOC_NRF5340_CPUNET select ARM_ON_ENTER_CPU_IDLE_PREPARE_HOOK if SOC_NRF5340_CPUNET @@ -202,6 +201,7 @@ config NRF53_SYNC_RTC_INIT_PRIORITY nRF53 Synchronized RTC initialization priority. config NRF_RTC_TIMER_USER_CHAN_COUNT + default 2 if NRF_802154_RADIO_DRIVER && SOC_NRF5340_CPUNET default 3 if NRF_802154_RADIO_DRIVER default 1 From 09bcf9d88014ee367f0db56ff244754b306efe31 Mon Sep 17 00:00:00 2001 From: Seppo Takalo Date: Tue, 5 Sep 2023 13:37:04 +0300 Subject: [PATCH 087/421] [nrf fromtree] test: lwm2m: Fix minor timing issue RD client tests work well on emulated (fast) environments but tend to fail on real HW with real time sleeps. This change refactors wait_for_service() to be a bit more syncronous on background service, instead of relying hardcoded sleeps. Fixes #61824 Signed-off-by: Seppo Takalo (cherry picked from commit 4798187801104fc3aa991617bdf1e9d730b00ca3) (cherry picked from commit 4f66f8223ae5c6c79a79d8a6c7532cb80145527a) --- tests/net/lib/lwm2m/lwm2m_rd_client/CMakeLists.txt | 2 +- tests/net/lib/lwm2m/lwm2m_rd_client/src/stubs.c | 12 +++++++----- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/tests/net/lib/lwm2m/lwm2m_rd_client/CMakeLists.txt b/tests/net/lib/lwm2m/lwm2m_rd_client/CMakeLists.txt index 5f29bdad0dd..81e129c56c1 100644 --- a/tests/net/lib/lwm2m/lwm2m_rd_client/CMakeLists.txt +++ b/tests/net/lib/lwm2m/lwm2m_rd_client/CMakeLists.txt @@ -23,7 +23,7 @@ add_compile_definitions(CONFIG_LWM2M_RD_CLIENT_ENDPOINT_NAME_MAX_LENGTH=32) add_compile_definitions(CONFIG_LWM2M_RD_CLIENT_MAX_RETRIES=2) add_compile_definitions(CONFIG_LWM2M_COAP_BLOCK_SIZE=256) add_compile_definitions(CONFIG_LWM2M_COAP_MAX_MSG_SIZE=512) -add_compile_definitions(CONFIG_LWM2M_ENGINE_DEFAULT_LIFETIME=60) +add_compile_definitions(CONFIG_LWM2M_ENGINE_DEFAULT_LIFETIME=20) add_compile_definitions(CONFIG_LWM2M_SECURITY_INSTANCE_COUNT=1) add_compile_definitions(CONFIG_LWM2M_SECONDS_TO_UPDATE_EARLY=10) add_compile_definitions(CONFIG_LWM2M_QUEUE_MODE_UPTIME=10) diff --git a/tests/net/lib/lwm2m/lwm2m_rd_client/src/stubs.c b/tests/net/lib/lwm2m/lwm2m_rd_client/src/stubs.c index 58f64f4984d..41789e20340 100644 --- a/tests/net/lib/lwm2m/lwm2m_rd_client/src/stubs.c +++ b/tests/net/lib/lwm2m/lwm2m_rd_client/src/stubs.c @@ -117,10 +117,12 @@ uint16_t counter = RD_CLIENT_MAX_SERVICE_ITERATIONS; struct lwm2m_message *pending_message; void *(*pending_message_cb)(); static bool running; +K_SEM_DEFINE(srv_sem, 0, 1); static void service_work_fn(struct k_work *work) { while (running) { + k_sleep(K_MSEC(10)); if (pending_message != NULL && pending_message_cb != NULL) { pending_message_cb(pending_message); pending_message = NULL; @@ -129,8 +131,9 @@ static void service_work_fn(struct k_work *work) if (next && next < k_uptime_get()) { next = 0; service(NULL); + k_sem_give(&srv_sem); } - k_sleep(K_MSEC(10)); + counter--; /* avoid endless loop if rd client is stuck somewhere */ @@ -143,10 +146,8 @@ static void service_work_fn(struct k_work *work) void wait_for_service(uint16_t cycles) { - uint16_t end = counter - cycles; - - while (counter > end) { - k_sleep(K_MSEC(10)); + while (cycles--) { + k_sem_take(&srv_sem, K_MSEC(100)); } } @@ -157,6 +158,7 @@ void test_lwm2m_engine_start_service(void) running = true; counter = RD_CLIENT_MAX_SERVICE_ITERATIONS; k_work_submit(&service_work); + k_sem_reset(&srv_sem); } void test_lwm2m_engine_stop_service(void) From 8ff85348030453c3562bf8edcc4f9a583f168f22 Mon Sep 17 00:00:00 2001 From: Seppo Takalo Date: Mon, 11 Sep 2023 15:23:53 +0300 Subject: [PATCH 088/421] [nrf fromtree] net: lwm2m: Add timeouts to state machine Allow certain RD-client states to timeout. As stated in LwM2M specification: The bootstrap procedure failed when the LwM2M Client did not receive the "Bootstrap-Finish" operation after the EXCHANGE_LIFETIME time period expired. The EXCHANGE_LIFETIME parameter is defined in RFC 7252 We must handle the case where Bootstrap server is not sending information towards us. Signed-off-by: Seppo Takalo (cherry picked from commit f49309cf52eb97b2f6556ad044c725c595aed2e5) (cherry picked from commit b6b14807f6093988c3d3d6d32c7308322c3d2790) --- subsys/net/lib/lwm2m/lwm2m_rd_client.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/subsys/net/lib/lwm2m/lwm2m_rd_client.c b/subsys/net/lib/lwm2m/lwm2m_rd_client.c index 0f4405bfc92..fca3f7d560f 100644 --- a/subsys/net/lib/lwm2m/lwm2m_rd_client.c +++ b/subsys/net/lib/lwm2m/lwm2m_rd_client.c @@ -70,6 +70,7 @@ LOG_MODULE_REGISTER(LOG_MODULE_NAME); #define CLIENT_QUEUE_LEN sizeof("Q") #define DELAY_BEFORE_CLOSING (1 * MSEC_PER_SEC) #define DELAY_FOR_ACK 100U +#define EXCHANGE_LIFETIME 247U static void sm_handle_registration_update_failure(void); static int sm_send_registration_msg(void); @@ -120,6 +121,7 @@ struct lwm2m_rd_client_info { int64_t last_update; int64_t last_tx; int64_t next_event; + int64_t last_state_change; char ep_name[CLIENT_EP_LEN]; char server_ep[CLIENT_EP_LEN]; @@ -172,6 +174,7 @@ void engine_update_tx_time(void) static void next_event_at(int64_t timestamp) { + client.next_event = timestamp; (void)lwm2m_engine_call_at(lwm2m_rd_client_service, timestamp); } @@ -236,6 +239,7 @@ static void set_sm_state_delayed(uint8_t sm_state, int64_t delay_ms) lwm2m_close_socket(client.ctx); } } + client.last_state_change = k_uptime_get(); next_event_at(k_uptime_get() + delay_ms); k_mutex_unlock(&client.mutex); } @@ -1288,8 +1292,11 @@ static void lwm2m_rd_client_service(struct k_work *work) { k_mutex_lock(&client.mutex, K_FOREVER); + int64_t timeout = 0; + if (client.ctx) { LOG_DBG("State: %d", get_sm_state()); + client.next_event = INT64_MAX; switch (get_sm_state()) { case ENGINE_IDLE: if (client.ctx->sock_fd > -1) { @@ -1312,10 +1319,12 @@ static void lwm2m_rd_client_service(struct k_work *work) case ENGINE_BOOTSTRAP_REG_SENT: /* wait for bootstrap registration done */ + timeout = EXCHANGE_LIFETIME; break; case ENGINE_BOOTSTRAP_REG_DONE: /* wait for transfer done */ + timeout = EXCHANGE_LIFETIME; break; case ENGINE_BOOTSTRAP_TRANS_DONE: @@ -1333,6 +1342,7 @@ static void lwm2m_rd_client_service(struct k_work *work) case ENGINE_REGISTRATION_SENT: /* wait registration to be done or timeout */ + timeout = EXCHANGE_LIFETIME; break; case ENGINE_REGISTRATION_DONE: @@ -1346,6 +1356,7 @@ static void lwm2m_rd_client_service(struct k_work *work) case ENGINE_UPDATE_SENT: /* wait update to be done or abort */ + timeout = EXCHANGE_LIFETIME; break; case ENGINE_DEREGISTER: @@ -1354,6 +1365,7 @@ static void lwm2m_rd_client_service(struct k_work *work) case ENGINE_DEREGISTER_SENT: /* wait for deregister to be done or reset */ + timeout = EXCHANGE_LIFETIME; break; case ENGINE_DEREGISTERED: @@ -1369,6 +1381,17 @@ static void lwm2m_rd_client_service(struct k_work *work) LOG_ERR("Unhandled state: %d", get_sm_state()); } + + if (timeout) { + int64_t end = client.last_state_change + timeout * MSEC_PER_SEC; + + if (end < k_uptime_get()) { + LOG_DBG("State machine have timed out"); + sm_handle_timeout_state(NULL, ENGINE_INIT); + } else if (client.next_event > end) { + next_event_at(end); + } + } } k_mutex_unlock(&client.mutex); From 2a642c8d8dace1cfe3ea52f80dcfd41bd0832d92 Mon Sep 17 00:00:00 2001 From: Seppo Takalo Date: Tue, 12 Sep 2023 11:39:37 +0300 Subject: [PATCH 089/421] [nrf fromtree] net: lwm2m: Allow Bootstrap server to close DTLS connection Allow Bootstrap server to close the DTLS connection immediately after receiving Ack to Bootstrap-Finish command. This is not an error as either parties are allowed to tear down the connection. Signed-off-by: Seppo Takalo (cherry picked from commit da1463756ebe524b3fcaa40b2a3c3fde32bd2592) (cherry picked from commit 73235503bfc6edc503ce988a3ecef49ab11a1aeb) --- subsys/net/lib/lwm2m/lwm2m_rd_client.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/subsys/net/lib/lwm2m/lwm2m_rd_client.c b/subsys/net/lib/lwm2m/lwm2m_rd_client.c index fca3f7d560f..feebcaeea17 100644 --- a/subsys/net/lib/lwm2m/lwm2m_rd_client.c +++ b/subsys/net/lib/lwm2m/lwm2m_rd_client.c @@ -89,12 +89,10 @@ static void set_sm_state(uint8_t sm_state); enum sm_engine_state { ENGINE_IDLE, ENGINE_INIT, -#if defined(CONFIG_LWM2M_RD_CLIENT_SUPPORT_BOOTSTRAP) ENGINE_DO_BOOTSTRAP_REG, ENGINE_BOOTSTRAP_REG_SENT, ENGINE_BOOTSTRAP_REG_DONE, ENGINE_BOOTSTRAP_TRANS_DONE, -#endif ENGINE_DO_REGISTRATION, ENGINE_SEND_REGISTRATION, ENGINE_REGISTRATION_SENT, @@ -355,14 +353,20 @@ static void sm_handle_failure_state(enum sm_engine_state sm_state) static void socket_fault_cb(int error) { LOG_ERR("RD Client socket error: %d", error); + lwm2m_socket_close(client.ctx); - if (sm_is_bootstrap()) { + if (IS_ENABLED(CONFIG_LWM2M_RD_CLIENT_SUPPORT_BOOTSTRAP) && sm_is_bootstrap()) { client.ctx->sec_obj_inst = -1; /* force full registration */ client.last_update = 0; - } - lwm2m_socket_close(client.ctx); + if (get_sm_state() == ENGINE_BOOTSTRAP_TRANS_DONE) { + /* Ignore the error, some servers close the connection immediately + * after receiving Ack to Bootstrap-Finish command. + */ + return; + } + } /* Network error state causes engine to re-register, * so only trigger that state if we are not stopping the From 2ea372c8833205e30b5986a1567ab48e735f1726 Mon Sep 17 00:00:00 2001 From: Seppo Takalo Date: Wed, 20 Sep 2023 10:08:50 +0300 Subject: [PATCH 090/421] [nrf fromtree] net: lwm2m: Fix build warning on access-control object With bootstrap one function is unused. Fix by changing ifdef to if (IS_ENABLED()) so linker can drop it. Signed-off-by: Seppo Takalo (cherry picked from commit d8d81a8075679cb04b8706de873ecfa1ae9ce438) (cherry picked from commit 777cc86cbb16a45f588bc1ee57cad605b75c0ac4) --- subsys/net/lib/lwm2m/lwm2m_obj_access_control.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/subsys/net/lib/lwm2m/lwm2m_obj_access_control.c b/subsys/net/lib/lwm2m/lwm2m_obj_access_control.c index 1a83ef5ad29..383dbe9b539 100644 --- a/subsys/net/lib/lwm2m/lwm2m_obj_access_control.c +++ b/subsys/net/lib/lwm2m/lwm2m_obj_access_control.c @@ -432,10 +432,10 @@ static int ac_control_init(void) ac_obj.create_cb = ac_create; lwm2m_register_obj(&ac_obj); -#if !IS_ENABLED(CONFIG_LWM2M_RD_CLIENT_SUPPORT_BOOTSTRAP) - /* add the objects/object instances that were created before the ac control object */ - add_existing_objects(); -#endif /* CONFIG_LWM2M_RD_CLIENT_SUPPORT_BOOTSTRAP */ + if (!IS_ENABLED(CONFIG_LWM2M_RD_CLIENT_SUPPORT_BOOTSTRAP)) { + /* add the objects/object instances that were created before the ac control */ + add_existing_objects(); + } return 0; } From 98a073881f16b6f656f52c697e333a38a25c0d3d Mon Sep 17 00:00:00 2001 From: Seppo Takalo Date: Wed, 20 Sep 2023 13:26:41 +0300 Subject: [PATCH 091/421] [nrf fromtree] net: lwm2m: Don't allow operations on security object In spec: The LwM2M Client MUST reject any LwM2M Server operation on the Security Object (ID: 0) with an "4.01 Unauthorized" response code. Signed-off-by: Seppo Takalo (cherry picked from commit b0303f5bd37bb1af8152a6910f70fbd569724ebb) (cherry picked from commit f2b8747d0ec91cb8d24fc4d923b0684a0ded77de) --- subsys/net/lib/lwm2m/lwm2m_message_handling.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/subsys/net/lib/lwm2m/lwm2m_message_handling.c b/subsys/net/lib/lwm2m/lwm2m_message_handling.c index 952a3d9c130..1a7d023ceb2 100644 --- a/subsys/net/lib/lwm2m/lwm2m_message_handling.c +++ b/subsys/net/lib/lwm2m/lwm2m_message_handling.c @@ -2330,6 +2330,11 @@ int handle_request(struct coap_packet *request, struct lwm2m_message *msg) goto error; } #endif + if (msg->path.obj_id == LWM2M_OBJECT_SECURITY_ID && !msg->ctx->bootstrap_mode) { + r = -EACCES; + goto error; + } + switch (msg->operation) { case LWM2M_OP_READ: From 52d120825d49c1d37430162fbf9c1d4a8edd1bb9 Mon Sep 17 00:00:00 2001 From: Seppo Takalo Date: Tue, 19 Sep 2023 10:27:22 +0300 Subject: [PATCH 092/421] [nrf fromtree] net: lwm2m: Add shell command to create object instances Some testcases might need to be able to create object instances, so add shell command for it. Signed-off-by: Seppo Takalo (cherry picked from commit 0a982c3617dbc7e98bfa51357c8644fe3e44ae4f) (cherry picked from commit 8b2651be500988d68c15a6000046c5c90335a6a1) --- subsys/net/lib/lwm2m/lwm2m_shell.c | 36 ++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/subsys/net/lib/lwm2m/lwm2m_shell.c b/subsys/net/lib/lwm2m/lwm2m_shell.c index f8374eb34f2..2a86aa88d69 100644 --- a/subsys/net/lib/lwm2m/lwm2m_shell.c +++ b/subsys/net/lib/lwm2m/lwm2m_shell.c @@ -40,6 +40,7 @@ LOG_MODULE_REGISTER(LOG_MODULE_NAME); "-sX\tWrite value as intX_t\n" \ "-f \tWrite value as float\n" \ "-t \tWrite value as time_t\n" +#define LWM2M_HELP_CREATE "Create object instance\ncreate PATH\n" #define LWM2M_HELP_START "Start the LwM2M RD (Registration / Discovery) Client\n" \ "start EP_NAME [BOOTSTRAP FLAG]\n" \ "-b \tSet the bootstrap flag (default 0)\n" @@ -372,6 +373,40 @@ static int cmd_write(const struct shell *sh, size_t argc, char **argv) return 0; } +static int cmd_create(const struct shell *sh, size_t argc, char **argv) +{ + struct lwm2m_obj_path path; + struct lwm2m_engine_obj_inst *obj_inst; + int ret; + + if (argc < 2) { + shell_error(sh, "No object ID given\n"); + shell_help(sh); + return -EINVAL; + } + + ret = lwm2m_string_to_path(argv[1], &path, '/'); + if (ret < 0) { + shell_error(sh, "failed to read path (%d)\n", ret); + return -ENOEXEC; + } + + if (path.level != LWM2M_PATH_LEVEL_OBJECT_INST) { + shell_error(sh, "path is not an object instance\n"); + shell_help(sh); + return -EINVAL; + } + + ret = lwm2m_create_obj_inst(path.obj_id, path.obj_inst_id, &obj_inst); + if (ret < 0) { + shell_error(sh, "Failed to create object instance %d/%d, ret=%d", path.obj_id, + path.obj_inst_id, ret); + return -ENOEXEC; + } + + return 0; +} + static int cmd_start(const struct shell *sh, size_t argc, char **argv) { struct lwm2m_ctx *ctx = lwm2m_rd_client_ctx(); @@ -561,6 +596,7 @@ SHELL_STATIC_SUBCMD_SET_CREATE( SHELL_CMD_ARG(exec, NULL, LWM2M_HELP_EXEC, cmd_exec, 2, 1), SHELL_CMD_ARG(read, NULL, LWM2M_HELP_READ, cmd_read, 2, 1), SHELL_CMD_ARG(write, NULL, LWM2M_HELP_WRITE, cmd_write, 3, 1), + SHELL_CMD_ARG(create, NULL, LWM2M_HELP_CREATE, cmd_create, 2, 0), SHELL_CMD_ARG(start, NULL, LWM2M_HELP_START, cmd_start, 2, 2), SHELL_CMD_ARG(stop, NULL, LWM2M_HELP_STOP, cmd_stop, 1, 1), SHELL_CMD_ARG(update, NULL, LWM2M_HELP_UPDATE, cmd_update, 1, 0), From 70a65804527ea66bf30a353d12ab4a348cf54cd8 Mon Sep 17 00:00:00 2001 From: Seppo Takalo Date: Thu, 1 Jun 2023 12:00:44 +0300 Subject: [PATCH 093/421] [nrf fromtree] net: lwm2m: Add functional tests for LwM2M against Leshan MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use the new Pytest integration to run testcases against Leshan. Test with: twister -T tests/net/lib/lwm2m/functional -p native_posix -vv This requires Leshan running in localhost using following setup: tcp/8080 Leshan web interface and REST API tcp/8081 Leshan bootstrap server REST API udp/5683 Leshan non-secure CoAP udp/5684 Leshan DTLS CoAP udp/5783 non-secure Bootstrap CoAP udp/5684 DTLS Bootstrap CoAP Leshan and Boostrap server must be reachable from native_posix run using IP address 192.0.2.2 as in most of the examples. Tests are written from test spec; OMA Enabler Test Specification (Interoperability) for Lightweight M2M Following tests are implemented in this commit: * LightweightM2M-1.1-int-0 – Client Initiated Bootstrap * LightweightM2M-1.1-int-1 – Client Initiated Bootstrap Full (PSK) * LightweightM2M-1.1-int-101 – Initial Registration * LightweightM2M-1.1-int-102 – Registration Update * LightweightM2M-1.1-int-104 – Registration Update Trigge * LightweightM2M-1.1-int-105 - Discarded Register Update * LightweightM2M-1.1-int-107 – Extending the lifetime of a registration * LightweightM2M-1.1-int-108 – Turn on Queue Mode * LightweightM2M-1.1-int-109 – Behavior in Queue Mode * LightweightM2M-1.1-int-201 – Querying basic information in Plain Text * LightweightM2M-1.1-int-203 – Querying basic information in TLV format * LightweightM2M-1.1-int-204 – Querying basic information in JSON format * LightweightM2M-1.1-int-205 – Setting basic information in Plain Text * LightweightM2M-1.1-int-211 – Querying basic information in CBOR format * LightweightM2M-1.1-int-212 – Setting basic information in CBOR format * LightweightM2M-1.1-int-215 – Setting basic information in TLV format * LightweightM2M-1.1-int-220 – Setting basic information in JSON format * LightweightM2M-1.1-int-221 – Attempt to perform operations on Security * LightweightM2M-1.1-int-401 – UDP Channel Security – PSK Mode Signed-off-by: Seppo Takalo (cherry picked from commit 7b4f22edd17acafa55add96da96cdae6d90ce973) (cherry picked from commit 66b555d0b5c8d2d6209319a0ea4fe48c5dd7807d) --- tests/net/lib/lwm2m/interop/CMakeLists.txt | 10 + tests/net/lib/lwm2m/interop/README.md | 103 ++++ .../lwm2m/interop/boards/native_posix.conf | 7 + .../lwm2m/interop/boards/qemu_cortex_m3.conf | 20 + tests/net/lib/lwm2m/interop/prj.conf | 90 ++++ tests/net/lib/lwm2m/interop/pytest/leshan.py | 104 ++++ .../lib/lwm2m/interop/pytest/test_lwm2m.py | 446 ++++++++++++++++++ tests/net/lib/lwm2m/interop/requirements.txt | 1 + .../net/lib/lwm2m/interop/src/lwm2m-client.c | 171 +++++++ tests/net/lib/lwm2m/interop/testcase.yaml | 14 + 10 files changed, 966 insertions(+) create mode 100644 tests/net/lib/lwm2m/interop/CMakeLists.txt create mode 100644 tests/net/lib/lwm2m/interop/README.md create mode 100644 tests/net/lib/lwm2m/interop/boards/native_posix.conf create mode 100644 tests/net/lib/lwm2m/interop/boards/qemu_cortex_m3.conf create mode 100644 tests/net/lib/lwm2m/interop/prj.conf create mode 100644 tests/net/lib/lwm2m/interop/pytest/leshan.py create mode 100644 tests/net/lib/lwm2m/interop/pytest/test_lwm2m.py create mode 100644 tests/net/lib/lwm2m/interop/requirements.txt create mode 100644 tests/net/lib/lwm2m/interop/src/lwm2m-client.c create mode 100644 tests/net/lib/lwm2m/interop/testcase.yaml diff --git a/tests/net/lib/lwm2m/interop/CMakeLists.txt b/tests/net/lib/lwm2m/interop/CMakeLists.txt new file mode 100644 index 00000000000..89c4d33e43e --- /dev/null +++ b/tests/net/lib/lwm2m/interop/CMakeLists.txt @@ -0,0 +1,10 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(lwm2m_interop_tests) + +FILE(GLOB app_sources src/*.c) +target_sources(app PRIVATE ${app_sources}) + +include(${ZEPHYR_BASE}/samples/net/common/common.cmake) diff --git a/tests/net/lib/lwm2m/interop/README.md b/tests/net/lib/lwm2m/interop/README.md new file mode 100644 index 00000000000..858f5007f64 --- /dev/null +++ b/tests/net/lib/lwm2m/interop/README.md @@ -0,0 +1,103 @@ +# LwM2M Interoperability tests using Leshan demo server + +This directory contains list of testcases that use +the Twister's Pytest integration to run testcases against Leshan demo server. +These tests use emulated hardware (native_posix). + +These tests require setup that is not done in Twister run, so follow this documentation to set +up the test environment. + +## Network setup + +As with typical network samples, host machine uses IP address `192.0.2.2` and the emulated device +running Zephyr is using address `192.0.2.1`. + +Follow [Networking with the host system](https://docs.zephyrproject.org/latest/connectivity/networking/networking_with_host.html#networking-with-the-host-system) +from Zephyr's documentation how to set it up, or follow [Create NAT and routing for Zephyr native network on Linux](https://github.com/zephyrproject-rtos/net-tools/blob/master/README%20NAT.md). + +### Leshan server setup + +* Leshan server must be reachable from the device using IP address `192.0.2.2`. + Configure the port forwarding, if you use Docker to run Leshan. +* Leshan demo server REST API must be reachable from localhost. +* tcp/8080 Leshan web interface and REST API +* tcp/8081 Leshan bootstrap server REST API +* udp/5683 Leshan non-secure CoAP +* udp/5684 Leshan DTLS CoAP +* udp/5783 non-secure Bootstrap CoAP +* udp/5684 DTLS Bootstrap CoAP +* Download Leshan JAR file from https://ci.eclipse.org/leshan/job/leshan/lastSuccessfulBuild/artifact/leshan-server-demo.jar +* Download Leshan Bootstrap server JAR file from https://ci.eclipse.org/leshan/job/leshan/lastSuccessfulBuild/artifact/leshan-bsserver-demo.jar + +Both server can be started like this: +``` +java -jar ./leshan-server-demo.jar -wp 8080 -vv +java -jar ./leshan-bsserver-demo.jar -lp=5783 -slp=5784 -wp 8081 +``` + +Or create a helper script that does everything, including download: +``` +#!/bin/sh -eu + +# Download Leshan if needed +if [ ! -f leshan-server-demo.jar ]; then + wget https://ci.eclipse.org/leshan/job/leshan/lastSuccessfulBuild/artifact/leshan-server-demo.jar +fi + +if [ ! -f leshan-bsserver-demo.jar ]; then + wget 'https://ci.eclipse.org/leshan/job/leshan/lastSuccessfulBuild/artifact/leshan-bsserver-demo.jar' +fi + +mkdir -p log + +start-stop-daemon --make-pidfile --pidfile log/leshan.pid --chdir $(pwd) --background --start \ + --startas /bin/bash -- -c "exec java -jar ./leshan-server-demo.jar -wp 8080 -vv --models-folder objects >log/leshan.log 2>&1" + +start-stop-daemon --make-pidfile --pidfile log/leshan_bs.pid --chdir $(pwd) --background --start \ + --startas /bin/bash -- -c "exec java -jar ./leshan-bsserver-demo.jar -lp=5783 -slp=5784 -wp 8081 -vv >log/leshan_bs.log 2>&1" +``` + +Then stopping would require similar script: +``` +#!/bin/sh -eu + +start-stop-daemon --remove-pidfile --pidfile log/leshan.pid --stop +start-stop-daemon --remove-pidfile --pidfile log/leshan_bs.pid --stop +``` + +## Python package requirements + +These tests require extra package that is not installed when you follow the Zephyr's setup. +Install with `pip install CoAPthon3` + +## Running tests + +``` +twister -p native_posix -vv --enable-slow -T tests/net/lib/lwm2m/interop +`````` + +## Test specification + +Tests are written from test spec; +[OMA Enabler Test Specification (Interoperability) for Lightweight M2M](https://www.openmobilealliance.org/release/LightweightM2M/ETS/OMA-ETS-LightweightM2M-V1_1-20190912-D.pdf) + +Following tests are implemented: +* LightweightM2M-1.1-int-0 – Client Initiated Bootstrap +* LightweightM2M-1.1-int-1 – Client Initiated Bootstrap Full (PSK) +* LightweightM2M-1.1-int-101 – Initial Registration +* LightweightM2M-1.1-int-102 – Registration Update +* LightweightM2M-1.1-int-104 – Registration Update Trigge +* LightweightM2M-1.1-int-105 - Discarded Register Update +* LightweightM2M-1.1-int-107 – Extending the lifetime of a registration +* LightweightM2M-1.1-int-108 – Turn on Queue Mode +* LightweightM2M-1.1-int-109 – Behavior in Queue Mode +* LightweightM2M-1.1-int-201 – Querying basic information in Plain Text +* LightweightM2M-1.1-int-203 – Querying basic information in TLV format +* LightweightM2M-1.1-int-204 – Querying basic information in JSON format +* LightweightM2M-1.1-int-205 – Setting basic information in Plain Text +* LightweightM2M-1.1-int-211 – Querying basic information in CBOR format +* LightweightM2M-1.1-int-212 – Setting basic information in CBOR format +* LightweightM2M-1.1-int-215 – Setting basic information in TLV format +* LightweightM2M-1.1-int-220 – Setting basic information in JSON format +* LightweightM2M-1.1-int-221 – Attempt to perform operations on Security +* LightweightM2M-1.1-int-401 – UDP Channel Security – PSK Mode diff --git a/tests/net/lib/lwm2m/interop/boards/native_posix.conf b/tests/net/lib/lwm2m/interop/boards/native_posix.conf new file mode 100644 index 00000000000..44346db12ed --- /dev/null +++ b/tests/net/lib/lwm2m/interop/boards/native_posix.conf @@ -0,0 +1,7 @@ +CONFIG_DNS_RESOLVER=y +CONFIG_DNS_SERVER_IP_ADDRESSES=y +CONFIG_DNS_SERVER1="192.0.2.2" +CONFIG_LWM2M_DNS_SUPPORT=y +CONFIG_NET_CONFIG_MY_IPV4_GW="192.0.2.2" +CONFIG_NATIVE_POSIX_SLOWDOWN_TO_REAL_TIME=y +CONFIG_NATIVE_UART_0_ON_STDINOUT=y diff --git a/tests/net/lib/lwm2m/interop/boards/qemu_cortex_m3.conf b/tests/net/lib/lwm2m/interop/boards/qemu_cortex_m3.conf new file mode 100644 index 00000000000..7a3fd344e50 --- /dev/null +++ b/tests/net/lib/lwm2m/interop/boards/qemu_cortex_m3.conf @@ -0,0 +1,20 @@ +CONFIG_NET_L2_ETHERNET=y +CONFIG_ETH_DRIVER=y +CONFIG_ETH_STELLARIS=y +CONFIG_NET_QEMU_ETHERNET=y + +# RAM/ROM tuning +CONFIG_IDLE_STACK_SIZE=128 +CONFIG_MBEDTLS_HEAP_SIZE=7000 +CONFIG_ISR_STACK_SIZE=512 +CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=1024 +CONFIG_LWM2M_ENGINE_STACK_SIZE=2000 +CONFIG_LWM2M_LOG_LEVEL_INF=y +CONFIG_LWM2M_ENGINE_MAX_MESSAGES=3 +CONFIG_LWM2M_ENGINE_VALIDATION_BUFFER_SIZE=0 +CONFIG_LWM2M_ENGINE_MAX_OBSERVER=5 +CONFIG_LWM2M_SECURITY_DTLS_TLS_CIPHERSUITE_MAX=3 +CONFIG_LWM2M_DEVICE_PWRSRC_MAX=2 +CONFIG_LWM2M_DEVICE_ERROR_CODE_MAX=5 +CONFIG_LWM2M_DEVICE_EXT_DEV_INFO_MAX=2 +CONFIG_LWM2M_NUM_ATTR=10 diff --git a/tests/net/lib/lwm2m/interop/prj.conf b/tests/net/lib/lwm2m/interop/prj.conf new file mode 100644 index 00000000000..5d255e0513e --- /dev/null +++ b/tests/net/lib/lwm2m/interop/prj.conf @@ -0,0 +1,90 @@ +CONFIG_NETWORKING=y +CONFIG_LOG=y +CONFIG_LWM2M_LOG_LEVEL_DBG=y +CONFIG_TEST_RANDOM_GENERATOR=y +CONFIG_NET_IPV6=y +CONFIG_NET_IF_UNICAST_IPV6_ADDR_COUNT=3 +CONFIG_NET_IF_MCAST_IPV6_ADDR_COUNT=2 +CONFIG_NET_IPV4=y +CONFIG_NET_DHCPV4=n +CONFIG_NET_IF_UNICAST_IPV4_ADDR_COUNT=3 +CONFIG_NET_IF_MCAST_IPV4_ADDR_COUNT=2 +CONFIG_PRINTK=y +CONFIG_NET_PKT_RX_COUNT=10 +CONFIG_NET_PKT_TX_COUNT=10 +CONFIG_NET_BUF_RX_COUNT=10 +CONFIG_NET_BUF_TX_COUNT=10 +CONFIG_NET_MAX_CONTEXTS=5 +CONFIG_NET_CONFIG_MY_IPV6_ADDR="2001:db8::1" +CONFIG_NET_CONFIG_PEER_IPV6_ADDR="2001:db8::2" +CONFIG_NET_CONFIG_MY_IPV4_ADDR="192.0.2.1" +CONFIG_NET_CONFIG_MY_IPV4_GW="192.0.2.2" + +CONFIG_NET_LOG=y + +CONFIG_NET_CONFIG_NEED_IPV6=y +CONFIG_NET_CONFIG_NEED_IPV4=y +CONFIG_NET_CONFIG_SETTINGS=y + +CONFIG_LWM2M=y +CONFIG_LWM2M_COAP_BLOCK_SIZE=512 +CONFIG_LWM2M_IPSO_SUPPORT=y +CONFIG_LWM2M_SHELL=y +CONFIG_LWM2M_ACCESS_CONTROL_ENABLE=n + +#Enable Portfolio object +CONFIG_LWM2M_PORTFOLIO_OBJ_SUPPORT=y + +#LwM2M v1.1 configure +CONFIG_LWM2M_VERSION_1_1=y +CONFIG_LWM2M_DTLS_SUPPORT=y +CONFIG_LWM2M_RD_CLIENT_SUPPORT_BOOTSTRAP=y + +#Enable SenML JSON content format +CONFIG_JSON_LIBRARY=y +CONFIG_BASE64=y +CONFIG_LWM2M_RW_SENML_JSON_SUPPORT=y + +#Enable SenML CBOR content format +CONFIG_LWM2M_RW_SENML_CBOR_SUPPORT=y +CONFIG_LWM2M_RW_SENML_CBOR_RECORDS=60 +CONFIG_ZCBOR_CANONICAL=y + +#Enable legacy content formats +CONFIG_LWM2M_RW_JSON_SUPPORT=y +CONFIG_LWM2M_RW_OMA_TLV_SUPPORT=y + +# Longer endpoint name might be returned in a registration reply +CONFIG_COAP_EXTENDED_OPTIONS_LEN=y +CONFIG_COAP_EXTENDED_OPTIONS_LEN_VALUE=40 + +# Use QUEUE mode by default +CONFIG_LWM2M_QUEUE_MODE_ENABLED=y +CONFIG_LWM2M_QUEUE_MODE_UPTIME=20 + +# LwM2M configuration as OMA-ETS-LightweightM2M_INT-V1_1-20190912-D Configuration 3 +CONFIG_LWM2M_ENGINE_DEFAULT_LIFETIME=30 +CONFIG_LWM2M_SERVER_DEFAULT_PMIN=1 +CONFIG_LWM2M_SERVER_DEFAULT_PMAX=10 + +CONFIG_MBEDTLS=y +CONFIG_MBEDTLS_TLS_VERSION_1_2=y + +# Special MbedTLS changes +CONFIG_MBEDTLS_ENABLE_HEAP=y +CONFIG_MBEDTLS_HEAP_SIZE=8192 +CONFIG_MBEDTLS_SSL_MAX_CONTENT_LEN=1500 +CONFIG_MBEDTLS_CIPHER_CCM_ENABLED=y + +# Disable RSA, we don't parse certs: saves flash/memory +CONFIG_MBEDTLS_KEY_EXCHANGE_RSA_ENABLED=n +# Enable PSK instead +CONFIG_MBEDTLS_KEY_EXCHANGE_PSK_ENABLED=y + +CONFIG_NET_SOCKETS_SOCKOPT_TLS=y +CONFIG_NET_SOCKETS_TLS_MAX_CONTEXTS=4 +CONFIG_NET_SOCKETS_ENABLE_DTLS=y + +# MbedTLS needs a larger stack +CONFIG_MAIN_STACK_SIZE=2048 +CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=2048 diff --git a/tests/net/lib/lwm2m/interop/pytest/leshan.py b/tests/net/lib/lwm2m/interop/pytest/leshan.py new file mode 100644 index 00000000000..4d69a3a977f --- /dev/null +++ b/tests/net/lib/lwm2m/interop/pytest/leshan.py @@ -0,0 +1,104 @@ +# Copyright (c) 2023 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: Apache-2.0 + +from __future__ import annotations + +import json +import requests +import binascii + +class Leshan: + def __init__(self, url: str): + self.api_url = url + self.timeout = 10 + self.format = 'TLV' + # self.format = "SENML_CBOR" + try: + resp = self.get('/security/clients') + if not isinstance(resp, list): + raise RuntimeError('Did not receive list of endpoints') + except requests.exceptions.ConnectionError: + raise RuntimeError('Leshan not responding') + + @staticmethod + def handle_response(resp: requests.models.Response): + """Generic response handler for all queries""" + if resp.status_code >= 300 or resp.status_code < 200: + raise RuntimeError(f'Error {resp.status_code}: {resp.text}') + if len(resp.text): + obj = json.loads(resp.text) + return obj + else: + return None + + def get(self, path: str): + """Send HTTP GET query""" + resp = requests.get(f'{self.api_url}{path}?timeout={self.timeout}&format={self.format}') + return Leshan.handle_response(resp) + + def put_raw(self, path: str, data: str | dict | None = None, headers: dict | None = None): + resp = requests.put(f'{self.api_url}{path}', data=data, headers=headers) + return Leshan.handle_response(resp) + + def put(self, path: str, data: str | dict, uri_options: str = ''): + if isinstance(data, dict): + data = json.dumps(data) + return self.put_raw(f'{path}?timeout={self.timeout}&format={self.format}' + uri_options, data=data, headers={'content-type': 'application/json'}) + + def post(self, path: str, data: str | dict | None = None): + resp = requests.post(f'{self.api_url}{path}', data=data, headers={'content-type': 'application/json'}) + return Leshan.handle_response(resp) + + def delete(self, path: str): + resp = requests.delete(f'{self.api_url}{path}') + return Leshan.handle_response(resp) + + def execute(self, endpoint: str, path: str): + return self.post(f'/clients/{endpoint}/{path}') + + def write(self, endpoint: str, path: str, value: bool | int | str): + if isinstance(value, bool): + type = 'boolean' + value = "true" if value else "false" + elif isinstance(value, int): + type = 'integer' + value = str(value) + elif isinstance(value, str): + type = 'string' + value = '"' + value + '"' + id = path.split('/')[2] + return self.put(f'/clients/{endpoint}/{path}', f'{{"id":{id},"kind":"singleResource","value":{value},"type":"{type}"}}') + + def read(self, endpoint: str, path: str): + resp = self.get(f'/clients/{endpoint}/{path}') + if not resp['success']: + return resp + content = resp['content'] + if content['kind'] == 'instance': + return content['resources'] + elif content['kind'] == 'singleResource': + return content['value'] + elif content['kind'] == 'multiResource': + return content['values'] + raise RuntimeError(f'Unhandled type {content["kind"]}') + + def create_psk_device(self, endpoint: str, passwd: str): + psk = binascii.b2a_hex(passwd.encode()).decode() + self.put('/security/clients/', f'{{"endpoint":"{endpoint}","tls":{{"mode":"psk","details":{{"identity":"{endpoint}","key":"{psk}"}} }} }}') + + def delete_device(self, endpoint: str): + self.delete(f'/security/clients/{endpoint}') + + def create_bs_device(self, endpoint: str, server_uri: str, passwd: str): + psk = binascii.b2a_hex(passwd.encode()).decode() + data = f'{{"tls":{{"mode":"psk","details":{{"identity":"{endpoint}","key":"{psk}"}}}},"endpoint":"{endpoint}"}}' + self.put('/security/clients/', data) + id = str([ord(n) for n in endpoint]) + key = str([ord(n) for n in passwd]) + content = '{"servers":{"0":{"binding":"U","defaultMinPeriod":1,"lifetime":86400,"notifIfDisabled":false,"shortId":1}},"security":{"1":{"bootstrapServer":false,"clientOldOffTime":1,"publicKeyOrId":' + id + ',"secretKey":' + key + ',"securityMode":"PSK","serverId":1,"serverSmsNumber":"","smsBindingKeyParam":[],"smsBindingKeySecret":[],"smsSecurityMode":"NO_SEC","uri":"'+server_uri+'"}},"oscore":{},"toDelete":["/0","/1"]}' + self.post(f'/bootstrap/{endpoint}', content) + + def delete_bs_device(self, endpoint: str): + self.delete(f'/security/clients/{endpoint}') + self.delete(f'/bootstrap/{endpoint}') diff --git a/tests/net/lib/lwm2m/interop/pytest/test_lwm2m.py b/tests/net/lib/lwm2m/interop/pytest/test_lwm2m.py new file mode 100644 index 00000000000..21ed51ef1e6 --- /dev/null +++ b/tests/net/lib/lwm2m/interop/pytest/test_lwm2m.py @@ -0,0 +1,446 @@ +# Copyright (c) 2023 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: Apache-2.0 + +import time +import logging +import pytest +from leshan import Leshan +import os +import binascii +import random +import string + +from twister_harness import Shell + +LESHAN_IP: str = '192.0.2.2' +COAP_PORT: int = 5683 +COAPS_PORT: int = 5684 +BOOTSTRAP_COAPS_PORT: int = 5784 + +logger = logging.getLogger(__name__) + +@pytest.fixture(scope='module') +def helperclient() -> object: + try: + from coapthon.client.helperclient import HelperClient + except ModuleNotFoundError: + pytest.skip('CoAPthon3 package not installed') + return HelperClient(server=('127.0.0.1', COAP_PORT)) + +@pytest.fixture(scope='session') +def leshan() -> Leshan: + try: + return Leshan("http://localhost:8080/api") + except RuntimeError: + pytest.skip('Leshan server not available') + +@pytest.fixture(scope='session') +def leshan_bootstrap() -> Leshan: + try: + return Leshan("http://localhost:8081/api") + except RuntimeError: + pytest.skip('Leshan Bootstrap server not available') + +# +# Test specification: +# https://www.openmobilealliance.org/release/LightweightM2M/ETS/OMA-ETS-LightweightM2M-V1_1-20190912-D.pdf +# + +def verify_LightweightM2M_1_1_int_0(shell: Shell): + logger.info("LightweightM2M-1.1-int-0 - Client Initiated Bootstrap") + shell._device.readlines_until(regex='.*Bootstrap started with endpoint', timeout=5.0) + shell._device.readlines_until(regex='.*Bootstrap registration done', timeout=5.0) + shell._device.readlines_until(regex='.*Bootstrap data transfer done', timeout=5.0) + +def verify_LightweightM2M_1_1_int_1(shell: Shell, leshan: Leshan, endpoint: str): + logger.info("LightweightM2M-1.1-int-1 - Client Initiated Bootstrap Full (PSK)") + verify_LightweightM2M_1_1_int_0(shell) + verify_LightweightM2M_1_1_int_101(shell, leshan, endpoint) + verify_LightweightM2M_1_1_int_401(shell, leshan, endpoint) + +def verify_LightweightM2M_1_1_int_101(shell: Shell, leshan: Leshan, endpoint: str): + logger.info("LightweightM2M-1.1-int-101 - Initial Registration") + shell._device.readlines_until(regex='.*Registration Done', timeout=5.0) + assert leshan.get(f'/clients/{endpoint}') + +def verify_LightweightM2M_1_1_int_102(shell: Shell, leshan: Leshan, endpoint: str): + logger.info("LightweightM2M-1.1-int-102 - Registration Update") + lines = shell.get_filtered_output(shell.exec_command('lwm2m read 1/0/1 -u32')) + litetime = int(lines[0]) + lifetime = litetime + 10 + start_time = time.time() * 1000 + leshan.write(endpoint, '1/0/1', lifetime) + shell._device.readlines_until(regex='.*net_lwm2m_rd_client: Update Done', timeout=5.0) + latest = leshan.get(f'/clients/{endpoint}') + assert latest["lastUpdate"] > start_time + assert latest["lastUpdate"] <= time.time()*1000 + assert latest["lifetime"] == lifetime + shell.exec_command('lwm2m write 1/0/1 -u32 86400') + +def verify_LightweightM2M_1_1_int_103(): + """LightweightM2M-1.1-int-103 - Deregistration""" + # Unsupported. We don't have "disabled" functionality in server object + +def verify_LightweightM2M_1_1_int_104(shell: Shell, leshan: Leshan, endpoint: str): + logger.info("LightweightM2M-1.1-int-104 - Registration Update Trigger") + shell.exec_command('lwm2m update') + shell._device.readlines_until(regex='.*net_lwm2m_rd_client: Update Done', timeout=5.0) + leshan.execute(endpoint, '1/0/8') + shell._device.readlines_until(regex='.*net_lwm2m_rd_client: Update Done', timeout=5.0) + +def verify_LightweightM2M_1_1_int_105(shell: Shell, leshan: Leshan, endpoint: str, helperclient: object): + logger.info("LightweightM2M-1.1-int-105 - Discarded Register Update") + status = leshan.get(f'/clients/{endpoint}') + if status["secure"]: + logger.debug("Skip, requires non-secure connection") + return + id = status["registrationId"] + assert id + # Fake unregister message + helperclient.delete(f'rd/{id}', timeout=0.1) + helperclient.stop() + time.sleep(1) + shell.exec_command('lwm2m update') + shell._device.readlines_until(regex=r'.*Failed with code 4\.4', timeout=5.0) + shell._device.readlines_until(regex='.*Registration Done', timeout=10.0) + +def verify_LightweightM2M_1_1_int_107(shell: Shell, leshan: Leshan, endpoint: str): + logger.info("LightweightM2M-1.1-int-107 - Extending the lifetime of a registration") + leshan.write(endpoint, '1/0/1', 120) + shell._device.readlines_until(regex='.*net_lwm2m_rd_client: Update Done', timeout=5.0) + lines = shell.get_filtered_output(shell.exec_command('lwm2m read 1/0/1 -u32')) + lifetime = int(lines[0]) + assert lifetime == 120 + logger.debug(f'sleeping for {lifetime} s') + shell._device.readlines_until(regex='.*net_lwm2m_rd_client: Update Done', timeout=lifetime) + assert leshan.get(f'/clients/{endpoint}') + +def verify_LightweightM2M_1_1_int_108(leshan, endpoint): + logger.info("LightweightM2M-1.1-int-108 - Turn on Queue Mode") + assert leshan.get(f'/clients/{endpoint}')["queuemode"] + +def verify_LightweightM2M_1_1_int_109(shell: Shell, leshan: Leshan, endpoint: str): + logger.info("LightweightM2M-1.1-int-109 - Behavior in Queue Mode") + verify_LightweightM2M_1_1_int_107(shell, leshan, endpoint) + shell._device.readlines_until(regex='.*Queue mode RX window closed', timeout=120) + # Restore previous value + shell.exec_command('lwm2m write 1/0/1 -u32 86400') + shell._device.readlines_until(regex='.*Registration update complete', timeout=10) + +def verify_LightweightM2M_1_1_int_201(shell: Shell, leshan: Leshan, endpoint: str): + + logger.info("LightweightM2M-1.1-int-201 - Querying basic information in Plain Text format") + fmt = leshan.format + leshan.format = 'TEXT' + assert leshan.get(f'/clients/{endpoint}/3/0/0')['content']['value'] == 'Zephyr' + assert leshan.get(f'/clients/{endpoint}/3/0/1')['content']['value'] == 'client-1' + assert leshan.get(f'/clients/{endpoint}/3/0/2')['content']['value'] == 'serial-1' + leshan.format = fmt + +def verify_device_object(resp): + ''' Verify that Device object match Configuration 3 ''' + assert resp['valid'] is True + found = 0 + for res in resp['content']['resources']: + if res['id'] == 0: + assert res['value'] == 'Zephyr' + found += 1 + elif res['id'] == 1: + assert res['value'] == 'client-1' + found += 1 + elif res['id'] == 2: + assert res['value'] == 'serial-1' + found += 1 + elif res['id'] == 3: + assert res['value'] == '1.2.3' + found += 1 + elif res['id'] == 11: + assert res['kind'] == 'multiResource' + assert res['values']['0'] == '0' + found += 1 + elif res['id'] == 16: + assert res['value'] == 'U' + found += 1 + assert found == 6 + +def verify_server_object(obj): + ''' Verify that server object match Configuration 3 ''' + found = 0 + for res in obj['resources']: + if res['id'] == 0: + assert res['value'] == '1' + found += 1 + elif res['id'] == 1: + assert res['value'] == '86400' + found += 1 + elif res['id'] == 2: + assert res['value'] == '1' + found += 1 + elif res['id'] == 3: + assert res['value'] == '10' + found += 1 + elif res['id'] == 5: + assert res['value'] == '86400' + found += 1 + elif res['id'] == 6: + assert res['value'] is False + found += 1 + elif res['id'] == 7: + assert res['value'] == 'U' + found += 1 + assert found == 7 + +def verify_LightweightM2M_1_1_int_203(shell: Shell, leshan: Leshan, endpoint: str): + shell.exec_command('lwm2m update') + logger.info('LightweightM2M-1.1-int-203 - Querying basic information in TLV format') + fmt = leshan.format + leshan.format = 'TLV' + resp = leshan.get(f'/clients/{endpoint}/3/0') + verify_device_object(resp) + leshan.format = fmt + +def verify_LightweightM2M_1_1_int_204(shell: Shell, leshan: Leshan, endpoint: str): + shell.exec_command('lwm2m update') + logger.info('LightweightM2M-1.1-int-204 - Querying basic information in JSON format') + fmt = leshan.format + leshan.format = 'JSON' + resp = leshan.get(f'/clients/{endpoint}/3/0') + verify_device_object(resp) + leshan.format = fmt + +def verify_LightweightM2M_1_1_int_205(shell: Shell, leshan: Leshan, endpoint: str): + logger.info('LightweightM2M-1.1-int-205 - Setting basic information in Plain Text format') + fmt = leshan.format + leshan.format = 'TEXT' + leshan.write(endpoint, '1/0/2', 101) + leshan.write(endpoint, '1/0/3', 1010) + leshan.write(endpoint, '1/0/5', 2000) + assert leshan.read(endpoint, '1/0/2') == '101' + assert leshan.read(endpoint, '1/0/3') == '1010' + assert leshan.read(endpoint, '1/0/5') == '2000' + leshan.write(endpoint, '1/0/2', 1) + leshan.write(endpoint, '1/0/3', 10) + leshan.write(endpoint, '1/0/5', 86400) + assert leshan.read(endpoint, '1/0/2') == '1' + assert leshan.read(endpoint, '1/0/3') == '10' + assert leshan.read(endpoint, '1/0/5') == '86400' + leshan.format = fmt + +def verify_LightweightM2M_1_1_int_211(shell: Shell, leshan: Leshan, endpoint: str): + logger.info('LightweightM2M-1.1-int-211 - Querying basic information in CBOR format') + fmt = leshan.format + leshan.format = 'CBOR' + lines = shell.get_filtered_output(shell.exec_command('lwm2m read 1/0/0 -u16')) + id = lines[0] + assert leshan.read(endpoint, '1/0/0') == id + assert leshan.read(endpoint, '1/0/6') is False + assert leshan.read(endpoint, '1/0/7') == 'U' + leshan.format = fmt + +def verify_LightweightM2M_1_1_int_212(shell: Shell, leshan: Leshan, endpoint: str): + logger.info('LightweightM2M-1.1-int-212 - Setting basic information in CBOR format') + fmt = leshan.format + leshan.format = 'CBOR' + leshan.write(endpoint, '1/0/2', 101) + leshan.write(endpoint, '1/0/3', 1010) + leshan.write(endpoint, '1/0/6', True) + assert leshan.read(endpoint, '1/0/2') == '101' + assert leshan.read(endpoint, '1/0/3') == '1010' + assert leshan.read(endpoint, '1/0/6') is True + leshan.write(endpoint, '1/0/2', 1) + leshan.write(endpoint, '1/0/3', 10) + leshan.write(endpoint, '1/0/6', False) + leshan.format = fmt + +def verify_setting_basic_in_format(shell, leshan, endpoint, format): + fmt = leshan.format + leshan.format = format + server_obj = leshan.get(f'/clients/{endpoint}/1/0')['content'] + verify_server_object(server_obj) + # Remove Read-Only resources, so we don't end up writing those + for res in server_obj['resources']: + if res['id'] in (0, 11, 12): + server_obj['resources'].remove(res) + data = '''{ + "kind": "instance", + "id": 0, + "resources": [ + { + "id": 2, + "kind": "singleResource", + "value": "101", + "type": "integer" + }, + { + "id": 3, + "kind": "singleResource", + "value": "1010", + "type": "integer" + }, + { + "id": 5, + "kind": "singleResource", + "value": "2000", + "type": "integer" + }, + { + "id": 6, + "kind": "singleResource", + "value": true, + "type": "boolean" + }, + { + "id": 7, + "kind": "singleResource", + "value": "U", + "type": "string" + } + ] + }''' + assert leshan.put(f'/clients/{endpoint}/1/0', data, uri_options = '&replace=false')['status'] == 'CHANGED(204)' + resp = leshan.get(f'/clients/{endpoint}/1/0') + assert resp['valid'] is True + found = 0 + for res in resp['content']['resources']: + if res['id'] == 2: + assert res['value'] == '101' + found += 1 + elif res['id'] == 3: + assert res['value'] == '1010' + found += 1 + elif res['id'] == 5: + assert res['value'] == '2000' + found += 1 + elif res['id'] == 6: + assert res['value'] is True + found += 1 + elif res['id'] == 7: + assert res['value'] == 'U' + found += 1 + assert found == 5 + assert leshan.put(f'/clients/{endpoint}/1/0', data = server_obj, uri_options = '&replace=true')['status'] == 'CHANGED(204)' + server_obj = leshan.get(f'/clients/{endpoint}/1/0')['content'] + verify_server_object(server_obj) + leshan.format = fmt + +def verify_LightweightM2M_1_1_int_215(shell: Shell, leshan: Leshan, endpoint: str): + logger.info('LightweightM2M-1.1-int-215 - Setting basic information in TLV format') + verify_setting_basic_in_format(shell, leshan, endpoint, 'TLV') + +def verify_LightweightM2M_1_1_int_220(shell: Shell, leshan: Leshan, endpoint: str): + logger.info('LightweightM2M-1.1-int-220 - Setting basic information in JSON format') + verify_setting_basic_in_format(shell, leshan, endpoint, 'JSON') + +def verify_LightweightM2M_1_1_int_221(shell: Shell, leshan: Leshan, endpoint: str): + logger.info('LightweightM2M-1.1-int-221 - Attempt to perform operations on Security') + assert leshan.read(endpoint, '0/0')['status'] == 'UNAUTHORIZED(401)' + assert leshan.write(endpoint, '0/0/0', 'coap://localhost')['status'] == 'UNAUTHORIZED(401)' + assert leshan.put_raw(f'/clients/{endpoint}/0/attributes?pmin=10')['status'] == 'UNAUTHORIZED(401)' + +def verify_LightweightM2M_1_1_int_401(shell: Shell, leshan: Leshan, endpoint: str): + logger.info("LightweightM2M-1.1-int-401 - UDP Channel Security - Pre-shared Key Mode") + lines = shell.get_filtered_output(shell.exec_command('lwm2m read 0/0/0 -s')) + host = lines[0] + assert 'coaps://' in host + lines = shell.get_filtered_output(shell.exec_command('lwm2m read 0/0/2 -u8')) + mode = int(lines[0]) + assert mode == 0 + resp = leshan.get(f'/clients/{endpoint}') + assert resp["secure"] + +def test_lwm2m_bootstrap_psk(shell: Shell, leshan, leshan_bootstrap): + try: + # Generate randon device id and password (PSK key) + endpoint = 'client_' + binascii.b2a_hex(os.urandom(1)).decode() + passwd = ''.join(random.choice(string.ascii_lowercase) for i in range(16)) + + + # Create device entries in Leshan and Bootstrap server + leshan_bootstrap.create_bs_device(endpoint, f'coaps://{LESHAN_IP}:{COAPS_PORT}', passwd) + leshan.create_psk_device(endpoint, passwd) + + # Allow engine to start & stop once. + time.sleep(2) + + # + # Verify PSK security using Bootstrap + # + + # Write bootsrap server information and PSK keys + shell.exec_command(f'lwm2m write 0/0/0 -s coaps://{LESHAN_IP}:{BOOTSTRAP_COAPS_PORT}') + shell.exec_command('lwm2m write 0/0/1 -b 1') + shell.exec_command('lwm2m write 0/0/2 -u8 0') + shell.exec_command(f'lwm2m write 0/0/3 -s {endpoint}') + shell.exec_command(f'lwm2m write 0/0/5 -s {passwd}') + shell.exec_command(f'lwm2m start {endpoint} -b 1') + + + # + # Bootstrap Interface test cases + # LightweightM2M-1.1-int-0 (included) + # LightweightM2M-1.1-int-401 (included) + verify_LightweightM2M_1_1_int_1(shell, leshan, endpoint) + + # + # Registration Interface test cases (using PSK security) + # + verify_LightweightM2M_1_1_int_102(shell, leshan, endpoint) + # skip, not implemented verify_LightweightM2M_1_1_int_103() + verify_LightweightM2M_1_1_int_104(shell, leshan, endpoint) + # skip, included in 109: verify_LightweightM2M_1_1_int_107(shell, leshan, endpoint) + verify_LightweightM2M_1_1_int_108(leshan, endpoint) + verify_LightweightM2M_1_1_int_109(shell, leshan, endpoint) + + # + # Device management & Service Enablement Interface test cases + # + verify_LightweightM2M_1_1_int_201(shell, leshan, endpoint) + verify_LightweightM2M_1_1_int_203(shell, leshan, endpoint) + verify_LightweightM2M_1_1_int_204(shell, leshan, endpoint) + verify_LightweightM2M_1_1_int_205(shell, leshan, endpoint) + verify_LightweightM2M_1_1_int_211(shell, leshan, endpoint) + verify_LightweightM2M_1_1_int_212(shell, leshan, endpoint) + verify_LightweightM2M_1_1_int_215(shell, leshan, endpoint) + + shell.exec_command('lwm2m stop') + shell._device.readlines_until(regex=r'.*Deregistration success', timeout=10.0) + + finally: + # Remove device and bootstrap information + # Leshan does not accept non-secure connection if device information is provided with PSK + leshan.delete_device(endpoint) + leshan_bootstrap.delete_bs_device(endpoint) + + +def test_lwm2m_nosecure(shell: Shell, leshan, helperclient): + + # Allow engine to start & stop once. + time.sleep(2) + + # Generate randon device id and password (PSK key) + endpoint = 'client_' + binascii.b2a_hex(os.urandom(1)).decode() + + # + # Registration Interface test cases (using Non-secure mode) + # + shell.exec_command(f'lwm2m write 0/0/0 -s coap://{LESHAN_IP}:{COAP_PORT}') + shell.exec_command('lwm2m write 0/0/1 -b 0') + shell.exec_command('lwm2m write 0/0/2 -u8 3') + shell.exec_command(f'lwm2m write 0/0/3 -s {endpoint}') + shell.exec_command('lwm2m create 1/0') + shell.exec_command('lwm2m write 0/0/10 -u16 1') + shell.exec_command('lwm2m write 1/0/0 -u16 1') + shell.exec_command('lwm2m write 1/0/1 -u32 86400') + shell.exec_command(f'lwm2m start {endpoint} -b 0') + shell._device.readlines_until(regex=f"RD Client started with endpoint '{endpoint}'", timeout=10.0) + + verify_LightweightM2M_1_1_int_101(shell, leshan, endpoint) + verify_LightweightM2M_1_1_int_105(shell, leshan, endpoint, helperclient) # needs no-security + verify_LightweightM2M_1_1_int_215(shell, leshan, endpoint) + verify_LightweightM2M_1_1_int_220(shell, leshan, endpoint) + verify_LightweightM2M_1_1_int_221(shell, leshan, endpoint) + + # All done + shell.exec_command('lwm2m stop') + shell._device.readlines_until(regex=r'.*Deregistration success', timeout=10.0) diff --git a/tests/net/lib/lwm2m/interop/requirements.txt b/tests/net/lib/lwm2m/interop/requirements.txt new file mode 100644 index 00000000000..38c501218ee --- /dev/null +++ b/tests/net/lib/lwm2m/interop/requirements.txt @@ -0,0 +1 @@ +CoAPthon3 diff --git a/tests/net/lib/lwm2m/interop/src/lwm2m-client.c b/tests/net/lib/lwm2m/interop/src/lwm2m-client.c new file mode 100644 index 00000000000..1278d807b71 --- /dev/null +++ b/tests/net/lib/lwm2m/interop/src/lwm2m-client.c @@ -0,0 +1,171 @@ +/* + * Copyright (c) 2017 Linaro Limited + * Copyright (c) 2017-2019 Foundries.io + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define LOG_MODULE_NAME net_lwm2m_client_app +#define LOG_LEVEL LOG_LEVEL_DBG + +#include +LOG_MODULE_REGISTER(LOG_MODULE_NAME); +#include +#include +#include +#include +#include +#include + +#define APP_BANNER "Run LWM2M client" + +#define WAIT_TIME K_SECONDS(10) +#define CONNECT_TIME K_SECONDS(10) + +#define NAME "Zephyr" +#define MODEL "client-1" +#define SERIAL "serial-1" +#define VERSION "1.2.3" + +static struct lwm2m_ctx client; + +static int device_reboot_cb(uint16_t obj_inst_id, + uint8_t *args, uint16_t args_len) +{ + LOG_INF("DEVICE: REBOOT"); + return 0; +} + + +static int lwm2m_setup(void) +{ + /* setup DEVICE object */ + + lwm2m_set_res_buf(&LWM2M_OBJ(3, 0, 0), NAME, sizeof(NAME), + sizeof(NAME), LWM2M_RES_DATA_FLAG_RO); + lwm2m_set_res_buf(&LWM2M_OBJ(3, 0, 1), MODEL, sizeof(MODEL), + sizeof(MODEL), LWM2M_RES_DATA_FLAG_RO); + lwm2m_set_res_buf(&LWM2M_OBJ(3, 0, 2), SERIAL, sizeof(SERIAL), + sizeof(SERIAL), LWM2M_RES_DATA_FLAG_RO); + lwm2m_set_res_buf(&LWM2M_OBJ(3, 0, 3), VERSION, sizeof(VERSION), + sizeof(VERSION), LWM2M_RES_DATA_FLAG_RO); + lwm2m_register_exec_callback(&LWM2M_OBJ(3, 0, 4), device_reboot_cb); + lwm2m_set_res_buf(&LWM2M_OBJ(3, 0, 17), CONFIG_BOARD, sizeof(CONFIG_BOARD), + sizeof(CONFIG_BOARD), LWM2M_RES_DATA_FLAG_RO); + + return 0; +} + +static void rd_client_event(struct lwm2m_ctx *client, + enum lwm2m_rd_client_event client_event) +{ + switch (client_event) { + + case LWM2M_RD_CLIENT_EVENT_NONE: + /* do nothing */ + break; + + case LWM2M_RD_CLIENT_EVENT_BOOTSTRAP_REG_FAILURE: + LOG_DBG("Bootstrap registration failure!"); + break; + + case LWM2M_RD_CLIENT_EVENT_BOOTSTRAP_REG_COMPLETE: + LOG_DBG("Bootstrap registration complete"); + break; + + case LWM2M_RD_CLIENT_EVENT_BOOTSTRAP_TRANSFER_COMPLETE: + LOG_DBG("Bootstrap transfer complete"); + break; + + case LWM2M_RD_CLIENT_EVENT_REGISTRATION_FAILURE: + LOG_DBG("Registration failure!"); + break; + + case LWM2M_RD_CLIENT_EVENT_REGISTRATION_COMPLETE: + LOG_DBG("Registration complete"); + break; + + case LWM2M_RD_CLIENT_EVENT_REG_TIMEOUT: + LOG_DBG("Registration timeout!"); + break; + + case LWM2M_RD_CLIENT_EVENT_REG_UPDATE_COMPLETE: + LOG_DBG("Registration update complete"); + break; + + case LWM2M_RD_CLIENT_EVENT_DEREGISTER_FAILURE: + LOG_DBG("Deregister failure!"); + break; + + case LWM2M_RD_CLIENT_EVENT_DISCONNECT: + LOG_DBG("Disconnected"); + break; + + case LWM2M_RD_CLIENT_EVENT_QUEUE_MODE_RX_OFF: + LOG_DBG("Queue mode RX window closed"); + break; + + case LWM2M_RD_CLIENT_EVENT_ENGINE_SUSPENDED: + LOG_DBG("LwM2M engine suspended"); + break; + + case LWM2M_RD_CLIENT_EVENT_NETWORK_ERROR: + LOG_ERR("LwM2M engine reported a network error."); + lwm2m_rd_client_stop(client, rd_client_event, true); + break; + + case LWM2M_RD_CLIENT_EVENT_REG_UPDATE: + LOG_DBG("Registration update"); + break; + } +} + +static void observe_cb(enum lwm2m_observe_event event, + struct lwm2m_obj_path *path, void *user_data) +{ + char buf[LWM2M_MAX_PATH_STR_SIZE]; + + switch (event) { + + case LWM2M_OBSERVE_EVENT_OBSERVER_ADDED: + LOG_INF("Observer added for %s", lwm2m_path_log_buf(buf, path)); + break; + + case LWM2M_OBSERVE_EVENT_OBSERVER_REMOVED: + LOG_INF("Observer removed for %s", lwm2m_path_log_buf(buf, path)); + break; + + case LWM2M_OBSERVE_EVENT_NOTIFY_ACK: + LOG_INF("Notify acknowledged for %s", lwm2m_path_log_buf(buf, path)); + break; + + case LWM2M_OBSERVE_EVENT_NOTIFY_TIMEOUT: + LOG_INF("Notify timeout for %s, trying registration update", + lwm2m_path_log_buf(buf, path)); + + lwm2m_rd_client_update(); + break; + } +} + +int main(void) +{ + int ret; + +#if defined(CONFIG_BOARD_NATIVE_POSIX) + srandom(time(NULL)); +#endif + + ret = lwm2m_setup(); + if (ret < 0) { + LOG_ERR("Cannot setup LWM2M fields (%d)", ret); + return 0; + } + + client.tls_tag = 1; + + lwm2m_rd_client_start(&client, CONFIG_BOARD, 0, rd_client_event, observe_cb); + lwm2m_rd_client_stop(&client, rd_client_event, false); + + return 0; +} diff --git a/tests/net/lib/lwm2m/interop/testcase.yaml b/tests/net/lib/lwm2m/interop/testcase.yaml new file mode 100644 index 00000000000..aeba64748df --- /dev/null +++ b/tests/net/lib/lwm2m/interop/testcase.yaml @@ -0,0 +1,14 @@ +tests: + net.lwm2m.interop: + harness: pytest + timeout: 300 + slow: true + integration_platforms: + - native_posix + platform_allow: + - native_posix + - qemu_cortex_m3 + tags: + - testing + - pytest + - shell From 79d70889263c4965c760e5835d1b2d1f7e69fbe9 Mon Sep 17 00:00:00 2001 From: Seppo Takalo Date: Tue, 26 Sep 2023 14:06:16 +0300 Subject: [PATCH 094/421] [nrf fromtree] net: lwm2m: Clean up shell documentation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move commands that require parameters first into the list. Move syntax line first, command documentation second, flags last. This is much like Unix commands do ❯ /bin/ls --help Usage: /bin/ls [OPTION]... [FILE]... List information about the FILEs (the current directory by default). Compared to: uart:~$ lwm2m lwm2m - LwM2M commands Subcommands: read :read PATH [OPTIONS] Read value from LwM2M resource -x Read value as hex stream (default) -s Read value as string Signed-off-by: Seppo Takalo (cherry picked from commit ebfbf831531c182ecd9de6878d6e63f2ec3155cf) (cherry picked from commit 5c8c3d6815e4541ba0f93b433c388c699b8e1da2) --- doc/connectivity/networking/api/lwm2m.rst | 68 ++++++++++++++--------- subsys/net/lib/lwm2m/lwm2m_shell.c | 22 ++++---- 2 files changed, 53 insertions(+), 37 deletions(-) diff --git a/doc/connectivity/networking/api/lwm2m.rst b/doc/connectivity/networking/api/lwm2m.rst index 6d26205511e..c630ea7785a 100644 --- a/doc/connectivity/networking/api/lwm2m.rst +++ b/doc/connectivity/networking/api/lwm2m.rst @@ -633,40 +633,58 @@ required actions from the server side. .. code-block:: console - uart:~$ lwm2m - lwm2m - LwM2M commands - Subcommands: - exec :Execute a resource - exec PATH - - read :Read value from LwM2M resource - read PATH [OPTIONS] - -s Read value as string (default) + uart:~$ lwm2m + lwm2m - LwM2M commands + Subcommands: + send :send PATHS + LwM2M SEND operation + + exec :exec PATH [PARAM] + Execute a resource + + read :read PATH [OPTIONS] + Read value from LwM2M resource + -x Read value as hex stream (default) + -s Read value as string -b Read value as bool (1/0) -uX Read value as uintX_t -sX Read value as intX_t -f Read value as float - - write :Write into LwM2M resource - write PATH [OPTIONS] VALUE - -s Value as string (default) - -b Value as bool - -uX Value as uintX_t - -sX Value as intX_t - -f Value as float - - start :Start the LwM2M RD (Registration / Discovery) Client - start EP_NAME [BOOTSTRAP FLAG] + -t Read value as time_t + + write :write PATH [OPTIONS] VALUE + Write into LwM2M resource + -s Write value as string (default) + -b Write value as bool + -uX Write value as uintX_t + -sX Write value as intX_t + -f Write value as float + -t Write value as time_t + + create :create PATH + Create object instance + + cache :cache PATH NUM + Enable data cache for resource + PATH is LwM2M path + NUM how many elements to cache + + start :start EP_NAME [BOOTSTRAP FLAG] + Start the LwM2M RD (Registration / Discovery) Client -b Set the bootstrap flag (default 0) - stop :Stop the LwM2M RD (De-register) Client - stop [OPTIONS] + stop :stop [OPTIONS] + Stop the LwM2M RD (De-register) Client -f Force close the connection - update :Trigger Registration Update of the LwM2M RD Client + update :Trigger Registration Update of the LwM2M RD Client + + pause :LwM2M engine thread pause + resume :LwM2M engine thread resume + lock :Lock the LwM2M registry + unlock :Unlock the LwM2M registry + - pause :LwM2M engine thread pause - resume :LwM2M engine thread resume .. _lwm2m_api_reference: diff --git a/subsys/net/lib/lwm2m/lwm2m_shell.c b/subsys/net/lib/lwm2m/lwm2m_shell.c index 2a86aa88d69..335004ec5d5 100644 --- a/subsys/net/lib/lwm2m/lwm2m_shell.c +++ b/subsys/net/lib/lwm2m/lwm2m_shell.c @@ -22,10 +22,9 @@ LOG_MODULE_REGISTER(LOG_MODULE_NAME); #include #define LWM2M_HELP_CMD "LwM2M commands" -#define LWM2M_HELP_SEND "LwM2M SEND operation\nsend [OPTION]... [PATH]...\n" \ - "Root-level operation is unsupported" -#define LWM2M_HELP_EXEC "Execute a resource\nexec PATH [PARAM]\n" -#define LWM2M_HELP_READ "Read value from LwM2M resource\nread PATH [OPTIONS]\n" \ +#define LWM2M_HELP_SEND "send PATHS\nLwM2M SEND operation\n" +#define LWM2M_HELP_EXEC "exec PATH [PARAM]\nExecute a resource\n" +#define LWM2M_HELP_READ "read PATH [OPTIONS]\nRead value from LwM2M resource\n" \ "-x \tRead value as hex stream (default)\n" \ "-s \tRead value as string\n" \ "-b \tRead value as bool (1/0)\n" \ @@ -33,26 +32,25 @@ LOG_MODULE_REGISTER(LOG_MODULE_NAME); "-sX\tRead value as intX_t\n" \ "-f \tRead value as float\n" \ "-t \tRead value as time_t\n" -#define LWM2M_HELP_WRITE "Write into LwM2M resource\nwrite PATH [OPTIONS] VALUE\n" \ +#define LWM2M_HELP_WRITE "write PATH [OPTIONS] VALUE\nWrite into LwM2M resource\n" \ "-s \tWrite value as string (default)\n" \ "-b \tWrite value as bool\n" \ "-uX\tWrite value as uintX_t\n" \ "-sX\tWrite value as intX_t\n" \ "-f \tWrite value as float\n" \ "-t \tWrite value as time_t\n" -#define LWM2M_HELP_CREATE "Create object instance\ncreate PATH\n" -#define LWM2M_HELP_START "Start the LwM2M RD (Registration / Discovery) Client\n" \ - "start EP_NAME [BOOTSTRAP FLAG]\n" \ +#define LWM2M_HELP_CREATE "create PATH\nCreate object instance\n" +#define LWM2M_HELP_START "start EP_NAME [BOOTSTRAP FLAG]\n" \ + "Start the LwM2M RD (Registration / Discovery) Client\n" \ "-b \tSet the bootstrap flag (default 0)\n" -#define LWM2M_HELP_STOP "Stop the LwM2M RD (De-register) Client\nstop [OPTIONS]\n" \ +#define LWM2M_HELP_STOP "stop [OPTIONS]\nStop the LwM2M RD (De-register) Client\n" \ "-f \tForce close the connection\n" #define LWM2M_HELP_UPDATE "Trigger Registration Update of the LwM2M RD Client\n" #define LWM2M_HELP_PAUSE "LwM2M engine thread pause" #define LWM2M_HELP_RESUME "LwM2M engine thread resume" #define LWM2M_HELP_LOCK "Lock the LwM2M registry" #define LWM2M_HELP_UNLOCK "Unlock the LwM2M registry" -#define LWM2M_HELP_CACHE "Enable data cache for resource\n" \ - "cache PATH NUM\n" \ +#define LWM2M_HELP_CACHE "cache PATH NUM\nEnable data cache for resource\n" \ "PATH is LwM2M path\n" \ "NUM how many elements to cache\n" \ @@ -597,6 +595,7 @@ SHELL_STATIC_SUBCMD_SET_CREATE( SHELL_CMD_ARG(read, NULL, LWM2M_HELP_READ, cmd_read, 2, 1), SHELL_CMD_ARG(write, NULL, LWM2M_HELP_WRITE, cmd_write, 3, 1), SHELL_CMD_ARG(create, NULL, LWM2M_HELP_CREATE, cmd_create, 2, 0), + SHELL_CMD_ARG(cache, NULL, LWM2M_HELP_CACHE, cmd_cache, 3, 0), SHELL_CMD_ARG(start, NULL, LWM2M_HELP_START, cmd_start, 2, 2), SHELL_CMD_ARG(stop, NULL, LWM2M_HELP_STOP, cmd_stop, 1, 1), SHELL_CMD_ARG(update, NULL, LWM2M_HELP_UPDATE, cmd_update, 1, 0), @@ -604,7 +603,6 @@ SHELL_STATIC_SUBCMD_SET_CREATE( SHELL_CMD_ARG(resume, NULL, LWM2M_HELP_RESUME, cmd_resume, 1, 0), SHELL_CMD_ARG(lock, NULL, LWM2M_HELP_LOCK, cmd_lock, 1, 0), SHELL_CMD_ARG(unlock, NULL, LWM2M_HELP_UNLOCK, cmd_unlock, 1, 0), - SHELL_CMD_ARG(cache, NULL, LWM2M_HELP_CACHE, cmd_cache, 3, 0), SHELL_SUBCMD_SET_END); SHELL_COND_CMD_ARG_REGISTER(CONFIG_LWM2M_SHELL, lwm2m, &sub_lwm2m, From 5f6827522ce81d9091dcd0bf43d48e2e45ee1150 Mon Sep 17 00:00:00 2001 From: Seppo Takalo Date: Tue, 8 Aug 2023 13:28:11 +0300 Subject: [PATCH 095/421] [nrf fromtree] net: lwm2m: Allow content formats to support only some data types Partial content format support is required to have a proper support for content format OPAQUE instead of threading it as a part of plain text format. Signed-off-by: Seppo Takalo (cherry picked from commit 42ce4bbfd76535765c1837734f39aff805714815) (cherry picked from commit 851b1391623d065bfbfdeb3bfc28219fad102172) --- subsys/net/lib/lwm2m/lwm2m_object.h | 143 ++++++++++++++++++---------- 1 file changed, 91 insertions(+), 52 deletions(-) diff --git a/subsys/net/lib/lwm2m/lwm2m_object.h b/subsys/net/lib/lwm2m/lwm2m_object.h index ca8fdf12fd0..05bc818c99c 100644 --- a/subsys/net/lib/lwm2m/lwm2m_object.h +++ b/subsys/net/lib/lwm2m/lwm2m_object.h @@ -705,71 +705,95 @@ static inline int engine_put_end_ri(struct lwm2m_output_context *out, return 0; } -static inline int engine_put_s8(struct lwm2m_output_context *out, - struct lwm2m_obj_path *path, int8_t value) +static inline int engine_put_s8(struct lwm2m_output_context *out, struct lwm2m_obj_path *path, + int8_t value) { - return out->writer->put_s8(out, path, value); + if (out->writer->put_s8) { + return out->writer->put_s8(out, path, value); + } + return -ENOTSUP; } -static inline int engine_put_s16(struct lwm2m_output_context *out, - struct lwm2m_obj_path *path, int16_t value) +static inline int engine_put_s16(struct lwm2m_output_context *out, struct lwm2m_obj_path *path, + int16_t value) { - return out->writer->put_s16(out, path, value); + if (out->writer->put_s16) { + return out->writer->put_s16(out, path, value); + } + return -ENOTSUP; } -static inline int engine_put_s32(struct lwm2m_output_context *out, - struct lwm2m_obj_path *path, int32_t value) +static inline int engine_put_s32(struct lwm2m_output_context *out, struct lwm2m_obj_path *path, + int32_t value) { - return out->writer->put_s32(out, path, value); + if (out->writer->put_s32) { + return out->writer->put_s32(out, path, value); + } + return -ENOTSUP; } -static inline int engine_put_s64(struct lwm2m_output_context *out, - struct lwm2m_obj_path *path, int64_t value) +static inline int engine_put_s64(struct lwm2m_output_context *out, struct lwm2m_obj_path *path, + int64_t value) { - return out->writer->put_s64(out, path, value); + if (out->writer->put_s64) { + return out->writer->put_s64(out, path, value); + } + return -ENOTSUP; } -static inline int engine_put_string(struct lwm2m_output_context *out, - struct lwm2m_obj_path *path, char *buf, - size_t buflen) +static inline int engine_put_string(struct lwm2m_output_context *out, struct lwm2m_obj_path *path, + char *buf, size_t buflen) { - return out->writer->put_string(out, path, buf, buflen); + if (out->writer->put_string) { + return out->writer->put_string(out, path, buf, buflen); + } + return -ENOTSUP; } -static inline int engine_put_float(struct lwm2m_output_context *out, - struct lwm2m_obj_path *path, double *value) +static inline int engine_put_float(struct lwm2m_output_context *out, struct lwm2m_obj_path *path, + double *value) { - return out->writer->put_float(out, path, value); + if (out->writer->put_float) { + return out->writer->put_float(out, path, value); + } + return -ENOTSUP; } -static inline int engine_put_time(struct lwm2m_output_context *out, - struct lwm2m_obj_path *path, time_t value) +static inline int engine_put_time(struct lwm2m_output_context *out, struct lwm2m_obj_path *path, + time_t value) { - return out->writer->put_time(out, path, value); + if (out->writer->put_time) { + return out->writer->put_time(out, path, value); + } + return -ENOTSUP; } -static inline int engine_put_bool(struct lwm2m_output_context *out, - struct lwm2m_obj_path *path, bool value) +static inline int engine_put_bool(struct lwm2m_output_context *out, struct lwm2m_obj_path *path, + bool value) { - return out->writer->put_bool(out, path, value); + if (out->writer->put_bool) { + return out->writer->put_bool(out, path, value); + } + return -ENOTSUP; } -static inline int engine_put_opaque(struct lwm2m_output_context *out, - struct lwm2m_obj_path *path, char *buf, - size_t buflen) +static inline int engine_put_opaque(struct lwm2m_output_context *out, struct lwm2m_obj_path *path, + char *buf, size_t buflen) { if (out->writer->put_opaque) { return out->writer->put_opaque(out, path, buf, buflen); } - return 0; + return -ENOTSUP; } -static inline int engine_put_objlnk(struct lwm2m_output_context *out, - struct lwm2m_obj_path *path, +static inline int engine_put_objlnk(struct lwm2m_output_context *out, struct lwm2m_obj_path *path, struct lwm2m_objlnk *value) { - return out->writer->put_objlnk(out, path, value); + if (out->writer->put_objlnk) { + return out->writer->put_objlnk(out, path, value); + } + return -ENOTSUP; } static inline int engine_put_corelink(struct lwm2m_output_context *out, @@ -793,53 +817,68 @@ static inline int engine_put_timestamp(struct lwm2m_output_context *out, time_t static inline int engine_get_s32(struct lwm2m_input_context *in, int32_t *value) { - return in->reader->get_s32(in, value); + if (in->reader->get_s32) { + return in->reader->get_s32(in, value); + } + return -ENOTSUP; } static inline int engine_get_s64(struct lwm2m_input_context *in, int64_t *value) { - return in->reader->get_s64(in, value); + if (in->reader->get_s64) { + return in->reader->get_s64(in, value); + } + return -ENOTSUP; } -static inline int engine_get_string(struct lwm2m_input_context *in, - uint8_t *buf, size_t buflen) +static inline int engine_get_string(struct lwm2m_input_context *in, uint8_t *buf, size_t buflen) { - return in->reader->get_string(in, buf, buflen); + if (in->reader->get_string) { + return in->reader->get_string(in, buf, buflen); + } + return -ENOTSUP; } static inline int engine_get_time(struct lwm2m_input_context *in, time_t *value) { - return in->reader->get_time(in, value); + if (in->reader->get_time) { + return in->reader->get_time(in, value); + } + return -ENOTSUP; } -static inline int engine_get_float(struct lwm2m_input_context *in, - double *value) +static inline int engine_get_float(struct lwm2m_input_context *in, double *value) { - return in->reader->get_float(in, value); + if (in->reader->get_float) { + return in->reader->get_float(in, value); + } + return -ENOTSUP; } static inline int engine_get_bool(struct lwm2m_input_context *in, bool *value) { - return in->reader->get_bool(in, value); + if (in->reader->get_bool) { + return in->reader->get_bool(in, value); + } + return -ENOTSUP; } -static inline int engine_get_opaque(struct lwm2m_input_context *in, - uint8_t *buf, size_t buflen, - struct lwm2m_opaque_context *opaque, - bool *last_block) +static inline int engine_get_opaque(struct lwm2m_input_context *in, uint8_t *buf, size_t buflen, + struct lwm2m_opaque_context *opaque, bool *last_block) { if (in->reader->get_opaque) { - return in->reader->get_opaque(in, buf, buflen, - opaque, last_block); + return in->reader->get_opaque(in, buf, buflen, opaque, last_block); } - return 0; + return -ENOTSUP; } -static inline int engine_get_objlnk(struct lwm2m_input_context *in, - struct lwm2m_objlnk *value) +static inline int engine_get_objlnk(struct lwm2m_input_context *in, struct lwm2m_objlnk *value) { - return in->reader->get_objlnk(in, value); + if (in->reader->get_objlnk) { + return in->reader->get_objlnk(in, value); + } + return -ENOTSUP; } #endif /* LWM2M_OBJECT_H_ */ From 6f6fd46e43ba5b13d47f4940d82652bfe91a4fee Mon Sep 17 00:00:00 2001 From: Seppo Takalo Date: Tue, 8 Aug 2023 13:31:40 +0300 Subject: [PATCH 096/421] [nrf fromtree] net: lwm2m: Separate opaque content format into its own Opaque content format is not part of clear-text, so it should be separated into its own file. Signed-off-by: Seppo Takalo (cherry picked from commit f227b5679221a57c85d0ad39ebb2024cb8590105) (cherry picked from commit 6b602c5803078e5fdcbb26c7b13224bd03152491) --- subsys/net/lib/lwm2m/CMakeLists.txt | 1 + subsys/net/lib/lwm2m/lwm2m_message_handling.c | 12 ++ subsys/net/lib/lwm2m/lwm2m_rw_opaque.c | 165 ++++++++++++++++++ subsys/net/lib/lwm2m/lwm2m_rw_opaque.h | 18 ++ subsys/net/lib/lwm2m/lwm2m_rw_plain_text.c | 44 ----- .../lib/lwm2m/content_plain_text/src/main.c | 31 ---- 6 files changed, 196 insertions(+), 75 deletions(-) create mode 100644 subsys/net/lib/lwm2m/lwm2m_rw_opaque.c create mode 100644 subsys/net/lib/lwm2m/lwm2m_rw_opaque.h diff --git a/subsys/net/lib/lwm2m/CMakeLists.txt b/subsys/net/lib/lwm2m/CMakeLists.txt index 5cb0ab158d5..2e895ec381b 100644 --- a/subsys/net/lib/lwm2m/CMakeLists.txt +++ b/subsys/net/lib/lwm2m/CMakeLists.txt @@ -14,6 +14,7 @@ zephyr_library_sources( lwm2m_obj_device.c lwm2m_rw_link_format.c lwm2m_rw_plain_text.c + lwm2m_rw_opaque.c lwm2m_util.c lwm2m_rd_client.c ) diff --git a/subsys/net/lib/lwm2m/lwm2m_message_handling.c b/subsys/net/lib/lwm2m/lwm2m_message_handling.c index 1a7d023ceb2..8b18f918752 100644 --- a/subsys/net/lib/lwm2m/lwm2m_message_handling.c +++ b/subsys/net/lib/lwm2m/lwm2m_message_handling.c @@ -47,6 +47,7 @@ LOG_MODULE_REGISTER(LOG_MODULE_NAME); #include "lwm2m_rw_link_format.h" #include "lwm2m_rw_oma_tlv.h" #include "lwm2m_rw_plain_text.h" +#include "lwm2m_rw_opaque.h" #include "lwm2m_util.h" #include "lwm2m_rd_client.h" #if defined(CONFIG_LWM2M_RW_SENML_JSON_SUPPORT) @@ -807,6 +808,10 @@ static int select_writer(struct lwm2m_output_context *out, uint16_t accept) out->writer = &link_format_writer; break; + case LWM2M_FORMAT_APP_OCTET_STREAM: + out->writer = &opaque_writer; + break; + case LWM2M_FORMAT_PLAIN_TEXT: case LWM2M_FORMAT_OMA_PLAIN_TEXT: out->writer = &plain_text_writer; @@ -857,6 +862,9 @@ static int select_reader(struct lwm2m_input_context *in, uint16_t format) switch (format) { case LWM2M_FORMAT_APP_OCTET_STREAM: + in->reader = &opaque_reader; + break; + case LWM2M_FORMAT_PLAIN_TEXT: case LWM2M_FORMAT_OMA_PLAIN_TEXT: in->reader = &plain_text_reader; @@ -1537,6 +1545,8 @@ static int do_read_op(struct lwm2m_message *msg, uint16_t content_format) switch (content_format) { case LWM2M_FORMAT_APP_OCTET_STREAM: + return do_read_op_opaque(msg, content_format); + case LWM2M_FORMAT_PLAIN_TEXT: case LWM2M_FORMAT_OMA_PLAIN_TEXT: return do_read_op_plain_text(msg, content_format); @@ -1919,6 +1929,8 @@ static int do_write_op(struct lwm2m_message *msg, uint16_t format) switch (format) { case LWM2M_FORMAT_APP_OCTET_STREAM: + return do_write_op_opaque(msg); + case LWM2M_FORMAT_PLAIN_TEXT: case LWM2M_FORMAT_OMA_PLAIN_TEXT: return do_write_op_plain_text(msg); diff --git a/subsys/net/lib/lwm2m/lwm2m_rw_opaque.c b/subsys/net/lib/lwm2m/lwm2m_rw_opaque.c new file mode 100644 index 00000000000..90cb4619d9a --- /dev/null +++ b/subsys/net/lib/lwm2m/lwm2m_rw_opaque.c @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * Copyright (c) 2015, Yanzi Networks AB. + * 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 HOLDER 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. + */ + +#define LOG_MODULE_NAME net_lwm2m_opaque +#define LOG_LEVEL CONFIG_LWM2M_LOG_LEVEL + +#include +LOG_MODULE_REGISTER(LOG_MODULE_NAME); + +#include +#include +#include +#include +#include + +#include "lwm2m_object.h" +#include "lwm2m_rw_opaque.h" +#include "lwm2m_engine.h" +#include "lwm2m_util.h" + +static int get_opaque(struct lwm2m_input_context *in, uint8_t *value, + size_t buflen, struct lwm2m_opaque_context *opaque, + bool *last_block) +{ + uint16_t in_len; + + if (opaque->remaining == 0) { + coap_packet_get_payload(in->in_cpkt, &in_len); + + if (in_len == 0) { + return -ENODATA; + } + + if (in->block_ctx != NULL) { + uint32_t block_num = + in->block_ctx->ctx.current / + coap_block_size_to_bytes( + in->block_ctx->ctx.block_size); + + if (block_num == 0) { + opaque->len = in->block_ctx->ctx.total_size; + } + + if (opaque->len == 0) { + /* No size1 option provided, use current + * payload size. This will reset on next packet + * received. + */ + opaque->remaining = in_len; + } else { + opaque->remaining = opaque->len; + } + + } else { + opaque->len = in_len; + opaque->remaining = in_len; + } + } + + return lwm2m_engine_get_opaque_more(in, value, buflen, + opaque, last_block); +} + +static int put_opaque(struct lwm2m_output_context *out, + struct lwm2m_obj_path *path, char *buf, + size_t buflen) +{ + int ret; + + ret = buf_append(CPKT_BUF_WRITE(out->out_cpkt), buf, buflen); + if (ret < 0) { + return ret; + } + + return buflen; +} + + +const struct lwm2m_writer opaque_writer = { + .put_opaque = put_opaque, +}; + +const struct lwm2m_reader opaque_reader = { + .get_opaque = get_opaque, +}; + +int do_read_op_opaque(struct lwm2m_message *msg, int content_format) +{ + /* Opaque can only return single resource (instance) */ + if (msg->path.level < LWM2M_PATH_LEVEL_RESOURCE) { + return -EPERM; + } else if (msg->path.level > LWM2M_PATH_LEVEL_RESOURCE) { + if (!IS_ENABLED(CONFIG_LWM2M_VERSION_1_1)) { + return -ENOENT; + } else if (msg->path.level > LWM2M_PATH_LEVEL_RESOURCE_INST) { + return -ENOENT; + } + } + + return lwm2m_perform_read_op(msg, content_format); +} + +int do_write_op_opaque(struct lwm2m_message *msg) +{ + struct lwm2m_engine_obj_inst *obj_inst = NULL; + struct lwm2m_engine_obj_field *obj_field; + struct lwm2m_engine_res *res = NULL; + struct lwm2m_engine_res_inst *res_inst = NULL; + int ret; + uint8_t created = 0U; + + ret = lwm2m_get_or_create_engine_obj(msg, &obj_inst, &created); + if (ret < 0) { + return ret; + } + + ret = lwm2m_engine_validate_write_access(msg, obj_inst, &obj_field); + if (ret < 0) { + return ret; + } + + ret = lwm2m_engine_get_create_res_inst(&msg->path, &res, &res_inst); + if (ret < 0) { + return -ENOENT; + } + + if (msg->path.level < LWM2M_PATH_LEVEL_RESOURCE) { + msg->path.level = LWM2M_PATH_LEVEL_RESOURCE; + } + + return lwm2m_write_handler(obj_inst, res, res_inst, obj_field, msg); +} diff --git a/subsys/net/lib/lwm2m/lwm2m_rw_opaque.h b/subsys/net/lib/lwm2m/lwm2m_rw_opaque.h new file mode 100644 index 00000000000..4118049efe8 --- /dev/null +++ b/subsys/net/lib/lwm2m/lwm2m_rw_opaque.h @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef LWM2M_RW_OPAQUE_H_ +#define LWM2M_RW_OPAQUE_H_ + +#include "lwm2m_object.h" + +extern const struct lwm2m_writer opaque_writer; +extern const struct lwm2m_reader opaque_reader; + +int do_read_op_opaque(struct lwm2m_message *msg, int content_format); +int do_write_op_opaque(struct lwm2m_message *msg); + +#endif /* LWM2M_RW_OPAQUE_H_ */ diff --git a/subsys/net/lib/lwm2m/lwm2m_rw_plain_text.c b/subsys/net/lib/lwm2m/lwm2m_rw_plain_text.c index 9650b33fc29..3ec69e8db82 100644 --- a/subsys/net/lib/lwm2m/lwm2m_rw_plain_text.c +++ b/subsys/net/lib/lwm2m/lwm2m_rw_plain_text.c @@ -341,49 +341,6 @@ static int get_bool(struct lwm2m_input_context *in, bool *value) return sizeof(uint8_t); } -static int get_opaque(struct lwm2m_input_context *in, uint8_t *value, - size_t buflen, struct lwm2m_opaque_context *opaque, - bool *last_block) -{ - uint16_t in_len; - - if (opaque->remaining == 0) { - coap_packet_get_payload(in->in_cpkt, &in_len); - - if (in_len == 0) { - return -ENODATA; - } - - if (in->block_ctx != NULL) { - uint32_t block_num = - in->block_ctx->ctx.current / - coap_block_size_to_bytes( - in->block_ctx->ctx.block_size); - - if (block_num == 0) { - opaque->len = in->block_ctx->ctx.total_size; - } - - if (opaque->len == 0) { - /* No size1 option provided, use current - * payload size. This will reset on next packet - * received. - */ - opaque->remaining = in_len; - } else { - opaque->remaining = opaque->len; - } - - } else { - opaque->len = in_len; - opaque->remaining = in_len; - } - } - - return lwm2m_engine_get_opaque_more(in, value, buflen, - opaque, last_block); -} - static int get_objlnk(struct lwm2m_input_context *in, struct lwm2m_objlnk *value) { @@ -432,7 +389,6 @@ const struct lwm2m_reader plain_text_reader = { .get_time = get_time, .get_float = get_float, .get_bool = get_bool, - .get_opaque = get_opaque, .get_objlnk = get_objlnk, }; diff --git a/tests/net/lib/lwm2m/content_plain_text/src/main.c b/tests/net/lib/lwm2m/content_plain_text/src/main.c index c7cc857224c..7bc77a82327 100644 --- a/tests/net/lib/lwm2m/content_plain_text/src/main.c +++ b/tests/net/lib/lwm2m/content_plain_text/src/main.c @@ -470,37 +470,6 @@ ZTEST(net_content_plain_text_nodata, test_get_bool_nodata) zassert_equal(ret, -ENODATA, "Invalid error code returned"); } -ZTEST(net_content_plain_text, test_get_opaque) -{ - int ret; - const char *payload = "test_payload"; - uint8_t buf[16]; - bool last_block; - struct lwm2m_opaque_context ctx = { 0 }; - - test_payload_set(payload); - - ret = plain_text_reader.get_opaque(&test_in, buf, sizeof(buf), - &ctx, &last_block); - zassert_equal(ret, strlen(payload), "Invalid length returned"); - zassert_mem_equal(buf, payload, strlen(payload), - "Invalid value parsed"); - zassert_equal(test_in.offset, strlen(payload) + 1, - "Invalid packet offset"); -} - -ZTEST(net_content_plain_text_nodata, test_get_opaque_nodata) -{ - int ret; - uint8_t value[4]; - bool last_block; - struct lwm2m_opaque_context ctx = { 0 }; - - ret = plain_text_reader.get_opaque(&test_in, value, sizeof(value), - &ctx, &last_block); - zassert_equal(ret, 0, "Invalid error code returned"); -} - ZTEST(net_content_plain_text, test_get_objlnk) { int ret; From 142c5e169eaff5e0ef611f95556e5bc8b3ee2d9b Mon Sep 17 00:00:00 2001 From: Seppo Takalo Date: Wed, 9 Aug 2023 15:34:23 +0300 Subject: [PATCH 097/421] [nrf fromtree] net: lwm2m: Only parse block1 option for WRITE operation In reality, single-write is the only operation that handles BLOCK1 operations when receiving paylod. Signed-off-by: Seppo Takalo (cherry picked from commit 4e97607c27b5dfff3ab5d0ee7075ee6249c5174b) (cherry picked from commit 44300fbeb01474d8f7d4107f709684379c1cb2cd) --- subsys/net/lib/lwm2m/lwm2m_message_handling.c | 398 ++++++++++-------- 1 file changed, 213 insertions(+), 185 deletions(-) diff --git a/subsys/net/lib/lwm2m/lwm2m_message_handling.c b/subsys/net/lib/lwm2m/lwm2m_message_handling.c index 8b18f918752..299b0330c0b 100644 --- a/subsys/net/lib/lwm2m/lwm2m_message_handling.c +++ b/subsys/net/lib/lwm2m/lwm2m_message_handling.c @@ -1926,50 +1926,179 @@ static int do_discover_op(struct lwm2m_message *msg, uint16_t content_format) static int do_write_op(struct lwm2m_message *msg, uint16_t format) { + int r; + switch (format) { case LWM2M_FORMAT_APP_OCTET_STREAM: - return do_write_op_opaque(msg); + r = do_write_op_opaque(msg); + break; case LWM2M_FORMAT_PLAIN_TEXT: case LWM2M_FORMAT_OMA_PLAIN_TEXT: - return do_write_op_plain_text(msg); + r = do_write_op_plain_text(msg); + break; #ifdef CONFIG_LWM2M_RW_OMA_TLV_SUPPORT case LWM2M_FORMAT_OMA_TLV: case LWM2M_FORMAT_OMA_OLD_TLV: - return do_write_op_tlv(msg); + r = do_write_op_tlv(msg); + break; #endif #ifdef CONFIG_LWM2M_RW_JSON_SUPPORT case LWM2M_FORMAT_OMA_JSON: case LWM2M_FORMAT_OMA_OLD_JSON: - return do_write_op_json(msg); + r = do_write_op_json(msg); + break; #endif #if defined(CONFIG_LWM2M_RW_SENML_JSON_SUPPORT) case LWM2M_FORMAT_APP_SEML_JSON: - return do_write_op_senml_json(msg); + r = do_write_op_senml_json(msg); + break; #endif #ifdef CONFIG_LWM2M_RW_CBOR_SUPPORT case LWM2M_FORMAT_APP_CBOR: - return do_write_op_cbor(msg); + r = do_write_op_cbor(msg); + break; #endif #ifdef CONFIG_LWM2M_RW_SENML_CBOR_SUPPORT case LWM2M_FORMAT_APP_SENML_CBOR: - return do_write_op_senml_cbor(msg); + r = do_write_op_senml_cbor(msg); + break; #endif default: LOG_ERR("Unsupported format: %u", format); - return -ENOMSG; + r = -ENOMSG; + break; + } + + return r; +} + +static int parse_write_op(struct lwm2m_message *msg, uint16_t format) +{ + int block_opt, block_num; + struct lwm2m_block_context *block_ctx = NULL; + enum coap_block_size block_size; + bool last_block = false; + int r; + uint16_t payload_len = 0U; + const uint8_t *payload_start; + + /* setup incoming data */ + payload_start = coap_packet_get_payload(msg->in.in_cpkt, &payload_len); + if (payload_len > 0) { + msg->in.offset = payload_start - msg->in.in_cpkt->data; + } else { + msg->in.offset = msg->in.in_cpkt->offset; + } + + /* Check for block transfer */ + block_opt = coap_get_option_int(msg->in.in_cpkt, COAP_OPTION_BLOCK1); + if (block_opt > 0) { + last_block = !GET_MORE(block_opt); + + /* RFC7252: 4.6. Message Size */ + block_size = GET_BLOCK_SIZE(block_opt); + if (!last_block && coap_block_size_to_bytes(block_size) > payload_len) { + LOG_DBG("Trailing payload is discarded!"); + return -EFBIG; + } + + block_num = GET_BLOCK_NUM(block_opt); + + /* Try to retrieve existing block context. If one not exists, + * and we've received first block, allocate new context. + */ + r = get_block_ctx(&msg->path, &block_ctx); + if (r < 0 && block_num == 0) { + r = init_block_ctx(&msg->path, &block_ctx); + } + + if (r < 0) { + LOG_ERR("Cannot find block context"); + return r; + } + + msg->in.block_ctx = block_ctx; + + if (block_num < block_ctx->expected) { + LOG_WRN("Block already handled %d, expected %d", block_num, + block_ctx->expected); + return 0; + } + if (block_num > block_ctx->expected) { + LOG_WRN("Block out of order %d, expected %d", block_num, + block_ctx->expected); + r = -EFAULT; + return r; + } + r = coap_update_from_block(msg->in.in_cpkt, &block_ctx->ctx); + if (r < 0) { + LOG_ERR("Error from block update: %d", r); + return r; + } + + block_ctx->last_block = last_block; + + /* Initial block sent by the server might be larger than + * our block size therefore it is needed to take this + * into account when calculating next expected block + * number. + */ + block_ctx->expected += GET_BLOCK_SIZE(block_opt) - block_ctx->ctx.block_size + 1; + + /* Handle blockwise 1 (Part 1): Set response code */ + if (!last_block) { + msg->code = COAP_RESPONSE_CODE_CONTINUE; + } + } + + r = do_write_op(msg, format); + + /* Handle blockwise 1 (Part 2): Append BLOCK1 option / free context */ + if (block_ctx) { + if (r >= 0 && !last_block) { + /* More to come, ack with correspond block # */ + r = coap_append_block1_option(msg->out.out_cpkt, &block_ctx->ctx); + if (r < 0) { + /* report as internal server error */ + LOG_ERR("Fail adding block1 option: %d", r); + r = -EINVAL; + } + } + if (r < 0 || last_block) { + /* Free context when finished or when there is error */ + free_block_ctx(block_ctx); + + } } + + return r; } static int do_composite_write_op(struct lwm2m_message *msg, uint16_t format) { + uint16_t payload_len = 0U; + const uint8_t *payload_start; + + /* setup incoming data */ + payload_start = coap_packet_get_payload(msg->in.in_cpkt, &payload_len); + if (payload_len > 0) { + msg->in.offset = payload_start - msg->in.in_cpkt->data; + } else { + msg->in.offset = msg->in.in_cpkt->offset; + } + + if (coap_get_option_int(msg->in.in_cpkt, COAP_OPTION_BLOCK1) >= 0) { + return -ENOTSUP; + } + switch (format) { #if defined(CONFIG_LWM2M_RW_SENML_JSON_SUPPORT) case LWM2M_FORMAT_APP_SEML_JSON: @@ -2074,13 +2203,6 @@ int handle_request(struct coap_packet *request, struct lwm2m_message *msg) uint8_t tkl = 0U; uint16_t format = LWM2M_FORMAT_NONE, accept; int observe = -1; /* default to -1, 0 = ENABLE, 1 = DISABLE */ - int block_opt, block_num; - struct lwm2m_block_context *block_ctx = NULL; - enum coap_block_size block_size; - uint16_t payload_len = 0U; - bool last_block = false; - bool ignore = false; - const uint8_t *payload_start; /* set CoAP request / message */ msg->in.in_cpkt = request; @@ -2252,202 +2374,111 @@ int handle_request(struct coap_packet *request, struct lwm2m_message *msg) break; } - /* setup incoming data */ - payload_start = coap_packet_get_payload(msg->in.in_cpkt, &payload_len); - if (payload_len > 0) { - msg->in.offset = payload_start - msg->in.in_cpkt->data; - } else { - msg->in.offset = msg->in.in_cpkt->offset; - } - - /* Check for block transfer */ - - block_opt = coap_get_option_int(msg->in.in_cpkt, COAP_OPTION_BLOCK1); - if (block_opt > 0) { - last_block = !GET_MORE(block_opt); - - /* RFC7252: 4.6. Message Size */ - block_size = GET_BLOCK_SIZE(block_opt); - if (!last_block && coap_block_size_to_bytes(block_size) > payload_len) { - LOG_DBG("Trailing payload is discarded!"); - r = -EFBIG; - goto error; - } - - block_num = GET_BLOCK_NUM(block_opt); - - /* Try to retrieve existing block context. If one not exists, - * and we've received first block, allocate new context. - */ - r = get_block_ctx(&msg->path, &block_ctx); - if (r < 0 && block_num == 0) { - r = init_block_ctx(&msg->path, &block_ctx); - } - - if (r < 0) { - LOG_ERR("Cannot find block context"); - goto error; - } - - msg->in.block_ctx = block_ctx; - - if (block_num < block_ctx->expected) { - LOG_WRN("Block already handled %d, expected %d", block_num, - block_ctx->expected); - ignore = true; - } else if (block_num > block_ctx->expected) { - LOG_WRN("Block out of order %d, expected %d", block_num, - block_ctx->expected); - r = -EFAULT; - goto error; - } else { - r = coap_update_from_block(msg->in.in_cpkt, &block_ctx->ctx); - if (r < 0) { - LOG_ERR("Error from block update: %d", r); - goto error; - } - - block_ctx->last_block = last_block; - - /* Initial block sent by the server might be larger than - * our block size therefore it is needed to take this - * into account when calculating next expected block - * number. - */ - block_ctx->expected += - GET_BLOCK_SIZE(block_opt) - block_ctx->ctx.block_size + 1; - } - - /* Handle blockwise 1 (Part 1): Set response code */ - if (!last_block) { - msg->code = COAP_RESPONSE_CODE_CONTINUE; - } - } - /* render CoAP packet header */ r = lwm2m_init_message(msg); if (r < 0) { goto error; } - if (!ignore) { #if defined(CONFIG_LWM2M_ACCESS_CONTROL_ENABLE) - r = access_control_check_access(msg->path.obj_id, msg->path.obj_inst_id, - msg->ctx->srv_obj_inst, msg->operation, - msg->ctx->bootstrap_mode); - if (r < 0) { - LOG_ERR("Access denied - Server obj %u does not have proper access to " - "resource", - msg->ctx->srv_obj_inst); - goto error; - } + r = access_control_check_access(msg->path.obj_id, msg->path.obj_inst_id, + msg->ctx->srv_obj_inst, msg->operation, + msg->ctx->bootstrap_mode); + if (r < 0) { + LOG_ERR("Access denied - Server obj %u does not have proper access to " + "resource", + msg->ctx->srv_obj_inst); + goto error; + } #endif - if (msg->path.obj_id == LWM2M_OBJECT_SECURITY_ID && !msg->ctx->bootstrap_mode) { - r = -EACCES; - goto error; - } + if (msg->path.obj_id == LWM2M_OBJECT_SECURITY_ID && !msg->ctx->bootstrap_mode) { + r = -EACCES; + goto error; + } + + switch (msg->operation) { - switch (msg->operation) { + case LWM2M_OP_READ: + if (observe >= 0) { + /* Validate That Token is valid for Observation */ + if (!msg->token) { + LOG_ERR("OBSERVE request missing token"); + r = -EINVAL; + goto error; + } - case LWM2M_OP_READ: - if (observe >= 0) { - /* Validate That Token is valid for Observation */ - if (!msg->token) { - LOG_ERR("OBSERVE request missing token"); - r = -EINVAL; + if ((code & COAP_REQUEST_MASK) == COAP_METHOD_GET) { + /* Normal Observation Request or Cancel */ + r = lwm2m_engine_observation_handler(msg, observe, accept, + false); + if (r < 0) { goto error; } - if ((code & COAP_REQUEST_MASK) == COAP_METHOD_GET) { - /* Normal Observation Request or Cancel */ - r = lwm2m_engine_observation_handler(msg, observe, accept, - false); - if (r < 0) { - goto error; - } - - r = do_read_op(msg, accept); - } else { - /* Composite Observation request & cancel handler */ - r = lwm2m_engine_observation_handler(msg, observe, accept, - true); - if (r < 0) { - goto error; - } - } + r = do_read_op(msg, accept); } else { - if ((code & COAP_REQUEST_MASK) == COAP_METHOD_GET) { - r = do_read_op(msg, accept); - } else { - r = do_composite_read_op(msg, accept); + /* Composite Observation request & cancel handler */ + r = lwm2m_engine_observation_handler(msg, observe, accept, + true); + if (r < 0) { + goto error; } } - break; - - case LWM2M_OP_DISCOVER: - r = do_discover_op(msg, accept); - break; - - case LWM2M_OP_WRITE: - case LWM2M_OP_CREATE: - if ((code & COAP_REQUEST_MASK) == COAP_METHOD_IPATCH) { - /* iPATCH is for Composite purpose */ - r = do_composite_write_op(msg, format); + } else { + if ((code & COAP_REQUEST_MASK) == COAP_METHOD_GET) { + r = do_read_op(msg, accept); } else { - /* Single resource write Operation */ - r = do_write_op(msg, format); + r = do_composite_read_op(msg, accept); } + } + break; + + case LWM2M_OP_DISCOVER: + r = do_discover_op(msg, accept); + break; + + case LWM2M_OP_WRITE: + case LWM2M_OP_CREATE: + if ((code & COAP_REQUEST_MASK) == COAP_METHOD_IPATCH) { + /* iPATCH is for Composite purpose */ + r = do_composite_write_op(msg, format); + } else { + /* Single resource write Operation */ + r = parse_write_op(msg, format); + } #if defined(CONFIG_LWM2M_ACCESS_CONTROL_ENABLE) - if (msg->operation == LWM2M_OP_CREATE && r >= 0) { - access_control_add(msg->path.obj_id, msg->path.obj_inst_id, - msg->ctx->srv_obj_inst); - } + if (msg->operation == LWM2M_OP_CREATE && r >= 0) { + access_control_add(msg->path.obj_id, msg->path.obj_inst_id, + msg->ctx->srv_obj_inst); + } #endif - break; + break; - case LWM2M_OP_WRITE_ATTR: - r = lwm2m_write_attr_handler(obj, msg); - break; + case LWM2M_OP_WRITE_ATTR: + r = lwm2m_write_attr_handler(obj, msg); + break; - case LWM2M_OP_EXECUTE: - r = lwm2m_exec_handler(msg); - break; + case LWM2M_OP_EXECUTE: + r = lwm2m_exec_handler(msg); + break; - case LWM2M_OP_DELETE: + case LWM2M_OP_DELETE: #if defined(CONFIG_LWM2M_RD_CLIENT_SUPPORT_BOOTSTRAP) - if (msg->ctx->bootstrap_mode) { - r = bootstrap_delete(msg); - break; - } -#endif - r = lwm2m_delete_handler(msg); + if (msg->ctx->bootstrap_mode) { + r = bootstrap_delete(msg); break; - - default: - LOG_ERR("Unknown operation: %u", msg->operation); - r = -EINVAL; } +#endif + r = lwm2m_delete_handler(msg); + break; - if (r < 0) { - goto error; - } + default: + LOG_ERR("Unknown operation: %u", msg->operation); + r = -EINVAL; } - /* Handle blockwise 1 (Part 2): Append BLOCK1 option / free context */ - if (block_ctx) { - if (!last_block) { - /* More to come, ack with correspond block # */ - r = coap_append_block1_option(msg->out.out_cpkt, &block_ctx->ctx); - if (r < 0) { - /* report as internal server error */ - LOG_ERR("Fail adding block1 option: %d", r); - r = -EINVAL; - goto error; - } - } else { - /* Free context when finished */ - free_block_ctx(block_ctx); - } + if (r < 0) { + goto error; } return 0; @@ -2482,9 +2513,6 @@ int handle_request(struct coap_packet *request, struct lwm2m_message *msg) LOG_ERR("Error recreating message: %d", r); } - /* Free block context when error happened */ - free_block_ctx(block_ctx); - return 0; } From 58210f1e7f681cd8faf5f4a1a0d273bb7d7ec43f Mon Sep 17 00:00:00 2001 From: Seppo Takalo Date: Fri, 11 Aug 2023 15:39:58 +0300 Subject: [PATCH 098/421] [nrf fromtree] net: lwm2m: Remove unneeded function pointer parameter lwm2m_udp_receive() is only called with same function pointer, so there no need to carry that in the parameter. Signed-off-by: Seppo Takalo (cherry picked from commit b9028bb7222bd15ba31b3e7d310fc60537a60422) (cherry picked from commit 78fbe138393f9c74c8df8aef1eb8fadbe97073f7) --- subsys/net/lib/lwm2m/lwm2m_engine.c | 2 +- subsys/net/lib/lwm2m/lwm2m_message_handling.c | 14 +++++--------- subsys/net/lib/lwm2m/lwm2m_message_handling.h | 6 +----- tests/net/lib/lwm2m/lwm2m_engine/src/stubs.c | 4 ++-- tests/net/lib/lwm2m/lwm2m_engine/src/stubs.h | 2 +- 5 files changed, 10 insertions(+), 18 deletions(-) diff --git a/subsys/net/lib/lwm2m/lwm2m_engine.c b/subsys/net/lib/lwm2m/lwm2m_engine.c index 91d8c3bd605..d38c081ed34 100644 --- a/subsys/net/lib/lwm2m/lwm2m_engine.c +++ b/subsys/net/lib/lwm2m/lwm2m_engine.c @@ -642,7 +642,7 @@ static int socket_recv_message(struct lwm2m_ctx *client_ctx) } in_buf[len] = 0U; - lwm2m_udp_receive(client_ctx, in_buf, len, &from_addr, handle_request); + lwm2m_udp_receive(client_ctx, in_buf, len, &from_addr); return 0; } diff --git a/subsys/net/lib/lwm2m/lwm2m_message_handling.c b/subsys/net/lib/lwm2m/lwm2m_message_handling.c index 299b0330c0b..4eea849750b 100644 --- a/subsys/net/lib/lwm2m/lwm2m_message_handling.c +++ b/subsys/net/lib/lwm2m/lwm2m_message_handling.c @@ -97,6 +97,7 @@ sys_slist_t *lwm2m_engine_obj_list(void); sys_slist_t *lwm2m_engine_obj_inst_list(void); +static int handle_request(struct coap_packet *request, struct lwm2m_message *msg); #if defined(CONFIG_LWM2M_COAP_BLOCK_TRANSFER) struct coap_block_context *lwm2m_output_block_context(void); #endif @@ -2193,7 +2194,7 @@ static int lwm2m_exec_handler(struct lwm2m_message *msg) return -ENOENT; } -int handle_request(struct coap_packet *request, struct lwm2m_message *msg) +static int handle_request(struct coap_packet *request, struct lwm2m_message *msg) { int r; uint8_t code; @@ -2557,7 +2558,7 @@ static int lwm2m_response_promote_to_con(struct lwm2m_message *msg) } void lwm2m_udp_receive(struct lwm2m_ctx *client_ctx, uint8_t *buf, uint16_t buf_len, - struct sockaddr *from_addr, udp_request_handler_cb_t udp_request_handler) + struct sockaddr *from_addr) { struct lwm2m_message *msg = NULL; struct coap_pending *pending; @@ -2684,12 +2685,7 @@ void lwm2m_udp_receive(struct lwm2m_ctx *client_ctx, uint8_t *buf, uint16_t buf_ return; } - /* - * If no normal response handler is found, then this is - * a new request coming from the server. Let's look - * at registered objects to find a handler. - */ - if (udp_request_handler && coap_header_get_type(&response) == COAP_TYPE_CON) { + if (coap_header_get_type(&response) == COAP_TYPE_CON) { msg = lwm2m_get_message(client_ctx); if (!msg) { LOG_ERR("Unable to get a lwm2m message!"); @@ -2707,7 +2703,7 @@ void lwm2m_udp_receive(struct lwm2m_ctx *client_ctx, uint8_t *buf, uint16_t buf_ lwm2m_registry_lock(); /* process the response to this request */ - r = udp_request_handler(&response, msg); + r = handle_request(&response, msg); lwm2m_registry_unlock(); if (r < 0) { return; diff --git a/subsys/net/lib/lwm2m/lwm2m_message_handling.h b/subsys/net/lib/lwm2m/lwm2m_message_handling.h index 12ba9e762fd..a98be3f8dc2 100644 --- a/subsys/net/lib/lwm2m/lwm2m_message_handling.h +++ b/subsys/net/lib/lwm2m/lwm2m_message_handling.h @@ -39,8 +39,6 @@ #define NUM_OUTPUT_BLOCK_CONTEXT CONFIG_LWM2M_NUM_OUTPUT_BLOCK_CONTEXT #endif -/* Establish a request handler callback type */ -typedef int (*udp_request_handler_cb_t)(struct coap_packet *request, struct lwm2m_message *msg); /* LwM2M message functions */ struct lwm2m_message *lwm2m_get_message(struct lwm2m_ctx *client_ctx); struct lwm2m_message *find_msg(struct coap_pending *pending, struct coap_reply *reply); @@ -49,10 +47,8 @@ void lm2m_message_clear_allocations(struct lwm2m_message *msg); int lwm2m_init_message(struct lwm2m_message *msg); int lwm2m_send_message_async(struct lwm2m_message *msg); -int handle_request(struct coap_packet *request, struct lwm2m_message *msg); - void lwm2m_udp_receive(struct lwm2m_ctx *client_ctx, uint8_t *buf, uint16_t buf_len, - struct sockaddr *from_addr, udp_request_handler_cb_t udp_request_handler); + struct sockaddr *from_addr); int generate_notify_message(struct lwm2m_ctx *ctx, struct observe_node *obs, void *user_data); /* Notification and Send operation */ diff --git a/tests/net/lib/lwm2m/lwm2m_engine/src/stubs.c b/tests/net/lib/lwm2m/lwm2m_engine/src/stubs.c index 93f5cce1012..5db155f1e29 100644 --- a/tests/net/lib/lwm2m/lwm2m_engine/src/stubs.c +++ b/tests/net/lib/lwm2m/lwm2m_engine/src/stubs.c @@ -24,8 +24,8 @@ DEFINE_FAKE_VALUE_FUNC(int, generate_notify_message, struct lwm2m_ctx *, struct DEFINE_FAKE_VALUE_FUNC(int64_t, engine_observe_shedule_next_event, struct observe_node *, uint16_t, const int64_t); DEFINE_FAKE_VALUE_FUNC(int, handle_request, struct coap_packet *, struct lwm2m_message *); -DEFINE_FAKE_VOID_FUNC(lwm2m_udp_receive, struct lwm2m_ctx *, uint8_t *, uint16_t, struct sockaddr *, - udp_request_handler_cb_t); +DEFINE_FAKE_VOID_FUNC(lwm2m_udp_receive, struct lwm2m_ctx *, uint8_t *, uint16_t, + struct sockaddr *); DEFINE_FAKE_VALUE_FUNC(bool, lwm2m_rd_client_is_registred, struct lwm2m_ctx *); DEFINE_FAKE_VOID_FUNC(lwm2m_engine_context_close, struct lwm2m_ctx *); DEFINE_FAKE_VALUE_FUNC(int, lwm2m_get_res_buf, const struct lwm2m_obj_path *, void **, uint16_t *, diff --git a/tests/net/lib/lwm2m/lwm2m_engine/src/stubs.h b/tests/net/lib/lwm2m/lwm2m_engine/src/stubs.h index 088d72d4623..7b8ca481f85 100644 --- a/tests/net/lib/lwm2m/lwm2m_engine/src/stubs.h +++ b/tests/net/lib/lwm2m/lwm2m_engine/src/stubs.h @@ -39,7 +39,7 @@ DECLARE_FAKE_VALUE_FUNC(int64_t, engine_observe_shedule_next_event, struct obser const int64_t); DECLARE_FAKE_VALUE_FUNC(int, handle_request, struct coap_packet *, struct lwm2m_message *); DECLARE_FAKE_VOID_FUNC(lwm2m_udp_receive, struct lwm2m_ctx *, uint8_t *, uint16_t, - struct sockaddr *, udp_request_handler_cb_t); + struct sockaddr *); DECLARE_FAKE_VALUE_FUNC(bool, lwm2m_rd_client_is_registred, struct lwm2m_ctx *); DECLARE_FAKE_VOID_FUNC(lwm2m_engine_context_close, struct lwm2m_ctx *); DECLARE_FAKE_VALUE_FUNC(int, lwm2m_get_res_buf, const struct lwm2m_obj_path *, void **, uint16_t *, From a65e10df9b91edd5198495d3bc13e928c314aa38 Mon Sep 17 00:00:00 2001 From: Seppo Takalo Date: Thu, 10 Aug 2023 16:39:49 +0300 Subject: [PATCH 099/421] [nrf fromtree] net: lwm2m: Refactor blockwise SEND to support GET and FETCH Allow blockwise-send buffers to be used with GET and FETCH queries as well. When outgoing packet is split into multiple blocks, don't free it when first block is send. Keep it in memory until some other requests come. Following queries to next block are matched using CoAP token. However, this required Leshan to use COAP.BLOCKWISE_REUSE_TOKEN=true option from Californium. Signed-off-by: Seppo Takalo (cherry picked from commit 69cd5978875329e4eac6c55626e51f9f008e9eb3) (cherry picked from commit b992972e11e065fa1cc53567e757d63f204abeb5) --- include/zephyr/net/coap.h | 14 +++ subsys/net/lib/coap/coap.c | 13 +++ subsys/net/lib/lwm2m/lwm2m_engine.c | 4 +- subsys/net/lib/lwm2m/lwm2m_message_handling.c | 92 +++++++++++++++++-- subsys/net/lib/lwm2m/lwm2m_message_handling.h | 1 + subsys/net/lib/lwm2m/lwm2m_object.h | 5 +- 6 files changed, 121 insertions(+), 8 deletions(-) diff --git a/include/zephyr/net/coap.h b/include/zephyr/net/coap.h index 95bb0b45c65..55776bfc6d8 100644 --- a/include/zephyr/net/coap.h +++ b/include/zephyr/net/coap.h @@ -713,6 +713,20 @@ int coap_get_option_int(const struct coap_packet *cpkt, uint16_t code); */ int coap_get_block1_option(const struct coap_packet *cpkt, bool *has_more, uint8_t *block_number); +/** + * @brief Get values from CoAP block2 option. + * + * Decode block number and block size from option. Ignore the has_more flag + * as it should always be zero on queries. + * + * @param cpkt Packet to be inspected + * @param block_number Is set to the number of the block + * + * @return Integer value of the block size in case of success + * or negative in case of error. + */ +int coap_get_block2_option(const struct coap_packet *cpkt, uint8_t *block_number); + /** * @brief Retrieves BLOCK{1,2} and SIZE{1,2} from @a cpkt and updates * @a ctx accordingly. diff --git a/subsys/net/lib/coap/coap.c b/subsys/net/lib/coap/coap.c index a5c300bf0e2..e3427844bb5 100644 --- a/subsys/net/lib/coap/coap.c +++ b/subsys/net/lib/coap/coap.c @@ -1303,6 +1303,19 @@ int coap_get_block1_option(const struct coap_packet *cpkt, bool *has_more, uint8 return ret; } +int coap_get_block2_option(const struct coap_packet *cpkt, uint8_t *block_number) +{ + int ret = coap_get_option_int(cpkt, COAP_OPTION_BLOCK2); + + if (ret < 0) { + return ret; + } + + *block_number = GET_NUM(ret); + ret = 1 << (GET_BLOCK_SIZE(ret) + 4); + return ret; +} + int insert_option(struct coap_packet *cpkt, uint16_t code, const uint8_t *value, uint16_t len) { uint16_t offset = cpkt->hdr_len; diff --git a/subsys/net/lib/lwm2m/lwm2m_engine.c b/subsys/net/lib/lwm2m/lwm2m_engine.c index d38c081ed34..651baa30ff6 100644 --- a/subsys/net/lib/lwm2m/lwm2m_engine.c +++ b/subsys/net/lib/lwm2m/lwm2m_engine.c @@ -675,7 +675,9 @@ static int socket_send_message(struct lwm2m_ctx *client_ctx) } if (msg->type != COAP_TYPE_CON) { - lwm2m_reset_message(msg, true); + if (!lwm2m_outgoing_is_part_of_blockwise(msg)) { + lwm2m_reset_message(msg, true); + } } return rc; diff --git a/subsys/net/lib/lwm2m/lwm2m_message_handling.c b/subsys/net/lib/lwm2m/lwm2m_message_handling.c index 4eea849750b..df940cf4adb 100644 --- a/subsys/net/lib/lwm2m/lwm2m_message_handling.c +++ b/subsys/net/lib/lwm2m/lwm2m_message_handling.c @@ -81,6 +81,7 @@ LOG_MODULE_REGISTER(LOG_MODULE_NAME); /* Shared set of in-flight LwM2M messages */ static struct lwm2m_message messages[CONFIG_LWM2M_ENGINE_MAX_MESSAGES]; static struct lwm2m_block_context block1_contexts[NUM_BLOCK1_CONTEXT]; +static struct lwm2m_message *ongoing_block2_tx; #if defined(CONFIG_LWM2M_COAP_BLOCK_TRANSFER) /* we need 1 more buffer as the payload is encoded in that buffer first even if @@ -99,6 +100,7 @@ sys_slist_t *lwm2m_engine_obj_inst_list(void); static int handle_request(struct coap_packet *request, struct lwm2m_message *msg); #if defined(CONFIG_LWM2M_COAP_BLOCK_TRANSFER) +STATIC int build_msg_block_for_send(struct lwm2m_message *msg, uint16_t block_num); struct coap_block_context *lwm2m_output_block_context(void); #endif @@ -301,10 +303,16 @@ STATIC int build_msg_block_for_send(struct lwm2m_message *msg, uint16_t block_nu } msg->cpkt.hdr_len = msg->body_encode_buffer.hdr_len; } else { - /* reuse message for next block */ - tkl = coap_header_get_token(&msg->cpkt, token); + /* reuse message for next block. Copy token from the new query to allow + * CoAP clients to use new token for every query of ongoing transaction + */ + tkl = coap_header_get_token(msg->in.in_cpkt, token); lwm2m_reset_message(msg, false); - msg->mid = coap_next_id(); + if (msg->type == COAP_TYPE_ACK) { + msg->mid = coap_header_get_id(msg->in.in_cpkt); + } else { + msg->mid = coap_next_id(); + } msg->token = token; msg->tkl = tkl; ret = lwm2m_init_message(msg); @@ -333,10 +341,14 @@ STATIC int build_msg_block_for_send(struct lwm2m_message *msg, uint16_t block_nu return ret; } ret = coap_block_transfer_init(msg->out.block_ctx, lwm2m_default_block_size(), - msg->body_encode_buffer.offset); + complete_payload_len); if (ret < 0) { return ret; } + if (msg->type == COAP_TYPE_ACK) { + ongoing_block2_tx = msg; + } + msg->block_send = true; } else { /* update block context */ msg->out.block_ctx->current = block_num * block_size_bytes; @@ -402,8 +414,15 @@ STATIC int prepare_msg_for_send(struct lwm2m_message *msg) return 0; } + #endif +bool lwm2m_outgoing_is_part_of_blockwise(struct lwm2m_message *msg) +{ + return msg->block_send; +} + + void lwm2m_engine_context_close(struct lwm2m_ctx *client_ctx) { struct lwm2m_message *msg; @@ -2557,6 +2576,56 @@ static int lwm2m_response_promote_to_con(struct lwm2m_message *msg) return ret; } +static struct lwm2m_message *find_ongoing_block2_tx(void) +{ + /* TODO: I could try to check if there is Request-Tags attached, and then match queries + * for those, but currently popular LwM2M servers don't attach those tags, so in reality + * I have no way of properly matching query with BLOCK2 option to a previous query. + * Therefore we can only support one ongoing BLOCK2 transfer and assume all BLOCK2 requests + * are part of currently ongoing one. + */ + return ongoing_block2_tx; +} + +static void clear_ongoing_block2_tx(void) +{ + if (ongoing_block2_tx) { + LOG_DBG("clear"); + lwm2m_reset_message(ongoing_block2_tx, true); + ongoing_block2_tx = NULL; + } +} + +static void handle_ongoing_block2_tx(struct lwm2m_message *msg, struct coap_packet *cpkt) +{ +#if defined(CONFIG_LWM2M_COAP_BLOCK_TRANSFER) + int r; + uint8_t block; + + r = coap_get_block2_option(cpkt, &block); + if (r < 0) { + LOG_ERR("Failed to parse BLOCK2"); + return; + } + + msg->in.in_cpkt = cpkt; + + r = build_msg_block_for_send(msg, block); + if (r < 0) { + clear_ongoing_block2_tx(); + LOG_ERR("Unable to build next block of lwm2m message! r=%d", r); + return; + } + + r = lwm2m_send_message_async(msg); + if (r < 0) { + clear_ongoing_block2_tx(); + LOG_ERR("Unable to send next block of lwm2m message!"); + return; + } +#endif +} + void lwm2m_udp_receive(struct lwm2m_ctx *client_ctx, uint8_t *buf, uint16_t buf_len, struct sockaddr *from_addr) { @@ -2565,12 +2634,12 @@ void lwm2m_udp_receive(struct lwm2m_ctx *client_ctx, uint8_t *buf, uint16_t buf_ struct coap_reply *reply; struct coap_packet response; int r; - uint8_t token[8]; #if defined(CONFIG_LWM2M_COAP_BLOCK_TRANSFER) bool more_blocks = false; uint8_t block_num; uint8_t last_block_num; #endif + bool has_block2; r = coap_packet_parse(&response, buf, buf_len, NULL, 0); if (r < 0) { @@ -2578,7 +2647,7 @@ void lwm2m_udp_receive(struct lwm2m_ctx *client_ctx, uint8_t *buf, uint16_t buf_ return; } - (void)coap_header_get_token(&response, token); + has_block2 = coap_get_option_int(&response, COAP_OPTION_BLOCK2) > 0 ? true : false; pending = coap_pending_received(&response, client_ctx->pendings, ARRAY_SIZE(client_ctx->pendings)); if (pending && coap_header_get_type(&response) == COAP_TYPE_ACK) { @@ -2686,6 +2755,17 @@ void lwm2m_udp_receive(struct lwm2m_ctx *client_ctx, uint8_t *buf, uint16_t buf_ } if (coap_header_get_type(&response) == COAP_TYPE_CON) { + if (has_block2 && IS_ENABLED(CONFIG_LWM2M_COAP_BLOCK_TRANSFER)) { + msg = find_ongoing_block2_tx(); + if (msg) { + return handle_ongoing_block2_tx(msg, &response); + } + return; + } + + /* Clear out existing Block2 transfers when new requests come */ + clear_ongoing_block2_tx(); + msg = lwm2m_get_message(client_ctx); if (!msg) { LOG_ERR("Unable to get a lwm2m message!"); diff --git a/subsys/net/lib/lwm2m/lwm2m_message_handling.h b/subsys/net/lib/lwm2m/lwm2m_message_handling.h index a98be3f8dc2..fd6c4470d84 100644 --- a/subsys/net/lib/lwm2m/lwm2m_message_handling.h +++ b/subsys/net/lib/lwm2m/lwm2m_message_handling.h @@ -75,5 +75,6 @@ enum coap_block_size lwm2m_default_block_size(void); int lwm2m_parse_peerinfo(char *url, struct lwm2m_ctx *client_ctx, bool is_firmware_uri); void lwm2m_clear_block_contexts(void); +bool lwm2m_outgoing_is_part_of_blockwise(struct lwm2m_message *msg); #endif /* LWM2M_MESSAGE_HANDLING_H */ diff --git a/subsys/net/lib/lwm2m/lwm2m_object.h b/subsys/net/lib/lwm2m/lwm2m_object.h index 05bc818c99c..170a99c023d 100644 --- a/subsys/net/lib/lwm2m/lwm2m_object.h +++ b/subsys/net/lib/lwm2m/lwm2m_object.h @@ -521,8 +521,11 @@ struct lwm2m_message { /** Incoming message action */ uint8_t operation; - /* Information whether the message was acknowledged. */ + /** Information whether the message was acknowledged. */ bool acknowledged : 1; + + /** Indicate that this is part of outgoing block transfer. */ + bool block_send : 1; }; /* LWM2M format writer for the various formats supported */ From 73a6d196160abe543c52944c07953dafdc338ea6 Mon Sep 17 00:00:00 2001 From: Seppo Takalo Date: Thu, 24 Aug 2023 16:42:00 +0300 Subject: [PATCH 100/421] [nrf fromtree] net: lwm2m: Fix composite read on SenML-CBOR Composite read was incorrectly trying to parse CoAP packet instead of payload of the packet. Signed-off-by: Seppo Takalo (cherry picked from commit ebb90c5184cf296d324685862bd8a02a02e6bd23) (cherry picked from commit 7b61e70d81da42d1a7c5a92fcc8143e0971d05a2) --- subsys/net/lib/lwm2m/lwm2m_message_handling.c | 6 ------ subsys/net/lib/lwm2m/lwm2m_message_handling.h | 6 +++++- subsys/net/lib/lwm2m/lwm2m_rw_senml_cbor.c | 5 ++++- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/subsys/net/lib/lwm2m/lwm2m_message_handling.c b/subsys/net/lib/lwm2m/lwm2m_message_handling.c index df940cf4adb..06cc1b5ecf8 100644 --- a/subsys/net/lib/lwm2m/lwm2m_message_handling.c +++ b/subsys/net/lib/lwm2m/lwm2m_message_handling.c @@ -417,12 +417,6 @@ STATIC int prepare_msg_for_send(struct lwm2m_message *msg) #endif -bool lwm2m_outgoing_is_part_of_blockwise(struct lwm2m_message *msg) -{ - return msg->block_send; -} - - void lwm2m_engine_context_close(struct lwm2m_ctx *client_ctx) { struct lwm2m_message *msg; diff --git a/subsys/net/lib/lwm2m/lwm2m_message_handling.h b/subsys/net/lib/lwm2m/lwm2m_message_handling.h index fd6c4470d84..c41fbbac0ee 100644 --- a/subsys/net/lib/lwm2m/lwm2m_message_handling.h +++ b/subsys/net/lib/lwm2m/lwm2m_message_handling.h @@ -75,6 +75,10 @@ enum coap_block_size lwm2m_default_block_size(void); int lwm2m_parse_peerinfo(char *url, struct lwm2m_ctx *client_ctx, bool is_firmware_uri); void lwm2m_clear_block_contexts(void); -bool lwm2m_outgoing_is_part_of_blockwise(struct lwm2m_message *msg); + +static inline bool lwm2m_outgoing_is_part_of_blockwise(struct lwm2m_message *msg) +{ + return msg->block_send; +} #endif /* LWM2M_MESSAGE_HANDLING_H */ diff --git a/subsys/net/lib/lwm2m/lwm2m_rw_senml_cbor.c b/subsys/net/lib/lwm2m/lwm2m_rw_senml_cbor.c index d62af88200b..15dc9a9451e 100644 --- a/subsys/net/lib/lwm2m/lwm2m_rw_senml_cbor.c +++ b/subsys/net/lib/lwm2m/lwm2m_rw_senml_cbor.c @@ -836,12 +836,15 @@ static uint8_t parse_composite_read_paths(struct lwm2m_message *msg, uint_fast8_t dret; int len; int ret; + char *payload; + uint16_t in_len; setup_in_fmt_data(msg); fd = engine_get_in_user_data(&msg->in); + payload = (char *)coap_packet_get_payload(msg->in.in_cpkt, &in_len); - dret = cbor_decode_lwm2m_senml(ICTX_BUF_R_REGION(&msg->in), &fd->dcd, &isize); + dret = cbor_decode_lwm2m_senml(payload, in_len, &fd->dcd, &isize); if (dret != ZCBOR_SUCCESS) { __ASSERT_NO_MSG(false); From 821e53edec9e15d97e6248342daed14ebb97b5ee Mon Sep 17 00:00:00 2001 From: Seppo Takalo Date: Fri, 8 Sep 2023 14:21:18 +0300 Subject: [PATCH 101/421] [nrf fromtree] net: lwm2m: Append CoAP Etag to protect integrity of blockwise To protect the integrity of outgoing block-wise transfers, append Etag option that allows client to see if the received block is generated from same content as it is expecting. Signed-off-by: Seppo Takalo (cherry picked from commit 1606d352e1c3a108762c54681bee1e9133877c06) (cherry picked from commit 47a6c5cd9d6a9284cf4a28144cbaca2766d85ad2) --- subsys/net/lib/lwm2m/Kconfig | 2 ++ subsys/net/lib/lwm2m/lwm2m_message_handling.c | 14 +++++++++++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/subsys/net/lib/lwm2m/Kconfig b/subsys/net/lib/lwm2m/Kconfig index 41ac5bcf1ce..d826e5cd599 100644 --- a/subsys/net/lib/lwm2m/Kconfig +++ b/subsys/net/lib/lwm2m/Kconfig @@ -83,6 +83,8 @@ config LWM2M_COAP_BLOCK_TRANSFER help LwM2M messages with a big body that exceed the block size will be split into blocks for sending. + To append CoAP ETag option into outgoing block transfers, CONFIG_SYS_HASH_FUNC32 should + be enabled. config LWM2M_CANCEL_OBSERVE_BY_PATH bool "Use path matching as fallback for cancel-observe" diff --git a/subsys/net/lib/lwm2m/lwm2m_message_handling.c b/subsys/net/lib/lwm2m/lwm2m_message_handling.c index 06cc1b5ecf8..7aaa42c20ab 100644 --- a/subsys/net/lib/lwm2m/lwm2m_message_handling.c +++ b/subsys/net/lib/lwm2m/lwm2m_message_handling.c @@ -33,6 +33,7 @@ LOG_MODULE_REGISTER(LOG_MODULE_NAME); #include #include #include +#include #if defined(CONFIG_LWM2M_DTLS_SUPPORT) #include @@ -378,6 +379,7 @@ STATIC int prepare_msg_for_send(struct lwm2m_message *msg) { int ret; uint16_t len; + const uint8_t *payload; /* save the big buffer for later use (splitting blocks) */ msg->body_encode_buffer = msg->cpkt; @@ -387,7 +389,7 @@ STATIC int prepare_msg_for_send(struct lwm2m_message *msg) msg->cpkt.offset = 0; msg->cpkt.max_len = MAX_PACKET_SIZE; - coap_packet_get_payload(&msg->body_encode_buffer, &len); + payload = coap_packet_get_payload(&msg->body_encode_buffer, &len); if (len <= CONFIG_LWM2M_COAP_MAX_MSG_SIZE) { /* copy the packet */ @@ -406,6 +408,16 @@ STATIC int prepare_msg_for_send(struct lwm2m_message *msg) NET_ASSERT(msg->out.block_ctx == NULL, "Expecting to have no context to release"); } else { + /* Before splitting the content, append Etag option to protect the integrity of + * the payload. + */ + if (IS_ENABLED(CONFIG_SYS_HASH_FUNC32)) { + uint32_t hash = sys_hash32(payload, len); + + coap_packet_append_option(&msg->body_encode_buffer, COAP_OPTION_ETAG, + (const uint8_t *)&hash, sizeof(hash)); + } + ret = build_msg_block_for_send(msg, 0); if (ret != 0) { return ret; From d96b34effcd3ec9010f7e80a564e5fbd93e4c995 Mon Sep 17 00:00:00 2001 From: Seppo Takalo Date: Thu, 21 Sep 2023 16:34:11 +0300 Subject: [PATCH 102/421] [nrf fromtree] net: lwm2m: Generate new tokens for LwM2M SEND blocks Previously each piece of LwM2M SEND was using token length of zero. I think this was unintentional. Signed-off-by: Seppo Takalo (cherry picked from commit a8f977758637d1cf3f246e2bc330b0f6382e4d52) (cherry picked from commit ce0f62fc027bcb0b46b7cc4632e827290186d1aa) --- subsys/net/lib/lwm2m/lwm2m_message_handling.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/subsys/net/lib/lwm2m/lwm2m_message_handling.c b/subsys/net/lib/lwm2m/lwm2m_message_handling.c index 7aaa42c20ab..678f358d1ee 100644 --- a/subsys/net/lib/lwm2m/lwm2m_message_handling.c +++ b/subsys/net/lib/lwm2m/lwm2m_message_handling.c @@ -307,12 +307,13 @@ STATIC int build_msg_block_for_send(struct lwm2m_message *msg, uint16_t block_nu /* reuse message for next block. Copy token from the new query to allow * CoAP clients to use new token for every query of ongoing transaction */ - tkl = coap_header_get_token(msg->in.in_cpkt, token); lwm2m_reset_message(msg, false); if (msg->type == COAP_TYPE_ACK) { msg->mid = coap_header_get_id(msg->in.in_cpkt); + tkl = coap_header_get_token(msg->in.in_cpkt, token); } else { msg->mid = coap_next_id(); + tkl = LWM2M_MSG_TOKEN_GENERATE_NEW; } msg->token = token; msg->tkl = tkl; From b65d00b7190dbccc6b7998f6ef868c19fc9f982f Mon Sep 17 00:00:00 2001 From: Juha Ylinen Date: Thu, 28 Sep 2023 10:09:26 +0300 Subject: [PATCH 103/421] [nrf fromtree] net: coap: Fix coap client timeout Fix bug in timeout_expired() function. Coap client was resending pending messages after 500 ms (COAP_PERIODIC_TIMEOUT) and didn't wait for retransmission timeout. Use 64-bit k_uptime_get() Signed-off-by: Juha Ylinen (cherry picked from commit 3ffa1d5550928180cf24fcc5eb218bbc90d0eee1) (cherry picked from commit 7edfd81f85f19fa5e8345fbf9cbde1b9502b77cb) --- subsys/net/lib/coap/coap_client.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/subsys/net/lib/coap/coap_client.c b/subsys/net/lib/coap/coap_client.c index f8ba4283648..d096e39c62f 100644 --- a/subsys/net/lib/coap/coap_client.c +++ b/subsys/net/lib/coap/coap_client.c @@ -369,7 +369,7 @@ static void report_callback_error(struct coap_client_internal_request *internal_ static bool timeout_expired(struct coap_client_internal_request *internal_req) { return (internal_req->request_ongoing && - internal_req->pending.timeout <= k_uptime_get_32()); + internal_req->pending.timeout <= (k_uptime_get() - internal_req->pending.t0)); } static int resend_request(struct coap_client *client, @@ -649,7 +649,7 @@ static int handle_response(struct coap_client *client, const struct coap_packet /* Separate response coming */ if (payload_len == 0 && response_type == COAP_TYPE_ACK && response_code == COAP_CODE_EMPTY) { - internal_req->pending.t0 = k_uptime_get_32(); + internal_req->pending.t0 = k_uptime_get(); internal_req->pending.timeout = internal_req->pending.t0 + COAP_SEPARATE_TIMEOUT; internal_req->pending.retries = 0; return 1; From a63c627ac67cc7b2849f508113bebbf5db3370de Mon Sep 17 00:00:00 2001 From: Juha Heiskanen Date: Thu, 28 Sep 2023 17:19:45 +0300 Subject: [PATCH 104/421] [nrf fromtree] net: lwm2m: RD client Deregister event indicate Added a new event for LWM2M_RD_CLIENT_EVENT_DEREGISTER for indicate LwM2M client dereistartion. Updated unit test and sample for new event type Signed-off-by: Juha Heiskanen (cherry picked from commit 647fb4dc8f4f0cc09a38e223606dc239033ad8f5) (cherry picked from commit 6ce7ce6f775c45b422809cee6a05b0af93e82e21) --- doc/connectivity/networking/api/lwm2m.rst | 8 ++++++++ doc/releases/release-notes-3.5.rst | 1 + include/zephyr/net/lwm2m.h | 1 + samples/net/lwm2m_client/src/lwm2m-client.c | 3 +++ subsys/net/lib/lwm2m/lwm2m_rd_client.c | 2 ++ tests/net/lib/lwm2m/interop/src/lwm2m-client.c | 3 +++ tests/net/lib/lwm2m/lwm2m_rd_client/src/main.c | 6 ++++++ 7 files changed, 24 insertions(+) diff --git a/doc/connectivity/networking/api/lwm2m.rst b/doc/connectivity/networking/api/lwm2m.rst index c630ea7785a..8d727d48bf5 100644 --- a/doc/connectivity/networking/api/lwm2m.rst +++ b/doc/connectivity/networking/api/lwm2m.rst @@ -318,6 +318,14 @@ events, setup a callback function: LOG_DBG("Disconnected"); break; + case LWM2M_RD_CLIENT_EVENT_REG_UPDATE: + LOG_DBG("Registration update"); + break; + + case LWM2M_RD_CLIENT_EVENT_DEREGISTER: + LOG_DBG("Deregistration client"); + break; + } } diff --git a/doc/releases/release-notes-3.5.rst b/doc/releases/release-notes-3.5.rst index 1c2a38edcf2..4f9a8ab1793 100644 --- a/doc/releases/release-notes-3.5.rst +++ b/doc/releases/release-notes-3.5.rst @@ -255,6 +255,7 @@ Networking * Added support for tickless mode. This removes the 500 ms timeout from the socket loop so the engine does not constantly wake up the CPU. This can be enabled by :kconfig:option:`CONFIG_LWM2M_TICKLESS`. + * Added new :c:macro:`LWM2M_RD_CLIENT_EVENT_DEREGISTER` event. * Wi-Fi * Added Passive scan support. diff --git a/include/zephyr/net/lwm2m.h b/include/zephyr/net/lwm2m.h index e94297d3550..6262f6d103d 100644 --- a/include/zephyr/net/lwm2m.h +++ b/include/zephyr/net/lwm2m.h @@ -2073,6 +2073,7 @@ enum lwm2m_rd_client_event { LWM2M_RD_CLIENT_EVENT_ENGINE_SUSPENDED, LWM2M_RD_CLIENT_EVENT_NETWORK_ERROR, LWM2M_RD_CLIENT_EVENT_REG_UPDATE, + LWM2M_RD_CLIENT_EVENT_DEREGISTER, }; /** diff --git a/samples/net/lwm2m_client/src/lwm2m-client.c b/samples/net/lwm2m_client/src/lwm2m-client.c index e20008c2f66..748f654d9ee 100644 --- a/samples/net/lwm2m_client/src/lwm2m-client.c +++ b/samples/net/lwm2m_client/src/lwm2m-client.c @@ -231,6 +231,9 @@ static void rd_client_event(struct lwm2m_ctx *client, case LWM2M_RD_CLIENT_EVENT_REG_UPDATE: LOG_DBG("Registration update"); break; + case LWM2M_RD_CLIENT_EVENT_DEREGISTER: + LOG_DBG("Client De-register"); + break; } } diff --git a/subsys/net/lib/lwm2m/lwm2m_rd_client.c b/subsys/net/lib/lwm2m/lwm2m_rd_client.c index feebcaeea17..db8a84ce0b8 100644 --- a/subsys/net/lib/lwm2m/lwm2m_rd_client.c +++ b/subsys/net/lib/lwm2m/lwm2m_rd_client.c @@ -215,6 +215,8 @@ static void set_sm_state_delayed(uint8_t sm_state, int64_t delay_ms) } } else if (sm_state == ENGINE_UPDATE_REGISTRATION) { event = LWM2M_RD_CLIENT_EVENT_REG_UPDATE; + } else if (sm_state == ENGINE_DEREGISTER) { + event = LWM2M_RD_CLIENT_EVENT_DEREGISTER; } if (sm_is_suspended()) { diff --git a/tests/net/lib/lwm2m/interop/src/lwm2m-client.c b/tests/net/lib/lwm2m/interop/src/lwm2m-client.c index 1278d807b71..983fea79f3e 100644 --- a/tests/net/lib/lwm2m/interop/src/lwm2m-client.c +++ b/tests/net/lib/lwm2m/interop/src/lwm2m-client.c @@ -117,6 +117,9 @@ static void rd_client_event(struct lwm2m_ctx *client, case LWM2M_RD_CLIENT_EVENT_REG_UPDATE: LOG_DBG("Registration update"); break; + case LWM2M_RD_CLIENT_EVENT_DEREGISTER: + LOG_DBG("Deregistration client"); + break; } } diff --git a/tests/net/lib/lwm2m/lwm2m_rd_client/src/main.c b/tests/net/lib/lwm2m/lwm2m_rd_client/src/main.c index 08c0820d5e9..03d0dce7f49 100644 --- a/tests/net/lib/lwm2m/lwm2m_rd_client/src/main.c +++ b/tests/net/lib/lwm2m/lwm2m_rd_client/src/main.c @@ -106,6 +106,9 @@ static void lwm2m_event_cb(struct lwm2m_ctx *client, enum lwm2m_rd_client_event case LWM2M_RD_CLIENT_EVENT_REG_UPDATE: LOG_INF("*** LWM2M_RD_CLIENT_EVENT_REG_UPDATE"); break; + case LWM2M_RD_CLIENT_EVENT_DEREGISTER: + LOG_INF("*** LWM2M_RD_CLIENT_EVENT_DEREGISTER"); + break; } show_lwm2m_event(client_event); @@ -211,6 +214,7 @@ ZTEST(lwm2m_rd_client, test_start_registration_ok) coap_header_get_code_fake.custom_fake = coap_header_get_code_fake_deleted; zassert_true(lwm2m_rd_client_stop(&ctx, lwm2m_event_cb, true) == 0, NULL); + zassert_true(expect_lwm2m_rd_client_event(LWM2M_RD_CLIENT_EVENT_DEREGISTER), NULL); zassert_true(expect_lwm2m_rd_client_event(LWM2M_RD_CLIENT_EVENT_DISCONNECT), NULL); zassert_true(!lwm2m_rd_client_is_registred(&ctx), NULL); } @@ -425,6 +429,7 @@ ZTEST(lwm2m_rd_client, test_deregistration_timeout) test_prepare_pending_message_cb(&message_reply_timeout_cb_default); zassert_true(lwm2m_rd_client_stop(&ctx, lwm2m_event_cb, true) == 0, NULL); + zassert_true(expect_lwm2m_rd_client_event(LWM2M_RD_CLIENT_EVENT_DEREGISTER), NULL); zassert_true(expect_lwm2m_rd_client_event(LWM2M_RD_CLIENT_EVENT_DEREGISTER_FAILURE)); } @@ -529,6 +534,7 @@ ZTEST(lwm2m_rd_client, test_suspend_stop_resume) zassert_equal(lwm2m_rd_client_stop(&ctx, lwm2m_event_cb, false), 0); zassert_true(lwm2m_rd_client_resume() == 0, NULL); + zassert_false(expect_lwm2m_rd_client_event(LWM2M_RD_CLIENT_EVENT_DEREGISTER), NULL); zassert_true(expect_lwm2m_rd_client_event(LWM2M_RD_CLIENT_EVENT_DISCONNECT), NULL); } From 4baf98b57ba7177839d831e35aa56696f50a598a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20Cab=C3=A9?= Date: Thu, 24 Aug 2023 15:25:34 +0200 Subject: [PATCH 105/421] [nrf fromtree] net: coap: Capitalize and document COAP_MAKE_RESPONSE_CODE macro MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Capitalize COAP_MAKE_RESPONSE_CODE macro to align better with coding style - Added missing Doxygen comments Signed-off-by: Benjamin Cabé (cherry picked from commit fea507faee78a3927d45a700370db5c1fed19ca9) (cherry picked from commit 5585de60583fd0bb60b06cb23076e36a93f2b0e6) --- include/zephyr/net/coap.h | 62 +++++++++++++++++++++------------------ 1 file changed, 34 insertions(+), 28 deletions(-) diff --git a/include/zephyr/net/coap.h b/include/zephyr/net/coap.h index 55776bfc6d8..5952cf77d83 100644 --- a/include/zephyr/net/coap.h +++ b/include/zephyr/net/coap.h @@ -115,7 +115,13 @@ enum coap_msgtype { COAP_TYPE_RESET = 3 }; -#define coap_make_response_code(class, det) ((class << 5) | (det)) +/** + * Utility macro to create a CoAP response code. + * @param class Class of the response code (ex. 2, 4, 5, ...) + * @param det Detail of the response code + * @return Response code literal +*/ +#define COAP_MAKE_RESPONSE_CODE(class, det) ((class << 5) | (det)) /** * @brief Set of response codes available for a response packet. @@ -123,35 +129,35 @@ enum coap_msgtype { * To be used when creating a response. */ enum coap_response_code { - COAP_RESPONSE_CODE_OK = coap_make_response_code(2, 0), - COAP_RESPONSE_CODE_CREATED = coap_make_response_code(2, 1), - COAP_RESPONSE_CODE_DELETED = coap_make_response_code(2, 2), - COAP_RESPONSE_CODE_VALID = coap_make_response_code(2, 3), - COAP_RESPONSE_CODE_CHANGED = coap_make_response_code(2, 4), - COAP_RESPONSE_CODE_CONTENT = coap_make_response_code(2, 5), - COAP_RESPONSE_CODE_CONTINUE = coap_make_response_code(2, 31), - COAP_RESPONSE_CODE_BAD_REQUEST = coap_make_response_code(4, 0), - COAP_RESPONSE_CODE_UNAUTHORIZED = coap_make_response_code(4, 1), - COAP_RESPONSE_CODE_BAD_OPTION = coap_make_response_code(4, 2), - COAP_RESPONSE_CODE_FORBIDDEN = coap_make_response_code(4, 3), - COAP_RESPONSE_CODE_NOT_FOUND = coap_make_response_code(4, 4), - COAP_RESPONSE_CODE_NOT_ALLOWED = coap_make_response_code(4, 5), - COAP_RESPONSE_CODE_NOT_ACCEPTABLE = coap_make_response_code(4, 6), - COAP_RESPONSE_CODE_INCOMPLETE = coap_make_response_code(4, 8), - COAP_RESPONSE_CODE_CONFLICT = coap_make_response_code(4, 9), - COAP_RESPONSE_CODE_PRECONDITION_FAILED = coap_make_response_code(4, 12), - COAP_RESPONSE_CODE_REQUEST_TOO_LARGE = coap_make_response_code(4, 13), + COAP_RESPONSE_CODE_OK = COAP_MAKE_RESPONSE_CODE(2, 0), + COAP_RESPONSE_CODE_CREATED = COAP_MAKE_RESPONSE_CODE(2, 1), + COAP_RESPONSE_CODE_DELETED = COAP_MAKE_RESPONSE_CODE(2, 2), + COAP_RESPONSE_CODE_VALID = COAP_MAKE_RESPONSE_CODE(2, 3), + COAP_RESPONSE_CODE_CHANGED = COAP_MAKE_RESPONSE_CODE(2, 4), + COAP_RESPONSE_CODE_CONTENT = COAP_MAKE_RESPONSE_CODE(2, 5), + COAP_RESPONSE_CODE_CONTINUE = COAP_MAKE_RESPONSE_CODE(2, 31), + COAP_RESPONSE_CODE_BAD_REQUEST = COAP_MAKE_RESPONSE_CODE(4, 0), + COAP_RESPONSE_CODE_UNAUTHORIZED = COAP_MAKE_RESPONSE_CODE(4, 1), + COAP_RESPONSE_CODE_BAD_OPTION = COAP_MAKE_RESPONSE_CODE(4, 2), + COAP_RESPONSE_CODE_FORBIDDEN = COAP_MAKE_RESPONSE_CODE(4, 3), + COAP_RESPONSE_CODE_NOT_FOUND = COAP_MAKE_RESPONSE_CODE(4, 4), + COAP_RESPONSE_CODE_NOT_ALLOWED = COAP_MAKE_RESPONSE_CODE(4, 5), + COAP_RESPONSE_CODE_NOT_ACCEPTABLE = COAP_MAKE_RESPONSE_CODE(4, 6), + COAP_RESPONSE_CODE_INCOMPLETE = COAP_MAKE_RESPONSE_CODE(4, 8), + COAP_RESPONSE_CODE_CONFLICT = COAP_MAKE_RESPONSE_CODE(4, 9), + COAP_RESPONSE_CODE_PRECONDITION_FAILED = COAP_MAKE_RESPONSE_CODE(4, 12), + COAP_RESPONSE_CODE_REQUEST_TOO_LARGE = COAP_MAKE_RESPONSE_CODE(4, 13), COAP_RESPONSE_CODE_UNSUPPORTED_CONTENT_FORMAT = - coap_make_response_code(4, 15), - COAP_RESPONSE_CODE_UNPROCESSABLE_ENTITY = coap_make_response_code(4, 22), - COAP_RESPONSE_CODE_TOO_MANY_REQUESTS = coap_make_response_code(4, 29), - COAP_RESPONSE_CODE_INTERNAL_ERROR = coap_make_response_code(5, 0), - COAP_RESPONSE_CODE_NOT_IMPLEMENTED = coap_make_response_code(5, 1), - COAP_RESPONSE_CODE_BAD_GATEWAY = coap_make_response_code(5, 2), - COAP_RESPONSE_CODE_SERVICE_UNAVAILABLE = coap_make_response_code(5, 3), - COAP_RESPONSE_CODE_GATEWAY_TIMEOUT = coap_make_response_code(5, 4), + COAP_MAKE_RESPONSE_CODE(4, 15), + COAP_RESPONSE_CODE_UNPROCESSABLE_ENTITY = COAP_MAKE_RESPONSE_CODE(4, 22), + COAP_RESPONSE_CODE_TOO_MANY_REQUESTS = COAP_MAKE_RESPONSE_CODE(4, 29), + COAP_RESPONSE_CODE_INTERNAL_ERROR = COAP_MAKE_RESPONSE_CODE(5, 0), + COAP_RESPONSE_CODE_NOT_IMPLEMENTED = COAP_MAKE_RESPONSE_CODE(5, 1), + COAP_RESPONSE_CODE_BAD_GATEWAY = COAP_MAKE_RESPONSE_CODE(5, 2), + COAP_RESPONSE_CODE_SERVICE_UNAVAILABLE = COAP_MAKE_RESPONSE_CODE(5, 3), + COAP_RESPONSE_CODE_GATEWAY_TIMEOUT = COAP_MAKE_RESPONSE_CODE(5, 4), COAP_RESPONSE_CODE_PROXYING_NOT_SUPPORTED = - coap_make_response_code(5, 5) + COAP_MAKE_RESPONSE_CODE(5, 5) }; #define COAP_CODE_EMPTY (0) From 2158801356d3cfc3ed113afdc34b0e149446d9a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20Cab=C3=A9?= Date: Thu, 24 Aug 2023 15:35:22 +0200 Subject: [PATCH 106/421] [nrf fromtree] net: coap: Improve CoAP Doxygen comments MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Improve the Doxygen comments for coap.h by adding missing documentation for most of the compilation units. Signed-off-by: Benjamin Cabé (cherry picked from commit 9c7672bfbc4688b933420264170235d491c28b43) (cherry picked from commit 90f5e65dacd203db62f3e2b8b657148f06561f47) --- include/zephyr/net/coap.h | 156 +++++++++++++++++++++++--------------- 1 file changed, 95 insertions(+), 61 deletions(-) diff --git a/include/zephyr/net/coap.h b/include/zephyr/net/coap.h index 5952cf77d83..6fc21a6280b 100644 --- a/include/zephyr/net/coap.h +++ b/include/zephyr/net/coap.h @@ -42,25 +42,25 @@ extern "C" { * Refer to RFC 7252, section 12.2 for more information. */ enum coap_option_num { - COAP_OPTION_IF_MATCH = 1, - COAP_OPTION_URI_HOST = 3, - COAP_OPTION_ETAG = 4, - COAP_OPTION_IF_NONE_MATCH = 5, - COAP_OPTION_OBSERVE = 6, - COAP_OPTION_URI_PORT = 7, - COAP_OPTION_LOCATION_PATH = 8, - COAP_OPTION_URI_PATH = 11, - COAP_OPTION_CONTENT_FORMAT = 12, - COAP_OPTION_MAX_AGE = 14, - COAP_OPTION_URI_QUERY = 15, - COAP_OPTION_ACCEPT = 17, - COAP_OPTION_LOCATION_QUERY = 20, - COAP_OPTION_BLOCK2 = 23, - COAP_OPTION_BLOCK1 = 27, - COAP_OPTION_SIZE2 = 28, - COAP_OPTION_PROXY_URI = 35, - COAP_OPTION_PROXY_SCHEME = 39, - COAP_OPTION_SIZE1 = 60, + COAP_OPTION_IF_MATCH = 1, /**< If-Match */ + COAP_OPTION_URI_HOST = 3, /**< Uri-Host */ + COAP_OPTION_ETAG = 4, /**< ETag */ + COAP_OPTION_IF_NONE_MATCH = 5, /**< If-None-Match */ + COAP_OPTION_OBSERVE = 6, /**< Observe (RFC 7641) */ + COAP_OPTION_URI_PORT = 7, /**< Uri-Port */ + COAP_OPTION_LOCATION_PATH = 8, /**< Location-Path */ + COAP_OPTION_URI_PATH = 11, /**< Uri-Path */ + COAP_OPTION_CONTENT_FORMAT = 12, /**< Content-Format */ + COAP_OPTION_MAX_AGE = 14, /**< Max-Age */ + COAP_OPTION_URI_QUERY = 15, /**< Uri-Query */ + COAP_OPTION_ACCEPT = 17, /**< Accept */ + COAP_OPTION_LOCATION_QUERY = 20, /**< Location-Query */ + COAP_OPTION_BLOCK2 = 23, /**< Block2 (RFC 7959) */ + COAP_OPTION_BLOCK1 = 27, /**< Block1 (RFC 7959) */ + COAP_OPTION_SIZE2 = 28, /**< Size2 (RFC 7959) */ + COAP_OPTION_PROXY_URI = 35, /**< Proxy-Uri */ + COAP_OPTION_PROXY_SCHEME = 39, /**< Proxy-Scheme */ + COAP_OPTION_SIZE1 = 60 /**< Size1 */ }; /** @@ -69,13 +69,13 @@ enum coap_option_num { * To be used when creating a request or a response. */ enum coap_method { - COAP_METHOD_GET = 1, - COAP_METHOD_POST = 2, - COAP_METHOD_PUT = 3, - COAP_METHOD_DELETE = 4, - COAP_METHOD_FETCH = 5, - COAP_METHOD_PATCH = 6, - COAP_METHOD_IPATCH = 7, + COAP_METHOD_GET = 1, /**< GET */ + COAP_METHOD_POST = 2, /**< POST */ + COAP_METHOD_PUT = 3, /**< PUT */ + COAP_METHOD_DELETE = 4, /**< DELETE */ + COAP_METHOD_FETCH = 5, /**< FETCH */ + COAP_METHOD_PATCH = 6, /**< PATCH */ + COAP_METHOD_IPATCH = 7, /**< IPATCH */ }; #define COAP_REQUEST_MASK 0x07 @@ -120,7 +120,7 @@ enum coap_msgtype { * @param class Class of the response code (ex. 2, 4, 5, ...) * @param det Detail of the response code * @return Response code literal -*/ + */ #define COAP_MAKE_RESPONSE_CODE(class, det) ((class << 5) | (det)) /** @@ -129,33 +129,60 @@ enum coap_msgtype { * To be used when creating a response. */ enum coap_response_code { + /** 2.00 - OK */ COAP_RESPONSE_CODE_OK = COAP_MAKE_RESPONSE_CODE(2, 0), + /** 2.01 - Created */ COAP_RESPONSE_CODE_CREATED = COAP_MAKE_RESPONSE_CODE(2, 1), + /** 2.02 - Deleted */ COAP_RESPONSE_CODE_DELETED = COAP_MAKE_RESPONSE_CODE(2, 2), + /** 2.03 - Valid */ COAP_RESPONSE_CODE_VALID = COAP_MAKE_RESPONSE_CODE(2, 3), + /** 2.04 - Changed */ COAP_RESPONSE_CODE_CHANGED = COAP_MAKE_RESPONSE_CODE(2, 4), + /** 2.05 - Content */ COAP_RESPONSE_CODE_CONTENT = COAP_MAKE_RESPONSE_CODE(2, 5), + /** 2.31 - Continue */ COAP_RESPONSE_CODE_CONTINUE = COAP_MAKE_RESPONSE_CODE(2, 31), + /** 4.00 - Bad Request */ COAP_RESPONSE_CODE_BAD_REQUEST = COAP_MAKE_RESPONSE_CODE(4, 0), + /** 4.01 - Unauthorized */ COAP_RESPONSE_CODE_UNAUTHORIZED = COAP_MAKE_RESPONSE_CODE(4, 1), + /** 4.02 - Bad Option */ COAP_RESPONSE_CODE_BAD_OPTION = COAP_MAKE_RESPONSE_CODE(4, 2), + /** 4.03 - Forbidden */ COAP_RESPONSE_CODE_FORBIDDEN = COAP_MAKE_RESPONSE_CODE(4, 3), + /** 4.04 - Not Found */ COAP_RESPONSE_CODE_NOT_FOUND = COAP_MAKE_RESPONSE_CODE(4, 4), + /** 4.05 - Method Not Allowed */ COAP_RESPONSE_CODE_NOT_ALLOWED = COAP_MAKE_RESPONSE_CODE(4, 5), + /** 4.06 - Not Acceptable */ COAP_RESPONSE_CODE_NOT_ACCEPTABLE = COAP_MAKE_RESPONSE_CODE(4, 6), + /** 4.08 - Request Entity Incomplete */ COAP_RESPONSE_CODE_INCOMPLETE = COAP_MAKE_RESPONSE_CODE(4, 8), + /** 4.12 - Precondition Failed */ COAP_RESPONSE_CODE_CONFLICT = COAP_MAKE_RESPONSE_CODE(4, 9), + /** 4.12 - Precondition Failed */ COAP_RESPONSE_CODE_PRECONDITION_FAILED = COAP_MAKE_RESPONSE_CODE(4, 12), + /** 4.13 - Request Entity Too Large */ COAP_RESPONSE_CODE_REQUEST_TOO_LARGE = COAP_MAKE_RESPONSE_CODE(4, 13), + /** 4.15 - Unsupported Content-Format */ COAP_RESPONSE_CODE_UNSUPPORTED_CONTENT_FORMAT = COAP_MAKE_RESPONSE_CODE(4, 15), + /** 4.22 - Unprocessable Entity */ COAP_RESPONSE_CODE_UNPROCESSABLE_ENTITY = COAP_MAKE_RESPONSE_CODE(4, 22), + /** 4.29 - Too Many Requests */ COAP_RESPONSE_CODE_TOO_MANY_REQUESTS = COAP_MAKE_RESPONSE_CODE(4, 29), + /** 5.00 - Internal Server Error */ COAP_RESPONSE_CODE_INTERNAL_ERROR = COAP_MAKE_RESPONSE_CODE(5, 0), + /** 5.01 - Not Implemented */ COAP_RESPONSE_CODE_NOT_IMPLEMENTED = COAP_MAKE_RESPONSE_CODE(5, 1), + /** 5.02 - Bad Gateway */ COAP_RESPONSE_CODE_BAD_GATEWAY = COAP_MAKE_RESPONSE_CODE(5, 2), + /** 5.03 - Service Unavailable */ COAP_RESPONSE_CODE_SERVICE_UNAVAILABLE = COAP_MAKE_RESPONSE_CODE(5, 3), + /** 5.04 - Gateway Timeout */ COAP_RESPONSE_CODE_GATEWAY_TIMEOUT = COAP_MAKE_RESPONSE_CODE(5, 4), + /** 5.05 - Proxying Not Supported */ COAP_RESPONSE_CODE_PROXYING_NOT_SUPPORTED = COAP_MAKE_RESPONSE_CODE(5, 5) }; @@ -170,15 +197,15 @@ enum coap_response_code { * To be used when encoding or decoding a Content-Format option. */ enum coap_content_format { - COAP_CONTENT_FORMAT_TEXT_PLAIN = 0, /* charset=urf-8 */ - COAP_CONTENT_FORMAT_APP_LINK_FORMAT = 40, - COAP_CONTENT_FORMAT_APP_XML = 41, - COAP_CONTENT_FORMAT_APP_OCTET_STREAM = 42, - COAP_CONTENT_FORMAT_APP_EXI = 47, - COAP_CONTENT_FORMAT_APP_JSON = 50, - COAP_CONTENT_FORMAT_APP_JSON_PATCH_JSON = 51, - COAP_CONTENT_FORMAT_APP_MERGE_PATCH_JSON = 52, - COAP_CONTENT_FORMAT_APP_CBOR = 60, + COAP_CONTENT_FORMAT_TEXT_PLAIN = 0, /**< text/plain;charset=utf-8 */ + COAP_CONTENT_FORMAT_APP_LINK_FORMAT = 40, /**< application/link-format */ + COAP_CONTENT_FORMAT_APP_XML = 41, /**< application/xml */ + COAP_CONTENT_FORMAT_APP_OCTET_STREAM = 42, /**< application/octet-stream */ + COAP_CONTENT_FORMAT_APP_EXI = 47, /**< application/exi */ + COAP_CONTENT_FORMAT_APP_JSON = 50, /**< application/json */ + COAP_CONTENT_FORMAT_APP_JSON_PATCH_JSON = 51, /**< application/json-patch+json */ + COAP_CONTENT_FORMAT_APP_MERGE_PATCH_JSON = 52, /**< application/merge-patch+json */ + COAP_CONTENT_FORMAT_APP_CBOR = 60 /**< application/cbor */ }; /* block option helper */ @@ -239,25 +266,32 @@ struct coap_observer { * @brief Representation of a CoAP Packet. */ struct coap_packet { - uint8_t *data; /* User allocated buffer */ - uint16_t offset; /* CoAP lib maintains offset while adding data */ - uint16_t max_len; /* Max CoAP packet data length */ - uint8_t hdr_len; /* CoAP header length */ - uint16_t opt_len; /* Total options length (delta + len + value) */ - uint16_t delta; /* Used for delta calculation in CoAP packet */ -#if defined(CONFIG_COAP_KEEP_USER_DATA) - void *user_data; /* Application specific user data */ + uint8_t *data; /**< User allocated buffer */ + uint16_t offset; /**< CoAP lib maintains offset while adding data */ + uint16_t max_len; /**< Max CoAP packet data length */ + uint8_t hdr_len; /**< CoAP header length */ + uint16_t opt_len; /**< Total options length (delta + len + value) */ + uint16_t delta; /**< Used for delta calculation in CoAP packet */ +#if defined(CONFIG_COAP_KEEP_USER_DATA) || defined(DOXGEN) + /** + * Application specific user data. + * Only available when @kconfig{CONFIG_COAP_KEEP_USER_DATA} is enabled. + */ + void *user_data; #endif }; +/** + * @brief Representation of a CoAP option. + */ struct coap_option { - uint16_t delta; + uint16_t delta; /**< Option delta */ #if defined(CONFIG_COAP_EXTENDED_OPTIONS_LEN) uint16_t len; uint8_t value[CONFIG_COAP_EXTENDED_OPTIONS_LEN_VALUE]; #else - uint8_t len; - uint8_t value[12]; + uint8_t len; /**< Option length */ + uint8_t value[12]; /**< Option value */ #endif }; @@ -277,13 +311,13 @@ typedef int (*coap_reply_t)(const struct coap_packet *response, * @brief Represents a request awaiting for an acknowledgment (ACK). */ struct coap_pending { - struct sockaddr addr; - int64_t t0; - uint32_t timeout; - uint16_t id; - uint8_t *data; - uint16_t len; - uint8_t retries; + struct sockaddr addr; /**< Remote address */ + int64_t t0; /**< Time when the request was sent */ + uint32_t timeout; /**< Timeout in ms */ + uint16_t id; /**< Message id */ + uint8_t *data; /**< User allocated buffer */ + uint16_t len; /**< Length of the CoAP packet */ + uint8_t retries; /**< Number of times the request has been sent */ }; /** @@ -563,13 +597,13 @@ int coap_handle_request(struct coap_packet *cpkt, * https://tools.ietf.org/html/rfc7959 */ enum coap_block_size { - COAP_BLOCK_16, - COAP_BLOCK_32, - COAP_BLOCK_64, - COAP_BLOCK_128, - COAP_BLOCK_256, - COAP_BLOCK_512, - COAP_BLOCK_1024, + COAP_BLOCK_16, /**< 16-byte block size */ + COAP_BLOCK_32, /**< 32-byte block size */ + COAP_BLOCK_64, /**< 64-byte block size */ + COAP_BLOCK_128, /**< 128-byte block size */ + COAP_BLOCK_256, /**< 256-byte block size */ + COAP_BLOCK_512, /**< 512-byte block size */ + COAP_BLOCK_1024, /**< 1024-byte block size */ }; /** From 7f84783145206883918b27572dcd32f25698e265 Mon Sep 17 00:00:00 2001 From: Juha Heiskanen Date: Tue, 19 Sep 2023 13:53:10 +0300 Subject: [PATCH 107/421] [nrf fromtree] mgmt: mcumgr: Image management client fix Fix broken MCUmgr image group client. Signed-off-by: Juha Heiskanen (cherry picked from commit 0c6a3faeb4ae0973aaa31980f8e8fbef8f5b28b3) (cherry picked from commit 964580907ec9c9618256a3b1ce2d534b01305c78) --- .../mgmt/mcumgr/grp/img_mgmt/img_mgmt_client.h | 4 ++-- .../mgmt/mcumgr/grp/img_mgmt_client/CMakeLists.txt | 1 + .../mcumgr/grp/img_mgmt_client/src/img_mgmt_client.c | 12 ++++++------ 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/include/zephyr/mgmt/mcumgr/grp/img_mgmt/img_mgmt_client.h b/include/zephyr/mgmt/mcumgr/grp/img_mgmt/img_mgmt_client.h index 6ee12fb5a61..8cede40d64e 100644 --- a/include/zephyr/mgmt/mcumgr/grp/img_mgmt/img_mgmt_client.h +++ b/include/zephyr/mgmt/mcumgr/grp/img_mgmt/img_mgmt_client.h @@ -40,7 +40,7 @@ struct mcumgr_image_data { /** Image number */ uint32_t img_num; /** Image SHA256 checksum */ - char hash[IMG_MGMT_HASH_LEN]; + char hash[IMG_MGMT_DATA_SHA_LEN]; /** Image Version */ char version[IMG_MGMT_VER_MAX_STR_LEN + 1]; /** Image Flags */ @@ -76,7 +76,7 @@ struct mcumgr_image_upload { */ struct img_gr_upload { /** Image 256-bit hash */ - char sha256[IMG_MGMT_HASH_LEN]; + char sha256[IMG_MGMT_DATA_SHA_LEN]; /** True when Hash is configured, false when not */ bool hash_initialized; /** Image size */ diff --git a/subsys/mgmt/mcumgr/grp/img_mgmt_client/CMakeLists.txt b/subsys/mgmt/mcumgr/grp/img_mgmt_client/CMakeLists.txt index 693891896d8..cae17e865ff 100644 --- a/subsys/mgmt/mcumgr/grp/img_mgmt_client/CMakeLists.txt +++ b/subsys/mgmt/mcumgr/grp/img_mgmt_client/CMakeLists.txt @@ -13,3 +13,4 @@ zephyr_library_sources( ) zephyr_library_include_directories(include) +zephyr_library_link_libraries(MCUBOOT_BOOTUTIL) diff --git a/subsys/mgmt/mcumgr/grp/img_mgmt_client/src/img_mgmt_client.c b/subsys/mgmt/mcumgr/grp/img_mgmt_client/src/img_mgmt_client.c index b0e38640e8c..9ab8ee02dcd 100644 --- a/subsys/mgmt/mcumgr/grp/img_mgmt_client/src/img_mgmt_client.c +++ b/subsys/mgmt/mcumgr/grp/img_mgmt_client/src/img_mgmt_client.c @@ -126,7 +126,7 @@ static int image_state_res_fn(struct net_buf *nb, void *user_data) goto out; } /* Check that mandatory parameters have decoded */ - if (hash.len != IMG_MGMT_HASH_LEN || !version.len || + if (hash.len != IMG_MGMT_DATA_SHA_LEN || !version.len || !zcbor_map_decode_bulk_key_found(list_res_decode, ARRAY_SIZE(list_res_decode), "slot")) { LOG_ERR("Missing mandatory parametrs"); @@ -138,7 +138,7 @@ static int image_state_res_fn(struct net_buf *nb, void *user_data) image_info->image_list[image_info->image_list_length].img_num = img_num; image_info->image_list[image_info->image_list_length].slot_num = slot_num; memcpy(image_info->image_list[image_info->image_list_length].hash, - hash.value, IMG_MGMT_HASH_LEN); + hash.value, IMG_MGMT_DATA_SHA_LEN); if (version.len > IMG_MGMT_VER_MAX_STR_LEN) { LOG_WRN("Version truncated len %d -> %d", version.len, IMG_MGMT_VER_MAX_STR_LEN); @@ -277,7 +277,7 @@ static size_t upload_message_header_size(struct img_gr_upload *upload_state) /* Write hash when it defined and offset is 0 */ if (ok && upload_state->hash_initialized) { ok = zcbor_tstr_put_lit(zse, "sha") && - zcbor_bstr_encode_ptr(zse, upload_state->sha256, IMG_MGMT_HASH_LEN); + zcbor_bstr_encode_ptr(zse, upload_state->sha256, IMG_MGMT_DATA_SHA_LEN); } if (ok) { @@ -311,7 +311,7 @@ int img_mgmt_client_upload_init(struct img_mgmt_client *client, size_t image_siz client->upload.offset = 0; client->upload.image_num = image_num; if (image_hash) { - memcpy(client->upload.sha256, image_hash, IMG_MGMT_HASH_LEN); + memcpy(client->upload.sha256, image_hash, IMG_MGMT_DATA_SHA_LEN); client->upload.hash_initialized = true; } else { client->upload.hash_initialized = false; @@ -395,7 +395,7 @@ int img_mgmt_client_upload(struct img_mgmt_client *client, const uint8_t *data, if (ok && active_client->upload.hash_initialized) { ok = zcbor_tstr_put_lit(zse, "sha") && zcbor_bstr_encode_ptr(zse, active_client->upload.sha256, - IMG_MGMT_HASH_LEN); + IMG_MGMT_DATA_SHA_LEN); } } @@ -485,7 +485,7 @@ int img_mgmt_client_state_write(struct img_mgmt_client *client, char *hash, bool /* Write hash data */ if (ok && hash) { ok = zcbor_tstr_put_lit(zse, "hash") && - zcbor_bstr_encode_ptr(zse, hash, IMG_MGMT_HASH_LEN); + zcbor_bstr_encode_ptr(zse, hash, IMG_MGMT_DATA_SHA_LEN); } /* Close map */ if (ok) { From 63548546a8126ab0b0c7c780cf9add80d00c2c73 Mon Sep 17 00:00:00 2001 From: Juha Heiskanen Date: Tue, 19 Sep 2023 13:57:25 +0300 Subject: [PATCH 108/421] [nrf fromtree] tests: mcumgr: Updated MCUmg & smp client tests Fixed broken MCUmgr client unit test. Added test_ -prefix to tests. Added testcase.yaml to test trigger test run. Signed-off-by: Juha Heiskanen (cherry picked from commit 3e0ed42427046d988601b2222f63e16669657c2d) (cherry picked from commit 39a684cf591712aa0c5669217e818d295f070179) --- .../subsys/mgmt/mcumgr/mcumgr_client/CMakeLists.txt | 2 +- tests/subsys/mgmt/mcumgr/mcumgr_client/prj.conf | 7 +++++-- .../mgmt/mcumgr/mcumgr_client/src/img_gr_stub.c | 10 ++++++++-- tests/subsys/mgmt/mcumgr/mcumgr_client/src/main.c | 12 ++++++------ tests/subsys/mgmt/mcumgr/mcumgr_client/testcase.yaml | 11 +++++++++++ tests/subsys/mgmt/mcumgr/smp_client/src/main.c | 6 +++--- tests/subsys/mgmt/mcumgr/smp_client/testcase.yaml | 11 +++++++++++ 7 files changed, 45 insertions(+), 14 deletions(-) create mode 100644 tests/subsys/mgmt/mcumgr/mcumgr_client/testcase.yaml create mode 100644 tests/subsys/mgmt/mcumgr/smp_client/testcase.yaml diff --git a/tests/subsys/mgmt/mcumgr/mcumgr_client/CMakeLists.txt b/tests/subsys/mgmt/mcumgr/mcumgr_client/CMakeLists.txt index a0f76554629..20a96480514 100644 --- a/tests/subsys/mgmt/mcumgr/mcumgr_client/CMakeLists.txt +++ b/tests/subsys/mgmt/mcumgr/mcumgr_client/CMakeLists.txt @@ -14,4 +14,4 @@ FILE(GLOB app_sources target_sources(app PRIVATE ${app_sources}) -add_compile_definitions(CONFIG_MCUMGR_GRP_IMG_UPDATABLE_IMAGE_NUMBER=1) +zephyr_library_link_libraries(MCUBOOT_BOOTUTIL) diff --git a/tests/subsys/mgmt/mcumgr/mcumgr_client/prj.conf b/tests/subsys/mgmt/mcumgr/mcumgr_client/prj.conf index 46835a49dc7..461a0ec9477 100644 --- a/tests/subsys/mgmt/mcumgr/mcumgr_client/prj.conf +++ b/tests/subsys/mgmt/mcumgr/mcumgr_client/prj.conf @@ -12,14 +12,17 @@ CONFIG_NET_BUF=y CONFIG_BASE64=y CONFIG_ZCBOR=y CONFIG_CRC=y -# Enable mcumgr +# Enable MCUboot util library +CONFIG_MCUBOOT_BOOTUTIL_LIB=y +# Enable mcumgr client CONFIG_MCUMGR=y CONFIG_SMP_CLIENT=y -CONFIG_MCUMGR_GRP_IMG_UPDATABLE_IMAGE_NUMBER=1 CONFIG_MCUMGR_GRP_OS_CLIENT=y CONFIG_MCUMGR_GRP_IMG_CLIENT=y CONFIG_MCUMGR_GRP_OS_CLIENT_ECHO=y CONFIG_MCUMGR_GRP_OS_CLIENT_RESET=y +# disable default image group build +CONFIG_IMG_MANAGER=n # Extend System Workqueue stack size CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=2304 diff --git a/tests/subsys/mgmt/mcumgr/mcumgr_client/src/img_gr_stub.c b/tests/subsys/mgmt/mcumgr/mcumgr_client/src/img_gr_stub.c index 5bd784a3954..aea03935fe6 100644 --- a/tests/subsys/mgmt/mcumgr/mcumgr_client/src/img_gr_stub.c +++ b/tests/subsys/mgmt/mcumgr/mcumgr_client/src/img_gr_stub.c @@ -24,6 +24,12 @@ static struct mcumgr_image_data image_dummy_info[2]; static size_t test_offset; static uint8_t *image_hash_ptr; +#ifdef CONFIG_MCUMGR_GRP_IMG_UPDATABLE_IMAGE_NUMBER +#define IMG_UPDATABLE_IMAGE_COUNT CONFIG_MCUMGR_GRP_IMG_UPDATABLE_IMAGE_NUMBER +#else +#define IMG_UPDATABLE_IMAGE_COUNT 1 +#endif + #define ZCBOR_ENCODE_FLAG(zse, label, value) \ (zcbor_tstr_put_lit(zse, label) && zcbor_bool_put(zse, value)) @@ -117,7 +123,7 @@ void img_read_response(int count) zcbor_tstr_put_term(zse, image_dummy_info[i].version) && zcbor_tstr_put_term(zse, "hash") && - zcbor_bstr_encode_ptr(zse, image_dummy_info[i].hash, IMG_MGMT_HASH_LEN) && + zcbor_bstr_encode_ptr(zse, image_dummy_info[i].hash, IMG_MGMT_DATA_SHA_LEN) && ZCBOR_ENCODE_FLAG(zse, "bootable", image_dummy_info[i].flags.bootable) && ZCBOR_ENCODE_FLAG(zse, "pending", image_dummy_info[i].flags.pending) && ZCBOR_ENCODE_FLAG(zse, "confirmed", image_dummy_info[i].flags.confirmed) && @@ -126,7 +132,7 @@ void img_read_response(int count) zcbor_map_end_encode(zse, 15); } - ok = ok && zcbor_list_end_encode(zse, 2 * CONFIG_MCUMGR_GRP_IMG_UPDATABLE_IMAGE_NUMBER); + ok = ok && zcbor_list_end_encode(zse, 2 * IMG_UPDATABLE_IMAGE_COUNT); ok = ok && zcbor_map_end_encode(zse, 15); diff --git a/tests/subsys/mgmt/mcumgr/mcumgr_client/src/main.c b/tests/subsys/mgmt/mcumgr/mcumgr_client/src/main.c index a15e82f17a6..bf70f178fe7 100644 --- a/tests/subsys/mgmt/mcumgr/mcumgr_client/src/main.c +++ b/tests/subsys/mgmt/mcumgr/mcumgr_client/src/main.c @@ -27,7 +27,7 @@ static struct smp_client_object smp_client; static struct img_mgmt_client img_client; static struct os_mgmt_client os_client; -ZTEST(mcumgr_client, img_upload) +ZTEST(mcumgr_client, test_img_upload) { int rc; struct mcumgr_image_upload response; @@ -108,7 +108,7 @@ ZTEST(mcumgr_client, img_upload) response.image_upload_offset); } -ZTEST(mcumgr_client, img_erase) +ZTEST(mcumgr_client, test_img_erase) { int rc; @@ -130,7 +130,7 @@ ZTEST(mcumgr_client, img_erase) zassert_equal(MGMT_ERR_EOK, rc, "Expected to receive %d response %d", MGMT_ERR_EOK, rc); } -ZTEST(mcumgr_client, image_state_read) +ZTEST(mcumgr_client, test_image_state_read) { int rc; struct mcumgr_image_state res_buf; @@ -153,7 +153,7 @@ ZTEST(mcumgr_client, image_state_read) res_buf.image_list_length); } -ZTEST(mcumgr_client, image_state_set) +ZTEST(mcumgr_client, test_image_state_set) { int rc; char hash[32]; @@ -199,7 +199,7 @@ ZTEST(mcumgr_client, image_state_set) true, image_info[0].flags.confirmed); } -ZTEST(mcumgr_client, os_reset) +ZTEST(mcumgr_client, test_os_reset) { int rc; @@ -217,7 +217,7 @@ ZTEST(mcumgr_client, os_reset) zassert_equal(MGMT_ERR_EOK, rc, "Expected to receive %d response %d", MGMT_ERR_EOK, rc); } -ZTEST(mcumgr_client, os_echo) +ZTEST(mcumgr_client, test_os_echo) { int rc; diff --git a/tests/subsys/mgmt/mcumgr/mcumgr_client/testcase.yaml b/tests/subsys/mgmt/mcumgr/mcumgr_client/testcase.yaml new file mode 100644 index 00000000000..99b9fac34ad --- /dev/null +++ b/tests/subsys/mgmt/mcumgr/mcumgr_client/testcase.yaml @@ -0,0 +1,11 @@ +# +# Copyright (c) 2023 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: Apache-2.0 +# +tests: + mgmt.mcumgr.mcumgr.client: + platform_allow: native_posix + tags: + - mcumgr + - mcumgr_client diff --git a/tests/subsys/mgmt/mcumgr/smp_client/src/main.c b/tests/subsys/mgmt/mcumgr/smp_client/src/main.c index be1a3968274..7b6ad8eafa8 100644 --- a/tests/subsys/mgmt/mcumgr/smp_client/src/main.c +++ b/tests/subsys/mgmt/mcumgr/smp_client/src/main.c @@ -32,7 +32,7 @@ int smp_client_res_cb(struct net_buf *nb, void *user_data) return 0; } -ZTEST(smp_client, buf_alloc) +ZTEST(smp_client, test_buf_alloc) { struct smp_client_object smp_client; @@ -56,7 +56,7 @@ ZTEST(smp_client, buf_alloc) } } -ZTEST(smp_client, msg_send_timeout) +ZTEST(smp_client, test_msg_send_timeout) { struct net_buf *nb; @@ -72,7 +72,7 @@ ZTEST(smp_client, msg_send_timeout) zassert_equal_ptr(response_ptr, &testing_user_data, "User data not returned correctly"); } -ZTEST(smp_client, msg_response_handler) +ZTEST(smp_client, test_msg_response_handler) { struct smp_hdr dst_hdr; int rc; diff --git a/tests/subsys/mgmt/mcumgr/smp_client/testcase.yaml b/tests/subsys/mgmt/mcumgr/smp_client/testcase.yaml new file mode 100644 index 00000000000..49971116251 --- /dev/null +++ b/tests/subsys/mgmt/mcumgr/smp_client/testcase.yaml @@ -0,0 +1,11 @@ +# +# Copyright (c) 2023 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: Apache-2.0 +# +tests: + mgmt.mcumgr.smp.client: + platform_allow: native_posix + tags: + - mcumgr + - smp_client From db7577339d36b3f44997d478cb10207df51fc23a Mon Sep 17 00:00:00 2001 From: Juha Ylinen Date: Mon, 2 Oct 2023 14:53:41 +0300 Subject: [PATCH 109/421] [nrf fromlist] net: coap: release non-confirmable messages Only confirmable messages need pending tracking. Non-confirmable messages are released after sending. Match incoming packets with token, not message ID. Ignore responses with non-matching tokens. Remove unused function send_reset(). Upstream PR: https://github.com/zephyrproject-rtos/zephyr/pull/63378 Signed-off-by: Juha Ylinen (cherry picked from commit ae072e80c219d5fc81b8ad885fd7c9f22e3d84af) --- subsys/net/lib/coap/coap_client.c | 79 +++++++++------------------- tests/net/lib/coap_client/src/main.c | 4 +- 2 files changed, 25 insertions(+), 58 deletions(-) diff --git a/subsys/net/lib/coap/coap_client.c b/subsys/net/lib/coap/coap_client.c index d096e39c62f..e78aafd6829 100644 --- a/subsys/net/lib/coap/coap_client.c +++ b/subsys/net/lib/coap/coap_client.c @@ -308,12 +308,6 @@ int coap_client_req(struct coap_client *client, int sock, const struct sockaddr reset_internal_request(internal_req); - if (retries == -1) { - internal_req->retry_count = DEFAULT_RETRY_AMOUNT; - } else { - internal_req->retry_count = retries; - } - if (k_mutex_lock(&client->send_mutex, K_NO_WAIT)) { return -EAGAIN; } @@ -332,16 +326,25 @@ int coap_client_req(struct coap_client *client, int sock, const struct sockaddr goto out; } - ret = coap_pending_init(&internal_req->pending, &internal_req->request, &client->address, - internal_req->retry_count); + /* only TYPE_CON messages need pending tracking */ + if (coap_header_get_type(&internal_req->request) == COAP_TYPE_CON) { + if (retries == -1) { + internal_req->retry_count = DEFAULT_RETRY_AMOUNT; + } else { + internal_req->retry_count = retries; + } - if (ret < 0) { - LOG_ERR("Failed to initialize pending struct"); - k_mutex_unlock(&client->send_mutex); - goto out; - } + ret = coap_pending_init(&internal_req->pending, &internal_req->request, + &client->address, internal_req->retry_count); + + if (ret < 0) { + LOG_ERR("Failed to initialize pending struct"); + k_mutex_unlock(&client->send_mutex); + goto out; + } - coap_pending_cycle(&internal_req->pending); + coap_pending_cycle(&internal_req->pending); + } ret = send_request(sock, internal_req->request.data, internal_req->request.offset, 0, &client->address, client->socklen); @@ -368,6 +371,10 @@ static void report_callback_error(struct coap_client_internal_request *internal_ static bool timeout_expired(struct coap_client_internal_request *internal_req) { + if (internal_req->pending.timeout == 0) { + return false; + } + return (internal_req->request_ongoing && internal_req->pending.timeout <= (k_uptime_get() - internal_req->pending.t0)); } @@ -547,35 +554,6 @@ static int send_ack(struct coap_client *client, const struct coap_packet *req, return 0; } -static int send_reset(struct coap_client *client, const struct coap_packet *req, - uint8_t response_code) -{ - int ret; - uint16_t id; - uint8_t token[COAP_TOKEN_MAX_LEN]; - uint8_t tkl; - struct coap_packet reset; - - id = coap_header_get_id(req); - tkl = response_code ? coap_header_get_token(req, token) : 0; - ret = coap_packet_init(&reset, client->send_buf, MAX_COAP_MSG_LEN, COAP_VERSION, - COAP_TYPE_RESET, tkl, token, response_code, id); - - if (ret < 0) { - LOG_ERR("Error creating CoAP reset message"); - return ret; - } - - ret = send_request(client->fd, reset.data, reset.offset, 0, - &client->address, client->socklen); - if (ret < 0) { - LOG_ERR("Error sending CoAP reset message"); - return ret; - } - - return 0; -} - struct coap_client_internal_request *get_request_with_id(struct coap_client *client, uint16_t message_id) { @@ -631,7 +609,7 @@ static int handle_response(struct coap_client *client, const struct coap_packet */ response_type = coap_header_get_type(response); - internal_req = get_request_with_id(client, coap_header_get_id(response)); + internal_req = get_request_with_token(client, response); /* Reset and Ack need to match the message ID with request */ if ((response_type == COAP_TYPE_ACK || response_type == COAP_TYPE_RESET) && internal_req == NULL) { @@ -655,17 +633,8 @@ static int handle_response(struct coap_client *client, const struct coap_packet return 1; } - /* Check for tokens - * Separate response doesn't match with message ID, - * check if there is a separate request waiting with matching token - */ - if (internal_req == NULL) { - internal_req = get_request_with_token(client, response); - } - if (internal_req == NULL || !token_compare(internal_req, response)) { - LOG_ERR("Not matching tokens, respond with reset"); - ret = send_reset(client, response, COAP_RESPONSE_CODE_NOT_FOUND); + LOG_WRN("Not matching tokens"); return 1; } @@ -795,7 +764,7 @@ void coap_client_recv(void *coap_cl, void *a, void *b) ret = handle_response(clients[i], &response); if (ret < 0) { - LOG_ERR("Error handling respnse"); + LOG_ERR("Error handling response"); } clients[i]->response_ready = false; diff --git a/tests/net/lib/coap_client/src/main.c b/tests/net/lib/coap_client/src/main.c index a3862852c21..bb9d9fc38c5 100644 --- a/tests/net/lib/coap_client/src/main.c +++ b/tests/net/lib/coap_client/src/main.c @@ -392,7 +392,5 @@ ZTEST(coap_client, test_unmatching_tokens) k_sleep(K_MSEC(1)); k_sleep(K_MSEC(1)); clear_socket_events(); - zassert_equal(last_response_code, COAP_RESPONSE_CODE_NOT_FOUND, "Unexpected response %d", - last_response_code); - k_sleep(K_MSEC(1)); + k_sleep(K_MSEC(1000)); } From bd268c7f0e0b6c301a34df53c0d41075dd844d3d Mon Sep 17 00:00:00 2001 From: Seppo Takalo Date: Thu, 28 Sep 2023 13:28:33 +0300 Subject: [PATCH 110/421] [nrf fromlist] net: lwm2m: Allow configuring update period Add new configuration value CONFIG_LWM2M_UPDATE_PERIOD that allows calculating update period from last update, instead of calculating it from the lifetime. In runtime, server is allowed to change the lifetime of the registration which causes update perdiod to be effected. When fixed update period is preferred, UPDATE_PERIOD config is then used. Upstream PR: https://github.com/zephyrproject-rtos/zephyr/pull/63216/ Signed-off-by: Seppo Takalo (cherry picked from commit fcbf3786cd8f40829dfe4cd3b1421c63437a47b6) --- .../api/images/lwm2m_lifetime_both.png | Bin 0 -> 17612 bytes .../images/lwm2m_lifetime_seconds_early.png | Bin 0 -> 14563 bytes doc/connectivity/networking/api/lwm2m.rst | 47 ++++++++++++++++++ samples/net/lwm2m_client/overlay-queue.conf | 6 ++- subsys/net/lib/lwm2m/Kconfig | 12 ++++- subsys/net/lib/lwm2m/lwm2m_rd_client.c | 22 +++++--- tests/net/lib/lwm2m/interop/prj.conf | 2 + .../lib/lwm2m/lwm2m_rd_client/CMakeLists.txt | 1 + 8 files changed, 82 insertions(+), 8 deletions(-) create mode 100644 doc/connectivity/networking/api/images/lwm2m_lifetime_both.png create mode 100644 doc/connectivity/networking/api/images/lwm2m_lifetime_seconds_early.png diff --git a/doc/connectivity/networking/api/images/lwm2m_lifetime_both.png b/doc/connectivity/networking/api/images/lwm2m_lifetime_both.png new file mode 100644 index 0000000000000000000000000000000000000000..1cdf0bbb662965d525b6b24f6dade674d9b2f0fe GIT binary patch literal 17612 zcmd^n2Ut|wk}e`Bh)PZ>N=BmOAVG3&K!P*^LIX`~GBh~~LK9VjWDyZ0C&@X9f|7HP zBp_KpBniIN2|T5ATC1x53ae^=qSRF6E?u~C0Rsc$l7hUn zItB(N1YGCfoCDt;uCLd?pEHi?a*`PNo!1sIFi7m2WS~yguBH|UI0gfc)UPWBZccMs zM<)gzX$Ed?n4KMmi3QBe0cP#UVFPypL*Tx(t%-%H1>EG<9Bxi-9(GP4c5XpUP9X*! z30_|C#m&dT&%=5D*L;{6+~$NJ#Ma#cfq*e^%kpt>0#Y}jTwDx1lHf|&!p7MZ{B;%N zH{j=G23Hbxb_lpO+(^j+tSigMBf!DKkA6f+UK66sz%2!?5f)Z(@J9}AY-NjnM9SR3 z)*6h+a&ZZ8aH9W#K@FHG%)#O}5@;Tfa0f>VTbmOWxH$MZgnn%n?gTSCVO~?n#K^(S zK?UMyWzS{cqNIa>{+i?DW(WT@#{`bFFa`^9Gw{eTa7qBe=ns$7iO|3g8yMKou`tzu z9N4*jQLs1>9=o|SmjKMjQXOhyq-HOtaNo`OSjfLqJEdvuD(3*RGl$rkz!8A3iR;Pc z1vmwM5jAo9HNwR!c*2aC!|6gN>!JrVEZk3a#07SX7KWL#g$dm8L;Q7A+rq@j{MTGTzLV{t zXUoGa%*;<$=HfiLV+}iUd@p8 zOwgt$>0)l-1lO>GfzZGs?E<_u82hu;nA+Mn{T1(Mg78yh{Mxx4?B9?0(@4R?_h+o} zoM7!Yi{KJC8T;KNPUoFs@^|$A?*Q`OrD@*3Xj)56T0&FiFN$?Ax3xBM1_t^M#s8b1 z`(3pR+&m^QxS**qcr`f;Lgbw{_ko>=tS}-X35R_SM8iy?(fPu9s4g) z&IzD?GsC~A1%%||Y{?V>cRdLc=vZ(XF^mx~M@I{^_#)7{n z{`4&HTP)x{O@)4UH~*!v;N+n5&)kg}@Evw1fcUGwJ~_d_j7~G;6Ce8@7-j!Hqx-{( zf0yj3nf)%=Q&T*(_W#r^GOxrH*-Dl#%eO^3aaSi&;OXz{NIY((=*s#b3LyAD(`!ot^W(vk<%02-wIK` z+v@S%)6&v2=g@W)a zGcAS0hck4h7gJMHgDJ$_QYpkq&Zg25DO2yagyEj04L+l$Ol>N2G0t_K?Z|3qe>uOd zIUvQuY#zDeSxTk^bI;B}zAESx($ZLd?sK%)7A-A~^~a}}=ru!6`gK}NTI!QeC9XX0 zoM}4KA5)|o=o9*J|Mrs_>kKM`;PJO$oM7LRk34S{{vSVr#c?o+AT-pAgoFfVPCk## z)o=XqgTRjfi#|b8yqE4hLjxbY)N&vjiH#SdT8gLcd-18}Gt4P9GW2%TB*fDcl3(1! zx_94#;oxAso^`Iaoh1kQ@Z2TDq}NUNq7orJghHLN#gT9Hk-Ov4rSvktLyD5jJ`kM-K}nGr%d zS;3UgIrM1R&8di|WsQ4?KUs=2zx}o0?CP*_WS(pDt@es&BnYtC4q( z3L77uul_MwW^Fa;xfQ;>IyO}H$=%9oC||#GC;dXf`5T_yr9;uo8V=st$GQ;j1&U;- z4YYdg9h|Y%Dcq$asjl%{%nR}P-IMPF+6Fp@``cEp158_qAg{93vdtB}*5?y#ZO&6U zJ=XVFEqxIh&5|JLa~D4ZC|R76;ITQ&L)m;3izzV#D#=mvRq|ja^j0oVLB1>4T*X28 z-qwOJ%|M>6z|IcoJ?M+HUE{Z5MLGFZ?P3QjJY#MP$*Z5ERLf=~?|iB|+PBKlF8Jg? zi-Y$b?8F-Cy?YI>zx#!h^?;Uk>1e6d7*N{U<|o(L@Kx|Y8Q+jzA4lb9qN{hjYaA^$ zCXFM6-o~tMcHAo0Ht-s#yjC=-ha7<;8_t{;ygOX)^D~6|llyXB*=pGs$3jYTwrp+I zc~~ zWKiF$O~#@3CHKLIpz&d|=t7^|4KEXDg8!OO0He)E@S|T850vtf+`q3_@R)VJkqy66 ziM+j1*vztdp|6gwM|E2T4gYsRzS0_EZ@wYSF@qV&dd{3Zr|G${@Z6_Nr^Iwb$1EAn zu3PqIA;lwKlGAx*xaYFaX9A{xPi_lTOmS5%>uYT4^jO`@nMp=wDQ+2|DEBWff|4qz z2N{#iY1b!QCMWE42(`a`AF~w}AjK2G`~rqb2lI5RU8WSrocbWi7|=3AJnIeG<#%+E zZ&dFb_9Mrv1$J!4eeN9Xz6@=X4EQ=?;Bz<^Kq)x`SavbOE+P!Gs5<;UmZ$WLV-4T! z>x9I^b0gP1R$%yde%J+?(~{wC@Y+p@?_3Wc#k}PAG}3%#Z|9Rom;I2p`bJS+HY#)moTc8$g? zGLw@i(jPqc+(hM7uT`nMp0k|nrc(L^zDq=p&9fzT6}+9R#O;=pI4cYgMY)d&D6mYr zQbem~=*K<^Os@FH6=4)n8(WXSpXsl33a{rjJZcaZc?HlKO~9=b%f{6%*>s`hJ!b$V z^MGiOIql_l=bg4bgbRE!j}-k5eYKk-J1)!^N0!pK|?{50|$vL@#teV0oEbqd$akYYreofo>Lx8rgzDmYwN&M!xfSY)Zi~z}7zD7HPr)18uekviKe=x& z%^h8O5z>0eirD&Dj+a}(Q?&DM@dMz#cAxnXT$#Mj3HaUH9q$333*(4%e6igIRERQa zonWjl19H{l`-oYd*THwvNFzdEjkVlwd8ad)oCAC%)2VChm{#k59&toErQw$AsMQea z_P>NE&U(O?G=FR}{ zNV3yrhZZ(qOVf!95=HXOr-gDjFx9H}ox6&dV$-^6Q}F_lA~MoSx#tAbC$tR75V!kz zE$v|{d?t~M{l1BT_ui|L&2(Z&%beX(7gN5n>rz&xo-*l7xcI8Tq-S5*h-so)8py8NuRR|Iydm86Xm5dBpEqzi%=vY98p^d;Z#D7Co9oSM`Lva#_M$xx;l6LJoolm+BQ>fD$2OwXM*WU+1%pD%Sy)clcdEgtwGV5L`45CakEDS=VL$X`At#??9$tu$G+FR%#MtGHhf_2u%wMXe_shPlg|&Qo>XeX$3QS)Y+P4I* zpXD$F+`5v5hbl3cJ(jv&Qxn;@63TZT5YpGMx~gh?Wm3CoKx3TXnYb_$CNI-q&vMyM zJ~^8;!PO;yCpJxWiRw82(Z|Flh9qGc5l-P(Ycdetq(6g&)i|Y#D3XyWgGN-mBP7f? z&OBOaQ@8V=CbQ29q&0qw=CUb$VCJ*=Zo1i|&SU#YgsGEIrSWQI2T=qIJ4mWDL2@S3 zdNt<*LxRzO-kdJfzg#GxQ-Oc&nq_Y~DpY1>$$x4>X--L=kNgbbO)?-iqbK18bwrR2 zE1nqWapssB0P;6Q9O0RQr{*E9XR}<7Lx;DiP$a<)s*zNZQRK^vl0&)QHzd4R9UU;-Q%O$hglgSxiveBrW%uQsY4DlVI#=CY$i3t_dc5lNd z*W|RfD|cV}Xfmd5yx5c2GUgpRkIJBZ9T{h;W7mTfq)e_izvQ|va)A9}hE8mRB1R>$Y05D^sO^G3GL;p8de-V>2;?Gb}>kn1E{HcNHCvXCp=D&ZyI10^TybYb@Zl} z0imN4Wj_%R9p=ukPDi%)Mt?nbZ~NE6*>Yer?mwP>TlGg}&`aFa|65v~YQ84)g7h@u zCh(&te*B90eO^u#>NHCy2?M^mQH_P}G%rWbF;{e0&bIlbK=6%CN8O{z8Qm^_!jv@i zd%)P!@hWu4`b9{*5p0e0;wx^V)5YYu0ZQo0^OqRW0z-e)I04GArLw~Q*xyrS;B@~3 zx1(E%E3)~HZm`I>&2r)8MQQ3Am`g5u-MuBWYPZ4KuZ;5qTEoN_I+IuZ&R;L=xK%&C z|80@Dq&KI+o`KV-1?Qm4=g2sS3K<7U;APGqP^*-oegZfp8p+Mpq`}d1c+c=1q!q*C zm5zDN%Y(?~O9CXcx^py`l(^rP209*i@4?4lK~%X9YTfzGyQzDCEP@Gu6ma++g%GiW zM6b8O@9b)Nlu9x1U!yklhe)g8LfD%N*}W|(4Nn=A^ls!B)YmN=KRl0*bOu)B)t8Nl z3uGT%cuvdtf?Pu=W4)ce=SC|!LoI*3TD6=X=<&pX#R{{;^rM6SVhgcqE`dUpS3&NX ztW8=18o)83CY7y-NO=`XZC{=hZ4Ut!vnvKpX~sgjI%_n2nSEY~*JH~ta@X9GI;GR1*ohb{^w z9aR;KBOL`$#5*SQDg?t1fj89qN-0?w9?myt7y4jzw3JTGh?M3smiNJ`08^FE-W>Um z%Tj+MhqzFTVEL#tWm{@N4w!}B|n zsMYVQV`E>Zn|b_k`gYo%rCD-d@}Z$WKfL^rkcj{}eTC05dV76x5|?Rh@Gg;`6IR6* z9$p_fLac`IbiTX5jF=?009MqCUXIP-ub5p@gLU3o?G0%3gjw}0B$o&hL z+WO8h`i>v@_+d?0V`k629O}5A*FEFm5&Z>YY*NTYrwBMJN?aYM`+4)Hm@RN#xUJMQ zsB3EtPB;n|Fb7^HV5x|1YwA|my(p1JA2T&=5|pH1EQ?ZmAFvtN;~v~o$HXRwM2oG^ zYV;;7!D-cKG4-pFr81#pl`_Tlvu_#Pa~=@$VTO|5Lejd=h6|MG+Sc+}wraR-Qd4&r zTrVU#dM&NdbQL;~Ly7t0!30EL;&XsT&}Ayi3<7tnaKbn-uPVo(?<*sHhY?BYHQ?CS zT77sy#~qa+*{k`0mVlbmZPUceqGGLTIoD%n%}9e0>um&;m07ZLEb#|9Dre33{@Wu1 z(dLTCgLw^MREDSdq7LD^sD>K1tt7iqpPz@;0J?78x{+<+;`QE#D;sS$T>P`Na_-r) z*0m>s1Td=V5fk;Xhm&Fay0`GW+8}S?om(Qmb;u8XxPb=N{D=72{G>QxmwY~O7RU&B zu|tMV8wpe2@+zS+;`oz7sPKUYY<-!0K}%65;erhJ{XKbJnH*8eVqPK$pMt@<3h$X4 zeY_5z{GEr*EW>Uj}vcb#O%2>kLd@y zGn4H1-vr-X)$C88=JYx8WJ&_(WwYiW{4Qt!r&j@Edx1-ccqQ=bEIZdz_q8pi?^iix z>HfH9;N@%v%hsm@caY(`e5_-B> zW-Ey0^(%IT*GR}J^j#+S)&?~8=p+pXb9GdLpW8Lz&KDq_n1{&EzNVmkED6G{z9g0d zG~wLkYhTDp(JmG@06M&hdha9saSO+Of_lez z!65L9qu@aL2y5t`Rw$+)@aQ8TTp)y33Lg&SXsf0%UkFd*4i@)C$?I*}KO(ar@y$we^f74#9N>zdJ#e=Wvgr~#$aVhG z-I(IO#5`MxKG=Q#Ul~*wn!XfSe&as881vR}_1Z-Bs76LTBrZwI#wH!&X%D4EK zC{V7UDmqYwTumrT#`$L5|N05K{_!0c>sWS9{!+^9QMB^p1|^m2l;0!D)u3olovN;0 z#ogqP>^x{szN~NGN;+5!?+B@xYMb*oB8mLzdn1Ek-XHI}&*8Qst?UP{(Wp zu&Tdt=w#iNHor>up{kz`KOBIwa@{I8o*_X6M+mt` zpN|^0E}uaA%yJ+f+scBbN0mtn@_KhS0VQqsh&|g-_A0Mfq@+xs67_-X)&qobTSVz4{^5p8h=2%k$k9%cYXoWrR6Xq;MqQ3sD^JO< zUb{Wp1%jn%`M5(UmB&iany9ZN^{!Kw=*}>Zzyk$oUhC2R%VN8RO!A*V1PNx-_p5<8&J&$atYIl$0MLQt{qIh~)<-#M31fDbqEuUskaU|ISG zj#pKv&u_2VzR|j;(>lI95ZG>9V#)6NEBQ!6zd*d5e6CxKw8^{gH6LXMGv>!kIi;&2 zZjU(C14FY}g+-;<9GUt3{Mw8^ArdO+y3tC`I@ml_)#&~%hV-+a_zp8$rpu()&^8m+ z;XPgJn6jlej!PM0#4odRL*oaHe_rlNh5&;&To2JM8Ket?mQYIJz|;(>Dq~%JIAbduKI7*#!V@E?psMV%+`<~f^ z;$bCb#M8dJU!pIjD3iUsF6us9yYp!oc{7VSahq+ZLG^GP{|b`iC{6h12T-gw)U~O6 zWo3dS@lJz(o!eh6LBP{X8Xu$1vJxrTP&i?X`B}Dt^jmeiO_U4-JBum>Z}0KK ztc}VWY(f=iqs%ce&pyP%rHpQTk5_W-A!-7@t5B+W)E}FfPey|GF5`!}XiCDUF6qR) zvj-8bpoTTV)pjlF9xoS^FlI%$Zxze7ZqL-rNX0oXBT@OVyi?nECv+YN)E6F{I^!j0bHr z7h8J9&Cm?aWqXdbT*tzV*fPB|l=F=TU(W9H)36q{ScaBoff85;S6H6;X6(iKm+g!R zulZsh7u4;yLwLn{&e*%1q0}aw8h(|2KsczEhU+NcvY)P`EWS8ywwUsf-<(3TVq8UR z&xE{Vis}CC;KG zB*(+*GQ@7al<={)WycQJ5HcHU-JV5{sX*W0Osf3t=+i6ZA|6;9x8$Q?2{PAl?@FSp zin+HuZ$6Hv!PH~n=d~^ZbXwnQFzgW=tzHD0>kvhTXl)HcMJ(Q1kFzGX(3I#5OJzPPK&6* z=)$x6py?BP^s{Wl5Z zl=WKpHVmHor{R9W`sh~gk>Rc;=RaV7<1-Ot_HDT1nSEsvthdM3Ur15>#8A@gT1f?= zYq*R61uG$v?O;N1w(UH=+3cfI6qQq%uZ7PS>>YyH@lZxGVlpGWO+?vc!71Mwc1YH2 z682@9*0&+8*Ojh0QpR$znN&7ik2V*+t{1-PvVA$=z2D%11CKCe3+f+ z+Hec8$J=wRU%Fq|KstbcLkLAWUA}13*DwV$@Ye-jVN=PqekmJXoFeLRFI$D8Cpzn> z#lJ_pDMQb1s?nKi#XX6cAc=c=-ZVMG$8E@#qNl|LRX|r3R@dZ00Et(BFGI|PQ5a_; zEZXM3{E$FHwQDcLP{ovBw`+?O(kSBvj`7YTz0~L)-Bpnv0&xx~#@j5WeNMP{yoaNV z7FAStMYMIT`N)G;Rb_WkvA9C|cGoe_ku#z$huKb^Z=QYB(km54PDQ`nuc*d5{gm!Y zM5+R&0uO`#cDxfqLX!%sd%hk{AqCGuVPzBiQLqs3!mFSFfV}sm&^R7KYagEUj?Pd( zdxk2QW`>4`fz0Nu^X;C1YW!zc$j;747s_t!^!GW&kAIElmupEj;G70UkF>aG5Vkt86|R-ya7zL)QvYK0b&sAF*GB)~pkO2eTR>5?JE1+a zr)4xaF~XVmON5H{(9=*xB#AObLGAZZhq=b~W}9=ZL6e^zw)D%+DQJdBw9Z^}a+@Q9 zfU<=nqvg*BGl@82%Fl++5OGo{1Hfijku)JWedST`X?B8kZ@KSAjD1GWaLp;u_L9b(ZOLiDO{kAEDm`5Lysq<#xQm zWYWjLZxm)7KsYO6ZZYGQ&r2(bOwHF%wE%Gd=hxJMYS96i!hoHuuO z9DJF#?*|*|m{+G_T%b$f)_+OxNa<_5CuU=Fe%m6OXBd-z8LW9hB2od`BVD<;lUtC* zB&)Hk@6Z#V^awlQOhQ7OJSR^tpt)$}FrJKEHOXMDxTf>A*c?e>~J^pguRZ$ud7 z^_&{1RI_9>fV#74npEC+-qJX4s@}RE5GnYMcKh44v?%^&t!KBVpWNZlbmdks)ae*N zI;jPia=vAol*n3;p>D^rJD44%jU^D!w50VWAZ&8n3xmIC7OO5_yB3a~Y_%Dc{EzmE= z0Bs77W8eI~vyZ)HmM`b3*2ZaXW`k~_=YzP^J%Mxhjj>`3TD;RN47-=` zt_y3f%PNyX;<_t^Lpr_+qKHIFn|BJKJuso##;K2k$One@3XDa%pr9a)`G7wCDo+a~ zES!2bI^0Ao?Y)6egCD7X#Y5a>;-7ElBOw>@1h-gdl#HdhvTuOt6*jGyXs2?=^tTzqge-^6m zc8K($vX$X9*Zf!+pzj_|lh=9q+nWUvKt7Z}e+c$}#;3Y_PJ}?hZ@D8B2Yy}F(9Oz> zL`Fkw*}e?QeZz;Gq!>j2i8JF`H-a^gbSz%vEZg?y zC4g_~U?+SE{q~iChuWUlu+vl^P%8q}ofyKSZ=;}Vmx&XF(-lyAll`KwC>`cqx`rAq z(+?Eog@o=6Gwn6aX>F!~kaKwV#f;-`8%a=KK37g;e+}vrzigK`wS;p{)UiM15`JdD z2pg>mP7`A+A*_udvEqxTB2&U{SOsD3yL8Q-X!lBZhJ6I}O#iieSN!|;Zf%Jfo#T?t zWi4XZ%Rm_U))+RsHz#4A#e7x7IjtpLNb_~`5N2a!4$X<%dW|Qsl56#bJ(TZajS{ax z4@u2!XawjShEY1&d=R3vG+$8M4CEA{QcR+0j!fg38*m>$bq^UgC*aLpF{G8 zhM3?nrQ;@bdyF`wGbSL&q*^G6zmffsN0FY!ZEZsqyvv@iszYdSKY-$3e@F|-S0-Ir zbIuif+1S^^?&0VjO>{K+$(A2>?YDGiTCUkc=Mn^=k6AZ#17WwEI%Bl^#h#gm+z)*% z^2Z*Y(1U{1d(*ow{@7<4C`d6|vZrmH^n84Aq@RL19etuq;2&L|;47e1__{Q>o$j>j zL!bayd4eD#WwF2_^Zb?vNiG@wZq+xOAdr>#W+_YTxHCkCZabvKYrRjP_cg3qY!t|| z4h=_q|Dl@O_JW-u$+B4Dn+>`Q_L>%uXYubFlBT|R=2qNgo5^whk<mM7ozPF&U!f^W`cmo; znj>*SbPMZDb}^eRW+hfsfQH)+{=fq)Y3e$#xtTE}iyIbh0I4#O3L!#-^jIAZps}Y; zPUwe8_)eQsL68)urWoD3^CKbzl~zLYTE-EqY?e6sq^A?NG=;&q2^d$r=aJ3NC!Sh` zUi#b>NC64@2^K&p8d21~?G5|m|bxw&GNT?)kE1bPNC<<^?TIE1g6!4o7eR8rH>P!a{3DqhFLd>kqcK|i3! zp5BG7TBh=%i_^_IwkT%5*Erxt9Fm$;7YOh!7$+J?%2uYqm4=`NRqPz|42{aqpjXQ5 zW4bR(Nf4ZE_|%T&VP_@_c(+VC7U0SxQ5HLg8S^eV;G1uN=i39og#&0QXs(HhZx={Y za{vh{P-&y3p$Obicq%Omf4wmF>hM8~7}G;i?fdWVmru01 z@6-+-O=Lq}St{4;ovTKO-$?xNWvguUyY*_g_QI%r(8^lMp2x^!*~)tTgonHw)#OLy za$)4Q;6`_d&sO|^ZFhG@{SUu`<+kVSrOZ5J&`2rW`&*38p@ERS<2Uhi&>gJ~Q|(tY zk1b*Q(+BI4sEn&Y_(jZp^IGDbhMQQ`={~lJT&56s&1RBV^woy--ir*MuNFq?pa2AFis%wCxqXxxlYB0_&h)Ae~D~uJzPO8 zkegVG1C-jLQF`+-0K|-)Rz4xq<4y)`tsZHuM1cnrYi=vp2PQq|W2B?n>{PmD^K5F* z@lO?7P2BnD4SST__p(Iv>*s4@C97oLKZoL3AIgTazSffCeLq98(U~~|8q_Ul6d)2+ zunSoHl)03(2qEB2)u0KFg*^V5c8TvRtT#r(EFv>WA?1 zTr+Nm71P;$oG2J^cRqq!mycAaPx$O_oVO}orkTjKEzKP&N(hBdt>~Rui>o{vGza@R41?YWjNhlC z9IZo5*;k5~cZO5zGRHn>-zgioXV6?*UKPt|usdSQR($K(k>SGiTI-S05*9YJBMk)I z0ZsF?_FJ1++&T&9!najX&z0}pZ?q95>QrptSu zp*vdnlM?YVp9&#xxqkdgZh76oD5$-!%7%vUUm9RA?GbJZj{Vp08W{F7#mGPxTG2-Oewr&K;`4fWDDYQ}k|=^aa39`tJt zUm$SPiB%@Ow_^0Ydn&(=e`8u5GVn&)%P~1G!;`C1)&$|j^q`1Rv3@VFHsK(1v{buf zehgt|W?&azI$l;PD(W1f-}_V9!?e>QCjav8(ZNrhpuxn^(wFOn6Fax5Uz*Rf`;F%0 z)#)XQZZ}Ci{a zZ{dB#qAm|Sp9+z3Ai{d?_?44s5S;>N(=*#2i)#i(VQEkzWwmqwYKeezrR}-MBCQFW ztDpj>Oljt8J+SN?c%d!p+I=18Tr%K|!GwxyuYdHOH?4BC31U<;O zjrO|9z~1_G<>x{#`Xvy7wVy0vvVa%5#pBVP!>!AyOAB(T{piisfA8r7OVFw*17WnL z=hP4@q-vsXJeiP-LBI9D1-PIPNC|o12%=CDeH?Hx+oou~-$|q2j*-I3mQRJE#Ts%c ztpNQl${(sw<@b}s1G_cZAso2`Q`#AeN#j zVT7l$p@Eh94m=TZ5jye=-!J4kGNH8k{qOhW>!j9ijiUd;nF{;cEf$OJ?=9%%*YolW? zd;$IX4=&+NT0hNcfOP5McF?gE#|i;2xn#Zbjj6?Po$fDdmF4$1Vj7(7jvcH~(D(cG zu1_!}kXIaET*y^bOq|RtN3t<*>nlo}ttGfxmgpT8{yh5@Gw^6UKztnh_aqn!GAh#f Il7{~O3l2&u4FCWD literal 0 HcmV?d00001 diff --git a/doc/connectivity/networking/api/images/lwm2m_lifetime_seconds_early.png b/doc/connectivity/networking/api/images/lwm2m_lifetime_seconds_early.png new file mode 100644 index 0000000000000000000000000000000000000000..119005ce5c7f0ea96030961a6f8c04cbf6ec4d11 GIT binary patch literal 14563 zcmeHu2UwF^wT$?!Eua+&eSR%rnpNA<6#MxAxkrulM^-xUr$mfqlpJ z(a_Kwfa_|R($LT$!1p4CJ>YME-@RGzLF;9zqd`;Ba$VQFyQfu4Ax{XeTtvaf?P;Qd&k_QeIs8 zteK=dL`EGdL;VAlfXYFww&?AgQSRFe5m7P%;o*j|MA_@3!M@tEGG`=YzW}9Akv!PyBpdS1wM384z5`0 zEt)PkEC#G-OG%xPkfi^$ZrXY!rM7-tr|*V zpzcmG($e-wOC6M*yt=Nr{uT|M;DOqraYXr`9l(at5E&RmQXMd+{*%$%RvP%>ZU+R~ zRHiY|gSgZd2lTe`&Y~q{^-xf0O+ybuf;q+r^xi$SVxo_VC?9( zE&LhDGh0j@30o^t(6ifzamMXzw7oBN0g3kCmPiUnOI3!mH`)>9wSDu}5*~|n!=pX^ zy6Av)cSkvFn{u0@9S(=}{VSOh)@}QE+cX~FOVSS;Z8o7H~5yhDWX(?q#Z zwY{Uq?R|hZ{g2=Kr#5hZ#>0Px9kAS{C)>GsZ|iYu!3$5=Q7p>cQJrcZpb&dIFO-&@ z7tpPSBly^iUTWyM;4yCCGW9EU-PjI~N8zY(0i=}#p{(JB$6;MjJ9Yt%u7SgPyE|?& z0Im+M+u`v4#x9%d+928iFDf07<*&cC{ZLA7hso~?TSq}T{>^dzp}S3W{>KLVhZ%KH zATi)^1aK(df4JC=hq?UbT{~+yl$#wM?ekX`wcGY|=Reu~HS+)NL%*+3bF48I4U!?q zb3iTNkW$p^R5R|xuH5$Tot?a}-Z%%;_FYuMf9-nzVoTYbE&jbNfkB;7`2UG5Wk62W z25D+XIsdV7wy8G*>|as-Ee>V2wC3{<=Ql+;qk*pin}M`WEe%d6Jepbzs7m`SCh#af z5cj|P{g#JoV%@MfU=(+(JFvM1sETg?v}EUocBV##0|;LfAk_dx1dj%3Onv(T2JPrb z4LuEC7c?G)^sob^K}O3LWNona*QjyAy5s-u?^K4U9naX3+{5la@9{g8LPqwlz9zHn zYrjQ=)S2zI-$P=DZpSBo_x}GLhx|`j8u~X&n;UDXo5B8OSey$MWA6`;NaE zekc3i0p0 zjA9Sv3B+Vei`~5`E$~9t>Hg1FU*%SnR)Uf9hcV^#CtnBGuXHag_7^=~p|}Qi`&(zO zR0aj4i@Nrd*toJYsL{}|T&1Dsr3txDU&xDi$MWY&bSe!wK9$w-PYPPilw|rXVp;~Z zr+aCMO?w3-LZ~-`-!yc(Y+gIeXc@lqUWKk+ZG`+uPlL8U_zzY*^wEMm(NzNV^mv2w z38LovW-l2pvG+&Qh=w6A(mhq@px$=~5D99UFt|NX;Ru7TlM)5ivmL~#UI~Z z%=~fO{lPKW%k*p0;uRmBmsAbyTX}7CRLcIkd9hWO|H|yl*!-=YD~s(q-E{%JsWQ&D zYrnid^RY~M`NIp_pjA|#YiZrSLdCxKJr{%PCR*>P{v4N>YReAYn0w75=k>*4<)hbF zOS$_%P4E2Z+nHN3Ee{?#y#C_$w!=sjb4O*(Wr)(AtD~4vm_!FopVi68i^x;i710?C z?`YTI!4zcpUmjvCvM7FJX-jxHTeo7XI23l$ZEbNPL}jCq&8W;UU7=bvNUuINfz)F5 z@cT%d(e#gn)-xL$Es9^K3q(e11kF=Q>Xxn6r%D^#-bC}2)XQNgAACOsItQ*Vm)rOb zbWtiWsSEO?p{4J`cWUQS_la##fPov>}Qde%v@?30b zVJv-&-&FKamRGBCj|3n|Vw3frG!r`9Tn-mP6s}+0bx;y>UZixqZe`G`&&=u*M2+Xl zw~%tTUb3>LHCl1{K`7f*S=a8WW%wgQg$aT6p~%y2zcyBUTf3J(o^JRtH2+Y5Z*4j= z_@}46V2s~Xab?gNF&zPg|yKD16hc)A=J+@8BIZCm~ zOCWEgPsEC`UIB)~FBNh(q#-NEOxFdSnxp1%X=N`9J>#$3J}UD{S%+M7FR{_PVPkng zw%+sS`7A7m(JKtRh`FP0jhD2TelZHAU2@J0tcV=cJy_-^Hcu3nEFFJ;8g`O>!$jbX z*dad5fy|90x{8w46~hbp-6Q1C)3~V841H?y zXW31si)7apxrQ-F>VRJP?r~VYdNk3xUoN%zHBay~kssNv+&qIGs3})o>G$d`v8ip$ zi(ufwz2Q6Rl~RVtD?Z5>F8~|Ln<1XOqeSkCF-$4LB%Z=Hi%+)a-ei*-l_4D*J%z|n z>cuFEFbk(b!!;pPovL)i1{nkAl!_e%o#xY}+2g z_}IDCN8UX44CHddLW^R>`fTlbtYEr+UVm1nZrtrX#>dN|{8mSk4%?*s@UXxOyP!=~ z&X>#~5LS0S;R~98gM_oFrRX_kiPfau9n3(gM01*ox7<-)PIgV4zgQNPKOSWnZx%TB z@^G!VGNx!^i2yk&cKD5$zr)n$n>>bM2>)D!yhemH;idkY41ni6Z-Q*`LWdDdN-!y3IQChe+j1dBZe|UlRG@AA^6@MJkz> z+78rxDLqLiAij11+rZ^No-L87i}gXjHRzeb&yBokzkmMmh5DF7@devq3kiMztgBsu;AdMda<}VgisWCOeoxGGG^DRUR>swwns#VBPiJPphiN@ zj&rn+x{--8(V#>Kt&ElT*m^ljiA)lEK9pmGR%5;iXNnM}v|lp|>%hZb`41alJ>ezz z>8p*R-n9sMb%oQqr62X5;x(%IEh*B-n0LbV#4*>mhKz4XG5MwSYt3BntSh261t)11 z4Vseajg~}0ti4ZLmA%2x7S50^=JLZkEz%A(EnQ&@&q%mph@7{~x)-Sa1xj$phM2be!kj+9KX#Nx?ij3^iTG;Fhvv5Gs32#*mjC4|-LywhFC8MF&(4j%^8;CZu z3XRU!(`*f;_8Mxu`{<+dg>RX@EMr9%9%)h9BIVbkK}U=~<;d<0(T}UgX_Q`@3PwgA zWJo)M%~&U!tK4K>$UQ|Hr1E_wB$($#wF)l+_TWyK#nCE|De`wocp;QjT7%StuY8J| zp*jC$??UKm%<9!qjUW}=!14B_OsAw!wNGR%qDWeU2-=;ci8oeVAT-m6e`ED4o)|@Y zUQfo&4mnm?`XGsVfszQ=q1s_l<^C9Rne7WLj3+;Xm7U26YXi;ihj6HGldw1g_Gvmv^?xoL0g){kZ$`h_)PwV;QM*ZQo3%YV3zvYIo*J97 z?lk_Mf>)t03HXWQI}0JKYAJM@aM;eCjdyAO3x&{%eY!Z&Q4HGP7&pbJKYo`_>-N*} z_S_lOU#oY#r$4j{8m1koUhcTW@S6Z?M25x5uD7;~ewU#yA5Dk{ zYclBP*zzT8Y6Jw(pk38PR{as)t@adXA(?@y1JUrO-{*#lL60m^(^>5`rX>cv{um24 zQ^*N0;^Z>`y@lxUwlxF?rz#O1vE_qKKORj>He=lN{3PF}P#W^cu0u&wPh*I9$`kzK zbH%VlvDN5xl6KUwDYGc(Zdj^6FUu)lwsRSsR4ehG40#!OxVAsfXNJ;y&m>pc_9j#+ zoR`HAnELGN8y3LSQYR%*&FqKmKx`-5cs$#EKHw(wrQ5d&LpR`950C08fT`ws!qccT zgDxkvZ#`gS6Z~LzlPmG@U0tN1)&(Fg-&LsjJ|FIVU`E&%LYX)MY8Q=p z?LFB^8X+{&0_)v0*`Lp>i z`SZrZ+|+)(cdV$Fo4F>ue(?!ULH zi&Wz!?ExaG3DR9zIpMX7ZVt@ZFC9)yfU~gR=#cpao&>`ee;jzsBvHld>e_p7-|8ju zlUR`36QYI=Khh+j{sc6lD0j6K z+`{la2D3e2aFo8cU_d>llU&dbzbQ(25nDk^x}s1rFT#MC;d&fk)8d&8HUzy6HH7*~ z6o+rg7?hS5fzmAf9WR3eR)2Hg=z%|I=!di~y^P>6OuO7uGLvJd`Nw`wn-h|k)cR}m zf_Yicz^{on@4Nzq$&#4uF&&0M@w{`jD1X=g~4*(5NT5%3NASdiK^Xun|YDdx@)#VQk z%e~H-y@}TD6S414*MGNH{PuL$+Y7ZlwgJ6h#>RYovT%Fm!Ha_^m4(>Ov6gh#y(c`b zDlfc~@fpv)nOL0fYz+HVuZ2V_AHR)2s?p>y#En7CRhdYz7gf%C;Q6>6BC7f}$j z2a{&yQ5mNXtU4ziwiMehfV-1RkiFQ3jp>(%FP`#BuY#hORTT#dq_> z&^c$(BwK&d0Kf`RD&19`#nwG?eQq-AlSQR&xlwYW3)Qcc%MBmizt~W(IAw72mA|TG z?My}LOx5u1WzbtDRl@=Y0#^nGNI&$GB+7#~rY@pXdRk}d*Jr1KECvHtZ2IgY#Sdkk zMAZM08A&z&h>_Z_tFGB9YvZ|?%)n)-4F@Icpi-)GKt&u8U`pNQlkm7kL36*wYR>ma zBW2lk8u17#kFqx;_ohE4yBLRSW<&OJ>z+CRrY;iKm2c0M0W4GXI15;ndHv`5*O?d{ zZciLh?t*uhd3X&30R~-<72SwfeL*z&dFe~|D409FublyCKwrSux*6aIvf=T~@9xUj z1e7OxkGDM&e;WJv*LuS*uPXu$gV&NGmjOoLs`~54<648rRoR{k4nk=j*Vx!g(?HKl z1=9j1Nd?mYlEPm+pPS27_B0~0{+0F&M>hyM+7#;8njqZER@L#US}-lp_5{py_jUrz{Sc+1 znS$GJoR_C&cN|OGP~OK&Myeb5<1$VLcaOCwuUx2PxXjmueV747^DWVz>^R9G9(!Ux zw^G%u>G3rHfTaY5W`77A?)#pRRh$g)m%u&~+#+al&N_es zdja5dLF=8^U1C$D5~T9{7-C`&%uIvqFjEsp9Si~BRL!UAsc@6`1Ub(@ab8{GcEkzv zoIWR8SN3kd9vfe8Rw40gO);^cu(vN+n+ONqeUx(|NRL2-OW&8$l?dKgN&-O6yQozF zt|deROyfzYVck@h3j7|?n6+ete^p_&YB&w5Ymos|P-c?rmWEquVon-y?L5dhAy)ci zXx$c`xN&wFK)r2uKW=cW3YR65*L*qGIyM;~WI@RWR*gl5BiDahbC- z=ESBI4;&v*BJD5w#XI#CM`QE&2((YeG6MSLA~+|n5aCP({HLt6kh#)DmZd(dOyXIG ziV8A=D6muP@OGc`m)moScWXTVjDf&YD*D_NS8jpy^d56j*eW;n4s^o5i#qWo=Nu6o zTt$*1>nYjeY6XVr%~}yZ$Ss1q0BV{Sbwuhprkog;!>szF4Q7E)_r2#*GWO-rEqtHX z1QFgEqvm>rU3{Tpj0}$}F~1J8PQ7?#?ndM(0<1sr^u^g6<6}nQkBGA6*UzUwTLmg3 zwDp`gP^QE}lU(g^_mLq96Sm{0$%*mCaW%!2q*l@4%V1m*W!P?`X#k?w{2fgbwrL~ME!WZ z0qd!9gnfay;-~_FOzb}bQ!i7VYtv*-&`&8_5~BUS+=sQ{Da#W!F@x%|o`rFi8FN@Y zYPy=kOzHOjeB-dRineuV#JmXImx2+iCkruxu-j#R`q#YRas0Y7lyZHoLtPdy`tosC zYrPAyr=gkbQtcPu5kfFstb zkW_)&4JeQoKZP<2;^x@xVw3fiI0Cy8tA1KSlAseQIy`}$8yeYRML{ZE?x#&tOFrwy zeLVWqo7x)83uL`CmSMz!vhPN4x{OAwCJ5Fsj*W7n`~wW9pNw17 zRE~9WVoLS0ATJ{%6LnI|Ds$8_qDi*!9DZktEkYuQAE9@z=PexxwqUf-hK+&3Kb55? zmk2k!4|q%tU_uUmd_wT@t)`yt+w+%_!^&+h#+U09_j%3ChjU{$s_;@tMyIxz-Xz+_2CU;y0VXHf_41G;)gMw zA__4j!ld)oJpQ?}vHB7Z6=$nnU|KQY!4A5V2kH{7uaI~IE*X0gQKPPNOjt)d=0KCV z3Yob3oHZnt6|;ek>F`OrZL2F0%K~u}BiMvjuO_-lXWg(hVW@kVL=s*rkkdP{!4A)u z?COroVJGE*rgZl1Ax91@Q_I`Cv8Uj8_CVxfyI3_59@u6bHRzQfneKl|3ug`WX`&m^ zNs;Et{d7}*UUpUB+LW`}>0LxI3bzGagI*0oW>7|anYi3qzoNZH&w7HOO%b6~3LfYH zEl21g>t#ZwsA=LmZx&_`1~cL9g3-+5tmBqoZ1)Dr@-D;lb$5}5=}g(4m0yLreQ1NU zUS^%+JP+eD1WyyZDOng+@l#fx%9THhbH_?xS_!b&e4j~g56te>C{U(MHJ((Au`jh< zOZ<^a^eWYLS1nWQn7-#yy*NZ!Le1`)NusD`b|K6 zukPebvEwt7jF=o&Jr(m7BNg%pmwXoed5EXbVOZv(ua#RF1DZC;QRJ{TmLARYPHfE} ze5m=fp2{6TSu%0T+b^G!7naLjK7SIS$8C9had%_j+M?&)^LkdDdtjGhnIDU#l5S^r$H(A}=L%)Pj# zCqHT(V_+%s8}K22YNwx|s}@cIk1>+0Kg8=6zciO;vszrtzirFfb1iYoL*H8+UN@NP z9lP(eM1rR>6wO0gL7;f{c==!CmTaE@}qr#N}A7c@F%#uF1 zOc`0H+Gi0RV5iw%Mn8amo8P$RINByGogx5QV-GBMC@6db8lvw6Uv!6-V z;lq&j&S$xo8-!Ty=7cFsn^a$jJp_ZA|IkHNyb$N8Yp&o*R&uXCSZPKy7xJ4@fJH2N z#gvRY>$K~IH&l4aq&G?!Dm+pfCb^b(-S=!eEvC@TSMKtpZrAyxqkUehKRZ3CpcRlcpM26b}2yAxVm;GqI zcI+oTXcAGFk^|EykS$n0me4sP&m5T)5If^))~StQ)w?a=Pm;IMqp=)8L^jNal~tiX zcec~72BnAhlw1G~R2Dt?W*1|8MNb(-KwhM^=bm3{mql)cc)~CdBbc5}JRyW(6l|Ey zEQLahG{Y-iX|hVe_S7xh6*$wpi)`&TQBTowzDT;GAg5uX-9V0?(cwiNw5$oh)hP=R zl1{nmBVN<{6$}@2kHVtMx=yXOEHB9p&e1j>?zDJBY*HMTE+6c4*d3jJ_19dk!p>-@ zmr4`Kt?oy2(G+zbke-RjyTBnv-J{vwKn%i= zZ}vuiQO^SJEFfvWRRLuPi_-<&VDuC%Ca7ce!Bbl^1qXx?!1m}EM#KO)?SpC#IzE7+ z+`wOQ;RGt@rW@rDY!p#)(ADQ(nA%79X(b2c58GP%aZRcwK;yqNpPTVR|~ies@G%GZ6ADi*TYOpP^?m z*J5@&&`F-s+9Cj=&fQdd2!ymJtMk?X8;sxP62A$s8bMzo z3urJ^4aUSa#6G*KHpLr#n}*!@1bB;Hh8l{IZOCjM$xOovY!7pL>LLLSbSk8o6CCKn z98r#e9UwDi1~r`rsAf<*2PEIO1kLtj(WQdg`+-Zq4>6;Xz10Z*y{N^E0gs0HNNsnSpeI=5D-z2J!ClPnzI=z3Up@~{gF zFPS~cGbaJC4x!Hx1PTw?)iT2(44yHO7>r4WfH@C`+}j5ZQ$o;k1&G%si*syYHGu8I zj10VlJ_?Y+F;i!6p8P~3NLLOkb97bSuP(8+)HV&E|chZu>Q6B z{hpPEH{67Im}|ZB@qqOxm=DEsZ>3IzJtP$XJO76MI39&fU0Ewwo@Z*cnjZrLN&$l4ckRIO4?WzOb#E%Loo78inqYh@ZBk_` z!2tML`{UB3qe^jtgAPcZbQfj=g52DSm$NFmhk4rBsG&+gOs`SIO(tqN{t!@Zymo56 zMwS)>u`gDv6v}wM!~b|6vB35bDl_1RL@8e9gT+5~HVyVaLHJ-wOS8 z=JM`g46Mc7DDQimt*qi2BioBQ6L6U#aJ+5hO2E&k z*86L(Qme)|kD=#}HGG6y0v^+g{~W+fE8?oMtDzU*~uS=?gbJ(FdjX!SK{*YtH{ ziyr>lm*aaVaY&wr1!Jc@u_GME&>G1RXMFD+rRxPz{*D=7r-}6B@Q#&_#bwz&7cQTE zmyT*EU3)*umEK#PvHWF2;}(GUoX#IUz(qq2g%zIVGYB!$@*tA!x!DM# z+7gSf5TH)`RCNG6AeRey5CJ5aA;6}F5deH%`A$~cMD`zqvpsLb-%zUpnf)_2j}@3B z+3%{IYh<(&omWFD)6;gP&IWiVy?3;2#+y;k%aT^!jRC@{zb2Y@23(#WdI3VEcWn+xRrxD=n=-Y~Qpq7hz z79F&+UsLBz0i-Usj~9cr2!pJ1;Dn?%yL7-=_`zAiJV?hj&yw|$(Jo^7O4bs!2JG5= zsC9|TAVr;b4KNtL!>0_Y3t-R&)NeLIo8!-5#sU~zQ(HI!PEDb27NZLBI=x$y7d#DY zyh80 client.lifetime) { + early = client.lifetime; + } + + next = MIN(period, client.lifetime - early); + next = MAX(next, MINIMUM_PERIOD); + + return client.last_update + next * MSEC_PER_SEC; } static int64_t next_rx_off(void) diff --git a/tests/net/lib/lwm2m/interop/prj.conf b/tests/net/lib/lwm2m/interop/prj.conf index 5d255e0513e..66d6334264f 100644 --- a/tests/net/lib/lwm2m/interop/prj.conf +++ b/tests/net/lib/lwm2m/interop/prj.conf @@ -61,6 +61,8 @@ CONFIG_COAP_EXTENDED_OPTIONS_LEN_VALUE=40 # Use QUEUE mode by default CONFIG_LWM2M_QUEUE_MODE_ENABLED=y CONFIG_LWM2M_QUEUE_MODE_UPTIME=20 +CONFIG_LWM2M_UPDATE_PERIOD=30 +CONFIG_LWM2M_SECONDS_TO_UPDATE_EARLY=10 # LwM2M configuration as OMA-ETS-LightweightM2M_INT-V1_1-20190912-D Configuration 3 CONFIG_LWM2M_ENGINE_DEFAULT_LIFETIME=30 diff --git a/tests/net/lib/lwm2m/lwm2m_rd_client/CMakeLists.txt b/tests/net/lib/lwm2m/lwm2m_rd_client/CMakeLists.txt index 81e129c56c1..2a8e8959c25 100644 --- a/tests/net/lib/lwm2m/lwm2m_rd_client/CMakeLists.txt +++ b/tests/net/lib/lwm2m/lwm2m_rd_client/CMakeLists.txt @@ -32,3 +32,4 @@ add_compile_definitions(CONFIG_LWM2M_QUEUE_MODE_ENABLED=1) add_compile_definitions(CONFIG_LWM2M_TLS_SESSION_CACHING=1) add_compile_definitions(CONFIG_LWM2M_RD_CLIENT_LISTEN_AT_IDLE=1) add_compile_definitions(CONFIG_LWM2M_RD_CLIENT_SUPPORT_BOOTSTRAP=1) +add_compile_definitions(CONFIG_LWM2M_UPDATE_PERIOD=0) From 1907327297f59993d41f2f7f5af50968b0316289 Mon Sep 17 00:00:00 2001 From: Robert Lubos Date: Fri, 1 Sep 2023 09:25:27 +0200 Subject: [PATCH 111/421] [nrf fromtree] net: tcp: Fix goto condition in case of RST/packet error In case RST packet is received or malformed packet is received, the TCP should not proceed with the state machine execution (which may process the invalid packet) but rather jump directly to exit, where the connection will be closed. Signed-off-by: Robert Lubos (cherry picked from commit 370096e4f5b3dc9c9565b0d9322e94c58803a9d3) (cherry picked from commit 100d814995d1a1ac34e78e03572b4b09026304b9) --- subsys/net/ip/tcp.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/subsys/net/ip/tcp.c b/subsys/net/ip/tcp.c index c90f7b92c20..ad9cd1e4c98 100644 --- a/subsys/net/ip/tcp.c +++ b/subsys/net/ip/tcp.c @@ -2276,7 +2276,7 @@ static enum net_verdict tcp_in(struct tcp *conn, struct net_pkt *pkt) tcp_out(conn, RST); do_close = true; close_status = -ECONNRESET; - goto next_state; + goto out; } if (FL(&fl, &, RST)) { @@ -2292,7 +2292,7 @@ static enum net_verdict tcp_in(struct tcp *conn, struct net_pkt *pkt) net_stats_update_tcp_seg_rst(net_pkt_iface(pkt)); do_close = true; close_status = -ECONNRESET; - goto next_state; + goto out; } if (tcp_options_len && !tcp_options_check(&conn->recv_options, pkt, @@ -2301,7 +2301,7 @@ static enum net_verdict tcp_in(struct tcp *conn, struct net_pkt *pkt) tcp_out(conn, RST); do_close = true; close_status = -ECONNRESET; - goto next_state; + goto out; } if (th && (conn->state != TCP_LISTEN) && (conn->state != TCP_SYN_SENT) && @@ -2316,7 +2316,7 @@ static enum net_verdict tcp_in(struct tcp *conn, struct net_pkt *pkt) tcp_out(conn, RST); do_close = true; close_status = -ECONNRESET; - goto next_state; + goto out; } if (th) { @@ -2904,6 +2904,7 @@ static enum net_verdict tcp_in(struct tcp *conn, struct net_pkt *pkt) tcp_state_to_str(conn->state, true)); } +out: if (pkt) { if (verdict == NET_OK) { net_pkt_unref(pkt); From 355032b839e85838fdd50baee5b645fb038c5068 Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Fri, 29 Sep 2023 19:07:12 +0200 Subject: [PATCH 112/421] [nrf fromtree] Bluetooth: Controller: Fix num cmplt for BIS HCI ISO Data fragments Fix number of completed packets generated when BIS HCI ISO Data packets sent to Controller are in fragments. Use the ISOAL stored sdu_fragment count to generate the number of completed packets count. Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit 48c83a1f4268e539afa03abe2ecaed43a0650b7e) (cherry picked from commit 31a885296ae3ac4e38bb13f679440ec99977baaa) --- subsys/bluetooth/controller/ll_sw/ull.c | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/subsys/bluetooth/controller/ll_sw/ull.c b/subsys/bluetooth/controller/ll_sw/ull.c index 2f325f1a86b..6be8bc4759e 100644 --- a/subsys/bluetooth/controller/ll_sw/ull.c +++ b/subsys/bluetooth/controller/ll_sw/ull.c @@ -2582,18 +2582,10 @@ static uint8_t tx_cmplt_get(uint16_t *handle, uint8_t *first, uint8_t last) /* We must count each SDU HCI fragment */ tx_node = tx->node; if (IS_NODE_TX_PTR(tx_node)) { - if (IS_ADV_ISO_HANDLE(tx->handle)) { - /* FIXME: ADV_ISO shall be updated to - * use ISOAL for TX. Until then, assume - * 1 node equals 1 fragment. - */ - sdu_fragments = 1U; - } else { - /* We count each SDU fragment completed - * by this PDU. - */ - sdu_fragments = tx_node->sdu_fragments; - } + /* We count each SDU fragment completed + * by this PDU. + */ + sdu_fragments = tx_node->sdu_fragments; /* Replace node reference with fragments * count From 865d0bb25b68360e203d68069c2f964041944a12 Mon Sep 17 00:00:00 2001 From: Ivan Iushkov Date: Thu, 28 Sep 2023 16:21:14 +0200 Subject: [PATCH 113/421] [nrf fromtree] Bluetooth: fix HCI ISO Data packets fragmentation this commit partially reverts e460847b6083c0bc57bd63f63bc13c756207c2c9 According to Core Spec 5.4, Vol. 4, Part E, 5.4.5, Data_Total_Length field contains length of the whole packet including optional fields of SDU (Time_Stamp, Packet_Sequence_Number, ISO_SDU_Length, RFU and Packet_Status_Flag). In Zephyr Host, Data_Total_Length value is stored in bt_dev.le.iso_mtu field. Therefore, there is no need to calculate iso_hdr_len(), this length is already taken into account in conn_mtu(conn). This commits removes iso_hdr_len() function and fixes calculation of HCI ISO Data packet length calculations. Signed-off-by: Ivan Iushkov (cherry picked from commit 4f5323a1cf5eab0182166ece2079ad8f0bb94efd) (cherry picked from commit 64826a0ac9a5d32ffede7d6c906485c523e174ba) --- subsys/bluetooth/host/conn.c | 26 ++------------------------ 1 file changed, 2 insertions(+), 24 deletions(-) diff --git a/subsys/bluetooth/host/conn.c b/subsys/bluetooth/host/conn.c index 5e69c8006c9..f56db35e837 100644 --- a/subsys/bluetooth/host/conn.c +++ b/subsys/bluetooth/host/conn.c @@ -655,21 +655,6 @@ static int do_send_frag(struct bt_conn *conn, struct net_buf *buf, uint8_t flags return err; } -static size_t iso_hdr_len(struct net_buf *buf, struct bt_conn *conn) -{ -#if defined(CONFIG_BT_ISO) - if (conn->type == BT_CONN_TYPE_ISO) { - if (tx_data(buf)->iso_has_ts) { - return BT_HCI_ISO_TS_DATA_HDR_SIZE; - } else { - return BT_HCI_ISO_DATA_HDR_SIZE; - } - } -#endif - - return 0; -} - static int send_frag(struct bt_conn *conn, struct net_buf *buf, struct net_buf *frag, uint8_t flags) @@ -682,9 +667,7 @@ static int send_frag(struct bt_conn *conn, /* Add the data to the buffer */ if (frag) { - size_t iso_hdr = flags == FRAG_START ? iso_hdr_len(buf, conn) : 0; - uint16_t frag_len = MIN(conn_mtu(conn) + iso_hdr, - net_buf_tailroom(frag)); + uint16_t frag_len = MIN(conn_mtu(conn), net_buf_tailroom(frag)); net_buf_add_mem(frag, buf->data, frag_len); net_buf_pull(buf, frag_len); @@ -732,11 +715,6 @@ static struct net_buf *create_frag(struct bt_conn *conn, struct net_buf *buf) return frag; } -static bool fits_single_ctlr_buf(struct net_buf *buf, struct bt_conn *conn) -{ - return buf->len - iso_hdr_len(buf, conn) <= conn_mtu(conn); -} - static int send_buf(struct bt_conn *conn, struct net_buf *buf) { struct net_buf *frag; @@ -746,7 +724,7 @@ static int send_buf(struct bt_conn *conn, struct net_buf *buf) LOG_DBG("conn %p buf %p len %u", conn, buf, buf->len); /* Send directly if the packet fits the ACL MTU */ - if (fits_single_ctlr_buf(buf, conn) && !tx_data(buf)->is_cont) { + if (buf->len <= conn_mtu(conn) && !tx_data(buf)->is_cont) { LOG_DBG("send single"); return send_frag(conn, buf, NULL, FRAG_SINGLE); } From f70cd160196e6e346321bb88243743eeb1c807a1 Mon Sep 17 00:00:00 2001 From: Ivan Iushkov Date: Thu, 28 Sep 2023 16:34:46 +0200 Subject: [PATCH 114/421] [nrf fromtree] Bluetooth: fix iso_has_ts field for SDU fragmented to multiple HCI packets iso_has_ts wasn't set correcrly for fragments of HCI ISO Data packets, now it is set depending on timestamp provided in the original buffer provided by host user Signed-off-by: Ivan Iushkov (cherry picked from commit a4a196f0027b11a5debd9025fb0ba8099ea6a3c0) (cherry picked from commit 0905dee30850bb16898006977957d5fbb4614962) --- subsys/bluetooth/host/conn.c | 1 + 1 file changed, 1 insertion(+) diff --git a/subsys/bluetooth/host/conn.c b/subsys/bluetooth/host/conn.c index f56db35e837..155b1a041a0 100644 --- a/subsys/bluetooth/host/conn.c +++ b/subsys/bluetooth/host/conn.c @@ -711,6 +711,7 @@ static struct net_buf *create_frag(struct bt_conn *conn, struct net_buf *buf) /* Fragments never have a TX completion callback */ tx_data(frag)->tx = NULL; tx_data(frag)->is_cont = false; + tx_data(frag)->iso_has_ts = tx_data(buf)->iso_has_ts; return frag; } From a977ac68d2b32f2c1c326c82467a6b3bf0d5882f Mon Sep 17 00:00:00 2001 From: Ivan Iushkov Date: Fri, 29 Sep 2023 12:08:10 +0200 Subject: [PATCH 115/421] [nrf fromtree] Bluetooth: documentation change of kconfig.iso configs Added comment to KConfig.iso file to make description of BT_ISO_TX_MTU and BT_ISO_RX_MTU more clear Signed-off-by: Ivan Iushkov (cherry picked from commit c650f6aea0bc5e6c4fcacb521435b1673553f221) (cherry picked from commit 328411d85839340607fe033fa4de4f59cb2eb038) --- subsys/bluetooth/Kconfig.iso | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/subsys/bluetooth/Kconfig.iso b/subsys/bluetooth/Kconfig.iso index 553ff3a7fb4..304c408f42f 100644 --- a/subsys/bluetooth/Kconfig.iso +++ b/subsys/bluetooth/Kconfig.iso @@ -99,6 +99,10 @@ config BT_ISO_TX_MTU range 1 4095 help Maximum MTU for Isochronous channels TX buffers. + This is the actual data payload. It doesn't include the optional + HCI ISO Data packet fields (e.g. `struct bt_hci_iso_ts_data_hdr`). + Set this value to 247 to fit 247 bytes of data within a single + HCI ISO Data packet with a size of 255, without utilizing timestamps. config BT_ISO_RX_BUF_COUNT int "Number of Isochronous RX buffers" @@ -113,6 +117,8 @@ config BT_ISO_RX_MTU range 23 4095 help Maximum MTU for Isochronous channels RX buffers. + This is the actual data payload. It doesn't include the optional + HCI ISO Data packet fields (e.g. `struct bt_hci_iso_ts_data_hdr`) config BT_ISO_ADVANCED bool "Advanced ISO parameters" From 59c0a7cb2c0dcdeea2794ee389e37a1b0e9da1be Mon Sep 17 00:00:00 2001 From: Damian Krolik Date: Mon, 25 Sep 2023 16:41:15 +0200 Subject: [PATCH 116/421] [nrf noup] settings: nvs: use dedicated lookup cache hash function Introduce NVS_LOOKUP_CACHE_FOR_SETTINGS Kconfig option that enables a dedicated hash function for the NVS lookup cache that takes advantage of the NVS ID allocation scheme used by the NVS settings backend. As such, this option should only be used if an application uses NVS via the settings layer. Signed-off-by: Damian Krolik (cherry picked from commit 72fbc3cde4f3dfabdaa80cd7bf78943ea174ca86) --- subsys/fs/nvs/Kconfig | 9 +++++++++ subsys/fs/nvs/nvs.c | 46 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+) diff --git a/subsys/fs/nvs/Kconfig b/subsys/fs/nvs/Kconfig index de4f282ee98..df0329a7c41 100644 --- a/subsys/fs/nvs/Kconfig +++ b/subsys/fs/nvs/Kconfig @@ -27,6 +27,15 @@ config NVS_LOOKUP_CACHE_SIZE Number of entries in Non-volatile Storage lookup cache. It is recommended that it be a power of 2. +config NVS_LOOKUP_CACHE_FOR_SETTINGS + bool "Non-volatile Storage lookup cache optimized for settings" + depends on NVS_LOOKUP_CACHE + help + Use the lookup cache hash function that results in the least number of + collissions and, in turn, the best NVS performance provided that the NVS + is used as the settings backend only. This option should NOT be enabled + if the NVS is also written to directly, outside the settings layer. + module = NVS module-str = nvs source "subsys/logging/Kconfig.template.log_config" diff --git a/subsys/fs/nvs/nvs.c b/subsys/fs/nvs/nvs.c index 8c4575700a8..14a4db5e347 100644 --- a/subsys/fs/nvs/nvs.c +++ b/subsys/fs/nvs/nvs.c @@ -13,6 +13,11 @@ #include #include "nvs_priv.h" +#ifdef CONFIG_NVS_LOOKUP_CACHE_FOR_SETTINGS +#include +#include +#endif + #include LOG_MODULE_REGISTER(fs_nvs, CONFIG_NVS_LOG_LEVEL); @@ -21,6 +26,45 @@ static int nvs_ate_valid(struct nvs_fs *fs, const struct nvs_ate *entry); #ifdef CONFIG_NVS_LOOKUP_CACHE +#ifdef CONFIG_NVS_LOOKUP_CACHE_FOR_SETTINGS + +static inline size_t nvs_lookup_cache_pos(uint16_t id) +{ + /* + * 1. The NVS settings backend uses up to (NVS_NAME_ID_OFFSET - 1) NVS IDs to + store keys and equal number of NVS IDs to store values. + * 2. For each key-value pair, the value is stored at NVS ID greater by exactly + * NVS_NAME_ID_OFFSET than NVS ID that holds the key. + * 3. The backend tries to minimize the range of NVS IDs used to store keys. + * That is, NVS IDs are allocated sequentially, and freed NVS IDs are reused + * before allocating new ones. + * + * Therefore, to assure the least number of collisions in the lookup cache, + * the least significant bit of the hash indicates whether the given NVS ID + * represents a key or a value, and remaining bits of the hash are set to + * the ordinal number of the key-value pair. Consequently, the hash function + * provides the following mapping: + * + * 1st settings key => hash 0 + * 1st settings value => hash 1 + * 2nd settings key => hash 2 + * 2nd settings value => hash 3 + * ... + */ + BUILD_ASSERT(IS_POWER_OF_TWO(NVS_NAMECNT_ID), "NVS_NAMECNT_ID is not power of 2"); + BUILD_ASSERT(IS_POWER_OF_TWO(NVS_NAME_ID_OFFSET), "NVS_NAME_ID_OFFSET is not power of 2"); + + uint16_t key_value_bit; + uint16_t key_value_ord; + + key_value_bit = (id >> LOG2(NVS_NAME_ID_OFFSET)) & 1; + key_value_ord = id & (NVS_NAME_ID_OFFSET - 1); + + return ((key_value_ord << 1) | key_value_bit) % CONFIG_NVS_LOOKUP_CACHE_SIZE; +} + +#else /* CONFIG_NVS_LOOKUP_CACHE_FOR_SETTINGS */ + static inline size_t nvs_lookup_cache_pos(uint16_t id) { uint16_t hash; @@ -36,6 +80,8 @@ static inline size_t nvs_lookup_cache_pos(uint16_t id) return hash % CONFIG_NVS_LOOKUP_CACHE_SIZE; } +#endif /* CONFIG_NVS_LOOKUP_CACHE_FOR_SETTINGS */ + static int nvs_lookup_cache_rebuild(struct nvs_fs *fs) { int rc; From 020dcdc2ab9118bf2960ef1feb396b79e6924b77 Mon Sep 17 00:00:00 2001 From: Grzegorz Swiderski Date: Mon, 25 Sep 2023 12:45:10 +0200 Subject: [PATCH 117/421] [nrf fromtree] sysbuild: Do not exclude images from domains.yaml The recent support for BUILD_ONLY images was implemented by excluding them from `domains.yaml`, in order to crudely prevent them from being picked up by `west flash`. Arguably, this is incorrect or unexpected, because the sysbuild documentation defines a "domain" as: Every Zephyr CMake build system managed by sysbuild. Another consequence is that, given a build-only ``, this makes it impossible to pass `--domain ` to `west flash`, `west debug`, and ironically `west build`. To fix that, `domains.yaml` should again represent all domains, and the build-only ones should be indicated in another way. Enter `flash_order`: a new top-level key in the domains YAML schema. It contains the default sequence of images used by `west flash`, where the build-only images are excluded, and the order is influenced by `sysbuild_add_dependencies()`. Signed-off-by: Grzegorz Swiderski (cherry picked from commit 05d77690736b5ad022ee1d0f7dc9b4fea2bd2c24) (cherry picked from commit 92164b7c7793a9fda801319fb0e862016114d51f) --- scripts/pylib/build_helpers/domains.py | 43 +++++++++++++------------- scripts/west_commands/build_helpers.py | 3 +- scripts/west_commands/flash.py | 3 +- share/sysbuild/cmake/domains.cmake | 11 ++++--- 4 files changed, 31 insertions(+), 29 deletions(-) diff --git a/scripts/pylib/build_helpers/domains.py b/scripts/pylib/build_helpers/domains.py index c748a94a14f..8cacac7b4e8 100644 --- a/scripts/pylib/build_helpers/domains.py +++ b/scripts/pylib/build_helpers/domains.py @@ -38,6 +38,11 @@ build_dir: required: true type: str + flash_order: + required: false + type: seq + sequence: + - type: str ''' schema = yaml.safe_load(DOMAINS_SCHEMA) @@ -52,21 +57,19 @@ class Domains: def __init__(self, data): - self._domains = [] - self._domain_names = [] - self._domain_default = [] - self._build_dir = data.get('build_dir') - domain_list = data.get('domains') + domain_list = data.get('domains') or [] if not domain_list: logger.warning("no domains defined; this probably won't work") - for d in domain_list: - domain = Domain(d['name'], d['build_dir']) - self._domains.append(domain) - self._domain_names.append(domain.name) - if domain.name == data['default']: - self._default_domain = domain + self._domains = { + d['name']: Domain(d['name'], d['build_dir']) + for d in domain_list + } + self._default_domain = self._domains.get(data['default']) + + domains_flash_order = data.get('flash_order') or [] + self._flash_order = list(map(self._domains.get, domains_flash_order)) @staticmethod def from_file(domains_file): @@ -97,25 +100,21 @@ def from_data(domains_data): ''' return Domains(domains_data) - def get_domains(self, names=None): + def get_domains(self, names=None, default_flash_order=False): ret = [] if not names: - return self._domains + if default_flash_order: + return self._flash_order + return list(self._domains.values()) for n in names: - found = False - for d in self._domains: - if n == d.name: - ret.append(d) - found = True - break - # Getting here means the domain was not found. - # Todo: throw an error. + found = self._domains.get(n) if not found: logger.critical(f'domain {n} not found, ' - f'valid domains are:', *self._domain_names) + f'valid domains are: {", ".join(self._domains)}') exit(1) + ret.append(found) return ret def get_default_domain(self): diff --git a/scripts/west_commands/build_helpers.py b/scripts/west_commands/build_helpers.py index e4352ff1f28..88845e50f4b 100644 --- a/scripts/west_commands/build_helpers.py +++ b/scripts/west_commands/build_helpers.py @@ -153,6 +153,7 @@ def load_domains(path): if not domains_file.is_file(): return Domains.from_data({'default': 'app', 'build_dir': path, - 'domains': [{'name': 'app', 'build_dir': path}]}) + 'domains': [{'name': 'app', 'build_dir': path}], + 'flash_order': ['app']}) return Domains.from_file(domains_file) diff --git a/scripts/west_commands/flash.py b/scripts/west_commands/flash.py index 073a1ab2a28..4f173535be8 100644 --- a/scripts/west_commands/flash.py +++ b/scripts/west_commands/flash.py @@ -28,5 +28,6 @@ def do_add_parser(self, parser_adder): def do_run(self, my_args, runner_args): build_dir = get_build_dir(my_args) - domains = load_domains(build_dir).get_domains(my_args.domain) + domains = load_domains(build_dir).get_domains(my_args.domain, + default_flash_order=True) do_run_common(self, my_args, runner_args, domains=domains) diff --git a/share/sysbuild/cmake/domains.cmake b/share/sysbuild/cmake/domains.cmake index c46d261aff2..1d197059bf1 100644 --- a/share/sysbuild/cmake/domains.cmake +++ b/share/sysbuild/cmake/domains.cmake @@ -7,12 +7,13 @@ sysbuild_images_order(IMAGES_FLASHING_ORDER FLASH IMAGES ${IMAGES}) set(domains_yaml "default: ${DEFAULT_IMAGE}") set(domains_yaml "${domains_yaml}\nbuild_dir: ${CMAKE_BINARY_DIR}") set(domains_yaml "${domains_yaml}\ndomains:") -foreach(image ${IMAGES_FLASHING_ORDER}) - get_target_property(image_is_build_only ${image} BUILD_ONLY) - if(image_is_build_only) - continue() - endif() +foreach(image ${IMAGES}) set(domains_yaml "${domains_yaml}\n - name: ${image}") set(domains_yaml "${domains_yaml}\n build_dir: $") endforeach() +set(domains_yaml "${domains_yaml}\nflash_order:") +foreach(image ${IMAGES_FLASHING_ORDER}) + set(flash_cond "$>>") + set(domains_yaml "${domains_yaml}$<${flash_cond}:\n - ${image}>") +endforeach() file(GENERATE OUTPUT ${CMAKE_BINARY_DIR}/domains.yaml CONTENT "${domains_yaml}") From 49df79f70077cc7a69125e7c9812c2764c24a501 Mon Sep 17 00:00:00 2001 From: Grzegorz Swiderski Date: Mon, 25 Sep 2023 12:45:24 +0200 Subject: [PATCH 118/421] [nrf fromtree] doc: sysbuild: Update documentation about BUILD_ONLY It is now possible to `west flash` or `west debug` a build-only image. Signed-off-by: Grzegorz Swiderski (cherry picked from commit 8b273a45a678a62bcf3fa7e90cdb4c8faddf4553) (cherry picked from commit ec4ee96d4703e002e9c79cc2ab7fb3edeef1ac65) --- doc/build/sysbuild/index.rst | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/doc/build/sysbuild/index.rst b/doc/build/sysbuild/index.rst index 2c53cb0e88a..e09ee3e5617 100644 --- a/doc/build/sysbuild/index.rst +++ b/doc/build/sysbuild/index.rst @@ -569,13 +569,19 @@ You can mark ``my_sample`` as a build-only application in this manner: ) As a result, ``my_sample`` will be built as part of the sysbuild build invocation, -but neither ``west flash`` nor ``west debug`` will be aware of this application. +but it will be excluded from the default image sequence used by ``west flash``. Instead, you may use the outputs of this domain for other purposes - for example, to produce a secondary image for DFU, or to merge multiple images together. You can also replace ``TRUE`` with another boolean constant in CMake, such as a Kconfig option, which would make ``my_sample`` conditionally build-only. +.. note:: + + Applications marked as build-only can still be flashed manually, using + ``west flash --domain my_sample``. As such, the ``BUILD_ONLY`` option only + controls the default behavior of ``west flash``. + Zephyr application configuration ================================ From 6df09b137cd799e5fdc1ef2371a70609f175e8c4 Mon Sep 17 00:00:00 2001 From: Grzegorz Swiderski Date: Thu, 28 Sep 2023 09:36:01 +0200 Subject: [PATCH 119/421] [nrf fromtree] scripts: domains: Tighten up initialization Do extra checks to reject inconsistent `domains.yaml` contents early: default: app build_dir: /path/to/build domains: - name: image_1 build_dir: /path/to/build/image_1 - name: image_2 build_dir: /path/to/build/image_2 flash_order: - image_1 - image_2 - unknown This example lists "image_1" and "image_2" as known domains, but an entry for the default "app" is missing, which should never be allowed. A valid `domains.yaml` file shall also not contain extra domains under `flash_order`, such as "unknown", which doesn't appear under `domains`. Either of these cases can now be caught while initializing an instance of the Domains class. It follows that a valid `domains.yaml` file must always contain a list of domains with at least one entry - the default image. Since `default` is a required key in the YAML schema, `domains` should be required too. Thus, empty lists will be rejected by pykwalify, so the questionable warning for "no domains defined; this probably won't work" can be axed. Fixes #63166 Signed-off-by: Grzegorz Swiderski (cherry picked from commit f82e2ef043ea40c648094955b4a0c54c42a98d5a) (cherry picked from commit d87c3c5d73014b38fab1b3455b5d6cadc95af9f3) --- scripts/pylib/build_helpers/domains.py | 39 ++++++++++++-------------- 1 file changed, 18 insertions(+), 21 deletions(-) diff --git a/scripts/pylib/build_helpers/domains.py b/scripts/pylib/build_helpers/domains.py index 8cacac7b4e8..f4c2f085fd2 100644 --- a/scripts/pylib/build_helpers/domains.py +++ b/scripts/pylib/build_helpers/domains.py @@ -27,7 +27,7 @@ required: true type: str domains: - required: false + required: true type: seq sequence: - type: map @@ -57,19 +57,18 @@ class Domains: def __init__(self, data): - self._build_dir = data.get('build_dir') - domain_list = data.get('domains') or [] - if not domain_list: - logger.warning("no domains defined; this probably won't work") - + self._build_dir = data['build_dir'] self._domains = { d['name']: Domain(d['name'], d['build_dir']) - for d in domain_list + for d in data['domains'] } - self._default_domain = self._domains.get(data['default']) - domains_flash_order = data.get('flash_order') or [] - self._flash_order = list(map(self._domains.get, domains_flash_order)) + # In the YAML data, the values for "default" and "flash_order" + # must not name any domains that aren't listed under "domains". + # Now that self._domains has been initialized, we can leverage + # the common checks in self.get_domain to verify this. + self._default_domain = self.get_domain(data['default']) + self._flash_order = self.get_domains(data['flash_order'] or []) @staticmethod def from_file(domains_file): @@ -101,21 +100,19 @@ def from_data(domains_data): return Domains(domains_data) def get_domains(self, names=None, default_flash_order=False): - ret = [] - - if not names: + if names is None: if default_flash_order: return self._flash_order return list(self._domains.values()) + return list(map(self.get_domain, names)) - for n in names: - found = self._domains.get(n) - if not found: - logger.critical(f'domain {n} not found, ' - f'valid domains are: {", ".join(self._domains)}') - exit(1) - ret.append(found) - return ret + def get_domain(self, name): + found = self._domains.get(name) + if not found: + logger.critical(f'domain "{name}" not found, ' + f'valid domains are: {", ".join(self._domains)}') + exit(1) + return found def get_default_domain(self): return self._default_domain From f943f54c83a9ae04467dccdb01b33707bdcfffc0 Mon Sep 17 00:00:00 2001 From: Grzegorz Swiderski Date: Thu, 28 Sep 2023 09:36:18 +0200 Subject: [PATCH 120/421] [nrf fromtree] scripts: domains: Support initialization only from YAML By requiring a full-on YAML fragment, the Domains class can rely on pykwalify to do the heavy lifting with validating types and structure. Remove support for loading domains from a dictionary, so that we don't ever have to replicate the same checks on the input, and we can instead have a single entry point. Signed-off-by: Grzegorz Swiderski (cherry picked from commit 652b0a8a985481cb40d680a4864599d9294a296c) (cherry picked from commit a3b1b0f368e27339bfee6637fc2f03e0dbf30ac8) --- scripts/pylib/build_helpers/domains.py | 32 ++++++++++++-------------- scripts/west_commands/build_helpers.py | 13 +++++++---- 2 files changed, 24 insertions(+), 21 deletions(-) diff --git a/scripts/pylib/build_helpers/domains.py b/scripts/pylib/build_helpers/domains.py index f4c2f085fd2..475844e9a61 100644 --- a/scripts/pylib/build_helpers/domains.py +++ b/scripts/pylib/build_helpers/domains.py @@ -56,7 +56,15 @@ class Domains: - def __init__(self, data): + def __init__(self, domains_yaml): + try: + data = yaml.safe_load(domains_yaml) + pykwalify.core.Core(source_data=data, + schema_data=schema).validate() + except (yaml.YAMLError, pykwalify.errors.SchemaError): + logger.critical(f'malformed domains.yaml') + exit(1) + self._build_dir = data['build_dir'] self._domains = { d['name']: Domain(d['name'], d['build_dir']) @@ -72,32 +80,22 @@ def __init__(self, data): @staticmethod def from_file(domains_file): - '''Load domains from domains.yaml. - - Exception raised: - - ``FileNotFoundError`` if the domains file is not found. + '''Load domains from a domains.yaml file. ''' try: with open(domains_file, 'r') as f: - domains = yaml.safe_load(f.read()) + domains_yaml = f.read() except FileNotFoundError: logger.critical(f'domains.yaml file not found: {domains_file}') exit(1) - try: - pykwalify.core.Core(source_data=domains, schema_data=schema)\ - .validate() - except pykwalify.errors.SchemaError: - logger.critical(f'ERROR: Malformed yaml in file: {domains_file}') - exit(1) - - return Domains(domains) + return Domains(domains_yaml) @staticmethod - def from_data(domains_data): - '''Load domains from domains dictionary. + def from_yaml(domains_yaml): + '''Load domains from a string with YAML contents. ''' - return Domains(domains_data) + return Domains(domains_yaml) def get_domains(self, names=None, default_flash_order=False): if names is None: diff --git a/scripts/west_commands/build_helpers.py b/scripts/west_commands/build_helpers.py index 88845e50f4b..ca6845f01da 100644 --- a/scripts/west_commands/build_helpers.py +++ b/scripts/west_commands/build_helpers.py @@ -151,9 +151,14 @@ def load_domains(path): domains_file = Path(path) / 'domains.yaml' if not domains_file.is_file(): - return Domains.from_data({'default': 'app', - 'build_dir': path, - 'domains': [{'name': 'app', 'build_dir': path}], - 'flash_order': ['app']}) + return Domains.from_yaml(f'''\ +default: app +build_dir: {path} +domains: + - name: app + build_dir: {path} +flash_order: + - app +''') return Domains.from_file(domains_file) From 2cdbabc898855f447b8f17cd81548b16dfb6d045 Mon Sep 17 00:00:00 2001 From: Grzegorz Swiderski Date: Thu, 28 Sep 2023 09:36:36 +0200 Subject: [PATCH 121/421] [nrf fromtree] scripts: domains: Convert Domain to a dataclass For conciseness. Signed-off-by: Grzegorz Swiderski (cherry picked from commit 9bbf7e5a4806c158e0d5c19b816379ef02e0f3e3) (cherry picked from commit 9cf087a4d8274112ab1daa6f9cc2f943f9cb2256) --- scripts/pylib/build_helpers/domains.py | 24 +++++------------------- 1 file changed, 5 insertions(+), 19 deletions(-) diff --git a/scripts/pylib/build_helpers/domains.py b/scripts/pylib/build_helpers/domains.py index 475844e9a61..978569d9547 100644 --- a/scripts/pylib/build_helpers/domains.py +++ b/scripts/pylib/build_helpers/domains.py @@ -8,6 +8,8 @@ Domain class. ''' +from dataclasses import dataclass + import yaml import pykwalify.core import logging @@ -119,24 +121,8 @@ def get_top_build_dir(self): return self._build_dir +@dataclass class Domain: - def __init__(self, name, build_dir): - self.name = name - self.build_dir = build_dir - - @property - def name(self): - return self._name - - @name.setter - def name(self, value): - self._name = value - - @property - def build_dir(self): - return self._build_dir - - @build_dir.setter - def build_dir(self, value): - self._build_dir = value + name: str + build_dir: str From 90d276b0cd557bf7f3e35119e43106b09681194e Mon Sep 17 00:00:00 2001 From: Grzegorz Chwierut Date: Tue, 19 Sep 2023 15:07:21 +0200 Subject: [PATCH 122/421] [nrf fromtree] twister: pytest: Fix problems with no prompt in tests with shell Only impacts on twister-pytest scenarios. Exec command is waiting for the prompt message, but in some cases, e.g. after reseting the DUT, prompt can be followed by another strings. Solution is to clear internal serial buffer and to not request the prompt string before executing a command. Signed-off-by: Grzegorz Chwierut (cherry picked from commit 6c86af0331f2cd0f2e410b88c6ee290ea7648f83) (cherry picked from commit 938510fbf113906509c27e4af8d12ce9b1366a79) --- .../src/twister_harness/device/hardware_adapter.py | 1 + .../pytest-twister-harness/src/twister_harness/helpers/shell.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/pylib/pytest-twister-harness/src/twister_harness/device/hardware_adapter.py b/scripts/pylib/pytest-twister-harness/src/twister_harness/device/hardware_adapter.py index 3a3f242fa85..403978eed9a 100644 --- a/scripts/pylib/pytest-twister-harness/src/twister_harness/device/hardware_adapter.py +++ b/scripts/pylib/pytest-twister-harness/src/twister_harness/device/hardware_adapter.py @@ -250,6 +250,7 @@ def _clear_internal_resources(self) -> None: super()._clear_internal_resources() self._serial_connection = None self._serial_pty_proc = None + self._serial_buffer.clear() @staticmethod def _run_custom_script(script_path: str | Path, timeout: float) -> None: diff --git a/scripts/pylib/pytest-twister-harness/src/twister_harness/helpers/shell.py b/scripts/pylib/pytest-twister-harness/src/twister_harness/helpers/shell.py index fc8009d12fe..37f8ad432cf 100644 --- a/scripts/pylib/pytest-twister-harness/src/twister_harness/helpers/shell.py +++ b/scripts/pylib/pytest-twister-harness/src/twister_harness/helpers/shell.py @@ -57,7 +57,7 @@ def exec_command(self, command: str, timeout: float | None = None, print_output: timeout = timeout or self.base_timeout command_ext = f'{command}\n\n' regex_prompt = re.escape(self.prompt) - regex_command = f'{regex_prompt}.*{command}' + regex_command = f'.*{command}' self._device.clear_buffer() self._device.write(command_ext.encode()) lines: list[str] = [] From 801a64e6d1acfaac7bf1f5ebb2d647500464186e Mon Sep 17 00:00:00 2001 From: Grzegorz Chwierut Date: Thu, 14 Sep 2023 15:38:34 +0200 Subject: [PATCH 123/421] [nrf fromtree] twister: doc: Update pytest and twister docs Document how to use pytest_root keyword. Update docs with changes in pytest-twister-harness plugin. Signed-off-by: Grzegorz Chwierut (cherry picked from commit 033afe1c0c3c047b36c86ca9a1d225129e3e5315) (cherry picked from commit 7f2feef444a94ac58cd1c6a1d64e977d6828a317) --- doc/develop/test/pytest.rst | 55 +++++++++++++++++++++++------------- doc/develop/test/twister.rst | 26 +++++++++++------ 2 files changed, 53 insertions(+), 28 deletions(-) diff --git a/doc/develop/test/pytest.rst b/doc/develop/test/pytest.rst index 97737ce0ae2..d0fad4d6be6 100644 --- a/doc/develop/test/pytest.rst +++ b/doc/develop/test/pytest.rst @@ -49,28 +49,47 @@ How to create a pytest test An example of a pytest test is given at :zephyr_file:`samples/subsys/testsuite/pytest/shell/pytest/test_shell.py`. Twister calls pytest for each configuration from the .yaml file which uses ``harness: pytest``. By default, it points to ``pytest`` directory, located next to a directory with binary sources. -A keyword ``pytest_root`` placed under ``harness_config`` section can be used to point to another -location. +A keyword ``pytest_root`` placed under ``harness_config`` section can be used to point to other +files, directories or subtests. -Pytest scans the given folder looking for tests, following its default +Pytest scans the given locations looking for tests, following its default `discovery rules `_ One can also pass some extra arguments to the pytest from yaml file using ``pytest_args`` keyword under ``harness_config``, e.g.: ``pytest_args: [‘-k=test_method’, ‘--log-level=DEBUG’]``. -Following import is required to include in .py sources: +Helpers & fixtures +================== + +dut +--- + +Give access to a DeviceAdapter type object, that represents Device Under Test. +This fixture is the core of pytest harness plugin. It is required to launch +DUT (initialize logging, flash device, connect serial etc). +This fixture yields a device prepared according to the requested type +(native posix, qemu, hardware, etc.). All types of devices share the same API. +This allows for writing tests which are device-type-agnostic. .. code-block:: python - from twister_harness import Device + from twister_harness import DeviceAdapter -It is important for type checking and enabling IDE hints for ``dut`` s (objects representing -Devices Under Test). The ``dut`` fixture is the core of pytest harness plugin. When used as an -argument of a test function it gives access to a DeviceAbstract type object. The fixture yields a -device prepared according to the requested type (native posix, qemu, hardware, etc.). All types of -devices share the same API. This allows for writing tests which are device-type-agnostic. + def test_sample(dut: DeviceAdapter): + dut.readlines_until('Hello world') -Helpers & fixtures -================== +shell +----- + +Provide an object with methods used to interact with shell application. +It calls `wait_for_promt` method, to not start scenario until DUT is ready. +Note that it uses `dut` fixture, so `dut` can be skipped when `shell` is used. + +.. code-block:: python + + from twister_harness import Shell + + def test_shell(shell: Shell): + shell.exec_command('help') mcumgr ------ @@ -82,16 +101,15 @@ More information about MCUmgr can be found here :ref:`mcu_mgr`. This fixture requires the ``mcumgr`` available in the system PATH Only selected functionality of MCUmgr is wrapped by this fixture. - For example, here is a test with a fixture ``mcumgr`` .. code-block:: python - from twister_harness import Device, McuMgr + from twister_harness import DeviceAdapter, Shell, McuMgr - def test_upgrade(dut: Device, mcumgr: McuMgr): - # wait for dut is up - time.sleep(2) + def test_upgrade(dut: DeviceAdapter, shell: Shell, mcumgr: McuMgr): + # free the serial port for mcumgr + dut.disconnect() # upload the signed image mcumgr.image_upload('path/to/zephyr.signed.bin') # obtain the hash of uploaded image from the device @@ -105,7 +123,4 @@ For example, here is a test with a fixture ``mcumgr`` Limitations *********** -* Device adapters in pytest plugin provide `iter_stdout` method to read from devices. In some - cases, it is not the most convenient way, and it will be considered how to improve this - (for example replace it with a simple read function with a given byte size and timeout arguments). * Not every platform type is supported in the plugin (yet). diff --git a/doc/develop/test/twister.rst b/doc/develop/test/twister.rst index a29890c7899..4456386b77c 100644 --- a/doc/develop/test/twister.rst +++ b/doc/develop/test/twister.rst @@ -492,10 +492,11 @@ harness_config: Only one fixture can be defined per testcase and the fixture name has to be unique across all tests in the test suite. - pytest_root: (default pytest) - Specify a pytest directory which need to execute when test case begin to running, - default pytest directory name is pytest, after pytest finished, twister will - check if this case pass or fail according the pytest report. + pytest_root: (default pytest) + Specify a list of pytest directories, files or subtests that need to be executed + when test case begin to running, default pytest directory is pytest. + After pytest finished, twister will check if this case pass or fail according + to the pytest report. pytest_args: (default empty) Specify a list of additional arguments to pass to ``pytest``. @@ -526,15 +527,24 @@ harness_config: The following is an example yaml file with pytest harness_config options, default pytest_root name "pytest" will be used if pytest_root not specified. - please refer the example in samples/subsys/testsuite/pytest/. + please refer the examples in samples/subsys/testsuite/pytest/. :: + common: + harness: pytest tests: - pytest.example: - harness: pytest + pytest.example.directories: + harness_config: + pytest_root: + - pytest_dir1 + - $ENV_VAR/samples/test/pytest_dir2 + pytest.example.files_and_subtests: harness_config: - pytest_root: [pytest directory name] + pytest_root: + - pytest/test_file_1.py + - test_file_2.py::test_A + - test_file_2.py::test_B[param_a] The following is an example yaml file with robot harness_config options. From 29ccece157fa10782a41b8fa1eee15759174e24d Mon Sep 17 00:00:00 2001 From: Grzegorz Chwierut Date: Thu, 14 Sep 2023 15:34:07 +0200 Subject: [PATCH 124/421] [nrf fromtree] twister: pytest: Allow list of pytest testpaths Allow to specify a list of pytest directories, files or subtests with pytest_root keyword in test yaml. Signed-off-by: Grzegorz Chwierut (cherry picked from commit 5bb306794232d4e391987448bbf73724e21d5a08) (cherry picked from commit be22816677ec99e6deb93b9977c403b625ab0448) --- scripts/pylib/twister/twisterlib/harness.py | 5 +- scripts/schemas/twister/testsuite-schema.yaml | 8 ++- .../pytest_integration/test_harness_pytest.py | 61 +++++++++++++++++++ 3 files changed, 70 insertions(+), 4 deletions(-) diff --git a/scripts/pylib/twister/twisterlib/harness.py b/scripts/pylib/twister/twisterlib/harness.py index 96b4a2e3461..6ae2622c810 100644 --- a/scripts/pylib/twister/twisterlib/harness.py +++ b/scripts/pylib/twister/twisterlib/harness.py @@ -245,19 +245,20 @@ def pytest_run(self, timeout): def generate_command(self): config = self.instance.testsuite.harness_config - pytest_root = config.get('pytest_root', 'pytest') if config else 'pytest' + pytest_root = config.get('pytest_root', ['pytest']) if config else ['pytest'] pytest_args = config.get('pytest_args', []) if config else [] command = [ 'pytest', '--twister-harness', '-s', '-v', - os.path.join(self.source_dir, pytest_root), f'--build-dir={self.running_dir}', f'--junit-xml={self.report_file}', '--log-file-level=DEBUG', '--log-file-format=%(asctime)s.%(msecs)d:%(levelname)s:%(name)s: %(message)s', f'--log-file={self.pytest_log_file_path}' ] + command.extend([os.path.normpath(os.path.join( + self.source_dir, os.path.expanduser(os.path.expandvars(src)))) for src in pytest_root]) command.extend(pytest_args) handler: Handler = self.instance.handler diff --git a/scripts/schemas/twister/testsuite-schema.yaml b/scripts/schemas/twister/testsuite-schema.yaml index 116c1a43379..96a121767a5 100644 --- a/scripts/schemas/twister/testsuite-schema.yaml +++ b/scripts/schemas/twister/testsuite-schema.yaml @@ -95,8 +95,10 @@ mapping: type: int required: false "pytest_root": - type: str + type: seq required: false + sequence: + - type: str "pytest_args": type: seq required: false @@ -293,8 +295,10 @@ mapping: type: int required: false "pytest_root": - type: str + type: seq required: false + sequence: + - type: str "pytest_args": type: seq required: false diff --git a/scripts/tests/twister/pytest_integration/test_harness_pytest.py b/scripts/tests/twister/pytest_integration/test_harness_pytest.py index db7bf389fbd..e1b27a0cf02 100644 --- a/scripts/tests/twister/pytest_integration/test_harness_pytest.py +++ b/scripts/tests/twister/pytest_integration/test_harness_pytest.py @@ -48,6 +48,67 @@ def test_pytest_command(testinstance: TestInstance, device_type): assert c in command +@pytest.mark.parametrize( + ('pytest_root', 'expected'), + [ + ( + ['pytest/test_shell_help.py'], + ['samples/hello/pytest/test_shell_help.py'] + ), + ( + ['pytest/test_shell_help.py', 'pytest/test_shell_version.py', 'test_dir'], + ['samples/hello/pytest/test_shell_help.py', + 'samples/hello/pytest/test_shell_version.py', + 'samples/hello/test_dir'] + ), + ( + ['../shell/pytest/test_shell.py'], + ['samples/shell/pytest/test_shell.py'] + ), + ( + ['/tmp/test_temp.py'], + ['/tmp/test_temp.py'] + ), + ( + ['~/tmp/test_temp.py'], + ['/home/joe/tmp/test_temp.py'] + ), + ( + ['$ZEPHYR_BASE/samples/subsys/testsuite/pytest/shell/pytest'], + ['/zephyr_base/samples/subsys/testsuite/pytest/shell/pytest'] + ), + ( + ['pytest/test_shell_help.py::test_A', 'pytest/test_shell_help.py::test_B'], + ['samples/hello/pytest/test_shell_help.py::test_A', + 'samples/hello/pytest/test_shell_help.py::test_B'] + ), + ( + ['pytest/test_shell_help.py::test_A[param_a]'], + ['samples/hello/pytest/test_shell_help.py::test_A[param_a]'] + ) + ], + ids=[ + 'one_file', + 'more_files', + 'relative_path', + 'absollute_path', + 'user_dir', + 'with_env_var', + 'subtests', + 'subtest_with_param' + ] +) +def test_pytest_handle_source_list(testinstance: TestInstance, monkeypatch, pytest_root, expected): + monkeypatch.setenv('ZEPHYR_BASE', '/zephyr_base') + monkeypatch.setenv('HOME', '/home/joe') + testinstance.testsuite.harness_config['pytest_root'] = pytest_root + pytest_harness = Pytest() + pytest_harness.configure(testinstance) + command = pytest_harness.generate_command() + for pytest_src in expected: + assert pytest_src in command + + def test_if_report_is_parsed(pytester, testinstance: TestInstance): test_file_content = textwrap.dedent(""" def test_1(): From 885245b9c1eb4ecd0a3eb6825a70e97422ea2db9 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Wed, 20 Sep 2023 19:17:26 +0000 Subject: [PATCH 125/421] [nrf fromtree] drivers/flash/nrf: Workaround for nrf91 errata 7 Fix UICR read access. (cherry picked from commit 1f3605de21ef1ace85ba4aeced725411c1ed8ef4) Signed-off-by: Dominik Ermel (cherry picked from commit de6799beb339d5df40d65ef2ab76167c9ba50a98) --- drivers/flash/soc_flash_nrf.c | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/drivers/flash/soc_flash_nrf.c b/drivers/flash/soc_flash_nrf.c index f38492a41d1..ea76ae1e3f8 100644 --- a/drivers/flash/soc_flash_nrf.c +++ b/drivers/flash/soc_flash_nrf.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2018 Nordic Semiconductor ASA + * Copyright (c) 2017-2023 Nordic Semiconductor ASA * Copyright (c) 2016 Linaro Limited * Copyright (c) 2016 Intel Corporation * @@ -121,6 +121,26 @@ static inline bool is_uicr_addr_valid(off_t addr, size_t len) #endif /* CONFIG_SOC_FLASH_NRF_UICR */ } +#if CONFIG_SOC_FLASH_NRF_UICR && IS_ENABLED(NRF91_ERRATA_7_ENABLE_WORKAROUND) +static inline void nrf91_errata_7_enter(void) +{ + __disable_irq(); +} + +static inline void nrf91_errata_7_exit(void) +{ + __DSB(); + __enable_irq(); +} + +static void nrf_buffer_read_91_uicr(void *data, off_t addr, size_t len) +{ + nrf91_errata_7_enter(); + nrf_nvmc_buffer_read(data, (uint32_t)addr, len); + nrf91_errata_7_exit(); +} +#endif + static void nvmc_wait_ready(void) { while (!nrfx_nvmc_write_done_check()) { @@ -130,9 +150,11 @@ static void nvmc_wait_ready(void) static int flash_nrf_read(const struct device *dev, off_t addr, void *data, size_t len) { + const bool within_uicr = is_uicr_addr_valid(addr, len); + if (is_regular_addr_valid(addr, len)) { addr += DT_REG_ADDR(SOC_NV_FLASH_NODE); - } else if (!is_uicr_addr_valid(addr, len)) { + } else if (!within_uicr) { LOG_ERR("invalid address: 0x%08lx:%zu", (unsigned long)addr, len); return -EINVAL; @@ -147,6 +169,12 @@ static int flash_nrf_read(const struct device *dev, off_t addr, return soc_secure_mem_read(data, (void *)addr, len); } #endif +#if CONFIG_SOC_FLASH_NRF_UICR && IS_ENABLED(NRF91_ERRATA_7_ENABLE_WORKAROUND) + if (within_uicr) { + nrf_buffer_read_91_uicr(data, (uint32_t)addr, len); + return 0; + } +#endif nrf_nvmc_buffer_read(data, (uint32_t)addr, len); From 38f9d7e6f240c55d996e510e9a9d5deca27753cd Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Fri, 2 Jun 2023 19:40:24 +0000 Subject: [PATCH 126/421] [nrf fromtree] mgmt/MCUmgr/grp/img: Add support for DirectXIP with revert The commit adds support for uploading image to board with MCUboot configured with DirectXIP with revert. It allows to set uploaded image either for test or as permanent boot application, until newer image gets confirmed. Note that in DirectXIP with revert MCUboot will remove image that has not been set for test nor confirmed and MCUmgr does not set either mode unless image has the mode set within uploaded binary. The commit adds Kconfig option CONFIG_MCUBOOT_BOOTLOADER_MODE_DIRECT_XIP_WITH_REVERT that enabled the new mode of operation within MCUmgr. (cherry picked from commit f3067f2364b2051990575e2dc849d02b391b518d) Signed-off-by: Dominik Ermel (cherry picked from commit 2d442e924d62a8fb1714f904cdca20aa49780343) --- modules/Kconfig.mcuboot | 24 +++ .../mcumgr/grp/img_mgmt/src/img_mgmt_state.c | 201 ++++++++++++++---- 2 files changed, 185 insertions(+), 40 deletions(-) diff --git a/modules/Kconfig.mcuboot b/modules/Kconfig.mcuboot index 0bb47d8854c..5f83098a577 100644 --- a/modules/Kconfig.mcuboot +++ b/modules/Kconfig.mcuboot @@ -176,6 +176,21 @@ config MCUBOOT_BOOTLOADER_MODE_DIRECT_XIP means major.minor.patch triple, unless BOOT_VERSION_CMP_USE_BUILD_NUMBER is also selected that enables comparison of build number. +config MCUBOOT_BOOTLOADER_MODE_DIRECT_XIP_WITH_REVERT + bool "MCUboot has been configured for DirectXIP with revert" + select MCUBOOT_BOOTUTIL_LIB_FOR_DIRECT_XIP + help + MCUboot expects slot0_partition and slot1_partition to exist in DT. + In this mode MCUboot will boot the application with the higher version + from either slot, as long as it has been marked to be boot + next time for test or permanently. In case when application is marked + for test it needs to confirm itself, on the first boot, or it will + be removed and MCUboot will revert to booting previously approved + application. + This mode does not allow freely switching between application + versions, as, once higher version application is approved, it is + not possible to select lower version for boot. + endchoice # MCUBOOT_BOOTLOADER_MODE endif # BOOTLOADER_MCUBOOT @@ -208,4 +223,13 @@ config BOOT_IMAGE_ACCESS_HOOKS It is up to the application project to add source file which implements hooks to the build. +if MCUBOOT_BOOTLOADER_MODE_DIRECT_XIP_WITH_REVERT + +config MCUBOOT_BOOTUTIL_LIB_FOR_DIRECT_XIP + bool + help + Adds support for setting for test and confirming images + when bootloader is in DirectXIP-revert mode. +endif + endif # MCUBOOT_BOOTUTIL_LIB diff --git a/subsys/mgmt/mcumgr/grp/img_mgmt/src/img_mgmt_state.c b/subsys/mgmt/mcumgr/grp/img_mgmt/src/img_mgmt_state.c index a782acb92ee..0968694c614 100644 --- a/subsys/mgmt/mcumgr/grp/img_mgmt/src/img_mgmt_state.c +++ b/subsys/mgmt/mcumgr/grp/img_mgmt/src/img_mgmt_state.c @@ -55,6 +55,14 @@ LOG_MODULE_DECLARE(mcumgr_img_grp, CONFIG_MCUMGR_GRP_IMG_LOG_LEVEL); #define REPORT_SLOT_PENDING BIT(1) #define REPORT_SLOT_CONFIRMED BIT(2) #define REPORT_SLOT_PERMANENT BIT(3) + +#if defined(CONFIG_MCUBOOT_BOOTLOADER_MODE_DIRECT_XIP_WITH_REVERT) +#define DIRECT_XIP_BOOT_UNSET 0 +#define DIRECT_XIP_BOOT_ONCE 1 +#define DIRECT_XIP_BOOT_REVERT 2 +#define DIRECT_XIP_BOOT_FOREVER 3 +#endif + /** * Collects information about the specified image slot. */ @@ -139,7 +147,8 @@ img_mgmt_state_flags(int query_slot) } #endif -#ifndef CONFIG_MCUBOOT_BOOTLOADER_MODE_DIRECT_XIP +#if !defined(CONFIG_MCUBOOT_BOOTLOADER_MODE_DIRECT_XIP) && \ + !defined(CONFIG_MCUBOOT_BOOTLOADER_MODE_DIRECT_XIP_WITH_REVERT) int img_mgmt_get_next_boot_slot(int image, enum img_mgmt_next_boot_type *type) { const int active_slot = img_mgmt_active_slot(image); @@ -188,27 +197,115 @@ int img_mgmt_get_next_boot_slot(int image, enum img_mgmt_next_boot_type *type) return slot; } #else + +#if defined(CONFIG_MCUBOOT_BOOTLOADER_MODE_DIRECT_XIP_WITH_REVERT) + +static int read_directxip_state(int slot) +{ + struct boot_swap_state bss; + int fa_id = img_mgmt_flash_area_id(slot); + const struct flash_area *fa; + int rc = 0; + + __ASSERT(fa_id != -1, "Could not map slot to area ID"); + + rc = flash_area_open(fa_id, &fa); + if (rc < 0) { + return rc; + } + rc = boot_read_swap_state(fa, &bss); + flash_area_close(fa); + if (rc != 0) { + LOG_ERR("Failed to read state of slot %d with error %d", slot, rc); + return -1; + } + + if (bss.magic == BOOT_MAGIC_GOOD) { + if (bss.image_ok == BOOT_FLAG_SET) { + return DIRECT_XIP_BOOT_FOREVER; + } else if (bss.copy_done == BOOT_FLAG_SET) { + return DIRECT_XIP_BOOT_REVERT; + } + return DIRECT_XIP_BOOT_ONCE; + } + return DIRECT_XIP_BOOT_UNSET; +} +#endif /* defined(CONFIG_MCUBOOT_BOOTLOADER_MODE_DIRECT_XIP_WITH_REVERT) */ + int img_mgmt_get_next_boot_slot(int image, enum img_mgmt_next_boot_type *type) { struct image_version aver; struct image_version over; int active_slot = img_mgmt_active_slot(image); int other_slot = img_mgmt_get_opposite_slot(active_slot); +#if defined(CONFIG_MCUBOOT_BOOTLOADER_MODE_DIRECT_XIP_WITH_REVERT) + int active_slot_state; + int other_slot_state; +#endif /* defined(CONFIG_MCUBOOT_BOOTLOADER_MODE_DIRECT_XIP_WITH_REVERT) */ + enum img_mgmt_next_boot_type lt = NEXT_BOOT_TYPE_NORMAL; + int return_slot = active_slot; - if (type != NULL) { - *type = NEXT_BOOT_TYPE_NORMAL; - } int rcs = img_mgmt_read_info(other_slot, &over, NULL, NULL); int rca = img_mgmt_read_info(active_slot, &aver, NULL, NULL); +#if defined(CONFIG_MCUBOOT_BOOTLOADER_MODE_DIRECT_XIP_WITH_REVERT) + active_slot_state = read_directxip_state(active_slot); + other_slot_state = read_directxip_state(other_slot); + if (rca != 0 || + (rcs != 0 && rcs != IMG_MGMT_ERR_NO_IMAGE)) { + /* We do not really know what will happen, as we can not + * read states from bootloader. + */ + LOG_ERR("img_mgmt_read_info_failed rca = %d, rcs = %d", + rca, rcs); + goto out; + } + if (other_slot_state < 0 || active_slot_state < 0) { + LOG_ERR("Slot state read failed with status: active %d, other %d", + active_slot_state, other_slot_state); + /* We do not really know what will happen, as we can not + * read states from bootloader. + */ + goto out; + } + + /* There is not other image, the active one will boot next time */ + if (rcs == IMG_MGMT_ERR_NO_IMAGE) { + goto out; + } + + if (active_slot_state == DIRECT_XIP_BOOT_REVERT) { + lt = NEXT_BOOT_TYPE_REVERT; + return_slot = other_slot; + } else if (other_slot_state == DIRECT_XIP_BOOT_UNSET) { + if (active_slot_state == DIRECT_XIP_BOOT_ONCE) { + lt = NEXT_BOOT_TYPE_TEST; + } + } else if (img_mgmt_vercmp(&aver, &over) < 0) { + if (other_slot_state == DIRECT_XIP_BOOT_FOREVER) { + return_slot = other_slot; + } else if (other_slot_state == DIRECT_XIP_BOOT_ONCE) { + lt = NEXT_BOOT_TYPE_TEST; + return_slot = other_slot; + } + } +#else if (rcs == 0 && rca == 0 && img_mgmt_vercmp(&aver, &over) < 0) { - return other_slot; + return_slot = other_slot; } +#endif /* defined(CONFIG_MCUBOOT_BOOTLOADER_MODE_DIRECT_XIP_WITH_REVERT) */ - return active_slot; +out: + if (type != NULL) { + *type = lt; + } + + return return_slot; } -#endif +#endif /* !defined(CONFIG_MCUBOOT_BOOTLOADER_MODE_DIRECT_XIP) && \ + * !defined(CONFIG_MCUBOOT_BOOTLOADER_MODE_DIRECT_XIP_WITH_REVERT) + */ /** @@ -422,11 +519,53 @@ img_mgmt_state_read(struct smp_streamer *ctxt) return ok ? MGMT_ERR_EOK : MGMT_ERR_EMSGSIZE; } -int img_mgmt_set_next_boot_slot(int slot, bool confirm) +static int img_mgmt_set_next_boot_slot_common(int slot, int active_slot, bool confirm) { const struct flash_area *fa; int area_id = img_mgmt_flash_area_id(slot); int rc = 0; + + if (flash_area_open(area_id, &fa) != 0) { + return IMG_MGMT_ERR_FLASH_OPEN_FAILED; + } + + rc = boot_set_next(fa, slot == active_slot, confirm); + if (rc != 0) { + /* Failed to set next slot for boot as desired */ + LOG_ERR("Faled boot_set_next with code %d, for slot %d," + " with active slot %d and confirm %d", + rc, slot, active_slot, confirm); + + /* Translate from boot util error code to IMG mgmt group error code */ + if (rc == BOOT_EFLASH) { + rc = IMG_MGMT_ERR_FLASH_WRITE_FAILED; + } else if (rc == BOOT_EBADVECT) { + rc = IMG_MGMT_ERR_INVALID_IMAGE_VECTOR_TABLE; + } else if (rc == BOOT_EBADIMAGE) { + rc = IMG_MGMT_ERR_INVALID_IMAGE_HEADER_MAGIC; + } else { + rc = IMG_MGMT_ERR_UNKNOWN; + } + } + flash_area_close(fa); + +#if defined(CONFIG_MCUMGR_GRP_IMG_STATUS_HOOKS) + if (rc == 0 && slot == active_slot && confirm) { + int32_t err_rc; + uint16_t err_group; + + /* Confirm event is only sent for active slot */ + (void)mgmt_callback_notify(MGMT_EVT_OP_IMG_MGMT_DFU_CONFIRMED, NULL, 0, &err_rc, + &err_group); + } +#endif + + return rc; +} + +#ifndef CONFIG_MCUBOOT_BOOTLOADER_MODE_DIRECT_XIP_WITH_REVERT +int img_mgmt_set_next_boot_slot(int slot, bool confirm) +{ /* image the requested slot is defined within */ int image = img_mgmt_slot_to_image(slot); /* active_slot is slot that is considered active/primary/executing @@ -498,43 +637,25 @@ int img_mgmt_set_next_boot_slot(int slot, bool confirm) /* Allow confirming slot == active_slot */ } - if (flash_area_open(area_id, &fa) != 0) { - return IMG_MGMT_ERR_FLASH_OPEN_FAILED; - } - - rc = boot_set_next(fa, slot == active_slot, confirm); - if (rc != 0) { - /* Failed to set next slot for boot as desired */ - LOG_ERR("Faled boot_set_next with code %d, for slot %d," - " with active slot %d and confirm %d", - rc, slot, active_slot, confirm); - - /* Translate from boot util error code to IMG mgmt group error code */ - if (rc == BOOT_EFLASH) { - rc = IMG_MGMT_ERR_FLASH_WRITE_FAILED; - } else if (rc == BOOT_EBADVECT) { - rc = IMG_MGMT_ERR_INVALID_IMAGE_VECTOR_TABLE; - } else if (rc == BOOT_EBADIMAGE) { - rc = IMG_MGMT_ERR_INVALID_IMAGE_HEADER_MAGIC; - } else { - rc = IMG_MGMT_ERR_UNKNOWN; - } - } - flash_area_close(fa); + return img_mgmt_set_next_boot_slot_common(slot, active_slot, confirm); +} +#else +int img_mgmt_set_next_boot_slot(int slot, bool confirm) +{ + int active_image = img_mgmt_active_image(); + int active_slot = img_mgmt_active_slot(active_image); -#if defined(CONFIG_MCUMGR_GRP_IMG_STATUS_HOOKS) - if (slot == active_slot && confirm) { - int32_t err_rc; - uint16_t err_group; + LOG_DBG("(%d, %s)", slot, confirm ? "confirm" : "test"); + LOG_DBG("aimg = %d, aslot = %d, slot = %d", + active_image, active_slot, slot); - /* Confirm event is only sent for active slot */ - (void)mgmt_callback_notify(MGMT_EVT_OP_IMG_MGMT_DFU_CONFIRMED, NULL, 0, &err_rc, - &err_group); + if (slot == active_slot && !confirm) { + return IMG_MGMT_ERR_IMAGE_SETTING_TEST_TO_ACTIVE_DENIED; } -#endif - return rc; + return img_mgmt_set_next_boot_slot_common(slot, active_slot, confirm); } +#endif /** * Command handler: image state write From 0e63631f6734ba12b8d5a8c02eeb706796d9f046 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Wed, 21 Jun 2023 11:42:05 +0000 Subject: [PATCH 127/421] [nrf fromtree] samples/mcumgr/smp_svr: Build for DirectXIP with revert Adds sample build for CONFIG_MCUBOOT_BOOTLOADER_MODE_DIRECT_XIP_WITH_REVERT=y (cherry picked from commit 11ab88f10c83e2bc5ed4120f19a6babf85ea2572) Signed-off-by: Dominik Ermel (cherry picked from commit 7079db0163693bec0c5dbdf62f32841df9cb783e) --- samples/subsys/mgmt/mcumgr/smp_svr/sample.yaml | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/samples/subsys/mgmt/mcumgr/smp_svr/sample.yaml b/samples/subsys/mgmt/mcumgr/smp_svr/sample.yaml index ed7ffe8f33e..a13270e5845 100644 --- a/samples/subsys/mgmt/mcumgr/smp_svr/sample.yaml +++ b/samples/subsys/mgmt/mcumgr/smp_svr/sample.yaml @@ -43,6 +43,19 @@ tests: - mg100 integration_platforms: - nrf52840dk_nrf52840 + # In mcuboot_flags test overlay-serial.conf is used for convenience as it is the simplest + # transport. Transport does not affect flags so it does not really matter which is selected, + # flags should affect any transport the same way. + sample.mcumgr.smp_svr.mcuboot_flags.direct_xip_withrevert: + extra_args: OVERLAY_CONFIG="overlay-serial.conf" + extra_configs: + - CONFIG_MCUBOOT_BOOTLOADER_MODE_DIRECT_XIP_WITH_REVERT=y + platform_allow: + - nrf52840dk_nrf52840 + - pinnacle_100_dvk + - mg100 + integration_platforms: + - nrf52840dk_nrf52840 sample.mcumgr.smp_svr.serial-console: extra_args: OVERLAY_CONFIG="overlay-serial-console.conf" platform_allow: From 8f6ede70c0db2e328b72e350ec5e6b79040d557c Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Mon, 25 Sep 2023 13:38:15 +0000 Subject: [PATCH 128/421] [nrf fromtree] modules/MCUboot: Add new Kconfig indicating downgrade prevention Add the MCUBOOT_BOOTLOADER_NO_DOWNGRADE Kconfig option that allows, when paired with MCUboot mode Kconfig, to indicate that the MCUboot has been configured with downgrade prevention, which means that only application with version higher than running can be swapped on next boot. (cherry picked from commit f17e4f1b76dd10bcf464dbc718073284e61d16fa) Signed-off-by: Dominik Ermel (cherry picked from commit 9bdf8883a69a689b57cd6b85674f4c822bf3b7ad) --- modules/Kconfig.mcuboot | 37 ++++++++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/modules/Kconfig.mcuboot b/modules/Kconfig.mcuboot index 5f83098a577..ab1dd44fbd5 100644 --- a/modules/Kconfig.mcuboot +++ b/modules/Kconfig.mcuboot @@ -116,7 +116,7 @@ config MCUBOOT_EXTRA_IMGTOOL_ARGS help When signing (CONFIG_MCUBOOT_SIGNATURE_KEY_FILE is a non-empty string) you can use this option to pass extra options to - imgtool. For example, you could set this to "--version 1.2". + imgtool. For example, you could set this to "--version 1.2". config MCUBOOT_GENERATE_UNSIGNED_IMAGE bool "Generate unsigned binary image bootable with MCUboot" @@ -136,6 +136,8 @@ config MCUBOOT_GENERATE_CONFIRMED_IMAGE The existence of bin and hex files depends on CONFIG_BUILD_OUTPUT_BIN and CONFIG_BUILD_OUTPUT_HEX. +menu "On board MCUboot operation mode" + choice MCUBOOT_BOOTLOADER_MODE prompt "Application assumed MCUboot mode of operation" default MCUBOOT_BOOTLOADER_MODE_SWAP_WITHOUT_SCRATCH # MCUBOOT_BOOTLOADER_MODE @@ -154,31 +156,43 @@ config MCUBOOT_BOOTLOADER_MODE_SINGLE_APP config MCUBOOT_BOOTLOADER_MODE_SWAP_WITHOUT_SCRATCH bool "MCUboot has been configured for swap without scratch operation" + select MCUBOOT_BOOTLOADER_MODE_HAS_NO_DOWNGRADE help MCUboot expects slot0_partition and slot1_partition to be present in DT and application will boot from slot0_partition. + MCUBOOT_BOOTLOADER_NO_DOWNGRADE should also be selected + if MCUboot has been built with MCUBOOT_DOWNGRADE_PREVENTION. config MCUBOOT_BOOTLOADER_MODE_SWAP_SCRATCH bool "MCUboot has been configured for swap using scratch operation" + select MCUBOOT_BOOTLOADER_MODE_HAS_NO_DOWNGRADE help MCUboot expects slot0_partition, slot1_partition and scratch_partition to be present in DT, and application will boot from slot0_partition. In this mode scratch_partition is used as temporary storage when MCUboot swaps application from the secondary slot to the primary slot. + MCUBOOT_BOOTLOADER_NO_DOWNGRADE should also be selected + if MCUboot has been built with MCUBOOT_DOWNGRADE_PREVENTION. config MCUBOOT_BOOTLOADER_MODE_DIRECT_XIP bool "MCUboot has been configured for DirectXIP operation" + select MCUBOOT_BOOTLOADER_MODE_HAS_NO_DOWNGRADE + select MCUBOOT_BOOTLOADER_NO_DOWNGRADE help MCUboot expects slot0_partition and slot1_partition to exist in DT. In this mode MCUboot can boot from either partition and will select one with higher application image version, which usually means major.minor.patch triple, unless BOOT_VERSION_CMP_USE_BUILD_NUMBER is also selected that enables comparison of build number. + This option automatically selectes + MCUBOOT_BOOTLOADER_NO_DOWNGRADE as it is not possible + to swap back to older version of application. config MCUBOOT_BOOTLOADER_MODE_DIRECT_XIP_WITH_REVERT bool "MCUboot has been configured for DirectXIP with revert" select MCUBOOT_BOOTUTIL_LIB_FOR_DIRECT_XIP + select MCUBOOT_BOOTLOADER_NO_DOWNGRADE help MCUboot expects slot0_partition and slot1_partition to exist in DT. In this mode MCUboot will boot the application with the higher version @@ -190,9 +204,30 @@ config MCUBOOT_BOOTLOADER_MODE_DIRECT_XIP_WITH_REVERT This mode does not allow freely switching between application versions, as, once higher version application is approved, it is not possible to select lower version for boot. + This mode selects MCUBOOT_BOOTLOADER_NO_DOWNGRADE as it is not possible + to downgrade running application, but note that MCUboot may do that + if application with higher version will not get confirmed. endchoice # MCUBOOT_BOOTLOADER_MODE +config MCUBOOT_BOOTLOADER_MODE_HAS_NO_DOWNGRADE + bool + help + Selected mode supports downgrade prevention, where you cannot switch to + an application with lower version than the currently running application. + +if MCUBOOT_BOOTLOADER_MODE_HAS_NO_DOWNGRADE +config MCUBOOT_BOOTLOADER_NO_DOWNGRADE + bool "MCUboot mode has downgrade prevention enabled" + help + Selected MCUboot mode has downgrade prevention enabled, where you are not + able to change back to image with lower version number. + This options should be selected when MCUboot has been built with + MCUBOOT_DOWNGRADE_PREVENTION option enabled. +endif + +endmenu # On board MCUboot operation mode + endif # BOOTLOADER_MCUBOOT menuconfig MCUBOOT_BOOTUTIL_LIB From c43324fe1614052517c8037351231e715c7f7d18 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Mon, 25 Sep 2023 13:47:32 +0000 Subject: [PATCH 129/421] [nrf fromtree] doc/release-notes: Add info on downgrade prevention Kconfig Adds note on addition of MCUBOOT_BOOTLOADER_MODE_WITH_DOWNGRADE_PREVENTION to MCUboot Kconfig module. (cherry picked from commit a43107299f6d4217f6730ccccf6a0e771357c3ca) Signed-off-by: Dominik Ermel (cherry picked from commit c0efcb71cf08290c193cf180e75d8005c01206d7) --- doc/releases/release-notes-3.5.rst | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/doc/releases/release-notes-3.5.rst b/doc/releases/release-notes-3.5.rst index 4f9a8ab1793..d22978d8a84 100644 --- a/doc/releases/release-notes-3.5.rst +++ b/doc/releases/release-notes-3.5.rst @@ -339,6 +339,11 @@ HALs MCUboot ******* + * Added :kconfig:option:`CONFIG_MCUBOOT_BOOTLOADER_NO_DOWNGRADE` + that allows to inform application that the on-board MCUboot has been configured + with downgrade prevention enabled. This option is automatically selected for + DirectXIP mode and is available for both swap modes. + Storage ******* From 8b829dcc8fdcd8d95fea171110fb3bec07a6f616 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Tue, 26 Sep 2023 17:45:55 +0000 Subject: [PATCH 130/421] [nrf fromtree] modules/MCUboot: Fix missing dependency The CONFIG_MCUBOOT_BOOTLOADER_MODE_DIRECT_XIP has been missing select of CONFIG_MCUBOOT_BOOTLOADER_MODE_HAS_NO_DOWNGRADE. (cherry picked from commit a2b238eee77cf9137db858618eb2881c53963330) Signed-off-by: Dominik Ermel (cherry picked from commit 64dc62fd2c921fb7a76542801f958411a5534f90) --- modules/Kconfig.mcuboot | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/Kconfig.mcuboot b/modules/Kconfig.mcuboot index ab1dd44fbd5..1679bfeb8a9 100644 --- a/modules/Kconfig.mcuboot +++ b/modules/Kconfig.mcuboot @@ -192,6 +192,7 @@ config MCUBOOT_BOOTLOADER_MODE_DIRECT_XIP config MCUBOOT_BOOTLOADER_MODE_DIRECT_XIP_WITH_REVERT bool "MCUboot has been configured for DirectXIP with revert" select MCUBOOT_BOOTUTIL_LIB_FOR_DIRECT_XIP + select MCUBOOT_BOOTLOADER_MODE_HAS_NO_DOWNGRADE select MCUBOOT_BOOTLOADER_NO_DOWNGRADE help MCUboot expects slot0_partition and slot1_partition to exist in DT. From 45ac1f809fef282566c124dc676c951428d707bc Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Thu, 28 Sep 2023 11:10:55 +0000 Subject: [PATCH 131/421] [nrf noup] mgmt/MCUmgr/grp/img: Move out label to make compiler happy Move it inside ifdef. Signed-off-by: Dominik Ermel (cherry picked from commit 2fb8d761dbe3aeecc9285205cb9760701134463a) --- subsys/mgmt/mcumgr/grp/img_mgmt/src/img_mgmt_state.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/subsys/mgmt/mcumgr/grp/img_mgmt/src/img_mgmt_state.c b/subsys/mgmt/mcumgr/grp/img_mgmt/src/img_mgmt_state.c index 0968694c614..61515c14655 100644 --- a/subsys/mgmt/mcumgr/grp/img_mgmt/src/img_mgmt_state.c +++ b/subsys/mgmt/mcumgr/grp/img_mgmt/src/img_mgmt_state.c @@ -290,13 +290,14 @@ int img_mgmt_get_next_boot_slot(int image, enum img_mgmt_next_boot_type *type) return_slot = other_slot; } } +out: + #else if (rcs == 0 && rca == 0 && img_mgmt_vercmp(&aver, &over) < 0) { return_slot = other_slot; } #endif /* defined(CONFIG_MCUBOOT_BOOTLOADER_MODE_DIRECT_XIP_WITH_REVERT) */ -out: if (type != NULL) { *type = lt; } From 04cd082a7d7b34ee66b07682e158ccbfafd93d8f Mon Sep 17 00:00:00 2001 From: Robert Lubos Date: Wed, 23 Aug 2023 13:31:48 +0200 Subject: [PATCH 132/421] [nrf fromtree] net: dhcpv6: Add Zephyr DHCPv6 client Add a DHCPv6 client implementation for Zephyr (RFC 8415). The implementation allows to request IPv6 address and/or prefix from the DHCPv6 server, and for now supports only the mandatory set of DHCPv6 options needed to achieve this. Currently the implementation supports the following scenarios: * Requesting new IPv6 address/prefix with Solicit/Request exchange * Refreshing existing leases with Confirm, Renew or Rebind (depending on the context). For now, no Information Request (the case where neither IPv6 address or prefix are requested) is supported. No support for Reconfigure was added either, as this is optional (the client manifests clearly to the server that it does not support Reconfigure). Support for these can be added later if needed. Signed-off-by: Robert Lubos (cherry picked from commit e73e78a550870d593e244226320dcd1c0acbcd41) (cherry picked from commit 793fcb68f839f64cd121894d9031cb149f08854d) --- include/zephyr/net/dhcpv6.h | 116 ++ include/zephyr/net/net_if.h | 70 + subsys/net/ip/CMakeLists.txt | 1 + subsys/net/ip/Kconfig.ipv6 | 14 + subsys/net/ip/dhcpv6.c | 2196 +++++++++++++++++++++++++++++++ subsys/net/ip/dhcpv6_internal.h | 196 +++ subsys/net/ip/net_core.c | 6 + 7 files changed, 2599 insertions(+) create mode 100644 include/zephyr/net/dhcpv6.h create mode 100644 subsys/net/ip/dhcpv6.c create mode 100644 subsys/net/ip/dhcpv6_internal.h diff --git a/include/zephyr/net/dhcpv6.h b/include/zephyr/net/dhcpv6.h new file mode 100644 index 00000000000..95b59f530b5 --- /dev/null +++ b/include/zephyr/net/dhcpv6.h @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** @file + * @brief DHCPv6 client + */ + +#ifndef ZEPHYR_INCLUDE_NET_DHCPV6_H_ +#define ZEPHYR_INCLUDE_NET_DHCPV6_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief DHCPv6 + * @defgroup dhcpv6 DHCPv6 + * @ingroup networking + * @{ + */ + +/** @cond INTERNAL_HIDDEN */ + +/** Current state of DHCPv6 client address/prefix negotiation. */ +enum net_dhcpv6_state { + NET_DHCPV6_DISABLED, + NET_DHCPV6_INIT, + NET_DHCPV6_SOLICITING, + NET_DHCPV6_REQUESTING, + NET_DHCPV6_CONFIRMING, + NET_DHCPV6_RENEWING, + NET_DHCPV6_REBINDING, + NET_DHCPV6_INFO_REQUESTING, + NET_DHCPV6_BOUND, +} __packed; + +#define DHCPV6_TID_SIZE 3 +#define DHCPV6_DUID_MAX_SIZE 20 + +struct net_dhcpv6_duid_raw { + uint16_t type; + uint8_t buf[DHCPV6_DUID_MAX_SIZE]; +} __packed; + +struct net_dhcpv6_duid_storage { + struct net_dhcpv6_duid_raw duid; + uint8_t length; +}; + +struct net_if; + +/** @endcond */ + +/** @brief DHCPv6 client configuration parameters. */ +struct net_dhcpv6_params { + bool request_addr : 1; /**< Request IPv6 address. */ + bool request_prefix : 1; /**< Request IPv6 prefix. */ +}; + +/** + * @brief Start DHCPv6 client on an iface + * + * @details Start DHCPv6 client on a given interface. DHCPv6 client will start + * negotiation for IPv6 address and/or prefix, depending on the configuration. + * Once the negotiation is complete, IPv6 address/prefix details will be added + * to the interface. + * + * @param iface A valid pointer to a network interface + * @param params DHCPv6 client configuration parameters. + */ +void net_dhcpv6_start(struct net_if *iface, struct net_dhcpv6_params *params); + +/** + * @brief Stop DHCPv6 client on an iface + * + * @details Stop DHCPv6 client on a given interface. DHCPv6 client + * will remove all configuration obtained from a DHCP server from the + * interface and stop any further negotiation with the server. + * + * @param iface A valid pointer to a network interface + */ +void net_dhcpv6_stop(struct net_if *iface); + +/** + * @brief Restart DHCPv6 client on an iface + * + * @details Restart DHCPv6 client on a given interface. DHCPv6 client + * will restart the state machine without any of the initial delays. + * + * @param iface A valid pointer to a network interface + */ +void net_dhcpv6_restart(struct net_if *iface); + +/** @cond INTERNAL_HIDDEN */ + +/** + * @brief DHCPv6 state name + * + * @internal + */ +const char *net_dhcpv6_state_name(enum net_dhcpv6_state state); + +/** @endcond */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* ZEPHYR_INCLUDE_NET_DHCPV6_H_ */ diff --git a/include/zephyr/net/net_if.h b/include/zephyr/net/net_if.h index cced3557b84..b06bf74de03 100644 --- a/include/zephyr/net/net_if.h +++ b/include/zephyr/net/net_if.h @@ -33,6 +33,9 @@ #if defined(CONFIG_NET_DHCPV4) && defined(CONFIG_NET_NATIVE_IPV4) #include #endif +#if defined(CONFIG_NET_DHCPV6) && defined(CONFIG_NET_NATIVE_IPV6) +#include +#endif #if defined(CONFIG_NET_IPV4_AUTO) && defined(CONFIG_NET_NATIVE_IPV4) #include #endif @@ -275,6 +278,69 @@ struct net_if_ipv6 { uint8_t hop_limit; }; +#if defined(CONFIG_NET_DHCPV6) && defined(CONFIG_NET_NATIVE_IPV6) +struct net_if_dhcpv6 { + /** Used for timer list. */ + sys_snode_t node; + + /** Generated Client ID. */ + struct net_dhcpv6_duid_storage clientid; + + /** Server ID of the selected server. */ + struct net_dhcpv6_duid_storage serverid; + + /** DHCPv6 client state. */ + enum net_dhcpv6_state state; + + /** DHCPv6 client configuration parameters. */ + struct net_dhcpv6_params params; + + /** Timeout for the next event, absolute time, milliseconds. */ + uint64_t timeout; + + /** Time of the current exchange start, absolute time, milliseconds */ + uint64_t exchange_start; + + /** Renewal time, absolute time, milliseconds. */ + uint64_t t1; + + /** Rebinding time, absolute time, milliseconds. */ + uint64_t t2; + + /** The time when the last lease expires (terminates rebinding, + * DHCPv6 RFC8415, ch. 18.2.5). Absolute time, milliseconds. + */ + uint64_t expire; + + /** Generated IAID for IA_NA. */ + uint32_t addr_iaid; + + /** Generated IAID for IA_PD. */ + uint32_t prefix_iaid; + + /** Retransmit timeout for the current message, milliseconds. */ + uint32_t retransmit_timeout; + + /** Current best server preference received. */ + int16_t server_preference; + + /** Retransmission counter. */ + uint8_t retransmissions; + + /** Transaction ID for current exchange. */ + uint8_t tid[DHCPV6_TID_SIZE]; + + /** Prefix length. */ + uint8_t prefix_len; + + /** Assigned IPv6 prefix. */ + struct in6_addr prefix; + + /** Assigned IPv6 address. */ + struct in6_addr addr; +}; +#endif /* defined(CONFIG_NET_DHCPV6) && defined(CONFIG_NET_NATIVE_IPV6) */ + /** @cond INTERNAL_HIDDEN */ #if defined(CONFIG_NET_NATIVE_IPV4) #define NET_IF_MAX_IPV4_ADDR CONFIG_NET_IF_UNICAST_IPV4_ADDR_COUNT @@ -413,6 +479,10 @@ struct net_if_config { struct net_if_dhcpv4 dhcpv4; #endif /* CONFIG_NET_DHCPV4 */ +#if defined(CONFIG_NET_DHCPV6) && defined(CONFIG_NET_NATIVE_IPV6) + struct net_if_dhcpv6 dhcpv6; +#endif /* CONFIG_NET_DHCPV6 */ + #if defined(CONFIG_NET_IPV4_AUTO) && defined(CONFIG_NET_NATIVE_IPV4) struct net_if_ipv4_autoconf ipv4auto; #endif /* CONFIG_NET_IPV4_AUTO */ diff --git a/subsys/net/ip/CMakeLists.txt b/subsys/net/ip/CMakeLists.txt index 70655e2f61c..7dc54935c5c 100644 --- a/subsys/net/ip/CMakeLists.txt +++ b/subsys/net/ip/CMakeLists.txt @@ -31,6 +31,7 @@ zephyr_library_sources(net_tc.c) zephyr_library_sources_ifdef(CONFIG_NET_IP connection.c) zephyr_library_sources_ifdef(CONFIG_NET_6LO 6lo.c) zephyr_library_sources_ifdef(CONFIG_NET_DHCPV4 dhcpv4.c) +zephyr_library_sources_ifdef(CONFIG_NET_DHCPV6 dhcpv6.c) zephyr_library_sources_ifdef(CONFIG_NET_IPV4_AUTO ipv4_autoconf.c) zephyr_library_sources_ifdef(CONFIG_NET_IPV4 icmpv4.c ipv4.c) zephyr_library_sources_ifdef(CONFIG_NET_IPV4_IGMP igmp.c) diff --git a/subsys/net/ip/Kconfig.ipv6 b/subsys/net/ip/Kconfig.ipv6 index b776d3756eb..18fb4b0ccc4 100644 --- a/subsys/net/ip/Kconfig.ipv6 +++ b/subsys/net/ip/Kconfig.ipv6 @@ -166,6 +166,12 @@ config NET_MAX_6LO_CONTEXTS 6lowpan context options table size. The value depends on your network and memory consumption. More 6CO options uses more memory. +config NET_DHCPV6 + bool "DHCPv6 client" + select NET_MGMT + select NET_MGMT_EVENT + depends on NET_UDP + if NET_6LO module = NET_6LO module-dep = NET_LOG @@ -192,5 +198,13 @@ module-str = Log level for IPv6 neighbor cache module-help = Enables IPv6 Neighbor Cache code to output debug messages. source "subsys/net/Kconfig.template.log_config.net" +if NET_DHCPV6 +module = NET_DHCPV6 +module-dep = NET_LOG +module-str = Log level for DHCPv6 client +module-help = Enables DHCPv6 client code to output debug messages. +source "subsys/net/Kconfig.template.log_config.net" +endif # NET_DHCPV6 + endif # NET_NATIVE_IPV6 endif # NET_IPV6 diff --git a/subsys/net/ip/dhcpv6.c b/subsys/net/ip/dhcpv6.c new file mode 100644 index 00000000000..040c9fa0e06 --- /dev/null +++ b/subsys/net/ip/dhcpv6.c @@ -0,0 +1,2196 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** @file + * @brief DHCPv6 client implementation + */ + +#include +LOG_MODULE_REGISTER(net_dhcpv6, CONFIG_NET_DHCPV6_LOG_LEVEL); + +#include +#include +#include +#include + +#include "dhcpv6_internal.h" +#include "ipv6.h" +#include "net_private.h" +#include "udp_internal.h" + +/* Maximum number of options client can request. */ +#define DHCPV6_MAX_OPTION_REQUEST 2 + +struct dhcpv6_options_include { + bool clientid : 1; + bool serverid : 1; + bool elapsed_time : 1; + bool ia_na : 1; + bool iaaddr : 1; + bool ia_pd : 1; + bool iaprefix : 1; + uint16_t oro[DHCPV6_MAX_OPTION_REQUEST]; +}; + +static K_MUTEX_DEFINE(lock); + +/* All_DHCP_Relay_Agents_and_Servers (ff02::1:2) */ +static const struct in6_addr all_dhcpv6_ra_and_servers = { { { 0xff, 0x02, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0x01, 0, 0x02 } } }; + +static sys_slist_t dhcpv6_ifaces = SYS_SLIST_STATIC_INIT(&dhcpv6_ifaces); +static struct k_work_delayable dhcpv6_timeout_work; +static struct net_mgmt_event_callback dhcpv6_mgmt_cb; + +const char *net_dhcpv6_state_name(enum net_dhcpv6_state state) +{ + static const char * const name[] = { + "disabled", + "init", + "soliciting", + "requesting", + "confirming", + "renewing", + "rebinding", + "information requesting", + "bound", + }; + + __ASSERT_NO_MSG(state >= 0 && state < sizeof(name)); + return name[state]; +} + +static void dhcpv6_generate_tid(struct net_if *iface) +{ + sys_rand_get(iface->config.dhcpv6.tid, sizeof(iface->config.dhcpv6.tid)); +} + +static void dhcvp6_update_deadlines(struct net_if *iface, int64_t now, + uint32_t t1, uint32_t t2, + uint32_t preferred_lifetime, + uint32_t valid_lifetime) +{ + uint64_t t1_abs, t2_abs, expire_abs; + + /* In case server does not set T1/T2 values, the time choice is left to + * the client discretion. + * Here, we use recommendations for the servers, where it's advised to + * set T1/T2 as 0.5 and 0.8 of the preferred lifetime. + */ + if (t1 == 0 && t2 == 0) { + if (preferred_lifetime == DHCPV6_INFINITY) { + t1 = DHCPV6_INFINITY; + t2 = DHCPV6_INFINITY; + } else { + t1 = preferred_lifetime * 0.5; + t2 = preferred_lifetime * 0.8; + } + } else if (t1 == 0) { + if (t2 == DHCPV6_INFINITY) { + t1 = DHCPV6_INFINITY; + } else { + t1 = t2 * 0.625; /* 0.5 / 0.8 */ + } + } else if (t2 == 0) { + if (t1 == DHCPV6_INFINITY) { + t2 = DHCPV6_INFINITY; + } else { + t2 = t1 * 1.6; /* 0.8 / 0.5 */ + /* Overflow check. */ + if (t2 < t1) { + t2 = DHCPV6_INFINITY; + } + } + } else if (t1 >= t2) { + NET_ERR("Invalid T1(%u)/T2(%u) values.", t1, t2); + return; + } + + if (t1 == DHCPV6_INFINITY || + u64_add_overflow(now, 1000ULL * t1, &t1_abs)) { + t1_abs = UINT64_MAX; + } + + if (t2 == DHCPV6_INFINITY || + u64_add_overflow(now, 1000ULL * t2, &t2_abs)) { + t2_abs = UINT64_MAX; + } + + if (valid_lifetime == DHCPV6_INFINITY || + u64_add_overflow(now, 1000ULL * valid_lifetime, &expire_abs)) { + expire_abs = UINT64_MAX; + } + + if (iface->config.dhcpv6.t1 > t1_abs) { + iface->config.dhcpv6.t1 = t1_abs; + } + + if (iface->config.dhcpv6.t2 > t2_abs) { + iface->config.dhcpv6.t2 = t2_abs; + } + + if (iface->config.dhcpv6.expire < expire_abs) { + iface->config.dhcpv6.expire = expire_abs; + } +} + +static void dhcpv6_set_timeout(struct net_if *iface, uint64_t timeout) +{ + int64_t now = k_uptime_get(); + + NET_DBG("sched dhcpv6 timeout iface=%p timeout=%llums", iface, timeout); + + if (u64_add_overflow(now, timeout, &iface->config.dhcpv6.timeout)) { + iface->config.dhcpv6.timeout = UINT64_MAX; + } +} + +static void dhcpv6_reschedule(void) +{ + k_work_reschedule(&dhcpv6_timeout_work, K_NO_WAIT); +} + +static int randomize_timeout(int multiplier, int timeout) +{ + int factor; + + /* DHCPv6 RFC8415, ch. 15. the randomization factor should be a random + * number between -0.1 nand +0.1. As we operate on integers here, we + * scale it to -100 and +100, and divide the result by 1000. + */ + factor = (int)(sys_rand32_get() % 201) - 100; + + return (multiplier * timeout) + ((factor * timeout) / 1000); +} + +static int dhcpv6_initial_retransmit_time(int init_retransmit_time) +{ + /* DHCPv6 RFC8415, ch. 15. Retransmission time for the first msg. */ + return randomize_timeout(1, init_retransmit_time); +} + +static uint32_t dhcpv6_next_retransmit_time(int prev_retransmit_time, + int max_retransmit_time) +{ + int retransmit_time; + + /* DHCPv6 RFC8415, ch. 15. Retransmission time for the subsequent msg. */ + retransmit_time = randomize_timeout(2, prev_retransmit_time); + + if (max_retransmit_time == 0) { + return retransmit_time; + } + + if (retransmit_time > max_retransmit_time) { + retransmit_time = randomize_timeout(1, max_retransmit_time); + } + + return retransmit_time; +} + +/* DHCPv6 packet encoding functions */ + +static int dhcpv6_add_header(struct net_pkt *pkt, enum dhcpv6_msg_type type, + uint8_t *tid) +{ + int ret; + + ret = net_pkt_write_u8(pkt, type); + if (ret < 0) { + return ret; + } + + ret = net_pkt_write(pkt, tid, DHCPV6_TID_SIZE); + + return ret; +} + +static int dhcpv6_add_option_header(struct net_pkt *pkt, + enum dhcpv6_option_code code, + uint16_t length) +{ + int ret; + + ret = net_pkt_write_be16(pkt, code); + if (ret < 0) { + return ret; + } + + ret = net_pkt_write_be16(pkt, length); + + return ret; +} + +static int dhcpv6_add_option_clientid(struct net_pkt *pkt, + struct net_dhcpv6_duid_storage *clientid) +{ + int ret; + + ret = dhcpv6_add_option_header(pkt, DHCPV6_OPTION_CODE_CLIENTID, + clientid->length); + if (ret < 0) { + return ret; + } + + ret = net_pkt_write(pkt, &clientid->duid, clientid->length); + + return ret; +} + +static int dhcpv6_add_option_serverid(struct net_pkt *pkt, + struct net_dhcpv6_duid_storage *serverid) +{ + int ret; + + ret = dhcpv6_add_option_header(pkt, DHCPV6_OPTION_CODE_SERVERID, + serverid->length); + if (ret < 0) { + return ret; + } + + ret = net_pkt_write(pkt, &serverid->duid, serverid->length); + + return ret; +} + + +static int dhcpv6_add_option_elapsed_time(struct net_pkt *pkt, uint64_t since) +{ + uint64_t elapsed; + int ret; + + ret = dhcpv6_add_option_header(pkt, DHCPV6_OPTION_CODE_ELAPSED_TIME, + DHCPV6_OPTION_ELAPSED_TIME_SIZE); + if (ret < 0) { + return ret; + } + + /* Elapsed time should be expressed in hundredths of a second. */ + elapsed = (k_uptime_get() - since) / 10ULL; + if (elapsed > 0xFFFF) { + elapsed = 0xFFFF; + } + + ret = net_pkt_write_be16(pkt, (uint16_t)elapsed); + + return ret; +} + +static int dhcpv6_add_option_ia_na(struct net_pkt *pkt, struct dhcpv6_ia_na *ia_na, + bool include_addr) +{ + uint16_t optlen; + int ret; + + if (!include_addr) { + optlen = DHCPV6_OPTION_IA_NA_HEADER_SIZE; + } else { + optlen = DHCPV6_OPTION_IA_NA_HEADER_SIZE + + DHCPV6_OPTION_HEADER_SIZE + + DHCPV6_OPTION_IAADDR_HEADER_SIZE; + } + + ret = dhcpv6_add_option_header(pkt, DHCPV6_OPTION_CODE_IA_NA, optlen); + if (ret < 0) { + return ret; + } + + ret = net_pkt_write_be32(pkt, ia_na->iaid); + if (ret < 0) { + return ret; + } + + ret = net_pkt_write_be32(pkt, ia_na->t1); + if (ret < 0) { + return ret; + } + + ret = net_pkt_write_be32(pkt, ia_na->t2); + if (ret < 0) { + return ret; + } + + if (!include_addr) { + return 0; + } + + ret = dhcpv6_add_option_header(pkt, DHCPV6_OPTION_CODE_IAADDR, + DHCPV6_OPTION_IAADDR_HEADER_SIZE); + if (ret < 0) { + return ret; + } + + ret = net_pkt_write(pkt, &ia_na->iaaddr.addr, sizeof(ia_na->iaaddr.addr)); + if (ret < 0) { + return ret; + } + + ret = net_pkt_write_be32(pkt, ia_na->iaaddr.preferred_lifetime); + if (ret < 0) { + return ret; + } + + ret = net_pkt_write_be32(pkt, ia_na->iaaddr.valid_lifetime); + + return ret; +} + +static int dhcpv6_add_option_ia_pd(struct net_pkt *pkt, struct dhcpv6_ia_pd *ia_pd, + bool include_prefix) +{ + uint16_t optlen; + int ret; + + if (!include_prefix) { + optlen = DHCPV6_OPTION_IA_PD_HEADER_SIZE; + } else { + optlen = DHCPV6_OPTION_IA_PD_HEADER_SIZE + + DHCPV6_OPTION_HEADER_SIZE + + DHCPV6_OPTION_IAPREFIX_HEADER_SIZE; + } + + ret = dhcpv6_add_option_header(pkt, DHCPV6_OPTION_CODE_IA_PD, + optlen); + if (ret < 0) { + return ret; + } + + ret = net_pkt_write_be32(pkt, ia_pd->iaid); + if (ret < 0) { + return ret; + } + + ret = net_pkt_write_be32(pkt, ia_pd->t1); + if (ret < 0) { + return ret; + } + + ret = net_pkt_write_be32(pkt, ia_pd->t2); + if (ret < 0) { + return ret; + } + + if (!include_prefix) { + return 0; + } + + ret = dhcpv6_add_option_header(pkt, DHCPV6_OPTION_CODE_IAPREFIX, + DHCPV6_OPTION_IAPREFIX_HEADER_SIZE); + if (ret < 0) { + return ret; + } + + ret = net_pkt_write_be32(pkt, ia_pd->iaprefix.preferred_lifetime); + if (ret < 0) { + return ret; + } + + ret = net_pkt_write_be32(pkt, ia_pd->iaprefix.valid_lifetime); + if (ret < 0) { + return ret; + } + + ret = net_pkt_write_u8(pkt, ia_pd->iaprefix.prefix_len); + if (ret < 0) { + return ret; + } + + ret = net_pkt_write(pkt, &ia_pd->iaprefix.prefix, + sizeof(ia_pd->iaprefix.prefix)); + + return ret; +} + +static int dhcpv6_add_option_oro(struct net_pkt *pkt, uint16_t *codes, + int code_cnt) +{ + int ret; + + ret = dhcpv6_add_option_header(pkt, DHCPV6_OPTION_CODE_ORO, + sizeof(uint16_t) * code_cnt); + if (ret < 0) { + return ret; + } + + for (int i = 0; i < code_cnt; i++) { + ret = net_pkt_write_be16(pkt, codes[i]); + if (ret < 0) { + return ret; + } + } + + return ret; +} + +static size_t dhcpv6_calculate_message_size(struct dhcpv6_options_include *options) +{ + size_t msg_size = sizeof(struct dhcpv6_msg_hdr); + uint8_t oro_cnt = 0; + + if (options->clientid) { + msg_size += DHCPV6_OPTION_HEADER_SIZE; + msg_size += sizeof(struct net_dhcpv6_duid_storage); + } + + if (options->serverid) { + msg_size += DHCPV6_OPTION_HEADER_SIZE; + msg_size += sizeof(struct net_dhcpv6_duid_storage); + } + + if (options->elapsed_time) { + msg_size += DHCPV6_OPTION_HEADER_SIZE; + msg_size += DHCPV6_OPTION_ELAPSED_TIME_SIZE; + } + + if (options->ia_na) { + msg_size += DHCPV6_OPTION_HEADER_SIZE; + msg_size += DHCPV6_OPTION_IA_NA_HEADER_SIZE; + } + + if (options->iaaddr) { + msg_size += DHCPV6_OPTION_HEADER_SIZE; + msg_size += DHCPV6_OPTION_IAADDR_HEADER_SIZE; + } + + if (options->ia_pd) { + msg_size += DHCPV6_OPTION_HEADER_SIZE; + msg_size += DHCPV6_OPTION_IA_PD_HEADER_SIZE; + } + + if (options->iaprefix) { + msg_size += DHCPV6_OPTION_HEADER_SIZE; + msg_size += DHCPV6_OPTION_IAPREFIX_HEADER_SIZE; + } + + for (uint8_t i = 0; i < ARRAY_SIZE(options->oro); i++) { + if (options->oro[i] == 0) { + break; + } + + oro_cnt++; + } + + if (oro_cnt > 0) { + msg_size += DHCPV6_OPTION_HEADER_SIZE; + msg_size += oro_cnt * sizeof(uint16_t); + } + + return msg_size; +} + +static int dhcpv6_add_options(struct net_if *iface, struct net_pkt *pkt, + struct dhcpv6_options_include *options) +{ + uint8_t oro_cnt = 0; + int ret; + + if (options->clientid) { + ret = dhcpv6_add_option_clientid( + pkt, &iface->config.dhcpv6.clientid); + if (ret < 0) { + goto fail; + } + } + + if (options->serverid) { + ret = dhcpv6_add_option_serverid( + pkt, &iface->config.dhcpv6.serverid); + if (ret < 0) { + goto fail; + } + } + + if (options->elapsed_time) { + ret = dhcpv6_add_option_elapsed_time( + pkt, iface->config.dhcpv6.exchange_start); + if (ret < 0) { + goto fail; + } + } + + if (options->ia_na) { + struct dhcpv6_ia_na ia_na = { + .iaid = iface->config.dhcpv6.addr_iaid, + }; + + if (options->iaaddr) { + memcpy(&ia_na.iaaddr.addr, &iface->config.dhcpv6.addr, + sizeof(ia_na.iaaddr.addr)); + } + + ret = dhcpv6_add_option_ia_na(pkt, &ia_na, options->iaaddr); + if (ret < 0) { + goto fail; + } + } + + if (options->ia_pd) { + struct dhcpv6_ia_pd ia_pd = { + .iaid = iface->config.dhcpv6.prefix_iaid, + }; + + if (options->iaprefix) { + memcpy(&ia_pd.iaprefix.prefix, &iface->config.dhcpv6.prefix, + sizeof(ia_pd.iaprefix.prefix)); + ia_pd.iaprefix.prefix_len = iface->config.dhcpv6.prefix_len; + } + + ret = dhcpv6_add_option_ia_pd(pkt, &ia_pd, options->iaprefix); + if (ret < 0) { + goto fail; + } + } + + for (uint8_t i = 0; i < ARRAY_SIZE(options->oro); i++) { + if (options->oro[i] == 0) { + break; + } + + oro_cnt++; + } + + if (oro_cnt > 0) { + ret = dhcpv6_add_option_oro(pkt, options->oro, oro_cnt); + if (ret < 0) { + goto fail; + } + } + + return 0; + +fail: + return ret; +} + +static struct net_pkt *dhcpv6_create_message(struct net_if *iface, + enum dhcpv6_msg_type msg_type, + struct dhcpv6_options_include *options) +{ + struct in6_addr *local_addr; + struct net_pkt *pkt; + size_t msg_size; + + local_addr = net_if_ipv6_get_ll(iface, NET_ADDR_ANY_STATE); + if (local_addr == NULL) { + NET_ERR("No LL address"); + return NULL; + } + + msg_size = dhcpv6_calculate_message_size(options); + + pkt = net_pkt_alloc_with_buffer(iface, msg_size, AF_INET6, + IPPROTO_UDP, K_FOREVER); + if (pkt == NULL) { + return NULL; + } + + if (net_ipv6_create(pkt, local_addr, &all_dhcpv6_ra_and_servers) < 0 || + net_udp_create(pkt, htons(DHCPV6_CLIENT_PORT), + htons(DHCPV6_SERVER_PORT)) < 0) { + goto fail; + } + + dhcpv6_generate_tid(iface); + + if (dhcpv6_add_header(pkt, msg_type, iface->config.dhcpv6.tid) < 0) { + goto fail; + } + + if (dhcpv6_add_options(iface, pkt, options) < 0) { + goto fail; + } + + net_pkt_cursor_init(pkt); + net_ipv6_finalize(pkt, IPPROTO_UDP); + + return pkt; + +fail: + net_pkt_unref(pkt); + + return NULL; +} + +static int dhcpv6_send_solicit(struct net_if *iface) +{ + int ret; + struct net_pkt *pkt; + struct dhcpv6_options_include options = { + .clientid = true, + .elapsed_time = true, + .ia_na = iface->config.dhcpv6.params.request_addr, + .ia_pd = iface->config.dhcpv6.params.request_prefix, + .oro = { DHCPV6_OPTION_CODE_SOL_MAX_RT }, + }; + + pkt = dhcpv6_create_message(iface, DHCPV6_MSG_TYPE_SOLICIT, &options); + if (pkt == NULL) { + return -ENOMEM; + } + + ret = net_send_data(pkt); + if (ret < 0) { + net_pkt_unref(pkt); + } + + return ret; +} + +static int dhcpv6_send_request(struct net_if *iface) +{ + int ret; + struct net_pkt *pkt; + struct dhcpv6_options_include options = { + .clientid = true, + .serverid = true, + .elapsed_time = true, + .ia_na = iface->config.dhcpv6.params.request_addr, + .ia_pd = iface->config.dhcpv6.params.request_prefix, + .oro = { DHCPV6_OPTION_CODE_SOL_MAX_RT }, + }; + + pkt = dhcpv6_create_message(iface, DHCPV6_MSG_TYPE_REQUEST, &options); + if (pkt == NULL) { + return -ENOMEM; + } + + ret = net_send_data(pkt); + if (ret < 0) { + net_pkt_unref(pkt); + } + + return ret; +} + +static int dhcpv6_send_renew(struct net_if *iface) +{ + int ret; + struct net_pkt *pkt; + struct dhcpv6_options_include options = { + .clientid = true, + .serverid = true, + .elapsed_time = true, + .ia_na = iface->config.dhcpv6.params.request_addr, + .iaaddr = iface->config.dhcpv6.params.request_addr, + .ia_pd = iface->config.dhcpv6.params.request_prefix, + .iaprefix = iface->config.dhcpv6.params.request_prefix, + .oro = { DHCPV6_OPTION_CODE_SOL_MAX_RT }, + }; + + pkt = dhcpv6_create_message(iface, DHCPV6_MSG_TYPE_RENEW, &options); + if (pkt == NULL) { + return -ENOMEM; + } + + ret = net_send_data(pkt); + if (ret < 0) { + net_pkt_unref(pkt); + } + + return ret; +} + +static int dhcpv6_send_rebind(struct net_if *iface) +{ + int ret; + struct net_pkt *pkt; + struct dhcpv6_options_include options = { + .clientid = true, + .elapsed_time = true, + .ia_na = iface->config.dhcpv6.params.request_addr, + .iaaddr = iface->config.dhcpv6.params.request_addr, + .ia_pd = iface->config.dhcpv6.params.request_prefix, + .iaprefix = iface->config.dhcpv6.params.request_prefix, + .oro = { DHCPV6_OPTION_CODE_SOL_MAX_RT }, + }; + + pkt = dhcpv6_create_message(iface, DHCPV6_MSG_TYPE_REBIND, &options); + if (pkt == NULL) { + return -ENOMEM; + } + + ret = net_send_data(pkt); + if (ret < 0) { + net_pkt_unref(pkt); + } + + return ret; +} + +static int dhcpv6_send_confirm(struct net_if *iface) +{ + int ret; + struct net_pkt *pkt; + struct dhcpv6_options_include options = { + .clientid = true, + .elapsed_time = true, + .ia_na = true, + .iaaddr = true, + }; + + pkt = dhcpv6_create_message(iface, DHCPV6_MSG_TYPE_CONFIRM, &options); + if (pkt == NULL) { + return -ENOMEM; + } + + ret = net_send_data(pkt); + if (ret < 0) { + net_pkt_unref(pkt); + } + + return ret; +} + +/* DHCPv6 packet parsing functions */ + +static int dhcpv6_parse_option_clientid(struct net_pkt *pkt, uint16_t length, + struct net_dhcpv6_duid_storage *clientid) +{ + struct net_dhcpv6_duid_raw duid; + int ret; + + if (length > sizeof(struct net_dhcpv6_duid_raw)) { + NET_ERR("DUID too large to handle"); + return -EMSGSIZE; + } + + ret = net_pkt_read(pkt, &duid, length); + if (ret < 0) { + return ret; + } + + clientid->length = length; + memcpy(&clientid->duid, &duid, length); + + return 0; +} + +static int dhcpv6_parse_option_serverid(struct net_pkt *pkt, uint16_t length, + struct net_dhcpv6_duid_storage *serverid) +{ + struct net_dhcpv6_duid_raw duid; + int ret; + + if (length > sizeof(struct net_dhcpv6_duid_raw)) { + NET_ERR("DUID too large to handle"); + return -EMSGSIZE; + } + + ret = net_pkt_read(pkt, &duid, length); + if (ret < 0) { + return ret; + } + + serverid->length = length; + memcpy(&serverid->duid, &duid, length); + + return 0; +} + +static int dhcpv6_parse_option_preference(struct net_pkt *pkt, uint16_t length, + uint8_t *preference) +{ + if (length != DHCPV6_OPTION_PREFERENCE_SIZE) { + return -EBADMSG; + } + + if (net_pkt_read_u8(pkt, preference) < 0) { + return -EBADMSG; + } + + return 0; +} + +static int dhcpv6_parse_option_status_code(struct net_pkt *pkt, + uint16_t length, uint16_t *status) +{ + int ret; + + if (length < DHCPV6_OPTION_STATUS_CODE_HEADER_SIZE) { + NET_ERR("Invalid IAADDR option size"); + return -EMSGSIZE; + } + + ret = net_pkt_read_be16(pkt, status); + if (ret < 0) { + return ret; + } + + NET_DBG("status code %d", *status); + + length -= DHCPV6_OPTION_STATUS_CODE_HEADER_SIZE; + if (length > 0) { + /* Ignore status message */ + ret = net_pkt_skip(pkt, length); + } + + return ret; +} + +static int dhcpv6_parse_option_iaaddr(struct net_pkt *pkt, uint16_t length, + struct dhcpv6_iaaddr *iaaddr) +{ + int ret; + + if (length < DHCPV6_OPTION_IAADDR_HEADER_SIZE) { + NET_ERR("Invalid IAADDR option size"); + return -EMSGSIZE; + } + + ret = net_pkt_read(pkt, &iaaddr->addr, sizeof(iaaddr->addr)); + if (ret < 0) { + return ret; + } + + ret = net_pkt_read_be32(pkt, &iaaddr->preferred_lifetime); + if (ret < 0) { + return ret; + } + + ret = net_pkt_read_be32(pkt, &iaaddr->valid_lifetime); + if (ret < 0) { + return ret; + } + + /* DHCPv6 RFC8415, ch. 21.6 The client MUST discard any addresses for + * which the preferred lifetime is greater than the valid lifetime. + */ + if (iaaddr->preferred_lifetime > iaaddr->valid_lifetime) { + return -EBADMSG; + } + + NET_DBG("addr %s preferred_lifetime %d valid_lifetime %d", + net_sprint_ipv6_addr(&iaaddr->addr), iaaddr->preferred_lifetime, + iaaddr->valid_lifetime); + + iaaddr->status = DHCPV6_STATUS_SUCCESS; + + length -= DHCPV6_OPTION_IAADDR_HEADER_SIZE; + while (length > 0) { + uint16_t code, sublen; + + ret = net_pkt_read_be16(pkt, &code); + if (ret < 0) { + return ret; + } + + ret = net_pkt_read_be16(pkt, &sublen); + if (ret < 0) { + return ret; + } + + switch (code) { + case DHCPV6_OPTION_CODE_STATUS_CODE: + ret = dhcpv6_parse_option_status_code(pkt, sublen, + &iaaddr->status); + if (ret < 0) { + return ret; + } + + break; + default: + net_pkt_skip(pkt, sublen); + NET_DBG("Unexpected option %d length %d", code, sublen); + break; + } + + length -= (sublen + 4); + } + + return 0; +} + +static int dhcpv6_parse_option_ia_na(struct net_pkt *pkt, uint16_t length, + struct dhcpv6_ia_na *ia_na) +{ + int ret; + + if (length < DHCPV6_OPTION_IA_NA_HEADER_SIZE) { + NET_ERR("Invalid IA_NA option size"); + return -EMSGSIZE; + } + + ret = net_pkt_read_be32(pkt, &ia_na->iaid); + if (ret < 0) { + return ret; + } + + ret = net_pkt_read_be32(pkt, &ia_na->t1); + if (ret < 0) { + return ret; + } + + ret = net_pkt_read_be32(pkt, &ia_na->t2); + if (ret < 0) { + return ret; + } + + /* DHCPv6 RFC8415, ch. 21.4 If a client receives an IA_NA with T1 + * greater than T2 and both T1 and T2 are greater than 0, the client + * discards the IA_NA option and processes the remainder of the message + * as though the server had not included the invalid IA_NA option. + */ + if (ia_na->t1 != 0 && ia_na->t2 != 0 && ia_na->t1 > ia_na->t2) { + return -ENOENT; + } + + NET_DBG("iaid %d t1 %d t2 %d", ia_na->iaid, ia_na->t1, ia_na->t2); + + /* In case there's no IAADDR option, make this visible be setting + * error status. If the option is present, option parser will overwrite + * the value. + */ + ia_na->iaaddr.status = DHCPV6_STATUS_NO_ADDR_AVAIL; + ia_na->status = DHCPV6_STATUS_SUCCESS; + + length -= DHCPV6_OPTION_IA_NA_HEADER_SIZE; + while (length > 0) { + uint16_t code, sublen; + + ret = net_pkt_read_be16(pkt, &code); + if (ret < 0) { + return ret; + } + + ret = net_pkt_read_be16(pkt, &sublen); + if (ret < 0) { + return ret; + } + + switch (code) { + case DHCPV6_OPTION_CODE_IAADDR: + ret = dhcpv6_parse_option_iaaddr(pkt, sublen, + &ia_na->iaaddr); + if (ret < 0) { + return ret; + } + + break; + + case DHCPV6_OPTION_CODE_STATUS_CODE: + ret = dhcpv6_parse_option_status_code(pkt, sublen, + &ia_na->status); + if (ret < 0) { + return ret; + } + + break; + + default: + net_pkt_skip(pkt, sublen); + NET_DBG("Unexpected option %d length %d", code, sublen); + break; + } + + length -= (sublen + 4); + } + + return 0; +} + +static int dhcpv6_parse_option_iaprefix(struct net_pkt *pkt, uint16_t length, + struct dhcpv6_iaprefix *iaprefix) +{ + int ret; + + if (length < DHCPV6_OPTION_IAPREFIX_HEADER_SIZE) { + NET_ERR("Invalid IAPREFIX option size"); + return -EMSGSIZE; + } + + ret = net_pkt_read_be32(pkt, &iaprefix->preferred_lifetime); + if (ret < 0) { + return ret; + } + + ret = net_pkt_read_be32(pkt, &iaprefix->valid_lifetime); + if (ret < 0) { + return ret; + } + + ret = net_pkt_read_u8(pkt, &iaprefix->prefix_len); + if (ret < 0) { + return ret; + } + + ret = net_pkt_read(pkt, &iaprefix->prefix, sizeof(iaprefix->prefix)); + if (ret < 0) { + return ret; + } + + /* DHCPv6 RFC8415, ch. 21.22 The client MUST discard any prefixes for + * which the preferred lifetime is greater than the valid lifetime. + */ + if (iaprefix->preferred_lifetime > iaprefix->valid_lifetime) { + return -EBADMSG; + } + + NET_DBG("prefix %s/%u preferred_lifetime %d valid_lifetime %d", + net_sprint_ipv6_addr(&iaprefix->prefix), iaprefix->prefix_len, + iaprefix->preferred_lifetime, iaprefix->valid_lifetime); + + iaprefix->status = DHCPV6_STATUS_SUCCESS; + + length -= DHCPV6_OPTION_IAPREFIX_HEADER_SIZE; + while (length > 0) { + uint16_t code, sublen; + + ret = net_pkt_read_be16(pkt, &code); + if (ret < 0) { + return ret; + } + + ret = net_pkt_read_be16(pkt, &sublen); + if (ret < 0) { + return ret; + } + + switch (code) { + case DHCPV6_OPTION_CODE_STATUS_CODE: + ret = dhcpv6_parse_option_status_code(pkt, sublen, + &iaprefix->status); + if (ret < 0) { + return ret; + } + + break; + default: + net_pkt_skip(pkt, sublen); + NET_DBG("Unexpected option %d length %d", code, sublen); + break; + } + + length -= (sublen + 4); + } + + return 0; +} + +static int dhcpv6_parse_option_ia_pd(struct net_pkt *pkt, uint16_t length, + struct dhcpv6_ia_pd *ia_pd) +{ + int ret; + + if (length < DHCPV6_OPTION_IA_PD_HEADER_SIZE) { + NET_ERR("Invalid IA_PD option size"); + return -EMSGSIZE; + } + + ret = net_pkt_read_be32(pkt, &ia_pd->iaid); + if (ret < 0) { + return ret; + } + + ret = net_pkt_read_be32(pkt, &ia_pd->t1); + if (ret < 0) { + return ret; + } + + ret = net_pkt_read_be32(pkt, &ia_pd->t2); + if (ret < 0) { + return ret; + } + + /* DHCPv6 RFC8415, ch. 21.21 If a client receives an IA_PD with T1 + * greater than T2 and both T1 and T2 are greater than 0, the client + * discards the IA_PD option and processes the remainder of the message + * as though the server had not included the IA_PD option. + */ + if (ia_pd->t1 != 0 && ia_pd->t2 != 0 && ia_pd->t1 > ia_pd->t2) { + return -ENOENT; + } + + NET_DBG("iaid %d t1 %d t2 %d", ia_pd->iaid, ia_pd->t1, ia_pd->t2); + + /* In case there's no IAPREFIX option, make this visible be setting + * error status. If the option is present, option parser will overwrite + * the value. + */ + ia_pd->iaprefix.status = DHCPV6_STATUS_NO_PREFIX_AVAIL; + ia_pd->status = DHCPV6_STATUS_SUCCESS; + + length -= DHCPV6_OPTION_IA_PD_HEADER_SIZE; + while (length > 0) { + uint16_t code, sublen; + + ret = net_pkt_read_be16(pkt, &code); + if (ret < 0) { + return ret; + } + + ret = net_pkt_read_be16(pkt, &sublen); + if (ret < 0) { + return ret; + } + + switch (code) { + case DHCPV6_OPTION_CODE_IAPREFIX: + ret = dhcpv6_parse_option_iaprefix(pkt, sublen, + &ia_pd->iaprefix); + if (ret < 0) { + return ret; + } + + break; + + case DHCPV6_OPTION_CODE_STATUS_CODE: + ret = dhcpv6_parse_option_status_code(pkt, sublen, + &ia_pd->status); + if (ret < 0) { + return ret; + } + + break; + default: + net_pkt_skip(pkt, sublen); + NET_DBG("Unexpected option %d length %d", code, sublen); + break; + } + + length -= (sublen + 4); + } + + return 0; +} + +static int dhcpv6_find_option(struct net_pkt *pkt, enum dhcpv6_option_code opt_code, + uint16_t *opt_len) +{ + uint16_t length; + uint16_t code; + + while (net_pkt_read_be16(pkt, &code) == 0) { + if (net_pkt_read_be16(pkt, &length) < 0) { + return -EBADMSG; + } + + if (code == opt_code) { + *opt_len = length; + return 0; + } + + net_pkt_skip(pkt, length); + } + + return -ENOENT; +} + +static int dhcpv6_find_clientid(struct net_pkt *pkt, + struct net_dhcpv6_duid_storage *clientid) +{ + struct net_pkt_cursor backup; + uint16_t length; + int ret; + + net_pkt_cursor_backup(pkt, &backup); + + ret = dhcpv6_find_option(pkt, DHCPV6_OPTION_CODE_CLIENTID, &length); + if (ret == 0) { + ret = dhcpv6_parse_option_clientid(pkt, length, clientid); + } + + net_pkt_cursor_restore(pkt, &backup); + + return ret; +} + +static int dhcpv6_find_serverid(struct net_pkt *pkt, + struct net_dhcpv6_duid_storage *serverid) +{ + struct net_pkt_cursor backup; + uint16_t length; + int ret; + + net_pkt_cursor_backup(pkt, &backup); + + ret = dhcpv6_find_option(pkt, DHCPV6_OPTION_CODE_SERVERID, &length); + if (ret == 0) { + ret = dhcpv6_parse_option_serverid(pkt, length, serverid); + } + + net_pkt_cursor_restore(pkt, &backup); + + return ret; +} + +static int dhcpv6_find_server_preference(struct net_pkt *pkt, + uint8_t *preference) +{ + struct net_pkt_cursor backup; + uint16_t length; + int ret; + + net_pkt_cursor_backup(pkt, &backup); + + ret = dhcpv6_find_option(pkt, DHCPV6_OPTION_CODE_PREFERENCE, &length); + if (ret == 0) { + ret = dhcpv6_parse_option_preference(pkt, length, preference); + } else if (ret == -ENOENT) { + /* In case no preference option is present, default to 0. + * DHCPv6 RFC8415, ch. 18.2.1. + */ + *preference = 0; + ret = 0; + } + + net_pkt_cursor_restore(pkt, &backup); + + return ret; +} + +static int dhcpv6_find_ia_na(struct net_pkt *pkt, struct dhcpv6_ia_na *ia_na) +{ + struct net_pkt_cursor backup; + uint16_t length; + int ret; + + net_pkt_cursor_backup(pkt, &backup); + + ret = dhcpv6_find_option(pkt, DHCPV6_OPTION_CODE_IA_NA, &length); + if (ret == 0) { + ret = dhcpv6_parse_option_ia_na(pkt, length, ia_na); + } + + net_pkt_cursor_restore(pkt, &backup); + + return ret; +} + +static int dhcpv6_find_ia_pd(struct net_pkt *pkt, struct dhcpv6_ia_pd *ia_pd) +{ + struct net_pkt_cursor backup; + uint16_t length; + int ret; + + net_pkt_cursor_backup(pkt, &backup); + + ret = dhcpv6_find_option(pkt, DHCPV6_OPTION_CODE_IA_PD, &length); + if (ret == 0) { + ret = dhcpv6_parse_option_ia_pd(pkt, length, ia_pd); + } + + net_pkt_cursor_restore(pkt, &backup); + + return ret; +} + +static int dhcpv6_find_status_code(struct net_pkt *pkt, uint16_t *status) +{ + struct net_pkt_cursor backup; + uint16_t length; + int ret; + + net_pkt_cursor_backup(pkt, &backup); + + ret = dhcpv6_find_option(pkt, DHCPV6_OPTION_CODE_STATUS_CODE, &length); + if (ret == 0) { + ret = dhcpv6_parse_option_status_code(pkt, length, status); + } else if (ret == -ENOENT) { + /* In case no status option is present, default to success. + * DHCPv6 RFC8415, ch. 21.13. + */ + *status = DHCPV6_STATUS_SUCCESS; + ret = 0; + } + + net_pkt_cursor_restore(pkt, &backup); + + return ret; +} + +/* DHCPv6 state changes */ + +static void dhcpv6_enter_init(struct net_if *iface) +{ + uint32_t timeout; + + /* RFC8415 requires to wait a random period up to 1 second before + * sending the initial solicit/information request/confirm. + */ + timeout = sys_rand32_get() % DHCPV6_SOL_MAX_DELAY; + + dhcpv6_set_timeout(iface, timeout); +} + +static void dhcpv6_enter_soliciting(struct net_if *iface) +{ + iface->config.dhcpv6.retransmit_timeout = + dhcpv6_initial_retransmit_time(DHCPV6_SOL_TIMEOUT); + iface->config.dhcpv6.retransmissions = 0; + iface->config.dhcpv6.server_preference = -1; + iface->config.dhcpv6.exchange_start = k_uptime_get(); + + (void)dhcpv6_send_solicit(iface); + dhcpv6_set_timeout(iface, iface->config.dhcpv6.retransmit_timeout); +} + +static void dhcpv6_enter_requesting(struct net_if *iface) +{ + iface->config.dhcpv6.retransmit_timeout = + dhcpv6_initial_retransmit_time(DHCPV6_REQ_TIMEOUT); + iface->config.dhcpv6.retransmissions = 0; + iface->config.dhcpv6.exchange_start = k_uptime_get(); + + (void)dhcpv6_send_request(iface); + dhcpv6_set_timeout(iface, iface->config.dhcpv6.retransmit_timeout); +} + +static void dhcpv6_enter_renewing(struct net_if *iface) +{ + iface->config.dhcpv6.retransmit_timeout = + dhcpv6_initial_retransmit_time(DHCPV6_REN_TIMEOUT); + iface->config.dhcpv6.retransmissions = 0; + iface->config.dhcpv6.exchange_start = k_uptime_get(); + + (void)dhcpv6_send_renew(iface); + dhcpv6_set_timeout(iface, iface->config.dhcpv6.retransmit_timeout); +} + +static void dhcpv6_enter_rebinding(struct net_if *iface) +{ + iface->config.dhcpv6.retransmit_timeout = + dhcpv6_initial_retransmit_time(DHCPV6_REB_TIMEOUT); + iface->config.dhcpv6.retransmissions = 0; + iface->config.dhcpv6.exchange_start = k_uptime_get(); + + (void)dhcpv6_send_rebind(iface); + dhcpv6_set_timeout(iface, iface->config.dhcpv6.retransmit_timeout); +} + +static void dhcpv6_enter_confirming(struct net_if *iface) +{ + iface->config.dhcpv6.retransmit_timeout = + dhcpv6_initial_retransmit_time(DHCPV6_CNF_TIMEOUT); + iface->config.dhcpv6.retransmissions = 0; + iface->config.dhcpv6.exchange_start = k_uptime_get(); + + (void)dhcpv6_send_confirm(iface); + dhcpv6_set_timeout(iface, iface->config.dhcpv6.retransmit_timeout); +} + +static void dhcpv6_enter_bound(struct net_if *iface) +{ + iface->config.dhcpv6.timeout = iface->config.dhcpv6.t1; +} + +static void dhcpv6_enter_state(struct net_if *iface, enum net_dhcpv6_state state) +{ + iface->config.dhcpv6.state = state; + + NET_DBG("enter state=%s", + net_dhcpv6_state_name(iface->config.dhcpv6.state)); + + switch (iface->config.dhcpv6.state) { + case NET_DHCPV6_DISABLED: + break; + case NET_DHCPV6_INIT: + return dhcpv6_enter_init(iface); + case NET_DHCPV6_SOLICITING: + return dhcpv6_enter_soliciting(iface); + case NET_DHCPV6_REQUESTING: + return dhcpv6_enter_requesting(iface); + case NET_DHCPV6_CONFIRMING: + return dhcpv6_enter_confirming(iface); + case NET_DHCPV6_RENEWING: + return dhcpv6_enter_renewing(iface); + case NET_DHCPV6_REBINDING: + return dhcpv6_enter_rebinding(iface); + case NET_DHCPV6_INFO_REQUESTING: + break; + case NET_DHCPV6_BOUND: + return dhcpv6_enter_bound(iface); + } +} + +/* DHCPv6 input processing */ + +static int dhcpv6_handle_advertise(struct net_if *iface, struct net_pkt *pkt, + uint8_t *tid) +{ + struct net_dhcpv6_duid_storage duid = { 0 }; + struct dhcpv6_ia_pd ia_pd = { 0 }; + struct dhcpv6_ia_na ia_na = { 0 }; + uint8_t server_preference = 0; + uint16_t status = 0; + int ret; + + if (iface->config.dhcpv6.state != NET_DHCPV6_SOLICITING) { + return -EINVAL; + } + + /* Verify client ID. */ + ret = dhcpv6_find_clientid(pkt, &duid); + if (ret < 0) { + NET_ERR("Client ID missing"); + return ret; + } + + if (iface->config.dhcpv6.clientid.length != duid.length || + memcmp(&iface->config.dhcpv6.clientid.duid, &duid.duid, + iface->config.dhcpv6.clientid.length) != 0) { + NET_ERR("Client ID mismatch"); + return -EBADMSG; + } + + /* Verify server ID is present. */ + memset(&duid, 0, sizeof(duid)); + ret = dhcpv6_find_serverid(pkt, &duid); + if (ret < 0) { + NET_ERR("Server ID missing"); + return ret; + } + + /* Verify TID. */ + if (memcmp(iface->config.dhcpv6.tid, tid, + sizeof(iface->config.dhcpv6.tid)) != 0) { + NET_INFO("TID mismatch"); + return -EBADMSG; + } + + /* Verify status code. */ + ret = dhcpv6_find_status_code(pkt, &status); + if (ret < 0) { + return ret; + } + + if (status != DHCPV6_STATUS_SUCCESS) { + /* Ignore. */ + return 0; + } + + /* TODO Process SOL_MAX_RT/INF_MAX_RT options. */ + + /* Verify server preference. */ + ret = dhcpv6_find_server_preference(pkt, &server_preference); + if (ret < 0) { + return ret; + } + + if ((int16_t)server_preference < iface->config.dhcpv6.server_preference) { + /* Ignore. */ + return 0; + } + + /* Find/verify address. */ + if (iface->config.dhcpv6.params.request_addr) { + ret = dhcpv6_find_ia_na(pkt, &ia_na); + if (ret < 0) { + NET_ERR("Address missing"); + return ret; + } + + if (ia_na.status != DHCPV6_STATUS_SUCCESS || + ia_na.iaaddr.status != DHCPV6_STATUS_SUCCESS) { + /* Ignore. */ + return 0; + } + } + + /* Find/verify prefix. */ + if (iface->config.dhcpv6.params.request_prefix) { + ret = dhcpv6_find_ia_pd(pkt, &ia_pd); + if (ret < 0) { + NET_ERR("Prefix missing"); + return ret; + } + + if (ia_pd.status != DHCPV6_STATUS_SUCCESS || + ia_pd.iaprefix.status != DHCPV6_STATUS_SUCCESS) { + /* Ignore. */ + return 0; + } + } + + /* Valid advertisement received, store received offer. */ + memcpy(&iface->config.dhcpv6.serverid, &duid, + sizeof(iface->config.dhcpv6.serverid)); + iface->config.dhcpv6.server_preference = server_preference; + + /* DHCPv6 RFC8415, ch. 18.2.1, if client received Advertise + * message with maximum preference, or after the first + * retransmission period, it should proceed with the exchange, + * w/o further wait. + */ + if (server_preference == DHCPV6_MAX_SERVER_PREFERENCE || + iface->config.dhcpv6.retransmissions > 0) { + /* Reschedule immediately */ + dhcpv6_enter_state(iface, NET_DHCPV6_REQUESTING); + dhcpv6_reschedule(); + } + + return 0; +} + +static int dhcpv6_handle_reply(struct net_if *iface, struct net_pkt *pkt, + uint8_t *tid) +{ + struct net_dhcpv6_duid_storage duid = { 0 }; + struct dhcpv6_ia_pd ia_pd = { 0 }; + struct dhcpv6_ia_na ia_na = { 0 }; + int64_t now = k_uptime_get(); + uint16_t status = 0; + bool rediscover = false; + int ret; + + if (iface->config.dhcpv6.state != NET_DHCPV6_REQUESTING && + iface->config.dhcpv6.state != NET_DHCPV6_CONFIRMING && + iface->config.dhcpv6.state != NET_DHCPV6_RENEWING && + iface->config.dhcpv6.state != NET_DHCPV6_REBINDING) { + return -EINVAL; + } + + /* Verify client ID. */ + ret = dhcpv6_find_clientid(pkt, &duid); + if (ret < 0) { + NET_ERR("Client ID missing"); + return ret; + } + + if (iface->config.dhcpv6.clientid.length != duid.length || + memcmp(&iface->config.dhcpv6.clientid.duid, &duid.duid, + iface->config.dhcpv6.clientid.length) != 0) { + NET_ERR("Client ID mismatch"); + return -EBADMSG; + } + + /* Verify server ID is present. */ + memset(&duid, 0, sizeof(duid)); + ret = dhcpv6_find_serverid(pkt, &duid); + if (ret < 0) { + NET_ERR("Server ID missing"); + return ret; + } + + /* Verify TID. */ + if (memcmp(iface->config.dhcpv6.tid, tid, + sizeof(iface->config.dhcpv6.tid)) != 0) { + NET_INFO("TID mismatch"); + return -EBADMSG; + } + + /* TODO Process SOL_MAX_RT/INF_MAX_RT options. */ + + /* Verify status code. */ + ret = dhcpv6_find_status_code(pkt, &status); + if (ret < 0) { + return ret; + } + + if (status == DHCPV6_STATUS_UNSPEC_FAIL) { + /* Ignore and try again later. */ + return 0; + } + + /* DHCPv6 RFC8415, ch. 18.2.10.1. If the client receives a NotOnLink + * status from the server in response to (...) Request, the client can + * either reissue the message without specifying any addresses or + * restart the DHCP server discovery process. + * + * Restart discovery for our case. + */ + if (iface->config.dhcpv6.state == NET_DHCPV6_REQUESTING && + status == DHCPV6_STATUS_NOT_ON_LINK) { + rediscover = true; + goto out; + } + + /* In case of Confirm Reply, status success indicates the client can + * still use the address. + */ + if (iface->config.dhcpv6.state == NET_DHCPV6_CONFIRMING) { + if (status != DHCPV6_STATUS_SUCCESS) { + rediscover = true; + } + + goto out; + } + + /* Find/verify address. */ + if (iface->config.dhcpv6.params.request_addr) { + ret = dhcpv6_find_ia_na(pkt, &ia_na); + if (ret < 0) { + NET_ERR("Address missing"); + return ret; + } + + if (iface->config.dhcpv6.addr_iaid != ia_na.iaid) { + return -EBADMSG; + } + } + + /* Find/verify prefix. */ + if (iface->config.dhcpv6.params.request_prefix) { + ret = dhcpv6_find_ia_pd(pkt, &ia_pd); + if (ret < 0) { + NET_ERR("Prefix missing"); + return ret; + } + + if (iface->config.dhcpv6.prefix_iaid != ia_pd.iaid) { + return -EBADMSG; + } + } + + /* Valid response received, store received data. */ + iface->config.dhcpv6.t1 = UINT64_MAX; + iface->config.dhcpv6.t2 = UINT64_MAX; + iface->config.dhcpv6.expire = now; + + if (iface->config.dhcpv6.params.request_addr) { + struct net_if_addr *ifaddr; + + if (ia_na.status == DHCPV6_STATUS_NO_ADDR_AVAIL || + ia_na.iaaddr.status == DHCPV6_STATUS_NO_ADDR_AVAIL || + ia_na.iaaddr.valid_lifetime == 0) { + /* Remove old lease. */ + net_if_ipv6_addr_rm(iface, &iface->config.dhcpv6.addr); + memset(&iface->config.dhcpv6.addr, 0, sizeof(struct in6_addr)); + rediscover = true; + goto prefix; + } + + /* TODO On nobiding (renew/rebind) go to requesting */ + + if (!net_ipv6_addr_cmp(&iface->config.dhcpv6.addr, + net_ipv6_unspecified_address()) && + !net_ipv6_addr_cmp(&iface->config.dhcpv6.addr, + &ia_na.iaaddr.addr)) { + /* Remove old lease. */ + net_if_ipv6_addr_rm(iface, &iface->config.dhcpv6.addr); + } + + memcpy(&iface->config.dhcpv6.addr, &ia_na.iaaddr.addr, + sizeof(iface->config.dhcpv6.addr)); + + dhcvp6_update_deadlines(iface, now, ia_na.t1, ia_na.t2, + ia_na.iaaddr.preferred_lifetime, + ia_na.iaaddr.valid_lifetime); + + ifaddr = net_if_ipv6_addr_lookup_by_iface(iface, &ia_na.iaaddr.addr); + if (ifaddr != NULL) { + net_if_ipv6_addr_update_lifetime( + ifaddr, ia_na.iaaddr.valid_lifetime); + } else if (net_if_ipv6_addr_add(iface, &ia_na.iaaddr.addr, NET_ADDR_DHCP, + ia_na.iaaddr.valid_lifetime) == NULL) { + NET_ERR("Failed to configure DHCPv6 address"); + net_dhcpv6_stop(iface); + return -EFAULT; + } + } + +prefix: + if (iface->config.dhcpv6.params.request_prefix) { + struct net_if_ipv6_prefix *ifprefix; + + if (ia_pd.status == DHCPV6_STATUS_NO_PREFIX_AVAIL || + ia_pd.iaprefix.status == DHCPV6_STATUS_NO_PREFIX_AVAIL || + ia_pd.iaprefix.valid_lifetime == 0) { + /* Remove old lease. */ + net_if_ipv6_prefix_rm(iface, &iface->config.dhcpv6.prefix, + iface->config.dhcpv6.prefix_len); + memset(&iface->config.dhcpv6.prefix, 0, sizeof(struct in6_addr)); + iface->config.dhcpv6.prefix_len = 0; + rediscover = true; + goto out; + } + + if (!net_ipv6_addr_cmp(&iface->config.dhcpv6.prefix, + net_ipv6_unspecified_address()) && + (!net_ipv6_addr_cmp(&iface->config.dhcpv6.prefix, + &ia_pd.iaprefix.prefix) || + iface->config.dhcpv6.prefix_len != ia_pd.iaprefix.prefix_len)) { + /* Remove old lease. */ + net_if_ipv6_prefix_rm(iface, &iface->config.dhcpv6.prefix, + iface->config.dhcpv6.prefix_len); + } + + iface->config.dhcpv6.prefix_len = ia_pd.iaprefix.prefix_len; + + memcpy(&iface->config.dhcpv6.prefix, &ia_pd.iaprefix.prefix, + sizeof(iface->config.dhcpv6.prefix)); + + dhcvp6_update_deadlines(iface, now, ia_pd.t1, ia_pd.t2, + ia_pd.iaprefix.preferred_lifetime, + ia_pd.iaprefix.valid_lifetime); + + ifprefix = net_if_ipv6_prefix_lookup(iface, &ia_pd.iaprefix.prefix, + ia_pd.iaprefix.prefix_len); + if (ifprefix != NULL) { + net_if_ipv6_prefix_set_timer(ifprefix, ia_pd.iaprefix.valid_lifetime); + } else if (net_if_ipv6_prefix_add(iface, &ia_pd.iaprefix.prefix, + ia_pd.iaprefix.prefix_len, + ia_pd.iaprefix.valid_lifetime) == NULL) { + NET_ERR("Failed to configure DHCPv6 prefix"); + net_dhcpv6_stop(iface); + return -EFAULT; + } + } + +out: + if (rediscover) { + dhcpv6_enter_state(iface, NET_DHCPV6_SOLICITING); + } else { + dhcpv6_enter_state(iface, NET_DHCPV6_BOUND); + } + + dhcpv6_reschedule(); + + return 0; +} + +static int dhcpv6_handle_reconfigure(struct net_if *iface, struct net_pkt *pkt) +{ + /* Reconfigure not supported yet. */ + return -ENOTSUP; +} + +static enum net_verdict dhcpv6_input(struct net_conn *conn, + struct net_pkt *pkt, + union net_ip_header *ip_hdr, + union net_proto_header *proto_hdr, + void *user_data) +{ + struct net_if *iface; + uint8_t msg_type; + uint8_t tid[DHCPV6_TID_SIZE]; + int ret; + + if (!conn) { + NET_ERR("Invalid connection"); + return NET_DROP; + } + + if (!pkt) { + NET_ERR("Invalid packet"); + return NET_DROP; + } + + iface = net_pkt_iface(pkt); + if (!iface) { + NET_ERR("No interface"); + return NET_DROP; + } + + net_pkt_cursor_init(pkt); + + if (net_pkt_skip(pkt, NET_IPV6UDPH_LEN)) { + NET_ERR("Missing IPv6/UDP header"); + return NET_DROP; + } + + if (net_pkt_read_u8(pkt, &msg_type) < 0) { + NET_ERR("Missing message type"); + return NET_DROP; + } + + if (net_pkt_read(pkt, tid, sizeof(tid)) < 0) { + NET_ERR("Missing transaction ID"); + return NET_DROP; + } + + NET_DBG("Received DHCPv6 packet [type=%d, tid=0x%02x%02x%02x]", + msg_type, tid[0], tid[1], tid[2]); + + switch (msg_type) { + case DHCPV6_MSG_TYPE_ADVERTISE: + ret = dhcpv6_handle_advertise(iface, pkt, tid); + break; + case DHCPV6_MSG_TYPE_REPLY: + ret = dhcpv6_handle_reply(iface, pkt, tid); + break; + case DHCPV6_MSG_TYPE_RECONFIGURE: + ret = dhcpv6_handle_reconfigure(iface, pkt); + break; + case DHCPV6_MSG_TYPE_SOLICIT: + case DHCPV6_MSG_TYPE_REQUEST: + case DHCPV6_MSG_TYPE_CONFIRM: + case DHCPV6_MSG_TYPE_RENEW: + case DHCPV6_MSG_TYPE_REBIND: + case DHCPV6_MSG_TYPE_RELEASE: + case DHCPV6_MSG_TYPE_DECLINE: + case DHCPV6_MSG_TYPE_INFORMATION_REQUEST: + case DHCPV6_MSG_TYPE_RELAY_FORW: + case DHCPV6_MSG_TYPE_RELAY_REPL: + default: + goto drop; + } + + if (ret < 0) { + goto drop; + } + + net_pkt_unref(pkt); + + return NET_OK; + +drop: + return NET_DROP; +} + +/* DHCPv6 timer management */ + +static uint64_t dhcpv6_timeleft(struct net_if *iface, int64_t now) +{ + uint64_t timeout = iface->config.dhcpv6.timeout; + + if (timeout > now) { + return timeout - now; + } + + return 0; +} + +static uint64_t dhcpv6_manage_timers(struct net_if *iface, int64_t now) +{ + uint64_t timeleft = dhcpv6_timeleft(iface, now); + + NET_DBG("iface %p state=%s timeleft=%llu", iface, + net_dhcpv6_state_name(iface->config.dhcpv6.state), timeleft); + + if (timeleft != 0U) { + return iface->config.dhcpv6.timeout; + } + + if (!net_if_is_up(iface)) { + /* An interface is down, the registered event handler will + * restart DHCP procedure when the interface is back up. + */ + return UINT64_MAX; + } + + switch (iface->config.dhcpv6.state) { + case NET_DHCPV6_DISABLED: + break; + case NET_DHCPV6_INIT: { + bool have_addr = false; + bool have_prefix = false; + + if (iface->config.dhcpv6.params.request_addr && + !net_ipv6_addr_cmp(&iface->config.dhcpv6.addr, + net_ipv6_unspecified_address())) { + have_addr = true; + } + + if (iface->config.dhcpv6.params.request_prefix && + !net_ipv6_addr_cmp(&iface->config.dhcpv6.prefix, + net_ipv6_unspecified_address())) { + have_prefix = true; + } + + if ((have_addr || have_prefix) && now < iface->config.dhcpv6.expire) { + /* Try to confirm the address/prefix. In case + * prefix is requested, Rebind is used with + * Confirm timings. + */ + iface->config.dhcpv6.expire = now + DHCPV6_CNF_MAX_RD; + + if (!iface->config.dhcpv6.params.request_prefix) { + dhcpv6_enter_state(iface, NET_DHCPV6_CONFIRMING); + } else { + dhcpv6_enter_state(iface, NET_DHCPV6_REBINDING); + } + } else { + dhcpv6_enter_state(iface, NET_DHCPV6_SOLICITING); + } + + return iface->config.dhcpv6.timeout; + } + case NET_DHCPV6_SOLICITING: + if (iface->config.dhcpv6.server_preference >= 0) { + dhcpv6_enter_state(iface, NET_DHCPV6_REQUESTING); + return iface->config.dhcpv6.timeout; + } + + iface->config.dhcpv6.retransmissions++; + iface->config.dhcpv6.retransmit_timeout = + dhcpv6_next_retransmit_time( + iface->config.dhcpv6.retransmit_timeout, + DHCPV6_SOL_MAX_RT); + + (void)dhcpv6_send_solicit(iface); + dhcpv6_set_timeout(iface, iface->config.dhcpv6.retransmit_timeout); + + return iface->config.dhcpv6.timeout; + case NET_DHCPV6_REQUESTING: + if (iface->config.dhcpv6.retransmissions >= DHCPV6_REQ_MAX_RC) { + /* Back to soliciting. */ + dhcpv6_enter_state(iface, NET_DHCPV6_SOLICITING); + return iface->config.dhcpv6.timeout; + } + + iface->config.dhcpv6.retransmissions++; + iface->config.dhcpv6.retransmit_timeout = + dhcpv6_next_retransmit_time( + iface->config.dhcpv6.retransmit_timeout, + DHCPV6_REQ_MAX_RT); + + (void)dhcpv6_send_request(iface); + dhcpv6_set_timeout(iface, iface->config.dhcpv6.retransmit_timeout); + + return iface->config.dhcpv6.timeout; + case NET_DHCPV6_CONFIRMING: + if (now >= iface->config.dhcpv6.expire) { + dhcpv6_enter_state(iface, NET_DHCPV6_SOLICITING); + return iface->config.dhcpv6.timeout; + } + + iface->config.dhcpv6.retransmissions++; + iface->config.dhcpv6.retransmit_timeout = + dhcpv6_next_retransmit_time( + iface->config.dhcpv6.retransmit_timeout, + DHCPV6_CNF_MAX_RT); + + (void)dhcpv6_send_confirm(iface); + dhcpv6_set_timeout(iface, iface->config.dhcpv6.retransmit_timeout); + + if (iface->config.dhcpv6.timeout > iface->config.dhcpv6.expire) { + iface->config.dhcpv6.timeout = iface->config.dhcpv6.expire; + } + + return iface->config.dhcpv6.timeout; + case NET_DHCPV6_RENEWING: + if (now >= iface->config.dhcpv6.t2) { + dhcpv6_enter_state(iface, NET_DHCPV6_REBINDING); + return iface->config.dhcpv6.timeout; + } + + iface->config.dhcpv6.retransmissions++; + iface->config.dhcpv6.retransmit_timeout = + dhcpv6_next_retransmit_time( + iface->config.dhcpv6.retransmit_timeout, + DHCPV6_REN_MAX_RT); + + (void)dhcpv6_send_renew(iface); + dhcpv6_set_timeout(iface, iface->config.dhcpv6.retransmit_timeout); + + if (iface->config.dhcpv6.timeout > iface->config.dhcpv6.t2) { + iface->config.dhcpv6.timeout = iface->config.dhcpv6.t2; + } + + return iface->config.dhcpv6.timeout; + case NET_DHCPV6_REBINDING: + if (now >= iface->config.dhcpv6.expire) { + dhcpv6_enter_state(iface, NET_DHCPV6_SOLICITING); + return iface->config.dhcpv6.timeout; + } + + iface->config.dhcpv6.retransmissions++; + iface->config.dhcpv6.retransmit_timeout = + dhcpv6_next_retransmit_time( + iface->config.dhcpv6.retransmit_timeout, + DHCPV6_REB_MAX_RT); + + (void)dhcpv6_send_rebind(iface); + dhcpv6_set_timeout(iface, iface->config.dhcpv6.retransmit_timeout); + + if (iface->config.dhcpv6.timeout > iface->config.dhcpv6.expire) { + iface->config.dhcpv6.timeout = iface->config.dhcpv6.expire; + } + + return iface->config.dhcpv6.timeout; + case NET_DHCPV6_INFO_REQUESTING: + break; + case NET_DHCPV6_BOUND: + dhcpv6_enter_state(iface, NET_DHCPV6_RENEWING); + return iface->config.dhcpv6.timeout; + } + + return UINT64_MAX; +} + +static void dhcpv6_timeout(struct k_work *work) +{ + uint64_t timeout_update = UINT64_MAX; + int64_t now = k_uptime_get(); + struct net_if_dhcpv6 *current, *next; + + ARG_UNUSED(work); + + k_mutex_lock(&lock, K_FOREVER); + + SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&dhcpv6_ifaces, current, next, node) { + struct net_if *iface = CONTAINER_OF( + CONTAINER_OF(current, struct net_if_config, dhcpv6), + struct net_if, config); + uint64_t next_timeout; + + next_timeout = dhcpv6_manage_timers(iface, now); + if (next_timeout < timeout_update) { + timeout_update = next_timeout; + } + } + + k_mutex_unlock(&lock); + + if (timeout_update != UINT64_MAX) { + if (now > timeout_update) { + timeout_update = 0ULL; + } else { + timeout_update -= now; + } + + NET_DBG("Waiting for %llums", timeout_update); + k_work_reschedule(&dhcpv6_timeout_work, K_MSEC(timeout_update)); + } +} + +static void dhcpv6_iface_event_handler(struct net_mgmt_event_callback *cb, + uint32_t mgmt_event, struct net_if *iface) +{ + sys_snode_t *node = NULL; + + k_mutex_lock(&lock, K_FOREVER); + + SYS_SLIST_FOR_EACH_NODE(&dhcpv6_ifaces, node) { + if (node == &iface->config.dhcpv6.node) { + break; + } + } + + if (node == NULL) { + goto out; + } + + if (mgmt_event == NET_EVENT_IF_DOWN) { + NET_DBG("Interface %p going down", iface); + dhcpv6_set_timeout(iface, UINT64_MAX); + } else if (mgmt_event == NET_EVENT_IF_UP) { + NET_DBG("Interface %p coming up", iface); + dhcpv6_enter_state(iface, NET_DHCPV6_INIT); + } + + dhcpv6_reschedule(); + +out: + k_mutex_unlock(&lock); +} + +static void dhcpv6_generate_client_duid(struct net_if *iface) +{ + struct net_linkaddr *lladdr = net_if_get_link_addr(iface); + struct net_dhcpv6_duid_storage *clientid = &iface->config.dhcpv6.clientid; + struct dhcpv6_duid_ll *duid_ll = + (struct dhcpv6_duid_ll *)&clientid->duid.buf; + + memset(clientid, 0, sizeof(*clientid)); + + UNALIGNED_PUT(htons(DHCPV6_DUID_TYPE_LL), &clientid->duid.type); + UNALIGNED_PUT(htons(DHCPV6_HARDWARE_ETHERNET_TYPE), &duid_ll->hw_type); + memcpy(duid_ll->ll_addr, lladdr->addr, lladdr->len); + + clientid->length = DHCPV6_DUID_LL_HEADER_SIZE + lladdr->len; +} + +/* DHCPv6 public API */ + +void net_dhcpv6_start(struct net_if *iface, struct net_dhcpv6_params *params) +{ + k_mutex_lock(&lock, K_FOREVER); + + if (iface->config.dhcpv6.state != NET_DHCPV6_DISABLED) { + NET_ERR("DHCPv6 already running on iface %p, state %s", iface, + net_dhcpv6_state_name(iface->config.dhcpv6.state)); + goto out; + } + + if (!params->request_addr && !params->request_addr) { + NET_ERR("Information Request not supported yet"); + goto out; + } + + NET_DBG("Starting DHCPv6 on iface %p", iface); + + iface->config.dhcpv6.params = *params; + + if (sys_slist_is_empty(&dhcpv6_ifaces)) { + net_mgmt_add_event_callback(&dhcpv6_mgmt_cb); + } + + sys_slist_append(&dhcpv6_ifaces, &iface->config.dhcpv6.node); + + if (params->request_addr) { + iface->config.dhcpv6.addr_iaid = net_if_get_by_iface(iface); + } + + if (params->request_prefix) { + iface->config.dhcpv6.prefix_iaid = net_if_get_by_iface(iface); + } + + dhcpv6_generate_client_duid(iface); + dhcpv6_enter_state(iface, NET_DHCPV6_INIT); + dhcpv6_reschedule(); + +out: + k_mutex_unlock(&lock); +} + +void net_dhcpv6_stop(struct net_if *iface) +{ + k_mutex_lock(&lock, K_FOREVER); + + switch (iface->config.dhcpv6.state) { + case NET_DHCPV6_DISABLED: + NET_INFO("DHCPv6 already disabled on iface %p", iface); + break; + + case NET_DHCPV6_INIT: + case NET_DHCPV6_SOLICITING: + case NET_DHCPV6_REQUESTING: + case NET_DHCPV6_CONFIRMING: + case NET_DHCPV6_RENEWING: + case NET_DHCPV6_REBINDING: + case NET_DHCPV6_INFO_REQUESTING: + case NET_DHCPV6_BOUND: + NET_DBG("Stopping DHCPv6 on iface %p, state %s", iface, + net_dhcpv6_state_name(iface->config.dhcpv6.state)); + + (void)dhcpv6_enter_state(iface, NET_DHCPV6_DISABLED); + + sys_slist_find_and_remove(&dhcpv6_ifaces, + &iface->config.dhcpv6.node); + + if (sys_slist_is_empty(&dhcpv6_ifaces)) { + (void)k_work_cancel_delayable(&dhcpv6_timeout_work); + net_mgmt_del_event_callback(&dhcpv6_mgmt_cb); + } + + break; + } + + k_mutex_unlock(&lock); +} + +void net_dhcpv6_restart(struct net_if *iface) +{ + struct net_dhcpv6_params params = iface->config.dhcpv6.params; + + net_dhcpv6_stop(iface); + net_dhcpv6_start(iface, ¶ms); +} + +int net_dhcpv6_init(void) +{ + struct sockaddr unspec_addr; + int ret; + + net_ipaddr_copy(&net_sin6(&unspec_addr)->sin6_addr, + net_ipv6_unspecified_address()); + unspec_addr.sa_family = AF_INET6; + + ret = net_udp_register(AF_INET6, NULL, &unspec_addr, + DHCPV6_SERVER_PORT, DHCPV6_CLIENT_PORT, + NULL, dhcpv6_input, NULL, NULL); + if (ret < 0) { + NET_DBG("UDP callback registration failed"); + return ret; + } + + k_work_init_delayable(&dhcpv6_timeout_work, dhcpv6_timeout); + net_mgmt_init_event_callback(&dhcpv6_mgmt_cb, dhcpv6_iface_event_handler, + NET_EVENT_IF_DOWN | NET_EVENT_IF_UP); + + return 0; +} diff --git a/subsys/net/ip/dhcpv6_internal.h b/subsys/net/ip/dhcpv6_internal.h new file mode 100644 index 00000000000..5ec129e601f --- /dev/null +++ b/subsys/net/ip/dhcpv6_internal.h @@ -0,0 +1,196 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** @file + * @brief DHCPv6 internal header + * + * This header should not be included by the application. + */ + +#ifndef DHCPV6_INTERNAL_H_ +#define DHCPV6_INTERNAL_H_ + +#include + +#define DHCPV6_DUID_TYPE_SIZE 2 +#define DHVPV6_DUID_LL_HW_TYPE_SIZE 2 +#define DHCPV6_DUID_LL_HEADER_SIZE (DHCPV6_DUID_TYPE_SIZE + \ + DHVPV6_DUID_LL_HW_TYPE_SIZE) + +#define DHCPV6_MSG_TYPE_SIZE 1 +#define DHCPV6_HEADER_SIZE (DHCPV6_MSG_TYPE_SIZE + DHCPV6_TID_SIZE) + +#define DHCPV6_OPTION_CODE_SIZE 2 +#define DHCPV6_OPTION_LENGTH_SIZE 2 +#define DHCPV6_OPTION_HEADER_SIZE (DHCPV6_OPTION_CODE_SIZE + \ + DHCPV6_OPTION_LENGTH_SIZE) + +#define DHCPV6_OPTION_PREFERENCE_SIZE 1 +#define DHCPV6_OPTION_ELAPSED_TIME_SIZE 2 +#define DHCPV6_OPTION_ELAPSED_TIME_SIZE 2 +#define DHCPV6_OPTION_IA_NA_HEADER_SIZE 12 +#define DHCPV6_OPTION_IAADDR_HEADER_SIZE 24 +#define DHCPV6_OPTION_IA_PD_HEADER_SIZE 12 +#define DHCPV6_OPTION_IAPREFIX_HEADER_SIZE 25 +#define DHCPV6_OPTION_IAADDR_HEADER_SIZE 24 +#define DHCPV6_OPTION_IAPREFIX_HEADER_SIZE 25 +#define DHCPV6_OPTION_STATUS_CODE_HEADER_SIZE 2 + +#define DHCPV6_INFINITY UINT32_MAX +#define DHCPV6_MAX_SERVER_PREFERENCE 255 + +#define DHCPV6_HARDWARE_ETHERNET_TYPE 1 + +#define DHCPV6_CLIENT_PORT 546 +#define DHCPV6_SERVER_PORT 547 + +/* DHCPv6 Transmission/retransmission timeouts */ +#define DHCPV6_SOL_MAX_DELAY 1000 /* Max delay of first Solicit, milliseconds */ +#define DHCPV6_SOL_TIMEOUT 1000 /* Initial Solicit timeout, milliseconds */ +#define DHCPV6_SOL_MAX_RT 3600000 /* Max Solicit timeout value, milliseconds */ +#define DHCPV6_REQ_TIMEOUT 1000 /* Initial Request timeout, milliseconds */ +#define DHCPV6_REQ_MAX_RT 30000 /* Max Request timeout value, milliseconds */ +#define DHCPV6_REQ_MAX_RC 10 /* Max Request retry attempts */ +#define DHCPV6_CNF_MAX_DELAY 1000 /* Max delay of first Confirm, milliseconds */ +#define DHCPV6_CNF_TIMEOUT 1000 /* Initial Confirm timeout, milliseconds */ +#define DHCPV6_CNF_MAX_RT 4000 /* Max Confirm timeout, milliseconds */ +#define DHCPV6_CNF_MAX_RD 10000 /* Max Confirm duration, milliseconds */ +#define DHCPV6_REN_TIMEOUT 10000 /* Initial Renew timeout, milliseconds */ +#define DHCPV6_REN_MAX_RT 600000 /* Max Renew timeout value, milliseconds */ +#define DHCPV6_REB_TIMEOUT 10000 /* Initial Rebind timeout, milliseconds */ +#define DHCPV6_REB_MAX_RT 600000 /* Max Rebind timeout value, milliseconds */ + +/* DUID structures */ +struct dhcpv6_duid_llt { + uint16_t hw_type; + uint32_t time; + uint8_t ll_addr[]; +} __packed; + +struct dhcpv6_duid_en { + uint32_t enterprise_number; + uint8_t identifier[]; +} __packed; + +struct dhcpv6_duid_ll { + uint16_t hw_type; + uint8_t ll_addr[]; +} __packed; + +struct dhcpv6_duid_uuid { + uint8_t uuid[16]; +} __packed; + +struct dhcpv6_msg_hdr { + uint8_t type; /* Message type */ + uint8_t tid[3]; /* Transaction ID */ +} __packed; + +struct dhcpv6_iaaddr { + uint32_t preferred_lifetime; + uint32_t valid_lifetime; + struct in6_addr addr; + uint16_t status; +}; + +struct dhcpv6_ia_na { + uint32_t iaid; + uint32_t t1; + uint32_t t2; + uint16_t status; + struct dhcpv6_iaaddr iaaddr; +}; + +struct dhcpv6_iaprefix { + uint32_t preferred_lifetime; + uint32_t valid_lifetime; + struct in6_addr prefix; + uint8_t prefix_len; + uint16_t status; +}; + +struct dhcpv6_ia_pd { + uint32_t iaid; + uint32_t t1; + uint32_t t2; + uint16_t status; + struct dhcpv6_iaprefix iaprefix; +}; + +/* DHCPv6 message types, RFC8415, ch. 7.3. */ +enum dhcpv6_msg_type { + DHCPV6_MSG_TYPE_SOLICIT = 1, + DHCPV6_MSG_TYPE_ADVERTISE = 2, + DHCPV6_MSG_TYPE_REQUEST = 3, + DHCPV6_MSG_TYPE_CONFIRM = 4, + DHCPV6_MSG_TYPE_RENEW = 5, + DHCPV6_MSG_TYPE_REBIND = 6, + DHCPV6_MSG_TYPE_REPLY = 7, + DHCPV6_MSG_TYPE_RELEASE = 8, + DHCPV6_MSG_TYPE_DECLINE = 9, + DHCPV6_MSG_TYPE_RECONFIGURE = 10, + DHCPV6_MSG_TYPE_INFORMATION_REQUEST = 11, + DHCPV6_MSG_TYPE_RELAY_FORW = 12, + DHCPV6_MSG_TYPE_RELAY_REPL = 13, +}; + +/* DHCPv6 option codes, RFC8415, ch. 21. */ +enum dhcpv6_option_code { + DHCPV6_OPTION_CODE_CLIENTID = 1, + DHCPV6_OPTION_CODE_SERVERID = 2, + DHCPV6_OPTION_CODE_IA_NA = 3, + DHCPV6_OPTION_CODE_IA_TA = 4, + DHCPV6_OPTION_CODE_IAADDR = 5, + DHCPV6_OPTION_CODE_ORO = 6, + DHCPV6_OPTION_CODE_PREFERENCE = 7, + DHCPV6_OPTION_CODE_ELAPSED_TIME = 8, + DHCPV6_OPTION_CODE_RELAY_MSG = 9, + DHCPV6_OPTION_CODE_AUTH = 11, + DHCPV6_OPTION_CODE_UNICAST = 12, + DHCPV6_OPTION_CODE_STATUS_CODE = 13, + DHCPV6_OPTION_CODE_RAPID_COMMIT = 14, + DHCPV6_OPTION_CODE_USER_CLASS = 15, + DHCPV6_OPTION_CODE_VENDOR_CLASS = 16, + DHCPV6_OPTION_CODE_VENDOR_OPTS = 17, + DHCPV6_OPTION_CODE_INTERFACE_ID = 18, + DHCPV6_OPTION_CODE_RECONF_MSG = 19, + DHCPV6_OPTION_CODE_RECONF_ACCEPT = 20, + DHCPV6_OPTION_CODE_IA_PD = 25, + DHCPV6_OPTION_CODE_IAPREFIX = 26, + DHCPV6_OPTION_CODE_INFORMATION_REFRESH_TIME = 32, + DHCPV6_OPTION_CODE_SOL_MAX_RT = 82, + DHCPV6_OPTION_CODE_INF_MAX_RT = 83, +}; + +/* DHCPv6 option codes, RFC8415, ch. 21.13. */ +enum dhcpv6_status_code { + DHCPV6_STATUS_SUCCESS = 0, + DHCPV6_STATUS_UNSPEC_FAIL = 1, + DHCPV6_STATUS_NO_ADDR_AVAIL = 2, + DHCPV6_STATUS_NO_BINDING = 3, + DHCPV6_STATUS_NOT_ON_LINK = 4, + DHCPV6_STATUS_USE_MULTICAST = 5, + DHCPV6_STATUS_NO_PREFIX_AVAIL = 6, +}; + +/* DHCPv6 Unique Identifier types, RFC8415, ch. 11.1. */ +enum dhcpv6_duid_type { + DHCPV6_DUID_TYPE_LLT = 1, /* Based on Link-Layer Address Plus Time */ + DHCPV6_DUID_TYPE_EN = 2, /* Assigned by Vendor Based on Enterprise Number */ + DHCPV6_DUID_TYPE_LL = 3, /* Based on Link-Layer Address */ + DHCPV6_DUID_TYPE_UUID = 4, /* Based on Universally Unique Identifier */ +}; + +#if defined(CONFIG_NET_DHCPV6) +int net_dhcpv6_init(void); +#else +static inline int net_dhcpv6_init(void) +{ + return 0; +} +#endif /* CONFIG_NET_DHCPV6 */ + +#endif /* DHCPV6_INTERNAL_H_ */ diff --git a/subsys/net/ip/net_core.c b/subsys/net/ip/net_core.c index 00829dfcf90..c94607b4485 100644 --- a/subsys/net/ip/net_core.c +++ b/subsys/net/ip/net_core.c @@ -45,6 +45,7 @@ LOG_MODULE_REGISTER(net_core, CONFIG_NET_CORE_LOG_LEVEL); #include "ipv4.h" #include "dhcpv4.h" +#include "dhcpv6_internal.h" #include "route.h" @@ -475,6 +476,11 @@ static inline int services_init(void) return status; } + status = net_dhcpv6_init(); + if (status != 0) { + return status; + } + dns_init_resolver(); websocket_init(); From 542166fc77cf4c9d8eb90bdfcb27984b17668017 Mon Sep 17 00:00:00 2001 From: Robert Lubos Date: Wed, 23 Aug 2023 13:41:25 +0200 Subject: [PATCH 133/421] [nrf fromtree] net: dhcpv6: Introduce net events for DHCPv6 Add net events for DHCPv6, in similar fashion as it's done for DHCPv4. Signed-off-by: Robert Lubos (cherry picked from commit afa5887b700db5d6aef773ea07e5ceb1bde4c9c1) (cherry picked from commit 324c985e0384c5e8ec07082e396cdee6c54f3131) --- include/zephyr/net/net_event.h | 12 ++++++++++++ subsys/net/ip/dhcpv6.c | 8 ++++++++ subsys/net/ip/net_private.h | 3 +++ 3 files changed, 23 insertions(+) diff --git a/include/zephyr/net/net_event.h b/include/zephyr/net/net_event.h index 819a5ae6639..34856aec6af 100644 --- a/include/zephyr/net/net_event.h +++ b/include/zephyr/net/net_event.h @@ -79,6 +79,9 @@ enum net_event_ipv6_cmd { NET_EVENT_IPV6_CMD_DAD_FAILED, NET_EVENT_IPV6_CMD_NBR_ADD, NET_EVENT_IPV6_CMD_NBR_DEL, + NET_EVENT_IPV6_CMD_DHCP_START, + NET_EVENT_IPV6_CMD_DHCP_BOUND, + NET_EVENT_IPV6_CMD_DHCP_STOP, }; #define NET_EVENT_IPV6_ADDR_ADD \ @@ -129,6 +132,15 @@ enum net_event_ipv6_cmd { #define NET_EVENT_IPV6_NBR_DEL \ (_NET_EVENT_IPV6_BASE | NET_EVENT_IPV6_CMD_NBR_DEL) +#define NET_EVENT_IPV6_DHCP_START \ + (_NET_EVENT_IPV4_BASE | NET_EVENT_IPV6_CMD_DHCP_START) + +#define NET_EVENT_IPV6_DHCP_BOUND \ + (_NET_EVENT_IPV4_BASE | NET_EVENT_IPV6_CMD_DHCP_BOUND) + +#define NET_EVENT_IPV6_DHCP_STOP \ + (_NET_EVENT_IPV4_BASE | NET_EVENT_IPV6_CMD_DHCP_STOP) + /* IPv4 Events*/ #define _NET_IPV4_LAYER NET_MGMT_LAYER_L3 #define _NET_IPV4_CORE_CODE 0x004 diff --git a/subsys/net/ip/dhcpv6.c b/subsys/net/ip/dhcpv6.c index 040c9fa0e06..6fae4f320bf 100644 --- a/subsys/net/ip/dhcpv6.c +++ b/subsys/net/ip/dhcpv6.c @@ -1374,6 +1374,10 @@ static void dhcpv6_enter_confirming(struct net_if *iface) static void dhcpv6_enter_bound(struct net_if *iface) { iface->config.dhcpv6.timeout = iface->config.dhcpv6.t1; + + net_mgmt_event_notify_with_info(NET_EVENT_IPV6_DHCP_BOUND, iface, + &iface->config.dhcpv6, + sizeof(iface->config.dhcpv6)); } static void dhcpv6_enter_state(struct net_if *iface, enum net_dhcpv6_state state) @@ -2101,6 +2105,8 @@ void net_dhcpv6_start(struct net_if *iface, struct net_dhcpv6_params *params) goto out; } + net_mgmt_event_notify(NET_EVENT_IPV6_DHCP_START, iface); + NET_DBG("Starting DHCPv6 on iface %p", iface); iface->config.dhcpv6.params = *params; @@ -2160,6 +2166,8 @@ void net_dhcpv6_stop(struct net_if *iface) break; } + net_mgmt_event_notify(NET_EVENT_IPV6_DHCP_STOP, iface); + k_mutex_unlock(&lock); } diff --git a/subsys/net/ip/net_private.h b/subsys/net/ip/net_private.h index be0466fc98b..c2b80aa4f05 100644 --- a/subsys/net/ip/net_private.h +++ b/subsys/net/ip/net_private.h @@ -30,6 +30,9 @@ union net_mgmt_events { #if defined(CONFIG_NET_DHCPV4) struct net_if_dhcpv4 dhcpv4; #endif /* CONFIG_NET_DHCPV4 */ +#if defined(CONFIG_NET_DHCPV6) + struct net_if_dhcpv6 dhcpv6; +#endif /* CONFIG_NET_DHCPV6 */ #if defined(CONFIG_NET_L2_WIFI_MGMT) union wifi_mgmt_events wifi; #endif /* CONFIG_NET_L2_WIFI_MGMT */ From 7b858ff1a5bb1cd919249412bdb1c8be3f7424d9 Mon Sep 17 00:00:00 2001 From: Robert Lubos Date: Wed, 23 Aug 2023 13:41:32 +0200 Subject: [PATCH 134/421] [nrf fromtree] net: config: Add DHCPv6 support Add DHCPv6 support to the net config library. In case DHCPv6 is enabled, net config will attempt to acquire IPv6 address and/or prefix when used. The user can select with Kconfig whether to request address or prefix (or both). Signed-off-by: Robert Lubos (cherry picked from commit 72cf06ada44992d018cd4675292f6395ad2b0710) (cherry picked from commit 4bfd0dba783f4cd133ccf59b188d0d2d933f7c21) --- subsys/net/lib/config/Kconfig | 17 +++++++++++++ subsys/net/lib/config/init.c | 46 +++++++++++++++++++++++++++++++---- 2 files changed, 58 insertions(+), 5 deletions(-) diff --git a/subsys/net/lib/config/Kconfig b/subsys/net/lib/config/Kconfig index 0f1e3c50544..5ca788cebf1 100644 --- a/subsys/net/lib/config/Kconfig +++ b/subsys/net/lib/config/Kconfig @@ -188,6 +188,23 @@ config NET_CONFIG_BT_NODE endif # NET_CONFIG_SETTINGS +if NET_DHCPV6 + +config NET_CONFIG_DHCPV6_REQUEST_ADDR + bool "Request IPv6 address when configuring DHCPv6 client" + default y + help + When DHCPv6 is enabled this will configure the DHCPv6 client to + request IPv6 address from the DHCPv6 server. + +config NET_CONFIG_DHCPV6_REQUEST_PREFIX + bool "Request IPv6 prefix when configuring DHCPv6 client" + help + When DHCPv6 is enabled this will configure the DHCPv6 client to + request IPv6 prefix from the DHCPv6 server. + +endif # NET_DHCPV6 + config NET_CONFIG_CLOCK_SNTP_INIT bool "Initialize system clock using SNTP on application startup" depends on SNTP && POSIX_CLOCK diff --git a/subsys/net/lib/config/init.c b/subsys/net/lib/config/init.c index cd2bf711a7d..098003b79b3 100644 --- a/subsys/net/lib/config/init.c +++ b/subsys/net/lib/config/init.c @@ -21,6 +21,7 @@ LOG_MODULE_REGISTER(net_config, CONFIG_NET_CONFIG_LOG_LEVEL); #include #include #include +#include #include #include @@ -203,8 +204,26 @@ static void setup_ipv4(struct net_if *iface) #endif /* CONFIG_NET_IPV4 && !CONFIG_NET_DHCPV4 */ #if defined(CONFIG_NET_NATIVE_IPV6) -#if !defined(CONFIG_NET_CONFIG_MY_IPV6_ADDR) -#error "You need to define an IPv6 address!" + +#if defined(CONFIG_NET_DHCPV6) +static void setup_dhcpv6(struct net_if *iface) +{ + struct net_dhcpv6_params params = { + .request_addr = IS_ENABLED(CONFIG_NET_CONFIG_DHCPV6_REQUEST_ADDR), + .request_prefix = IS_ENABLED(CONFIG_NET_CONFIG_DHCPV6_REQUEST_PREFIX), + }; + + NET_INFO("Running dhcpv6 client..."); + + net_dhcpv6_start(iface, ¶ms); +} +#else /* CONFIG_NET_DHCPV6 */ +#define setup_dhcpv6(...) +#endif /* CONFIG_NET_DHCPV6 */ + +#if !defined(CONFIG_NET_CONFIG_DHCPV6_REQUEST_ADDR) && \ + !defined(CONFIG_NET_CONFIG_MY_IPV6_ADDR) +#error "You need to define an IPv6 address or enable DHCPv6!" #endif static struct net_mgmt_event_callback mgmt6_cb; @@ -249,6 +268,21 @@ static void ipv6_event_handler(struct net_mgmt_event_callback *cb, #if CONFIG_NET_CONFIG_LOG_LEVEL >= LOG_LEVEL_INF NET_INFO("IPv6 address: %s", net_addr_ntop(AF_INET6, &laddr, hr_addr, NET_IPV6_ADDR_LEN)); + + if (ifaddr->addr_type == NET_ADDR_DHCP) { + char remaining_str[] = "infinite"; + uint32_t remaining; + + remaining = net_timeout_remaining(&ifaddr->lifetime, + k_uptime_get_32()); + + if (!ifaddr->is_infinite) { + snprintk(remaining_str, sizeof(remaining_str), + "%u", remaining); + } + + NET_INFO("Lifetime: %s seconds", remaining_str); + } #endif services_notify_ready(NET_CONFIG_NEED_IPV6); @@ -264,6 +298,9 @@ static void setup_ipv6(struct net_if *iface, uint32_t flags) struct net_if_addr *ifaddr; uint32_t mask = NET_EVENT_IPV6_DAD_SUCCEED; + net_mgmt_init_event_callback(&mgmt6_cb, ipv6_event_handler, mask); + net_mgmt_add_event_callback(&mgmt6_cb); + if (sizeof(CONFIG_NET_CONFIG_MY_IPV6_ADDR) == 1) { /* Empty address, skip setting ANY address in this case */ goto exit; @@ -279,9 +316,6 @@ static void setup_ipv6(struct net_if *iface, uint32_t flags) mask |= NET_EVENT_IPV6_ROUTER_ADD; } - net_mgmt_init_event_callback(&mgmt6_cb, ipv6_event_handler, mask); - net_mgmt_add_event_callback(&mgmt6_cb); - /* * check for CMD_ADDR_ADD bit here, NET_EVENT_IPV6_ADDR_ADD is * a combination of _NET_EVENT_IPV6_BASE | NET_EVENT_IPV6_CMD_ADDR_ADD @@ -310,6 +344,7 @@ static void setup_ipv6(struct net_if *iface, uint32_t flags) #else #define setup_ipv6(...) +#define setup_dhcpv6(...) #endif /* CONFIG_NET_IPV6 */ #if defined(CONFIG_NET_NATIVE) @@ -400,6 +435,7 @@ int net_config_init_by_iface(struct net_if *iface, const char *app_info, setup_ipv4(iface); setup_dhcpv4(iface); setup_ipv6(iface, flags); + setup_dhcpv6(iface); /* Network interface did not come up. */ if (timeout > 0 && count < 0) { From 0258a9960c452a3e0f69004ed421a8838108ad9c Mon Sep 17 00:00:00 2001 From: Robert Lubos Date: Wed, 23 Aug 2023 13:43:49 +0200 Subject: [PATCH 135/421] [nrf fromtree] net: shell: Add DHCPv6 support Print DHCPv6 status in net shell (with "net iface" command). Signed-off-by: Robert Lubos (cherry picked from commit 6fb19bc7f03cdbae897b09c3718722853a86b8b3) (cherry picked from commit d27251057f2a990a669c32e8069c064ed0852d4a) --- subsys/net/ip/net_shell.c | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/subsys/net/ip/net_shell.c b/subsys/net/ip/net_shell.c index c5b07afd6aa..e7af6e16632 100644 --- a/subsys/net/ip/net_shell.c +++ b/subsys/net/ip/net_shell.c @@ -719,6 +719,19 @@ static void iface_cb(struct net_if *iface, void *user_data) iface->config.dhcpv4.attempts); #endif /* CONFIG_NET_DHCPV4 */ +#if defined(CONFIG_NET_DHCPV6) + PR("DHCPv6 address requested : %s\n", + iface->config.dhcpv6.params.request_addr ? + net_sprint_ipv6_addr(&iface->config.dhcpv6.addr) : "none"); + PR("DHCPv6 prefix requested : %s\n", + iface->config.dhcpv6.params.request_prefix ? + net_sprint_ipv6_addr(&iface->config.dhcpv6.prefix) : "none"); + PR("DHCPv6 state : %s\n", + net_dhcpv6_state_name(iface->config.dhcpv6.state)); + PR("DHCPv6 attempts : %d\n", + iface->config.dhcpv6.retransmissions + 1); +#endif /* CONFIG_NET_DHCPV6 */ + #else ARG_UNUSED(iface); ARG_UNUSED(user_data); @@ -2513,6 +2526,29 @@ static char *get_l3_desc(struct event_msg *msg, info = net_addr_ntop(AF_INET6, msg->data, extra_info, extra_info_len); break; + case NET_EVENT_IPV6_DHCP_START: + *desc = "DHCPv6"; + *desc2 = "start"; + break; + case NET_EVENT_IPV6_DHCP_BOUND: + *desc = "DHCPv6"; + *desc2 = "bound"; +#if defined(CONFIG_NET_DHCPV6) + struct net_if_dhcpv6 *data = (struct net_if_dhcpv6 *)msg->data; + + if (data->params.request_addr) { + info = net_addr_ntop(AF_INET6, &data->addr, extra_info, + extra_info_len); + } else if (data->params.request_prefix) { + info = net_addr_ntop(AF_INET6, &data->prefix, extra_info, + extra_info_len); + } +#endif + break; + case NET_EVENT_IPV6_DHCP_STOP: + *desc = "DHCPv6"; + *desc2 = "stop"; + break; case NET_EVENT_IPV4_ADDR_ADD: *desc = "IPv4 address"; *desc2 = "add"; From 3c8028b93d9392629b9b5a123850d1ddea6b66a3 Mon Sep 17 00:00:00 2001 From: Andrei Emeltchenko Date: Mon, 2 Oct 2023 18:22:29 +0300 Subject: [PATCH 136/421] [nrf fromtree] net: dhcpv6: Fix params check Fix params check. Signed-off-by: Andrei Emeltchenko (cherry picked from commit d68db1ecfa512bc416bfa906d74f441cba2ab8fb) Signed-off-by: Robert Lubos (cherry picked from commit 972c7c3ca30d782e797c4ed304239b547057f3e6) --- subsys/net/ip/dhcpv6.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subsys/net/ip/dhcpv6.c b/subsys/net/ip/dhcpv6.c index 6fae4f320bf..fdfef3c5147 100644 --- a/subsys/net/ip/dhcpv6.c +++ b/subsys/net/ip/dhcpv6.c @@ -2100,7 +2100,7 @@ void net_dhcpv6_start(struct net_if *iface, struct net_dhcpv6_params *params) goto out; } - if (!params->request_addr && !params->request_addr) { + if (!params->request_addr && !params->request_prefix) { NET_ERR("Information Request not supported yet"); goto out; } From 577db5cae9568f33fb5a1bb3fc6ab1a4725813f7 Mon Sep 17 00:00:00 2001 From: Jonathan Rico Date: Tue, 26 Sep 2023 16:37:26 +0200 Subject: [PATCH 137/421] [nrf fromtree] Bluetooth: att: don't re-use the ATT buffer for confirmations If the peer is a zephyr host, there is no problem, as the Zephyr host limits sending parallel REQs and INDs. But the spec allows sending those in parallel, and it may end up that the re-used REQ buffer hasn't been destroyed when an indication comes. Only re-use the buffer when enqueuing ATT responses. This means that we may run out of buffers if the peer sends too many indications and our application also sends a lot of commands/notifications. The rationale for this is that having to handle a lot of requests is a more plausible scenario (e.g. being discovered by multiple peers) than handling lots of parallel indications. Signed-off-by: Jonathan Rico (cherry picked from commit 7093538c425b1bd3dd4bce3dfd3708a8281bd033) (cherry picked from commit 168b413c38b2cbee8f20800e7c76db9b31a5a978) --- subsys/bluetooth/host/att.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/subsys/bluetooth/host/att.c b/subsys/bluetooth/host/att.c index d2c41eaa928..f5ae3768cec 100644 --- a/subsys/bluetooth/host/att.c +++ b/subsys/bluetooth/host/att.c @@ -670,11 +670,13 @@ static struct net_buf *bt_att_chan_create_pdu(struct bt_att_chan *chan, uint8_t switch (att_op_get_type(op)) { case ATT_RESPONSE: - case ATT_CONFIRMATION: - /* Use a timeout only when responding/confirming */ + /* Use a timeout only when responding */ timeout = BT_ATT_TIMEOUT; re_use = true; break; + case ATT_CONFIRMATION: + timeout = BT_ATT_TIMEOUT; + break; default: timeout = K_FOREVER; } @@ -701,7 +703,7 @@ static struct net_buf *bt_att_chan_create_pdu(struct bt_att_chan *chan, uint8_t * This is better than an assert as an assert would * allow a peer to DoS us. */ - LOG_ERR("already processing a transaction on chan %p", chan); + LOG_ERR("already processing a REQ/RSP on chan %p", chan); return NULL; } From 079d1b105a61c46f7a8ffea881de673092a44b65 Mon Sep 17 00:00:00 2001 From: Pavel Vasilyev Date: Fri, 1 Sep 2023 15:17:52 +0200 Subject: [PATCH 138/421] [nrf fromtree] Bluetooth: Mesh: Fix Opcode Aggregator Server compilation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove ifdef around `srcs` and let linker exclude it when Opcode Aggregator Client model is not enabled. Signed-off-by: Pavel Vasilyev (cherry picked from commit 2a472b8b477ce4f46c88978d0970ea6cb65dea15) Signed-off-by: Alperen Şener (cherry picked from commit a3173f0e03058f75f75296e46c4b986af48239d9) --- subsys/bluetooth/mesh/op_agg.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/subsys/bluetooth/mesh/op_agg.c b/subsys/bluetooth/mesh/op_agg.c index 4f6baacc898..1580c7f0847 100644 --- a/subsys/bluetooth/mesh/op_agg.c +++ b/subsys/bluetooth/mesh/op_agg.c @@ -17,10 +17,7 @@ LOG_MODULE_REGISTER(bt_mesh_op_agg); #define LENGTH_SHORT_MAX BIT_MASK(7) NET_BUF_SIMPLE_DEFINE_STATIC(sdu, BT_MESH_TX_SDU_MAX); - -#if IS_ENABLED(CONFIG_BT_MESH_OP_AGG_CLI) NET_BUF_SIMPLE_DEFINE_STATIC(srcs, BT_MESH_TX_SDU_MAX); -#endif static struct op_agg_ctx agg_ctx = { .sdu = &sdu, From 4d987d3dcba621380f6714dd2cfa405dc78ad6fa Mon Sep 17 00:00:00 2001 From: Pavel Vasilyev Date: Fri, 1 Sep 2023 15:19:13 +0200 Subject: [PATCH 139/421] [nrf fromtree] Bluetooth: Mesh: Fix Solicitation RPL PDU Server compilation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A pointer to the key struct should be passed after the PSA support has been added. Signed-off-by: Pavel Vasilyev (cherry picked from commit d36b7f4de0b2feec55a5fcca30dec608cb7df8ad) Signed-off-by: Alperen Şener (cherry picked from commit c58978510a533613fc12746502af000857bf5ae7) --- subsys/bluetooth/mesh/solicitation.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/subsys/bluetooth/mesh/solicitation.c b/subsys/bluetooth/mesh/solicitation.c index 3f639fbf0d6..1bf9f9a465a 100644 --- a/subsys/bluetooth/mesh/solicitation.c +++ b/subsys/bluetooth/mesh/solicitation.c @@ -153,12 +153,12 @@ static bool sol_pdu_decrypt(struct bt_mesh_subnet *sub, void *data) net_buf_simple_init(out, 0); net_buf_simple_add_mem(out, in->data, in->len); - err = bt_mesh_net_obfuscate(out->data, 0, sub->keys[i].msg.privacy); + err = bt_mesh_net_obfuscate(out->data, 0, &sub->keys[i].msg.privacy); if (err) { LOG_DBG("obfuscation err %d", err); continue; } - err = bt_mesh_net_decrypt(sub->keys[i].msg.enc, out, + err = bt_mesh_net_decrypt(&sub->keys[i].msg.enc, out, 0, BT_MESH_NONCE_SOLICITATION); if (!err) { LOG_DBG("Decrypted PDU %s", bt_hex(out->data, out->len)); From 915c64c22fc212ef2f5b25e62682179159ce97c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anders=20Storr=C3=B8?= Date: Wed, 6 Sep 2023 10:06:38 +0200 Subject: [PATCH 140/421] [nrf fromtree] Bluetooth: Mesh: Send od priv proxy with devkey MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit According to the mesh 1.1 spec, section 4.4.14.1: “. The access layer security on the On-Demand Private Proxy Client model shall use the device key of the node supporting the On-Demand Private Proxy Server model.“ This commit alters the API and implementation to reflect this. Signed-off-by: Anders Storrø (cherry picked from commit 01a6ecb6bf4cef76bfd042eb5ab351347a1444f6) Signed-off-by: Alperen Şener (cherry picked from commit f51ca3b314489cc47bfef005816a729348b47c72) --- include/zephyr/bluetooth/mesh/od_priv_proxy_cli.h | 11 ++++++----- subsys/bluetooth/mesh/od_priv_proxy_cli.c | 12 +++++++----- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/include/zephyr/bluetooth/mesh/od_priv_proxy_cli.h b/include/zephyr/bluetooth/mesh/od_priv_proxy_cli.h index 89e63c177a0..f9734d78d3e 100644 --- a/include/zephyr/bluetooth/mesh/od_priv_proxy_cli.h +++ b/include/zephyr/bluetooth/mesh/od_priv_proxy_cli.h @@ -47,7 +47,6 @@ struct bt_mesh_od_priv_proxy_cli { _bt_mesh_od_priv_proxy_cli_op, NULL, cli_data, \ &_bt_mesh_od_priv_proxy_cli_cb) - /** @brief Get the target's On-Demand Private GATT Proxy state. * * This method can be used asynchronously by setting @p val_rsp as NULL. @@ -57,12 +56,13 @@ struct bt_mesh_od_priv_proxy_cli { * To process the response arguments of an async method, register * the @c od_status callback in @c bt_mesh_od_priv_proxy_cli struct. * - * @param ctx Message context for the message. + * @param net_idx Network index to encrypt with. + * @param addr Target node address. * @param val_rsp Response buffer for On-Demand Private GATT Proxy value. * * @return 0 on success, or (negative) error code otherwise. */ -int bt_mesh_od_priv_proxy_cli_get(struct bt_mesh_msg_ctx *ctx, uint8_t *val_rsp); +int bt_mesh_od_priv_proxy_cli_get(uint16_t net_idx, uint16_t addr, uint8_t *val_rsp); /** @brief Set the target's On-Demand Private GATT Proxy state. * @@ -73,13 +73,14 @@ int bt_mesh_od_priv_proxy_cli_get(struct bt_mesh_msg_ctx *ctx, uint8_t *val_rsp) * To process the response arguments of an async method, register * the @c od_status callback in @c bt_mesh_od_priv_proxy_cli struct. * - * @param ctx Message context for the message. + * @param net_idx Network index to encrypt with. + * @param addr Target node address. * @param val On-Demand Private GATT Proxy state to be set * @param val_rsp Response buffer for On-Demand Private GATT Proxy value. * * @return 0 on success, or (negative) error code otherwise. */ -int bt_mesh_od_priv_proxy_cli_set(struct bt_mesh_msg_ctx *ctx, uint8_t val, uint8_t *val_rsp); +int bt_mesh_od_priv_proxy_cli_set(uint16_t net_idx, uint16_t addr, uint8_t val, uint8_t *val_rsp); /** @brief Set the transmission timeout value. * diff --git a/subsys/bluetooth/mesh/od_priv_proxy_cli.c b/subsys/bluetooth/mesh/od_priv_proxy_cli.c index 3dc8722ff72..67f5ac961ad 100644 --- a/subsys/bluetooth/mesh/od_priv_proxy_cli.c +++ b/subsys/bluetooth/mesh/od_priv_proxy_cli.c @@ -54,23 +54,25 @@ const struct bt_mesh_model_op _bt_mesh_od_priv_proxy_cli_op[] = { BT_MESH_MODEL_OP_END }; -int bt_mesh_od_priv_proxy_cli_get(struct bt_mesh_msg_ctx *ctx, uint8_t *val) +int bt_mesh_od_priv_proxy_cli_get(uint16_t net_idx, uint16_t addr, uint8_t *val_rsp) { + struct bt_mesh_msg_ctx ctx = BT_MESH_MSG_CTX_INIT_DEV(net_idx, addr); const struct bt_mesh_msg_rsp_ctx rsp = { .ack = &cli->ack_ctx, .op = OP_OD_PRIV_PROXY_STATUS, - .user_data = val, + .user_data = val_rsp, .timeout = msg_timeout, }; BT_MESH_MODEL_BUF_DEFINE(msg, OP_OD_PRIV_PROXY_GET, 0); bt_mesh_model_msg_init(&msg, OP_OD_PRIV_PROXY_GET); - return bt_mesh_msg_ackd_send(cli->model, ctx, &msg, val ? &rsp : NULL); + return bt_mesh_msg_ackd_send(cli->model, &ctx, &msg, val_rsp ? &rsp : NULL); } -int bt_mesh_od_priv_proxy_cli_set(struct bt_mesh_msg_ctx *ctx, uint8_t val, uint8_t *val_rsp) +int bt_mesh_od_priv_proxy_cli_set(uint16_t net_idx, uint16_t addr, uint8_t val, uint8_t *val_rsp) { + struct bt_mesh_msg_ctx ctx = BT_MESH_MSG_CTX_INIT_DEV(net_idx, addr); const struct bt_mesh_msg_rsp_ctx rsp = { .ack = &cli->ack_ctx, .op = OP_OD_PRIV_PROXY_STATUS, @@ -83,7 +85,7 @@ int bt_mesh_od_priv_proxy_cli_set(struct bt_mesh_msg_ctx *ctx, uint8_t val, uint net_buf_simple_add_u8(&msg, val); - return bt_mesh_msg_ackd_send(cli->model, ctx, &msg, val_rsp ? &rsp : NULL); + return bt_mesh_msg_ackd_send(cli->model, &ctx, &msg, val_rsp ? &rsp : NULL); } void bt_mesh_od_priv_proxy_cli_timeout_set(int32_t timeout) From ced31ee9859ad299cf1a154124adef5bd9d25cda Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anders=20Storr=C3=B8?= Date: Wed, 30 Aug 2023 14:16:46 +0200 Subject: [PATCH 141/421] [nrf fromtree] Bluetooth: Mesh: Support for comp data page 2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds support for composition data page 2 & 130. In this implementation the responsibillity for filling the page 2 buffer is left to the application through the new comp page 2 cb API. Only the application can know/decide if the device is NLC compliant, and must thus be given the responsibillity for cheking the NLC profile requirements, defined in the NLC specs, and filling the response buffer for comp data page 2. Signed-off-by: Anders Storrø (cherry picked from commit 9d849736ef6da918fc8685d6fa79a66d69d866e4) Signed-off-by: Alperen Şener (cherry picked from commit cbbfec95d121cd1de482fc7c4055b48639ab7517) --- include/zephyr/bluetooth/mesh/access.h | 45 ++++++++++++++++++ subsys/bluetooth/mesh/Kconfig | 5 ++ subsys/bluetooth/mesh/access.c | 66 +++++++++++++++++++++++++- subsys/bluetooth/mesh/access.h | 1 - subsys/bluetooth/mesh/cfg_srv.c | 8 +++- 5 files changed, 121 insertions(+), 4 deletions(-) diff --git a/include/zephyr/bluetooth/mesh/access.h b/include/zephyr/bluetooth/mesh/access.h index f3b6c373128..5b1653c2487 100644 --- a/include/zephyr/bluetooth/mesh/access.h +++ b/include/zephyr/bluetooth/mesh/access.h @@ -1137,6 +1137,51 @@ struct bt_mesh_comp { struct bt_mesh_elem *elem; /**< List of elements. */ }; +/** Composition data page 2 record. */ +struct bt_mesh_comp2_record { + /** Mesh profile ID. */ + uint16_t id; + /** Mesh Profile Version. */ + struct { + /** Major version. */ + uint8_t x; + /** Minor version. */ + uint8_t y; + /** Z version. */ + uint8_t z; + } version; + /** Element offset count. */ + uint8_t elem_offset_cnt; + /** Element offset list. */ + const uint8_t *elem_offset; + /** Length of additional data. */ + uint16_t data_len; + /** Additional data. */ + const void *data; +}; + +/** Node Composition data page 2 */ +struct bt_mesh_comp2 { + /** The number of Mesh Profile records on a device. */ + size_t record_cnt; + /** List of records. */ + const struct bt_mesh_comp2_record *record; +}; + +/** @brief Register composition data page 2 of the device. + * + * Register Mesh Profiles information (Ref section 3.12 in + * Bluetooth SIG Assigned Numbers) for composition data + * page 2 of the device. + * + * @note There must be at least one record present in @c comp2 + * + * @param comp2 Pointer to composition data page 2. + * + * @return Zero on success or (negative) error code otherwise. + */ +int bt_mesh_comp2_register(const struct bt_mesh_comp2 *comp2); + #ifdef __cplusplus } #endif diff --git a/subsys/bluetooth/mesh/Kconfig b/subsys/bluetooth/mesh/Kconfig index 9b0c4bd80f0..b8e26309a28 100644 --- a/subsys/bluetooth/mesh/Kconfig +++ b/subsys/bluetooth/mesh/Kconfig @@ -1373,6 +1373,11 @@ config BT_MESH_COMP_PAGE_1 help Enable support for Composition Data Page 1. +config BT_MESH_COMP_PAGE_2 + bool "Support for Composition Data Page 2" + help + Enable support for Composition Data Page 2. + config BT_MESH_MODEL_EXTENSION_LIST_SIZE int "Model extensions list size" depends on BT_MESH_COMP_PAGE_1 diff --git a/subsys/bluetooth/mesh/access.c b/subsys/bluetooth/mesh/access.c index c022eedbadc..b6dab2d67a7 100644 --- a/subsys/bluetooth/mesh/access.c +++ b/subsys/bluetooth/mesh/access.c @@ -53,6 +53,7 @@ struct comp_foreach_model_arg { }; static const struct bt_mesh_comp *dev_comp; +static const struct bt_mesh_comp2 *dev_comp2; static uint16_t dev_primary_addr; static void (*msg_cb)(uint32_t opcode, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf); @@ -112,6 +113,9 @@ static const struct { #if IS_ENABLED(CONFIG_BT_MESH_COMP_PAGE_1) { "bt/mesh/cmp/1", 1, }, #endif +#if IS_ENABLED(CONFIG_BT_MESH_COMP_PAGE_2) + { "bt/mesh/cmp/2", 2, }, +#endif }; void bt_mesh_model_foreach(void (*func)(struct bt_mesh_model *mod, @@ -609,7 +613,7 @@ static size_t page1_elem_size(struct bt_mesh_elem *elem) return temp_size; } -int bt_mesh_comp_data_get_page_1(struct net_buf_simple *buf) +static int bt_mesh_comp_data_get_page_1(struct net_buf_simple *buf) { const struct bt_mesh_comp *comp; uint8_t cor_id = 0; @@ -660,6 +664,51 @@ int bt_mesh_comp_data_get_page_1(struct net_buf_simple *buf) return 0; } +static int bt_mesh_comp_data_get_page_2(struct net_buf_simple *buf) +{ + if (!dev_comp2) { + LOG_ERR("Composition data P2 not registered"); + return -ENODEV; + } + + for (int i = 0; i < dev_comp2->record_cnt; i++) { + if (net_buf_simple_tailroom(buf) < + (8 + dev_comp2->record[i].elem_offset_cnt + dev_comp2->record[i].data_len + + BT_MESH_MIC_SHORT)) { + if (IS_ENABLED(CONFIG_BT_MESH_LARGE_COMP_DATA_SRV)) { + /* Mesh Profile 1.1 Section 4.4.1.2.2: + * If the complete list of models does not fit in the Data field, + * the element shall not be reported. + */ + LOG_DBG("Record 0x%04x didn't fit in the Data field", + i); + return 0; + } + + LOG_ERR("Too large device composition"); + return -E2BIG; + } + + net_buf_simple_add_le16(buf, dev_comp2->record[i].id); + net_buf_simple_add_u8(buf, dev_comp2->record[i].version.x); + net_buf_simple_add_u8(buf, dev_comp2->record[i].version.y); + net_buf_simple_add_u8(buf, dev_comp2->record[i].version.z); + net_buf_simple_add_u8(buf, dev_comp2->record[i].elem_offset_cnt); + if (dev_comp2->record[i].elem_offset_cnt) { + net_buf_simple_add_mem(buf, dev_comp2->record[i].elem_offset, + dev_comp2->record[i].elem_offset_cnt); + } + + net_buf_simple_add_le16(buf, dev_comp2->record[i].data_len); + if (dev_comp2->record[i].data_len) { + net_buf_simple_add_mem(buf, dev_comp2->record[i].data, + dev_comp2->record[i].data_len); + } + } + + return 0; +} + int32_t bt_mesh_model_pub_period_get(struct bt_mesh_model *mod) { int32_t period; @@ -994,6 +1043,17 @@ int bt_mesh_comp_register(const struct bt_mesh_comp *comp) return err; } +int bt_mesh_comp2_register(const struct bt_mesh_comp2 *comp2) +{ + if (!IS_ENABLED(CONFIG_BT_MESH_COMP_PAGE_2)) { + return -EINVAL; + } + + dev_comp2 = comp2; + + return 0; +} + void bt_mesh_comp_provision(uint16_t addr) { int i; @@ -2151,8 +2211,10 @@ int bt_mesh_comp_data_get_page(struct net_buf_simple *buf, size_t page, size_t o { if (page == 0 || page == 128) { return bt_mesh_comp_data_get_page_0(buf, offset); - } else if (page == 1 || page == 129) { + } else if (IS_ENABLED(CONFIG_BT_MESH_COMP_PAGE_1) && (page == 1 || page == 129)) { return bt_mesh_comp_data_get_page_1(buf); + } else if (IS_ENABLED(CONFIG_BT_MESH_COMP_PAGE_2) && (page == 2 || page == 130)) { + return bt_mesh_comp_data_get_page_2(buf); } return -EINVAL; diff --git a/subsys/bluetooth/mesh/access.h b/subsys/bluetooth/mesh/access.h index a7d3ffe5865..4740963dd21 100644 --- a/subsys/bluetooth/mesh/access.h +++ b/subsys/bluetooth/mesh/access.h @@ -27,7 +27,6 @@ size_t bt_mesh_comp_page_0_size(void); int bt_mesh_comp_data_get_page_0(struct net_buf_simple *buf, size_t offset); size_t bt_mesh_metadata_page_0_size(void); int bt_mesh_metadata_get_page_0(struct net_buf_simple *buf, size_t offset); -int bt_mesh_comp_data_get_page_1(struct net_buf_simple *buf); /* Find local element based on unicast address */ struct bt_mesh_elem *bt_mesh_elem_find(uint16_t addr); diff --git a/subsys/bluetooth/mesh/cfg_srv.c b/subsys/bluetooth/mesh/cfg_srv.c index 2fba9360206..eb732a34910 100644 --- a/subsys/bluetooth/mesh/cfg_srv.c +++ b/subsys/bluetooth/mesh/cfg_srv.c @@ -61,13 +61,19 @@ static int dev_comp_data_get(struct bt_mesh_model *model, page = net_buf_simple_pull_u8(buf); - if (page >= 129U && IS_ENABLED(CONFIG_BT_MESH_COMP_PAGE_1) && + if (page >= 130U && IS_ENABLED(CONFIG_BT_MESH_COMP_PAGE_2) && + (atomic_test_bit(bt_mesh.flags, BT_MESH_COMP_DIRTY) || + IS_ENABLED(CONFIG_BT_MESH_RPR_SRV))) { + page = 130U; + } else if (page >= 129U && IS_ENABLED(CONFIG_BT_MESH_COMP_PAGE_1) && (atomic_test_bit(bt_mesh.flags, BT_MESH_COMP_DIRTY) || IS_ENABLED(CONFIG_BT_MESH_RPR_SRV))) { page = 129U; } else if (page >= 128U && (atomic_test_bit(bt_mesh.flags, BT_MESH_COMP_DIRTY) || IS_ENABLED(CONFIG_BT_MESH_RPR_SRV))) { page = 128U; + } else if (page >= 2U && IS_ENABLED(CONFIG_BT_MESH_COMP_PAGE_2)) { + page = 2U; } else if (page >= 1U && IS_ENABLED(CONFIG_BT_MESH_COMP_PAGE_1)) { page = 1U; } else if (page != 0U) { From c227d927cb85b7bf66c151063a15092a06a7850d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anders=20Storr=C3=B8?= Date: Wed, 30 Aug 2023 14:16:46 +0200 Subject: [PATCH 142/421] [nrf fromtree] Bluetooth: Mesh: Shell support for comp data page2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds shell support for composition data page 2 and 130 Signed-off-by: Anders Storrø (cherry picked from commit 6b627771c898ce2086cc69369eaec34302079e8f) Signed-off-by: Alperen Şener (cherry picked from commit 85fdab49a5550230e4259c6b58dd8485f1f61398) --- include/zephyr/bluetooth/mesh/cfg_cli.h | 34 ++++++++++++++++++++ subsys/bluetooth/mesh/cfg_cli.c | 35 +++++++++++++++++++++ subsys/bluetooth/mesh/shell/cfg.c | 42 +++++++++++++++++++++++-- 3 files changed, 108 insertions(+), 3 deletions(-) diff --git a/include/zephyr/bluetooth/mesh/cfg_cli.h b/include/zephyr/bluetooth/mesh/cfg_cli.h index e6fd31d7c3a..d2221da38da 100644 --- a/include/zephyr/bluetooth/mesh/cfg_cli.h +++ b/include/zephyr/bluetooth/mesh/cfg_cli.h @@ -1786,6 +1786,40 @@ struct bt_mesh_comp_p1_model_item *bt_mesh_comp_p1_item_pull( struct bt_mesh_comp_p1_ext_item *bt_mesh_comp_p1_pull_ext_item( struct bt_mesh_comp_p1_model_item *item, struct bt_mesh_comp_p1_ext_item *ext_item); +/** Composition data page 2 record parsing structure. */ +struct bt_mesh_comp_p2_record { + /** Mesh profile ID. */ + uint16_t id; + /** Mesh Profile Version. */ + struct { + /** Major version. */ + uint8_t x; + /** Minor version. */ + uint8_t y; + /** Z version. */ + uint8_t z; + } version; + /** Element offset buffer. */ + struct net_buf_simple *elem_buf; + /** Additional data buffer. */ + struct net_buf_simple *data_buf; +}; + +/** @brief Pull a Composition Data Page 2 Record from a composition data page 2 + * instance. + * + * Each call to this function will pull out a new element from the composition + * data page, until all elements have been pulled. + * + * @param buf Composition data page 2 buffer + * @param record Record to fill. + * + * @return A pointer to @c record on success, or NULL if no more elements could + * be pulled. + */ +struct bt_mesh_comp_p2_record *bt_mesh_comp_p2_record_pull(struct net_buf_simple *buf, + struct bt_mesh_comp_p2_record *record); + /** @brief Unpack a list of key index entries from a buffer. * * On success, @c dst_cnt is set to the amount of unpacked key index entries. diff --git a/subsys/bluetooth/mesh/cfg_cli.c b/subsys/bluetooth/mesh/cfg_cli.c index a5ad80193f3..68af4fae59d 100644 --- a/subsys/bluetooth/mesh/cfg_cli.c +++ b/subsys/bluetooth/mesh/cfg_cli.c @@ -2443,3 +2443,38 @@ struct bt_mesh_comp_p1_ext_item *bt_mesh_comp_p1_pull_ext_item( } return ext_item; } + +struct bt_mesh_comp_p2_record *bt_mesh_comp_p2_record_pull(struct net_buf_simple *buf, + struct bt_mesh_comp_p2_record *record) +{ + if (buf->len < 8) { + LOG_DBG("No more elements to pull or missing data"); + return NULL; + } + + uint8_t elem_offset_cnt; + uint16_t data_len; + + record->id = net_buf_simple_pull_le16(buf); + record->version.x = net_buf_simple_pull_u8(buf); + record->version.y = net_buf_simple_pull_u8(buf); + record->version.z = net_buf_simple_pull_u8(buf); + elem_offset_cnt = net_buf_simple_pull_u8(buf); + if (buf->len < elem_offset_cnt + 2) { + LOG_WRN("Invalid composition data offset count"); + return NULL; + } + + net_buf_simple_init_with_data(record->elem_buf, + net_buf_simple_pull_mem(buf, elem_offset_cnt), + elem_offset_cnt); + data_len = net_buf_simple_pull_le16(buf); + if (buf->len < data_len) { + LOG_WRN("Invalid composition data additional data length"); + return NULL; + } + + net_buf_simple_init_with_data(record->data_buf, + net_buf_simple_pull_mem(buf, data_len), data_len); + return record; +} diff --git a/subsys/bluetooth/mesh/shell/cfg.c b/subsys/bluetooth/mesh/shell/cfg.c index d47f04bcc00..c4a62a996e3 100644 --- a/subsys/bluetooth/mesh/shell/cfg.c +++ b/subsys/bluetooth/mesh/shell/cfg.c @@ -98,9 +98,10 @@ static int cmd_get_comp(const struct shell *sh, size_t argc, char *argv[]) return 0; } - if (page != 0 && page != 1 && page != 128 && page != 129) { - shell_print(sh, "Got page %d. No parser available.", - page); + if (page != 0 && page != 128 && + ((page != 1 && page != 129) || !IS_ENABLED(CONFIG_BT_MESH_COMP_PAGE_1)) && + ((page != 2 && page != 130) || !IS_ENABLED(CONFIG_BT_MESH_COMP_PAGE_2))) { + shell_print(sh, "Got page %d. No parser available.", page); return 0; } @@ -254,6 +255,41 @@ static int cmd_get_comp(const struct shell *sh, size_t argc, char *argv[]) } } + if (IS_ENABLED(CONFIG_BT_MESH_COMP_PAGE_2) && (page == 2 || page == 130)) { + /* size of 32 is chosen arbitrary, as sufficient for testing purposes */ + NET_BUF_SIMPLE_DEFINE(p2_elem_offset_buf, 32); + NET_BUF_SIMPLE_DEFINE(p2_data_buf, 32); + struct bt_mesh_comp_p2_record p2_elem = { + .elem_buf = &p2_elem_offset_buf, + .data_buf = &p2_data_buf + }; + + if (!buf.len) { + shell_error(sh, "Composition data empty"); + return 0; + } + shell_print(sh, "Got Composition Data for 0x%04x, page: %d:", + bt_mesh_shell_target_ctx.dst, page); + + while (bt_mesh_comp_p2_record_pull(&buf, &p2_elem)) { + + shell_print(sh, "\tMesh Profile id: %04x ", p2_elem.id); + shell_print(sh, "\t\tVersion: %d.%d.%d ", p2_elem.version.x, + p2_elem.version.y, p2_elem.version.z); + shell_print(sh, "\t\tElement offsets:"); + + while (p2_elem.elem_buf->len) { + shell_print(sh, "\t\t\t%d ", + net_buf_simple_pull_u8(p2_elem.elem_buf)); + } + + if (p2_elem.data_buf->len) { + shell_print(sh, "\t\t%d bytes of additional data is available", + p2_elem.data_buf->len); + } + } + } + if (buf.len) { shell_print(sh, "\t\t...truncated data!"); } From e99b89aedb7c7f2ece20244d5283d858b31ab29a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alperen=20=C5=9Eener?= Date: Thu, 7 Sep 2023 17:46:24 +0200 Subject: [PATCH 143/421] [nrf fromtree] Bluetooth: Mesh: Fix Solicitation Mesh crypto API use MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pointer of the keys should be send to mesh en/decryption APIs. Signed-off-by: Alperen Şener (cherry picked from commit 66bf33f0900854a3df968e8a93a8dba4bd676c3f) Signed-off-by: Alperen Şener (cherry picked from commit 5b69fd4353195fc0e1cd8c452431828044a7fd1a) --- subsys/bluetooth/mesh/solicitation.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/subsys/bluetooth/mesh/solicitation.c b/subsys/bluetooth/mesh/solicitation.c index 1bf9f9a465a..f6543dcb320 100644 --- a/subsys/bluetooth/mesh/solicitation.c +++ b/subsys/bluetooth/mesh/solicitation.c @@ -304,7 +304,7 @@ static int sol_pdu_create(struct bt_mesh_subnet *sub, struct net_buf_simple *pdu /* DST = 0x0000 */ net_buf_simple_add_le16(pdu, 0x0000); - err = bt_mesh_net_encrypt(sub->keys[SUBNET_KEY_TX_IDX(sub)].msg.enc, + err = bt_mesh_net_encrypt(&sub->keys[SUBNET_KEY_TX_IDX(sub)].msg.enc, pdu, 0, BT_MESH_NONCE_SOLICITATION); if (err) { @@ -313,7 +313,7 @@ static int sol_pdu_create(struct bt_mesh_subnet *sub, struct net_buf_simple *pdu } err = bt_mesh_net_obfuscate(pdu->data, 0, - sub->keys[SUBNET_KEY_TX_IDX(sub)].msg.privacy); + &sub->keys[SUBNET_KEY_TX_IDX(sub)].msg.privacy); if (err) { LOG_ERR("Obfuscation failed, err=%d", err); return err; From 6e082b4141d1dc295dbf9359cacb342fba06aa9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anders=20Storr=C3=B8?= Date: Wed, 6 Sep 2023 13:06:40 +0200 Subject: [PATCH 144/421] [nrf fromtree] Bluetooth: Mesh: Store priv beacon in sep entry MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Stores persistent private beacon state in separate settings entry. This is implemented to avoid issues related to backwards compatibility between device firmware updates. Signed-off-by: Anders Storrø (cherry picked from commit c80a52a1e31eaf74d83c1d4e2a47f82936ce4bc5) Signed-off-by: Alperen Şener (cherry picked from commit f93d50086c43854eb41f0616c79c3a387b3d8f24) --- subsys/bluetooth/mesh/cfg.c | 27 ++------- subsys/bluetooth/mesh/priv_beacon.h | 7 +++ subsys/bluetooth/mesh/priv_beacon_srv.c | 74 +++++++++++++++++++++++++ 3 files changed, 87 insertions(+), 21 deletions(-) create mode 100644 subsys/bluetooth/mesh/priv_beacon.h diff --git a/subsys/bluetooth/mesh/cfg.c b/subsys/bluetooth/mesh/cfg.c index 287023afa68..4a59f76bbbd 100644 --- a/subsys/bluetooth/mesh/cfg.c +++ b/subsys/bluetooth/mesh/cfg.c @@ -16,6 +16,7 @@ #include "friend.h" #include "adv.h" #include "cfg.h" +#include "priv_beacon.h" #define LOG_LEVEL CONFIG_BT_MESH_CFG_LOG_LEVEL #include @@ -30,11 +31,6 @@ struct cfg_val { uint8_t gatt_proxy; uint8_t frnd; uint8_t default_ttl; -#if defined(CONFIG_BT_MESH_PRIV_BEACONS) - uint8_t priv_beacon; - uint8_t priv_beacon_int; - uint8_t priv_gatt_proxy; -#endif #if defined(CONFIG_BT_MESH_OD_PRIV_PROXY_SRV) uint8_t on_demand_state; #endif @@ -109,9 +105,9 @@ int bt_mesh_priv_beacon_set(enum bt_mesh_feat_state priv_beacon) /* Beacon timer will stop automatically when all beacons are disabled. */ } - if (IS_ENABLED(CONFIG_BT_SETTINGS) && + if (IS_ENABLED(CONFIG_BT_SETTINGS) && IS_ENABLED(CONFIG_BT_MESH_PRIV_BEACON_SRV) && atomic_test_bit(bt_mesh.flags, BT_MESH_VALID)) { - bt_mesh_settings_store_schedule(BT_MESH_SETTINGS_CFG_PENDING); + bt_mesh_priv_beacon_srv_store_schedule(); } return 0; @@ -244,9 +240,9 @@ int bt_mesh_priv_gatt_proxy_set(enum bt_mesh_feat_state priv_gatt_proxy) bt_mesh_adv_gatt_update(); } - if (IS_ENABLED(CONFIG_BT_SETTINGS) && + if (IS_ENABLED(CONFIG_BT_SETTINGS) && IS_ENABLED(CONFIG_BT_MESH_PRIV_BEACON_SRV) && atomic_test_bit(bt_mesh.flags, BT_MESH_VALID)) { - bt_mesh_settings_store_schedule(BT_MESH_SETTINGS_CFG_PENDING); + bt_mesh_priv_beacon_srv_store_schedule(); } return 0; @@ -261,7 +257,6 @@ enum bt_mesh_feat_state bt_mesh_priv_gatt_proxy_get(void) return feature_get(BT_MESH_PRIV_GATT_PROXY); } - int bt_mesh_default_ttl_set(uint8_t default_ttl) { if (default_ttl == 1 || default_ttl > BT_MESH_TTL_MAX) { @@ -454,11 +449,6 @@ static int cfg_set(const char *name, size_t len_rd, bt_mesh_gatt_proxy_set(cfg.gatt_proxy); bt_mesh_friend_set(cfg.frnd); bt_mesh_default_ttl_set(cfg.default_ttl); -#if defined(CONFIG_BT_MESH_PRIV_BEACONS) - bt_mesh_priv_beacon_set(cfg.priv_beacon); - bt_mesh_priv_beacon_update_interval_set(cfg.priv_beacon_int); - bt_mesh_priv_gatt_proxy_set(cfg.priv_gatt_proxy); -#endif #if defined(CONFIG_BT_MESH_OD_PRIV_PROXY_SRV) bt_mesh_od_priv_proxy_set(cfg.on_demand_state); #endif @@ -476,7 +466,7 @@ static void clear_cfg(void) err = settings_delete("bt/mesh/Cfg"); if (err) { - LOG_ERR("Failed to clear configuration"); + LOG_ERR("Failed to clear configuration (err: %d)", err); } else { LOG_DBG("Cleared configuration"); } @@ -494,11 +484,6 @@ static void store_pending_cfg(void) val.gatt_proxy = bt_mesh_gatt_proxy_get(); val.frnd = bt_mesh_friend_get(); val.default_ttl = bt_mesh_default_ttl_get(); -#if defined(CONFIG_BT_MESH_PRIV_BEACONS) - val.priv_beacon = bt_mesh_priv_beacon_get(); - val.priv_beacon_int = bt_mesh_priv_beacon_update_interval_get(); - val.priv_gatt_proxy = bt_mesh_priv_gatt_proxy_get(); -#endif #if defined(CONFIG_BT_MESH_OD_PRIV_PROXY_SRV) val.on_demand_state = bt_mesh_od_priv_proxy_get(); #endif diff --git a/subsys/bluetooth/mesh/priv_beacon.h b/subsys/bluetooth/mesh/priv_beacon.h new file mode 100644 index 00000000000..0cbbdafd0b1 --- /dev/null +++ b/subsys/bluetooth/mesh/priv_beacon.h @@ -0,0 +1,7 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +void bt_mesh_priv_beacon_srv_store_schedule(void); diff --git a/subsys/bluetooth/mesh/priv_beacon_srv.c b/subsys/bluetooth/mesh/priv_beacon_srv.c index a1478efff80..377703e8352 100644 --- a/subsys/bluetooth/mesh/priv_beacon_srv.c +++ b/subsys/bluetooth/mesh/priv_beacon_srv.c @@ -11,11 +11,33 @@ #include "foundation.h" #include "beacon.h" #include "cfg.h" +#include "settings.h" #define LOG_LEVEL CONFIG_BT_MESH_MODEL_LOG_LEVEL #include LOG_MODULE_REGISTER(bt_mesh_priv_beacon_srv); +static struct bt_mesh_model *priv_beacon_srv; + +/* Private Beacon configuration server model states */ +struct { + uint8_t state; + uint8_t interval; + uint8_t proxy_state; +} priv_beacon_state; + +static int priv_beacon_store(bool delete) +{ + if (!IS_ENABLED(CONFIG_BT_SETTINGS)) { + return 0; + } + + const void *data = delete ? NULL : &priv_beacon_state; + size_t len = delete ? 0 : sizeof(priv_beacon_state); + + return bt_mesh_model_data_store(priv_beacon_srv, false, "pb", data, len); +} + static int beacon_status_rsp(struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx) { @@ -179,11 +201,63 @@ static int priv_beacon_srv_init(struct bt_mesh_model *mod) return -EINVAL; } + priv_beacon_srv = mod; mod->keys[0] = BT_MESH_KEY_DEV_LOCAL; return 0; } +static void priv_beacon_srv_reset(struct bt_mesh_model *model) +{ + (void)memset(&priv_beacon_state, 0, sizeof(priv_beacon_state)); + priv_beacon_store(true); +} + +#ifdef CONFIG_BT_SETTINGS +static int priv_beacon_srv_settings_set(struct bt_mesh_model *model, const char *name, + size_t len_rd, settings_read_cb read_cb, void *cb_data) +{ + int err; + + if (len_rd == 0) { + LOG_DBG("Cleared configuration state"); + return 0; + } + + err = bt_mesh_settings_set(read_cb, cb_data, &priv_beacon_state, sizeof(priv_beacon_state)); + if (err) { + LOG_ERR("Failed to set Private Beacon state"); + return err; + } + + bt_mesh_priv_beacon_set(priv_beacon_state.state); + bt_mesh_priv_beacon_update_interval_set(priv_beacon_state.interval); + bt_mesh_priv_gatt_proxy_set(priv_beacon_state.proxy_state); + return 0; +} + +static void priv_beacon_srv_pending_store(struct bt_mesh_model *model) +{ + priv_beacon_state.state = bt_mesh_priv_beacon_get(); + priv_beacon_state.interval = bt_mesh_priv_beacon_update_interval_get(); + priv_beacon_state.proxy_state = bt_mesh_priv_gatt_proxy_get(); + + priv_beacon_store(false); +} +#endif + const struct bt_mesh_model_cb bt_mesh_priv_beacon_srv_cb = { .init = priv_beacon_srv_init, + .reset = priv_beacon_srv_reset, +#ifdef CONFIG_BT_SETTINGS + .settings_set = priv_beacon_srv_settings_set, + .pending_store = priv_beacon_srv_pending_store, +#endif }; + +void bt_mesh_priv_beacon_srv_store_schedule(void) +{ + if (IS_ENABLED(CONFIG_BT_SETTINGS)) { + bt_mesh_model_data_store_schedule(priv_beacon_srv); + } +} From fbbfa43fae8509eef87eb3151281c3f10ed6265a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anders=20Storr=C3=B8?= Date: Wed, 6 Sep 2023 13:06:40 +0200 Subject: [PATCH 145/421] [nrf fromtree] Bluetooth: Mesh: Store priv proxy in sep entry MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Stores persistent on-demand private GATT proxy state in separate settings entry. This is implemented to avoid issues related to backwards compatibility between device firmware updates. Signed-off-by: Anders Storrø (cherry picked from commit 6559de3238d3ff6f5da5535811457ad29b6e9677) Signed-off-by: Alperen Şener (cherry picked from commit 6ec9512a51bd6edc73dfc26a089e345800726647) --- subsys/bluetooth/mesh/cfg.c | 15 ++---- subsys/bluetooth/mesh/od_priv_proxy.h | 7 +++ subsys/bluetooth/mesh/od_priv_proxy_srv.c | 65 +++++++++++++++++++++++ 3 files changed, 75 insertions(+), 12 deletions(-) create mode 100644 subsys/bluetooth/mesh/od_priv_proxy.h diff --git a/subsys/bluetooth/mesh/cfg.c b/subsys/bluetooth/mesh/cfg.c index 4a59f76bbbd..c7bea0d29b0 100644 --- a/subsys/bluetooth/mesh/cfg.c +++ b/subsys/bluetooth/mesh/cfg.c @@ -16,6 +16,7 @@ #include "friend.h" #include "adv.h" #include "cfg.h" +#include "od_priv_proxy.h" #include "priv_beacon.h" #define LOG_LEVEL CONFIG_BT_MESH_CFG_LOG_LEVEL @@ -31,9 +32,6 @@ struct cfg_val { uint8_t gatt_proxy; uint8_t frnd; uint8_t default_ttl; -#if defined(CONFIG_BT_MESH_OD_PRIV_PROXY_SRV) - uint8_t on_demand_state; -#endif }; void bt_mesh_beacon_set(bool beacon) @@ -157,9 +155,9 @@ int bt_mesh_od_priv_proxy_set(uint8_t on_demand_proxy) bt_mesh.on_demand_state = on_demand_proxy; } - if (IS_ENABLED(CONFIG_BT_SETTINGS) && + if (IS_ENABLED(CONFIG_BT_SETTINGS) && IS_ENABLED(CONFIG_BT_MESH_OD_PRIV_PROXY_SRV) && atomic_test_bit(bt_mesh.flags, BT_MESH_VALID)) { - bt_mesh_settings_store_schedule(BT_MESH_SETTINGS_CFG_PENDING); + bt_mesh_od_priv_proxy_srv_store_schedule(); } return 0; #endif @@ -449,9 +447,6 @@ static int cfg_set(const char *name, size_t len_rd, bt_mesh_gatt_proxy_set(cfg.gatt_proxy); bt_mesh_friend_set(cfg.frnd); bt_mesh_default_ttl_set(cfg.default_ttl); -#if defined(CONFIG_BT_MESH_OD_PRIV_PROXY_SRV) - bt_mesh_od_priv_proxy_set(cfg.on_demand_state); -#endif LOG_DBG("Restored configuration state"); @@ -484,10 +479,6 @@ static void store_pending_cfg(void) val.gatt_proxy = bt_mesh_gatt_proxy_get(); val.frnd = bt_mesh_friend_get(); val.default_ttl = bt_mesh_default_ttl_get(); -#if defined(CONFIG_BT_MESH_OD_PRIV_PROXY_SRV) - val.on_demand_state = bt_mesh_od_priv_proxy_get(); -#endif - err = settings_save_one("bt/mesh/Cfg", &val, sizeof(val)); if (err) { diff --git a/subsys/bluetooth/mesh/od_priv_proxy.h b/subsys/bluetooth/mesh/od_priv_proxy.h new file mode 100644 index 00000000000..7baa7f067fc --- /dev/null +++ b/subsys/bluetooth/mesh/od_priv_proxy.h @@ -0,0 +1,7 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +void bt_mesh_od_priv_proxy_srv_store_schedule(void); diff --git a/subsys/bluetooth/mesh/od_priv_proxy_srv.c b/subsys/bluetooth/mesh/od_priv_proxy_srv.c index 32f5ea44179..b18a8ec7530 100644 --- a/subsys/bluetooth/mesh/od_priv_proxy_srv.c +++ b/subsys/bluetooth/mesh/od_priv_proxy_srv.c @@ -9,11 +9,28 @@ #include "access.h" #include "cfg.h" #include "foundation.h" +#include "settings.h" #define LOG_LEVEL CONFIG_BT_MESH_MODEL_LOG_LEVEL #include LOG_MODULE_REGISTER(bt_mesh_od_priv_proxy_srv); + +static struct bt_mesh_model *od_priv_proxy_srv; +static uint8_t on_demand_state; + +static int od_priv_proxy_store(bool delete) +{ + if (!IS_ENABLED(CONFIG_BT_SETTINGS)) { + return 0; + } + + const void *data = delete ? NULL : &on_demand_state; + size_t len = delete ? 0 : sizeof(uint8_t); + + return bt_mesh_model_data_store(od_priv_proxy_srv, false, "pp", data, len); +} + static int proxy_status_rsp(struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx) { @@ -64,6 +81,8 @@ const struct bt_mesh_model_op _bt_mesh_od_priv_proxy_srv_op[] = { static int od_priv_proxy_srv_init(struct bt_mesh_model *mod) { + od_priv_proxy_srv = mod; + struct bt_mesh_model *priv_beacon_srv = bt_mesh_model_find( bt_mesh_model_elem(mod), BT_MESH_MODEL_ID_PRIV_BEACON_SRV); struct bt_mesh_model *sol_pdu_rpl_srv = bt_mesh_model_find( @@ -89,6 +108,52 @@ static int od_priv_proxy_srv_init(struct bt_mesh_model *mod) return 0; } +static void od_priv_proxy_srv_reset(struct bt_mesh_model *model) +{ + on_demand_state = 0; + od_priv_proxy_store(true); +} + +#ifdef CONFIG_BT_SETTINGS +static int od_priv_proxy_srv_settings_set(struct bt_mesh_model *model, const char *name, + size_t len_rd, settings_read_cb read_cb, void *cb_data) +{ + int err; + + if (len_rd == 0) { + LOG_DBG("Cleared configuration state"); + return 0; + } + + err = bt_mesh_settings_set(read_cb, cb_data, &on_demand_state, sizeof(uint8_t)); + if (err) { + LOG_ERR("Failed to set OD private proxy state"); + return err; + } + + bt_mesh_od_priv_proxy_set(on_demand_state); + return 0; +} + +static void od_priv_proxy_srv_pending_store(struct bt_mesh_model *model) +{ + on_demand_state = bt_mesh_od_priv_proxy_get(); + od_priv_proxy_store(false); +} +#endif + const struct bt_mesh_model_cb _bt_mesh_od_priv_proxy_srv_cb = { .init = od_priv_proxy_srv_init, + .reset = od_priv_proxy_srv_reset, +#ifdef CONFIG_BT_SETTINGS + .settings_set = od_priv_proxy_srv_settings_set, + .pending_store = od_priv_proxy_srv_pending_store, +#endif }; + +void bt_mesh_od_priv_proxy_srv_store_schedule(void) +{ + if (IS_ENABLED(CONFIG_BT_SETTINGS)) { + bt_mesh_model_data_store_schedule(od_priv_proxy_srv); + } +} From 96ac408fa71a6310e2a7565377854c1886cf5e42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alperen=20=C5=9Eener?= Date: Mon, 11 Sep 2023 15:47:39 +0200 Subject: [PATCH 146/421] [nrf fromtree] Bluetooth: Mesh: add optional OOB info to ext scan report MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Even though the OOB information is optional we can add it to extended scan reports in cases there is detected unprovisoned devices. Referring to MshPRT section 4.4.5.3: When the Remote Provisioning Extended Scan procedure completes without receiving an advertisement from the unprovisioned device, the OOBInformation and AdvStructures fields shall be skipped. When the obtained data is empty, the AdvStructures field shall be skipped. The Status field shall be set to Success. and referring to MshPRT section 4.3.4.9: The OOBInformation field contains the OOB Information of either the unprovisioned device or the Remote Provisioning Server. Signed-off-by: Alperen Şener (cherry picked from commit f6a9fc12025264f010eee4200bb4fd34a6a07e22) Signed-off-by: Alperen Şener (cherry picked from commit e28ae8300000b8fef7f139536693ffc16c44a7f9) --- subsys/bluetooth/mesh/rpr_srv.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/subsys/bluetooth/mesh/rpr_srv.c b/subsys/bluetooth/mesh/rpr_srv.c index b38bec4cd40..c8639d8b514 100644 --- a/subsys/bluetooth/mesh/rpr_srv.c +++ b/subsys/bluetooth/mesh/rpr_srv.c @@ -267,13 +267,15 @@ static void scan_ext_report_send(void) bt_mesh_model_msg_init(&buf, RPR_OP_EXTENDED_SCAN_REPORT); net_buf_simple_add_u8(&buf, BT_MESH_RPR_SUCCESS); net_buf_simple_add_mem(&buf, srv.scan.dev->uuid, 16); - if (!(srv.scan.dev->flags & BT_MESH_RPR_UNPROV_FOUND)) { + + if (srv.scan.dev->flags & BT_MESH_RPR_UNPROV_FOUND) { + net_buf_simple_add_le16(&buf, srv.scan.dev->oob); + } else { LOG_DBG("not found"); goto send; } if (srv.scan.dev->flags & BT_MESH_RPR_UNPROV_EXT_ADV_RXD) { - net_buf_simple_add_le16(&buf, srv.scan.dev->oob); net_buf_simple_add_mem(&buf, srv.scan.adv_data->data, srv.scan.adv_data->len); LOG_DBG("adv data: %s", From 34e20954d8d64805a6e1cd0c804361ce713da363 Mon Sep 17 00:00:00 2001 From: Ludvig Samuelsen Jordet Date: Wed, 9 Aug 2023 09:30:29 +0200 Subject: [PATCH 147/421] [nrf fromtree] Bluetooth: Mesh: Add support for Upload OOB Start MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This adds support for the Upload OOB Start message to the DFD server, by providing callbacks that the application can use to hook any OOB scheme into the model behavior. There are also extensive changes to the dfu_slot module, to accomodate the new needs that appeared with the support for OOB transfer (mainly, fwid, size and metadata are no longer available when the slot is allocated, they appear later in the handling). Signed-off-by: Ludvig Samuelsen Jordet (cherry picked from commit b990a74f8b41b91634061ee366c1005541f319eb) Signed-off-by: Alperen Şener (cherry picked from commit e7b8ff578bb605b7071e8ba220e5633e7f9c42b0) --- doc/connectivity/bluetooth/api/mesh/shell.rst | 5 +- include/zephyr/bluetooth/mesh/dfd_srv.h | 163 +++++++++- include/zephyr/bluetooth/mesh/dfu.h | 13 +- subsys/bluetooth/mesh/Kconfig | 8 + subsys/bluetooth/mesh/dfd_srv.c | 270 +++++++++++++--- subsys/bluetooth/mesh/dfu_slot.c | 294 ++++++++++-------- subsys/bluetooth/mesh/dfu_slot.h | 87 ++++-- subsys/bluetooth/mesh/shell/dfd.c | 9 +- subsys/bluetooth/mesh/shell/dfu.c | 53 ++-- tests/bsim/bluetooth/mesh/prj_mesh1d1.conf | 3 +- tests/bsim/bluetooth/mesh/src/test_dfu.c | 185 +++++++---- .../tests_scripts/dfu/dfu_slot_idempotency.sh | 14 + .../tests_scripts/dfu/dfu_slot_reservation.sh | 14 + 13 files changed, 792 insertions(+), 326 deletions(-) create mode 100755 tests/bsim/bluetooth/mesh/tests_scripts/dfu/dfu_slot_idempotency.sh create mode 100755 tests/bsim/bluetooth/mesh/tests_scripts/dfu/dfu_slot_reservation.sh diff --git a/doc/connectivity/bluetooth/api/mesh/shell.rst b/doc/connectivity/bluetooth/api/mesh/shell.rst index f9acf24d277..e6609f40e5c 100644 --- a/doc/connectivity/bluetooth/api/mesh/shell.rst +++ b/doc/connectivity/bluetooth/api/mesh/shell.rst @@ -1034,15 +1034,14 @@ Firmware Update Client model The Firmware Update Client model can be added to the mesh shell by enabling configuration options :kconfig:option:`CONFIG_BT_MESH_BLOB_CLI` and :kconfig:option:`CONFIG_BT_MESH_DFU_CLI`. The Firmware Update Client demonstrates the firmware update Distributor role by transferring a dummy firmware update to a set of Target nodes. -``mesh models dfu slot add [ [ []]]`` +``mesh models dfu slot add []`` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Add a virtual DFU image slot that can be transferred as a DFU image. The image slot will be assigned an image slot index, which is printed as a response, and can be used to reference the slot in other commands. To update the image slot, remove it using the ``mesh models dfu slot del`` shell command and then add it again. * ``Size``: DFU image slot size in bytes. - * ``FwID``: Optional firmware ID, formatted as a hexstring. + * ``FwID``: Firmware ID, formatted as a hexstring. * ``Metadata``: Optional firmware metadata, formatted as a hexstring. - * ``URI``: Optional URI for the firmware. ``mesh models dfu slot del `` diff --git a/include/zephyr/bluetooth/mesh/dfd_srv.h b/include/zephyr/bluetooth/mesh/dfd_srv.h index 0e281b29186..da339c57ec6 100644 --- a/include/zephyr/bluetooth/mesh/dfd_srv.h +++ b/include/zephyr/bluetooth/mesh/dfd_srv.h @@ -29,11 +29,47 @@ extern "C" { #define CONFIG_BT_MESH_DFD_SRV_TARGETS_MAX 0 #endif +#ifndef CONFIG_BT_MESH_DFD_SRV_SLOT_MAX_SIZE +#define CONFIG_BT_MESH_DFD_SRV_SLOT_MAX_SIZE 0 +#endif + +#ifndef CONFIG_BT_MESH_DFD_SRV_SLOT_SPACE +#define CONFIG_BT_MESH_DFD_SRV_SLOT_SPACE 0 +#endif + struct bt_mesh_dfd_srv; +#ifdef CONFIG_BT_MESH_DFD_SRV_OOB_UPLOAD +/** + * + * @brief Initialization parameters for the @ref bt_mesh_dfd_srv with OOB + * upload support. + * + * @param[in] _cb Pointer to a @ref bt_mesh_dfd_srv_cb instance. + * @param[in] _oob_schemes Array of OOB schemes supported by the server, + * each scheme being a code point from the + * Bluetooth SIG Assigned Numbers document. + * @param[in] _oob_schemes_count Number of schemes in @c _oob_schemes. + */ +#define BT_MESH_DFD_SRV_OOB_INIT(_cb, _oob_schemes, _oob_schemes_count) \ + { \ + .cb = _cb, \ + .dfu = BT_MESH_DFU_CLI_INIT(&_bt_mesh_dfd_srv_dfu_cb), \ + .upload = { \ + .blob = { .cb = &_bt_mesh_dfd_srv_blob_cb }, \ + }, \ + .oob_schemes = { \ + .schemes = _oob_schemes, \ + .count = _oob_schemes_count, \ + }, \ + } +#endif /* CONFIG_BT_MESH_DFD_SRV_OOB_UPLOAD */ + /** * * @brief Initialization parameters for the @ref bt_mesh_dfd_srv. + * + * @param[in] _cb Pointer to a @ref bt_mesh_dfd_srv_cb instance. */ #define BT_MESH_DFD_SRV_INIT(_cb) \ { \ @@ -75,6 +111,64 @@ struct bt_mesh_dfd_srv_cb { const struct bt_mesh_dfu_slot *slot, const struct bt_mesh_blob_io **io); +#ifdef CONFIG_BT_MESH_DFD_SRV_OOB_UPLOAD + /** @brief Firmware upload OOB start callback. + * + * Called at the start of an OOB firmware upload. The application must + * start a firmware check using an OOB mechanism, and then call + * @ref bt_mesh_dfd_srv_oob_check_complete. Depending on the return + * value of this function, the application must then start storing the + * firmware image using an OOB mechanism, and call + * @ref bt_mesh_dfd_srv_oob_store_complete. This callback is mandatory + * to support OOB uploads. + * + * @param srv Firmware Distribution Server model instance. + * @param slot Slot to be used for the upload. + * @param uri Pointer to buffer containing the URI used to + * check for new firmware. + * @param uri_len Length of the URI buffer. + * @param fwid Pointer to buffer containing the current + * firmware ID to be used when checking for + * availability of new firmware. + * @param fwid_len Length of the current firmware ID. Must be set + * to the length of the new firmware ID if it is + * available, or to 0 if new firmware is not + * available. + * + * @return BT_MESH_DFD_SUCCESS on success, or error code otherwise. + */ + int (*start_oob_upload)(struct bt_mesh_dfd_srv *srv, + const struct bt_mesh_dfu_slot *slot, + const char *uri, uint8_t uri_len, + const uint8_t *fwid, uint16_t fwid_len); + + /** @brief Cancel store OOB callback + * + * Called when an OOB store is cancelled. The application must stop + * any ongoing OOB image transfer. This callback is mandatory to + * support OOB uploads. + * + * @param srv Firmware Distribution Server model instance. + * @param slot DFU image slot to cancel + */ + void (*cancel_oob_upload)(struct bt_mesh_dfd_srv *srv, + const struct bt_mesh_dfu_slot *slot); + + /** @brief Get the progress of an ongoing OOB store + * + * Called by the Firmware Distribution Server model when it needs to + * get the current progress of an ongoing OOB store from the + * application. This callback is mandatory to support OOB uploads. + * + * @param srv Firmware Distribution Server model instance. + * @param slot DFU image slot to get progress for. + * + * @return The current progress of the ongoing OOB store, in percent. + */ + uint8_t (*oob_progress_get)(struct bt_mesh_dfd_srv *srv, + const struct bt_mesh_dfu_slot *slot); +#endif /* CONFIG_BT_MESH_DFD_SRV_OOB_UPLOAD */ + /** @brief Slot delete callback. * * Called when the Firmware Distribution Server is about to delete a DFU image slot. @@ -129,12 +223,79 @@ struct bt_mesh_dfd_srv { struct { enum bt_mesh_dfd_upload_phase phase; - const struct bt_mesh_dfu_slot *slot; + struct bt_mesh_dfu_slot *slot; const struct flash_area *area; struct bt_mesh_blob_srv blob; +#ifdef CONFIG_BT_MESH_DFD_SRV_OOB_UPLOAD + bool is_oob; + struct { + uint8_t uri_len; + uint8_t uri[CONFIG_BT_MESH_DFU_URI_MAXLEN]; + uint16_t current_fwid_len; + uint8_t current_fwid[CONFIG_BT_MESH_DFU_FWID_MAXLEN]; + struct bt_mesh_msg_ctx ctx; + } oob; +#endif /* CONFIG_BT_MESH_DFD_SRV_OOB_UPLOAD */ } upload; + +#ifdef CONFIG_BT_MESH_DFD_SRV_OOB_UPLOAD + struct { + const uint8_t *schemes; + const uint8_t count; + } oob_schemes; +#endif /* CONFIG_BT_MESH_DFD_SRV_OOB_UPLOAD */ }; +#ifdef CONFIG_BT_MESH_DFD_SRV_OOB_UPLOAD +/** @brief Call when an OOB check has completed or failed + * + * This should be called by the application after an OOB check started by the @c start_oob_upload + * callback has completed or failed. The @p status param should be set to one of the following + * values: + * + * * @c BT_MESH_DFD_SUCCESS if the check was succesfull and a new firmware ID was found. + * * @c BT_MESH_DFD_ERR_URI_MALFORMED if the URI is not formatted correctly. + * * @c BT_MESH_DFD_ERR_URI_NOT_SUPPORTED if the URI scheme is not supported by the node. + * * @c BT_MESH_DFD_ERR_URI_UNREACHABLE if the URI can't be reached. + * * @c BT_MESH_DFD_ERR_NEW_FW_NOT_AVAILABLE if the check completes successfully but no new + * firmware is available. + * + * If this function returns 0, the application should then download the firmware to the + * slot. If an error code is returned, the application should abort the OOB upload. + * + * @param srv Firmware Distribution Server model instance. + * @param slot The slot used in the OOB upload. + * @param status The result of the firmware check. + * @param fwid If the check was successful and new firmware found, this should point to a + * buffer containing the new firmware ID to store. + * @param fwid_len The length of the firmware ID pointed to by @p fwid. + * + * @return 0 on success, (negative) error code otherwise. + */ +int bt_mesh_dfd_srv_oob_check_complete(struct bt_mesh_dfd_srv *srv, + const struct bt_mesh_dfu_slot *slot, int status, + uint8_t *fwid, size_t fwid_len); + +/** @brief Call when an OOB store has completed or failed + * + * This should be called by the application after an OOB store started after a succesfull call to + * @c bt_mesh_dfd_srv_oob_check_complete has completed successfully or failed. + * + * @param srv Firmware Distribution Server model instance. + * @param slot The slot used when storing the firmware image. + * @param success @c true if the OOB store completed successfully, @c false otherwise. + * @param size The size of the stored firmware image, in bytes. + * @param metadata Pointer to the metadata received OOB, or @c NULL if no metadata was + * received. + * @param metadata_len Size of the metadata pointed to by @p metadata. + * + * @return 0 on success, (negative) error code otherwise. + */ +int bt_mesh_dfd_srv_oob_store_complete(struct bt_mesh_dfd_srv *srv, + const struct bt_mesh_dfu_slot *slot, bool success, + size_t size, const uint8_t *metadata, size_t metadata_len); +#endif /* CONFIG_BT_MESH_DFD_SRV_OOB_UPLOAD */ + /** @cond INTERNAL_HIDDEN */ extern const struct bt_mesh_model_op _bt_mesh_dfd_srv_op[]; extern const struct bt_mesh_model_cb _bt_mesh_dfd_srv_cb; diff --git a/include/zephyr/bluetooth/mesh/dfu.h b/include/zephyr/bluetooth/mesh/dfu.h index 91f36cdbaeb..4745355f039 100644 --- a/include/zephyr/bluetooth/mesh/dfu.h +++ b/include/zephyr/bluetooth/mesh/dfu.h @@ -34,6 +34,10 @@ extern "C" { #define CONFIG_BT_MESH_DFU_URI_MAXLEN 0 #endif +#ifndef CONFIG_BT_MESH_DFU_SLOT_CNT +#define CONFIG_BT_MESH_DFU_SLOT_CNT 0 +#endif + /** DFU transfer phase. */ enum bt_mesh_dfu_phase { /** Ready to start a Receive Firmware procedure. */ @@ -140,10 +144,7 @@ struct bt_mesh_dfu_img { /** Length of the firmware ID. */ size_t fwid_len; - /** Update URI, or NULL. - * - * Must use one of the http: or https: schemes. - */ + /** Update URI, or NULL. */ const char *uri; }; @@ -155,14 +156,10 @@ struct bt_mesh_dfu_slot { size_t fwid_len; /** Length of the metadata. */ size_t metadata_len; - /** Length of the image URI. */ - size_t uri_len; /** Firmware ID. */ uint8_t fwid[CONFIG_BT_MESH_DFU_FWID_MAXLEN]; /** Metadata. */ uint8_t metadata[CONFIG_BT_MESH_DFU_METADATA_MAXLEN]; - /** Image URI. */ - char uri[CONFIG_BT_MESH_DFU_URI_MAXLEN]; }; /** @} */ diff --git a/subsys/bluetooth/mesh/Kconfig b/subsys/bluetooth/mesh/Kconfig index b8e26309a28..2dfc125b8fd 100644 --- a/subsys/bluetooth/mesh/Kconfig +++ b/subsys/bluetooth/mesh/Kconfig @@ -1235,6 +1235,14 @@ config BT_MESH_DFD_SRV_TARGETS_MAX This value defines the maximum number of Target nodes the Firmware Distribution Server can target simultaneously. +config BT_MESH_DFD_SRV_OOB_UPLOAD + bool "Support for DFU image OOB upload" + help + This enables support for OOB upload of firmware images for + distribution. This makes several callbacks and use of the init + macro BT_MESH_DFD_SRV_INIT_OOB mandatory. See the API documentation + for bt_mesh_dfd_srv_cb for details about the mandatory callbacks. + endif config BT_MESH_RPR_SRV diff --git a/subsys/bluetooth/mesh/dfd_srv.c b/subsys/bluetooth/mesh/dfd_srv.c index 2898ca39a39..54de343c94a 100644 --- a/subsys/bluetooth/mesh/dfd_srv.c +++ b/subsys/bluetooth/mesh/dfd_srv.c @@ -224,7 +224,20 @@ static int handle_capabilities_get(struct bt_mesh_model *mod, struct bt_mesh_msg size = MIN(size, CONFIG_BT_MESH_DFD_SRV_SLOT_SPACE); net_buf_simple_add_le32(&rsp, CONFIG_BT_MESH_DFD_SRV_SLOT_SPACE - size); - net_buf_simple_add_u8(&rsp, 0U); /* OOB retrieval not supported */ + +#ifdef CONFIG_BT_MESH_DFD_SRV_OOB_UPLOAD + struct bt_mesh_dfd_srv *srv = mod->user_data; + + if (srv->oob_schemes.count > 0) { + net_buf_simple_add_u8(&rsp, 1); + net_buf_simple_add_mem(&rsp, srv->oob_schemes.schemes, + srv->oob_schemes.count); + } else +#else + { + net_buf_simple_add_u8(&rsp, 0); + } +#endif bt_mesh_model_send(mod, ctx, &rsp, NULL, NULL); @@ -346,10 +359,19 @@ static void upload_status_rsp(struct bt_mesh_dfd_srv *srv, return; } - net_buf_simple_add_u8(&rsp, - bt_mesh_blob_srv_progress(&srv->upload.blob)); - net_buf_simple_add_mem(&rsp, srv->upload.slot->fwid, - srv->upload.slot->fwid_len); +#ifdef CONFIG_BT_MESH_DFD_SRV_OOB_UPLOAD + if (srv->upload.is_oob) { + net_buf_simple_add_u8(&rsp, + srv->cb->oob_progress_get(srv, srv->upload.slot) | BIT(7)); + net_buf_simple_add_mem(&rsp, srv->upload.oob.current_fwid, + srv->upload.oob.current_fwid_len); + } else +#endif + { + net_buf_simple_add_u8(&rsp, bt_mesh_blob_srv_progress(&srv->upload.blob)); + net_buf_simple_add_mem(&rsp, srv->upload.slot->fwid, + srv->upload.slot->fwid_len); + } bt_mesh_model_send(srv->mod, ctx, &rsp, NULL, NULL); } @@ -364,16 +386,42 @@ static int handle_upload_get(struct bt_mesh_model *mod, struct bt_mesh_msg_ctx * return 0; } +static inline int set_upload_fwid(struct bt_mesh_dfd_srv *srv, struct bt_mesh_msg_ctx *ctx, + const uint8_t *fwid, size_t fwid_len) +{ + int err = bt_mesh_dfu_slot_fwid_set(srv->upload.slot, fwid, fwid_len); + + switch (err) { + case -EFBIG: /* Fwid too long */ + case -EALREADY: /* Other server is in progress with this fwid */ + bt_mesh_dfu_slot_release(srv->upload.slot); + upload_status_rsp(srv, ctx, BT_MESH_DFD_ERR_INTERNAL); + break; + case -EEXIST: /* Img with this fwid already is in list */ + srv->upload.phase = BT_MESH_DFD_UPLOAD_PHASE_TRANSFER_SUCCESS; + bt_mesh_dfu_slot_release(srv->upload.slot); + upload_status_rsp(srv, ctx, BT_MESH_DFD_SUCCESS); + break; + case 0: + srv->upload.phase = BT_MESH_DFD_UPLOAD_PHASE_TRANSFER_ACTIVE; + break; + case -EINVAL: /* Slot in wrong state. */ + default: + break; + } + + return err; +} + static int handle_upload_start(struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { struct bt_mesh_dfd_srv *srv = mod->user_data; - const struct bt_mesh_dfu_slot *old_slot = srv->upload.slot; size_t meta_len, fwid_len, size; const uint8_t *meta, *fwid; uint16_t timeout_base; uint64_t blob_id; - int err, idx; + int err; uint8_t ttl; ttl = net_buf_simple_pull_u8(buf); @@ -392,9 +440,7 @@ static int handle_upload_start(struct bt_mesh_model *mod, struct bt_mesh_msg_ctx LOG_DBG("Upload Start: size: %d, fwid: %s, metadata: %s", size, bt_hex(fwid, fwid_len), bt_hex(meta, meta_len)); - if (size > CONFIG_BT_MESH_DFD_SRV_SLOT_MAX_SIZE || - fwid_len > CONFIG_BT_MESH_DFU_FWID_MAXLEN || - meta_len > CONFIG_BT_MESH_DFU_METADATA_MAXLEN) { + if (size > CONFIG_BT_MESH_DFD_SRV_SLOT_MAX_SIZE) { upload_status_rsp(srv, ctx, BT_MESH_DFD_ERR_INSUFFICIENT_RESOURCES); return 0; @@ -413,7 +459,11 @@ static int handle_upload_start(struct bt_mesh_model *mod, struct bt_mesh_msg_ctx !memcmp(srv->upload.slot->metadata, meta, meta_len) && srv->upload.blob.state.xfer.id == blob_id && srv->upload.blob.state.ttl == ttl && - srv->upload.blob.state.timeout_base == timeout_base) { + srv->upload.blob.state.timeout_base == timeout_base +#ifdef CONFIG_BT_MESH_DFD_SRV_OOB_UPLOAD + && !srv->upload.is_oob +#endif + ) { LOG_DBG("Duplicate upload start"); upload_status_rsp(srv, ctx, BT_MESH_DFD_SUCCESS); return 0; @@ -424,23 +474,16 @@ static int handle_upload_start(struct bt_mesh_model *mod, struct bt_mesh_msg_ctx return 0; } - idx = bt_mesh_dfu_slot_get(fwid, fwid_len, &srv->upload.slot); - if (idx >= 0 && bt_mesh_dfu_slot_is_valid(srv->upload.slot)) { - LOG_DBG("Already received image"); - srv->upload.phase = BT_MESH_DFD_UPLOAD_PHASE_TRANSFER_SUCCESS; - upload_status_rsp(srv, ctx, BT_MESH_DFD_SUCCESS); - return 0; - } + /* This will be a no-op if the slot state isn't RESERVED, which is + * what we want. + */ + bt_mesh_dfu_slot_release(srv->upload.slot); - if (old_slot && !bt_mesh_dfu_slot_is_valid(old_slot)) { - LOG_DBG("Deleting old invalid slot"); - slot_del(srv, old_slot); - } +#ifdef CONFIG_BT_MESH_DFD_SRV_OOB_UPLOAD + srv->upload.is_oob = false; +#endif + srv->upload.slot = bt_mesh_dfu_slot_reserve(); - /* TODO Store transfer state before slot is added. */ - - srv->upload.slot = bt_mesh_dfu_slot_add(size, fwid, fwid_len, meta, - meta_len, NULL, 0); if (!srv->upload.slot) { LOG_WRN("No space for slot"); upload_status_rsp(srv, ctx, @@ -448,11 +491,27 @@ static int handle_upload_start(struct bt_mesh_model *mod, struct bt_mesh_msg_ctx return 0; } + err = set_upload_fwid(srv, ctx, fwid, fwid_len); + if (err) { + return err; + } + + err = bt_mesh_dfu_slot_info_set(srv->upload.slot, size, meta, meta_len); + switch (err) { + case -EFBIG: + upload_status_rsp(srv, ctx, BT_MESH_DFD_ERR_INTERNAL); + break; + case 0: + break; + default: + return err; + } + srv->io = NULL; err = srv->cb->recv(srv, srv->upload.slot, &srv->io); if (err || !srv->io) { LOG_ERR("App rejected upload. err: %d io: %p", err, srv->io); - slot_del(srv, srv->upload.slot); + bt_mesh_dfu_slot_release(srv->upload.slot); upload_status_rsp(srv, ctx, BT_MESH_DFD_ERR_INTERNAL); return 0; } @@ -461,7 +520,7 @@ static int handle_upload_start(struct bt_mesh_model *mod, struct bt_mesh_msg_ctx timeout_base); if (err) { LOG_ERR("BLOB Server rejected upload (err: %d)", err); - slot_del(srv, srv->upload.slot); + bt_mesh_dfu_slot_release(srv->upload.slot); upload_status_rsp(srv, ctx, BT_MESH_DFD_ERR_INTERNAL); return 0; } @@ -478,10 +537,71 @@ static int handle_upload_start_oob(struct bt_mesh_model *mod, struct bt_mesh_msg struct net_buf_simple *buf) { struct bt_mesh_dfd_srv *srv = mod->user_data; + uint8_t uri_len; + uint8_t *uri; + uint16_t fwid_len; + uint8_t *fwid; - LOG_DBG(""); + uri_len = net_buf_simple_pull_u8(buf); + + if (uri_len > buf->len) { + return -EINVAL; + } + + uri = net_buf_simple_pull_mem(buf, uri_len); + fwid_len = buf->len; + fwid = net_buf_simple_pull_mem(buf, fwid_len); + if (upload_is_busy(srv)) { +#ifdef CONFIG_BT_MESH_DFD_SRV_OOB_UPLOAD + if (srv->upload.is_oob && + uri_len == srv->upload.oob.uri_len && + fwid_len == srv->upload.oob.current_fwid_len && + !memcmp(uri, srv->upload.oob.uri, uri_len) && + !memcmp(fwid, srv->upload.oob.current_fwid, fwid_len)) { + /* Same image, return SUCCESS for idempotency */ + upload_status_rsp(srv, ctx, BT_MESH_DFD_SUCCESS); + return 0; + } +#endif + upload_status_rsp(srv, ctx, BT_MESH_DFD_ERR_BUSY_WITH_UPLOAD); + return 0; + } + +#ifdef CONFIG_BT_MESH_DFD_SRV_OOB_UPLOAD + if (uri_len > CONFIG_BT_MESH_DFU_URI_MAXLEN || + fwid_len > CONFIG_BT_MESH_DFU_FWID_MAXLEN) { + upload_status_rsp(srv, ctx, BT_MESH_DFD_ERR_INTERNAL); + return 0; + } + + struct bt_mesh_dfu_slot *slot = bt_mesh_dfu_slot_reserve(); + + if (slot == NULL) { + upload_status_rsp(srv, ctx, BT_MESH_DFD_ERR_INSUFFICIENT_RESOURCES); + return 0; + } + + srv->upload.is_oob = true; + srv->upload.slot = slot; + memcpy(srv->upload.oob.uri, uri, uri_len); + srv->upload.oob.uri_len = uri_len; + memcpy(srv->upload.oob.current_fwid, fwid, fwid_len); + srv->upload.oob.current_fwid_len = fwid_len; + memcpy(&srv->upload.oob.ctx, ctx, sizeof(struct bt_mesh_msg_ctx)); + + int status = srv->cb->start_oob_upload(srv, srv->upload.slot, srv->upload.oob.uri, + srv->upload.oob.uri_len, + srv->upload.oob.current_fwid, + srv->upload.oob.current_fwid_len); + + if (status != BT_MESH_DFD_SUCCESS) { + upload_status_rsp(srv, ctx, status); + bt_mesh_dfu_slot_release(srv->upload.slot); + } +#else upload_status_rsp(srv, ctx, BT_MESH_DFD_ERR_URI_NOT_SUPPORTED); +#endif /* CONFIG_BT_MESH_DFD_SRV_OOB_UPLOAD */ return 0; } @@ -492,7 +612,14 @@ static int handle_upload_cancel(struct bt_mesh_model *mod, struct bt_mesh_msg_ct struct bt_mesh_dfd_srv *srv = mod->user_data; srv->upload.phase = BT_MESH_DFD_UPLOAD_PHASE_IDLE; - (void)bt_mesh_blob_srv_cancel(&srv->upload.blob); +#ifdef CONFIG_BT_MESH_DFD_SRV_OOB_UPLOAD + if (srv->upload.is_oob) { + srv->cb->cancel_oob_upload(srv, srv->upload.slot); + } else +#endif + { + (void)bt_mesh_blob_srv_cancel(&srv->upload.blob); + } upload_status_rsp(srv, ctx, BT_MESH_DFD_SUCCESS); return 0; @@ -508,7 +635,7 @@ static void fw_status_rsp(struct bt_mesh_dfd_srv *srv, bt_mesh_model_msg_init(&rsp, BT_MESH_DFD_OP_FW_STATUS); net_buf_simple_add_u8(&rsp, status); - net_buf_simple_add_le16(&rsp, bt_mesh_dfu_slot_foreach(NULL, NULL)); + net_buf_simple_add_le16(&rsp, bt_mesh_dfu_slot_count()); net_buf_simple_add_le16(&rsp, idx); if (fwid) { @@ -522,7 +649,7 @@ static int handle_fw_get(struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { struct bt_mesh_dfd_srv *srv = mod->user_data; - const struct bt_mesh_dfu_slot *slot; + struct bt_mesh_dfu_slot *slot; const uint8_t *fwid; size_t fwid_len; int idx; @@ -531,7 +658,7 @@ static int handle_fw_get(struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, fwid = net_buf_simple_pull_mem(buf, fwid_len); idx = bt_mesh_dfu_slot_get(fwid, fwid_len, &slot); - if (idx >= 0 && bt_mesh_dfu_slot_is_valid(slot)) { + if (idx >= 0) { fw_status_rsp(srv, ctx, BT_MESH_DFD_SUCCESS, idx, fwid, fwid_len); } else { @@ -552,7 +679,7 @@ static int handle_fw_get_by_index(struct bt_mesh_model *mod, struct bt_mesh_msg_ idx = net_buf_simple_pull_le16(buf); slot = bt_mesh_dfu_slot_at(idx); - if (slot && bt_mesh_dfu_slot_is_valid(slot)) { + if (slot) { fw_status_rsp(srv, ctx, BT_MESH_DFD_SUCCESS, idx, slot->fwid, slot->fwid_len); } else { @@ -729,8 +856,7 @@ static void upload_end(struct bt_mesh_blob_srv *b, uint64_t id, bool success) LOG_DBG("%u", success); - if (success) { - bt_mesh_dfu_slot_valid_set(srv->upload.slot, true); + if (success && (bt_mesh_dfu_slot_commit(srv->upload.slot) == 0)) { srv->upload.phase = BT_MESH_DFD_UPLOAD_PHASE_TRANSFER_SUCCESS; return; } @@ -850,7 +976,7 @@ enum bt_mesh_dfd_status bt_mesh_dfd_srv_start(struct bt_mesh_dfd_srv *srv, xfer.mode = params->xfer_mode; xfer.slot = bt_mesh_dfu_slot_at(params->slot_idx); - if (!xfer.slot || !bt_mesh_dfu_slot_is_valid(xfer.slot)) { + if (!xfer.slot) { return BT_MESH_DFD_ERR_FW_NOT_FOUND; } @@ -1013,7 +1139,7 @@ enum bt_mesh_dfd_status bt_mesh_dfd_srv_apply(struct bt_mesh_dfd_srv *srv) enum bt_mesh_dfd_status bt_mesh_dfd_srv_fw_delete(struct bt_mesh_dfd_srv *srv, size_t *fwid_len, const uint8_t **fwid) { - const struct bt_mesh_dfu_slot *slot; + struct bt_mesh_dfu_slot *slot; int idx, err; if (srv->phase != BT_MESH_DFD_PHASE_IDLE) { @@ -1023,7 +1149,7 @@ enum bt_mesh_dfd_status bt_mesh_dfd_srv_fw_delete(struct bt_mesh_dfd_srv *srv, s } idx = bt_mesh_dfu_slot_get(*fwid, *fwid_len, &slot); - if (idx < 0 || !bt_mesh_dfu_slot_is_valid(slot)) { + if (idx < 0) { return BT_MESH_DFD_SUCCESS; } @@ -1049,3 +1175,69 @@ enum bt_mesh_dfd_status bt_mesh_dfd_srv_fw_delete_all(struct bt_mesh_dfd_srv *sr return BT_MESH_DFD_SUCCESS; } + +#ifdef CONFIG_BT_MESH_DFD_SRV_OOB_UPLOAD +int bt_mesh_dfd_srv_oob_check_complete(struct bt_mesh_dfd_srv *srv, + const struct bt_mesh_dfu_slot *slot, int status, + uint8_t *fwid, size_t fwid_len) +{ + int err; + + if (slot != srv->upload.slot || !srv->upload.is_oob || + srv->upload.phase == BT_MESH_DFD_UPLOAD_PHASE_TRANSFER_ACTIVE) { + /* This should not happen, unless the application calls the function with a + * "wrong" pointer or at a wrong time. + */ + return -EINVAL; + } + + if (status != BT_MESH_DFD_SUCCESS) { + bt_mesh_dfu_slot_release(srv->upload.slot); + upload_status_rsp(srv, &srv->upload.oob.ctx, status); + return -ECANCELED; + } + + err = set_upload_fwid(srv, &srv->upload.oob.ctx, fwid, fwid_len); + + if (err) { + return err; + } + + upload_status_rsp(srv, &srv->upload.oob.ctx, BT_MESH_DFD_SUCCESS); + return 0; +} + +int bt_mesh_dfd_srv_oob_store_complete(struct bt_mesh_dfd_srv *srv, + const struct bt_mesh_dfu_slot *slot, bool success, + size_t size, const uint8_t *metadata, size_t metadata_len) +{ + int err = 0; + + if (srv->upload.phase != BT_MESH_DFD_UPLOAD_PHASE_TRANSFER_ACTIVE || + srv->upload.slot != slot || !srv->upload.is_oob) { + return -EINVAL; + } + + if (!success) { + goto error; + } + + err = bt_mesh_dfu_slot_info_set(srv->upload.slot, size, metadata, metadata_len); + if (err) { + goto error; + } + + err = bt_mesh_dfu_slot_commit(srv->upload.slot); + if (err) { + goto error; + } + + srv->upload.phase = BT_MESH_DFD_UPLOAD_PHASE_TRANSFER_SUCCESS; + return 0; + +error: + srv->upload.phase = BT_MESH_DFD_UPLOAD_PHASE_TRANSFER_ERROR; + bt_mesh_dfu_slot_release(srv->upload.slot); + return err; +} +#endif /* CONFIG_BT_MESH_DFD_SRV_OOB_UPLOAD */ diff --git a/subsys/bluetooth/mesh/dfu_slot.c b/subsys/bluetooth/mesh/dfu_slot.c index 16628793457..097d5abcc82 100644 --- a/subsys/bluetooth/mesh/dfu_slot.c +++ b/subsys/bluetooth/mesh/dfu_slot.c @@ -20,23 +20,22 @@ LOG_MODULE_REGISTER(bt_mesh_dfu_slot); #define DFU_SLOT_SETTINGS_PATH "bt/mesh-dfu/slot" -#define HEADER_SIZE offsetof(struct bt_mesh_dfu_slot, fwid) +#define HEADER_SIZE offsetof(struct slot, slot.fwid) #define PROP_HEADER "h" #define PROP_FWID "id" #define PROP_METADATA "m" -#define PROP_URI "u" -#define VALID_SLOTS_TAG "v" -#define SLOT_IN_ARRAY(_slot) PART_OF_ARRAY(slots, CONTAINER_OF(_slot, struct slot, slot)) - -static ATOMIC_DEFINE(valid_slots, CONFIG_BT_MESH_DFU_SLOT_CNT); static sys_slist_t list; + static struct slot { - sys_snode_t n; + uint32_t idx; struct bt_mesh_dfu_slot slot; + sys_snode_t n; } slots[CONFIG_BT_MESH_DFU_SLOT_CNT]; +static uint32_t slot_index; + static char *slot_entry_encode(uint16_t idx, char buf[SLOT_ENTRY_BUFLEN], const char *property) { @@ -46,32 +45,29 @@ static char *slot_entry_encode(uint16_t idx, char buf[SLOT_ENTRY_BUFLEN], return buf; } -static inline bool slot_in_use(const struct bt_mesh_dfu_slot *slot) +static bool slot_eq(const struct bt_mesh_dfu_slot *slot, + const uint8_t *fwid, size_t fwid_len) { - return slot->size > 0U; + return (slot->fwid_len == fwid_len) && + !memcmp(fwid, slot->fwid, fwid_len); } -static inline uint16_t slot_idx(const struct bt_mesh_dfu_slot *slot) +static bool is_slot_committed(struct slot *slot_to_check) { - return CONTAINER_OF(slot, struct slot, slot) - &slots[0]; -} + struct slot *s; -static inline void slot_invalidate(struct slot *slot_to_invalidate) -{ - slot_to_invalidate->slot.size = 0U; - atomic_clear_bit(valid_slots, slot_to_invalidate - &slots[0]); -} + SYS_SLIST_FOR_EACH_CONTAINER(&list, s, n) { + if (s == slot_to_check) { + return true; + } + } -static bool slot_eq(const struct bt_mesh_dfu_slot *slot, - const uint8_t *fwid, size_t fwid_len) -{ - return (slot->fwid_len == fwid_len) && - !memcmp(fwid, slot->fwid, fwid_len); + return false; } static int slot_store(const struct slot *slot_to_store) { - uint16_t idx = slot_to_store - &slots[0]; + uint16_t idx = ARRAY_INDEX(slots, slot_to_store); char buf[SLOT_ENTRY_BUFLEN]; int err; @@ -90,55 +86,51 @@ static int slot_store(const struct slot *slot_to_store) err = settings_save_one(slot_entry_encode(idx, buf, PROP_METADATA), slot_to_store->slot.metadata, slot_to_store->slot.metadata_len); - if (err) { - return err; - } - return settings_save_one(slot_entry_encode(idx, buf, PROP_URI), - slot_to_store->slot.uri, slot_to_store->slot.uri_len); + return err; } static void slot_erase(struct slot *slot_to_erase) { - uint16_t idx = slot_to_erase - &slots[0]; + uint16_t idx = ARRAY_INDEX(slots, slot_to_erase); char buf[SLOT_ENTRY_BUFLEN]; settings_delete(slot_entry_encode(idx, buf, PROP_HEADER)); settings_delete(slot_entry_encode(idx, buf, PROP_FWID)); settings_delete(slot_entry_encode(idx, buf, PROP_METADATA)); - settings_delete(slot_entry_encode(idx, buf, PROP_URI)); } -static int valid_slots_store(void) +static void slot_index_defrag(void) { - return settings_save_one(DFU_SLOT_SETTINGS_PATH "/" VALID_SLOTS_TAG, - valid_slots, sizeof(valid_slots)); + slot_index = 0; + struct slot *s; + + SYS_SLIST_FOR_EACH_CONTAINER(&list, s, n) { + s->idx = ++slot_index; + slot_store(s); + } } -const struct bt_mesh_dfu_slot * -bt_mesh_dfu_slot_add(size_t size, const uint8_t *fwid, - size_t fwid_len, const uint8_t *metadata, - size_t metadata_len, const char *uri, size_t uri_len) +int bt_mesh_dfu_slot_count(void) { - struct slot *slot = NULL; - int err, i; + int cnt = 0; + sys_snode_t *n; - if (size == 0 || fwid_len > CONFIG_BT_MESH_DFU_FWID_MAXLEN || - metadata_len > CONFIG_BT_MESH_DFU_METADATA_MAXLEN || - uri_len > CONFIG_BT_MESH_DFU_URI_MAXLEN) { - LOG_WRN("Param too large: (size: %d, fwid: %d, metadata: %d, uri: %d)", - size, fwid_len, metadata_len, uri_len); - return NULL; + SYS_SLIST_FOR_EACH_NODE(&list, n) { + cnt++; } - for (i = 0; i < ARRAY_SIZE(slots); ++i) { - if (!slot_in_use(&slots[i].slot)) { - slot = &slots[i]; - continue; - } + return cnt; +} - if (slot_eq(&slots[i].slot, fwid, fwid_len)) { - return &slots[i].slot; +struct bt_mesh_dfu_slot *bt_mesh_dfu_slot_reserve(void) +{ + struct slot *slot = NULL; + + for (int i = 0; i < ARRAY_SIZE(slots); ++i) { + if (slots[i].idx == 0) { + slot = &slots[i]; + break; } } @@ -147,110 +139,136 @@ bt_mesh_dfu_slot_add(size_t size, const uint8_t *fwid, return NULL; } - slot->slot.fwid_len = fwid_len; - slot->slot.metadata_len = metadata_len; - slot->slot.uri_len = uri_len; - memcpy(slot->slot.fwid, fwid, fwid_len); - memcpy(slot->slot.metadata, metadata, metadata_len); - memcpy(slot->slot.uri, uri, uri_len); - slot->slot.size = size; - - err = slot_store(slot); - if (err) { - slot_invalidate(slot); - LOG_WRN("Store failed (err: %d)", err); - return NULL; + if (slot_index == UINT32_MAX) { + slot_index_defrag(); } - sys_slist_append(&list, &slot->n); + slot->slot.fwid_len = 0; + slot->slot.metadata_len = 0; + slot->slot.size = 0; + slot->idx = ++slot_index; + + LOG_DBG("Reserved slot #%u", slot - &slots[0]); - LOG_DBG("Added slot #%u: %s", slot - &slots[0], - bt_hex(slot->slot.fwid, slot->slot.fwid_len)); return &slot->slot; } -int bt_mesh_dfu_slot_valid_set(const struct bt_mesh_dfu_slot *slot, bool valid) +int bt_mesh_dfu_slot_info_set(struct bt_mesh_dfu_slot *dfu_slot, size_t size, + const uint8_t *metadata, size_t metadata_len) { - uint16_t idx; - bool prev; - int err; + struct slot *slot = CONTAINER_OF(dfu_slot, struct slot, slot); + + if (metadata_len > CONFIG_BT_MESH_DFU_METADATA_MAXLEN) { + return -EFBIG; + } - if (!SLOT_IN_ARRAY(slot) || !slot_in_use(slot)) { - return -ENOENT; + if (slot->idx == 0 || is_slot_committed(slot)) { + return -EINVAL; } - idx = slot_idx(slot); + slot->slot.size = size; + slot->slot.metadata_len = metadata_len; + memcpy(slot->slot.metadata, metadata, metadata_len); + return 0; +} + +int bt_mesh_dfu_slot_fwid_set(struct bt_mesh_dfu_slot *dfu_slot, + const uint8_t *fwid, size_t fwid_len) +{ + struct slot *slot = CONTAINER_OF(dfu_slot, struct slot, slot); - LOG_DBG("%u: %u", idx, valid); + if (fwid_len > CONFIG_BT_MESH_DFU_FWID_MAXLEN) { + return -EFBIG; + } - if (valid) { - prev = atomic_test_and_set_bit(valid_slots, idx); - } else { - prev = atomic_test_and_clear_bit(valid_slots, idx); + if (slot->idx == 0 || is_slot_committed(slot)) { + return -EINVAL; } - if (valid == prev) { - return 0; + for (int i = 0; i < ARRAY_SIZE(slots); i++) { + if (slots[i].idx != 0 && + slot_eq(&slots[i].slot, fwid, fwid_len)) { + return is_slot_committed(&slots[i]) ? + -EEXIST : -EALREADY; + } + } + + slot->slot.fwid_len = fwid_len; + memcpy(slot->slot.fwid, fwid, fwid_len); + return 0; +} + +int bt_mesh_dfu_slot_commit(struct bt_mesh_dfu_slot *dfu_slot) +{ + int err; + struct slot *slot = CONTAINER_OF(dfu_slot, struct slot, slot); + + if (slot->idx == 0 || + slot->slot.fwid_len == 0 || + slot->slot.size == 0 || + is_slot_committed(slot)) { + return -EINVAL; } - err = valid_slots_store(); + err = slot_store(slot); if (err) { - LOG_WRN("Storage failed. err: %d", err); - atomic_set_bit_to(valid_slots, idx, prev); + LOG_WRN("Store failed (err: %d)", err); + return err; } - return err; + sys_slist_append(&list, &slot->n); + + LOG_DBG("Stored slot #%u: %s", ARRAY_INDEX(slots, slot), + bt_hex(slot->slot.fwid, slot->slot.fwid_len)); + return 0; } -bool bt_mesh_dfu_slot_is_valid(const struct bt_mesh_dfu_slot *slot) +void bt_mesh_dfu_slot_release(const struct bt_mesh_dfu_slot *dfu_slot) { - uint16_t idx; + struct slot *slot = CONTAINER_OF(dfu_slot, struct slot, slot); - if (!SLOT_IN_ARRAY(slot) || !slot_in_use(slot)) { - return false; + if (is_slot_committed(slot)) { + return; } - idx = slot_idx(slot); - return atomic_test_bit(valid_slots, idx); + slot->idx = 0; } -int bt_mesh_dfu_slot_del(const struct bt_mesh_dfu_slot *slot) +int bt_mesh_dfu_slot_del(const struct bt_mesh_dfu_slot *dfu_slot) { - struct slot *s = CONTAINER_OF(slot, struct slot, slot); + struct slot *slot = CONTAINER_OF(dfu_slot, struct slot, slot); - if (!SLOT_IN_ARRAY(slot) || !slot_in_use(slot)) { - return -ENOENT; + if (!sys_slist_find_and_remove(&list, &slot->n)) { + return -EINVAL; } - LOG_DBG("%u", s - &slots[0]); + int idx = ARRAY_INDEX(slots, slot); - slot_erase(s); - slot_invalidate(s); - sys_slist_find_and_remove(&list, &s->n); + LOG_DBG("%u", idx); + + slot_erase(slot); + slot->idx = 0; return 0; } -int bt_mesh_dfu_slot_del_all(void) +void bt_mesh_dfu_slot_del_all(void) { struct slot *s; - SYS_SLIST_FOR_EACH_CONTAINER(&list, s, n) { slot_erase(s); - slot_invalidate(s); + s->idx = 0; } sys_slist_init(&list); - - return 0; } -const struct bt_mesh_dfu_slot *bt_mesh_dfu_slot_at(uint16_t idx) +const struct bt_mesh_dfu_slot *bt_mesh_dfu_slot_at(uint16_t img_idx) { struct slot *s; SYS_SLIST_FOR_EACH_CONTAINER(&list, s, n) { - if (!idx--) { + if (!img_idx--) { return &s->slot; } } @@ -258,34 +276,33 @@ const struct bt_mesh_dfu_slot *bt_mesh_dfu_slot_at(uint16_t idx) return NULL; } -int bt_mesh_dfu_slot_get(const uint8_t *fwid, size_t fwid_len, - const struct bt_mesh_dfu_slot **slot) +int bt_mesh_dfu_slot_get(const uint8_t *fwid, size_t fwid_len, struct bt_mesh_dfu_slot **slot) { struct slot *s; int idx = 0; SYS_SLIST_FOR_EACH_CONTAINER(&list, s, n) { if (slot_eq(&s->slot, fwid, fwid_len)) { - *slot = &s->slot; + if (slot) { + *slot = &s->slot; + } return idx; } - idx++; } return -ENOENT; } -int bt_mesh_dfu_slot_idx_get(const struct bt_mesh_dfu_slot *slot) +int bt_mesh_dfu_slot_img_idx_get(const struct bt_mesh_dfu_slot *dfu_slot) { struct slot *s; int idx = 0; SYS_SLIST_FOR_EACH_CONTAINER(&list, s, n) { - if (&s->slot == slot) { + if (&s->slot == dfu_slot) { return idx; } - idx++; } @@ -295,11 +312,12 @@ int bt_mesh_dfu_slot_idx_get(const struct bt_mesh_dfu_slot *slot) size_t bt_mesh_dfu_slot_foreach(bt_mesh_dfu_slot_cb_t cb, void *user_data) { enum bt_mesh_dfu_iter iter; - struct slot *s; size_t cnt = 0; + struct slot *s; SYS_SLIST_FOR_EACH_CONTAINER(&list, s, n) { cnt++; + if (!cb) { continue; } @@ -320,15 +338,6 @@ static int slot_data_load(const char *key, size_t len_rd, size_t len; uint16_t idx; - if (!strncmp(key, VALID_SLOTS_TAG, 1)) { - if (read_cb(cb_arg, valid_slots, - MIN(sizeof(valid_slots), len_rd)) < 0) { - return -EINVAL; - } - - return 0; - } - idx = strtol(key, NULL, 16); if (idx >= ARRAY_SIZE(slots)) { @@ -339,16 +348,34 @@ static int slot_data_load(const char *key, size_t len_rd, if (!strncmp(prop, PROP_HEADER, len)) { if (read_cb(cb_arg, &slots[idx], HEADER_SIZE) > 0) { - sys_slist_append(&list, &slots[idx].n); - } + struct slot *s, *prev = NULL; + + SYS_SLIST_FOR_EACH_CONTAINER(&list, s, n) { + if (s->idx > slots[idx].idx) { + break; + } + + prev = s; + } + if (prev == NULL) { + sys_slist_prepend(&list, &slots[idx].n); + } else { + sys_slist_insert(&list, &prev->n, &slots[idx].n); + } + + if (slots[idx].idx >= slot_index) { + slot_index = slots[idx].idx + 1; + } + } return 0; } if (!strncmp(prop, PROP_FWID, len)) { if (read_cb(cb_arg, &slots[idx].slot.fwid, sizeof(slots[idx].slot.fwid)) < 0) { - slot_invalidate(&slots[idx]); + slots[idx].idx = 0; + sys_slist_find_and_remove(&list, &slots[idx].n); return 0; } @@ -359,7 +386,8 @@ static int slot_data_load(const char *key, size_t len_rd, if (!strncmp(prop, PROP_METADATA, len)) { if (read_cb(cb_arg, &slots[idx].slot.metadata, sizeof(slots[idx].slot.metadata)) < 0) { - slot_invalidate(&slots[idx]); + slots[idx].idx = 0; + sys_slist_find_and_remove(&list, &slots[idx].n); return 0; } @@ -367,16 +395,6 @@ static int slot_data_load(const char *key, size_t len_rd, return 0; } - if (!strncmp(prop, PROP_URI, len)) { - if (read_cb(cb_arg, &slots[idx].slot.uri, - sizeof(slots[idx].slot.uri)) < 0) { - slot_invalidate(&slots[idx]); - return 0; - } - - slots[idx].slot.uri_len = len_rd; - } - return 0; } diff --git a/subsys/bluetooth/mesh/dfu_slot.h b/subsys/bluetooth/mesh/dfu_slot.h index 1bc58f64de9..969c6d3d25b 100644 --- a/subsys/bluetooth/mesh/dfu_slot.h +++ b/subsys/bluetooth/mesh/dfu_slot.h @@ -16,50 +16,69 @@ typedef enum bt_mesh_dfu_iter (*bt_mesh_dfu_slot_cb_t)( const struct bt_mesh_dfu_slot *slot, void *user_data); -/** @brief Register a new DFU image slot for a distributable image. +/** @brief Get the number of slots committed to the firmware list. + * + * @return Number of committed slots. + */ +int bt_mesh_dfu_slot_count(void); + +/** @brief Reserve a new DFU image slot for a distributable image. * * A DFU image slot represents a single distributable DFU image with all its - * metadata. + * metadata. The slot data must be set using @ref bt_mesh_dfu_slot_info_set and + * @ref bt_mesh_dfu_slot_fwid_set, and the slot committed using + * @ref bt_mesh_dfu_slot_commit for the slot to be considered part of the slot + * list. * - * @note The slot is allocated as invalid. Call - * @ref bt_mesh_dfu_slot_valid_set to make it valid. + * @return A pointer to the reserved slot, or NULL if allocation failed. + */ +struct bt_mesh_dfu_slot *bt_mesh_dfu_slot_reserve(void); + +/** @brief Set the size and metadata for a reserved slot. * - * @param size Size of the image in bytes. - * @param fwid Firmware ID. - * @param fwid_len Length of the firmware ID, at most @c - * CONFIG_BT_MESH_DFU_FWID_MAXLEN. + * @param dfu_slot Pointer to the reserved slot for which to set the + * metadata. + * @param size The size of the image. * @param metadata Metadata or NULL. * @param metadata_len Length of the metadata, at most @c * CONFIG_BT_MESH_DFU_METADATA_MAXLEN. - * @param uri Image URI or NULL. - * @param uri_len Length of the image URI, at most @c - * CONFIG_BT_MESH_DFU_URI_MAXLEN. * - * @return A pointer to the allocated slot, or NULL if allocation failed. + * @return 0 on success, (negative) error code otherwise. */ -const struct bt_mesh_dfu_slot * -bt_mesh_dfu_slot_add(size_t size, const uint8_t *fwid, size_t fwid_len, - const uint8_t *metadata, size_t metadata_len, - const char *uri, size_t uri_len); +int bt_mesh_dfu_slot_info_set(struct bt_mesh_dfu_slot *dfu_slot, size_t size, + const uint8_t *metadata, size_t metadata_len); -/** @brief Set whether the given slot is valid. +/** @brief Set the new fwid for the incoming image for a reserved slot. * - * @param slot Allocated DFU image slot. - * @param valid New valid state of the slot. + * @param dfu_slot Pointer to the reserved slot for which to set the fwid. + * @param fwid Fwid to set. + * @param fwid_len Length of the fwid, at most @c + * CONFIG_BT_MESH_DFU_FWID_MAXLEN. * - * @return 0 on success, or (negative) error code on failure. + * @return 0 on success, (negative) error code otherwise. */ -int bt_mesh_dfu_slot_valid_set(const struct bt_mesh_dfu_slot *slot, bool valid); +int bt_mesh_dfu_slot_fwid_set(struct bt_mesh_dfu_slot *dfu_slot, + const uint8_t *fwid, size_t fwid_len); -/** @brief Check whether a slot is valid. +/** @brief Commit the reserved slot to the list of slots, and store it + * persistently. + * + * If the commit fails for any reason, the slot will still be in the reserved + * state after this call. + * + * @param dfu_slot Pointer to the reserved slot. * - * @param slot Slot to check. + * @return 0 on success, (negative) error code otherwise. + */ +int bt_mesh_dfu_slot_commit(struct bt_mesh_dfu_slot *dfu_slot); + +/** @brief Release a reserved slot so that it can be reserved again. * - * @return true if the slot is valid, false otherwise. + * @param dfu_slot Pointer to the reserved slot. */ -bool bt_mesh_dfu_slot_is_valid(const struct bt_mesh_dfu_slot *slot); +void bt_mesh_dfu_slot_release(const struct bt_mesh_dfu_slot *dfu_slot); -/** @brief Delete an allocated DFU image slot. +/** @brief Delete a committed DFU image slot. * * @param slot Slot to delete. Must be a valid pointer acquired from this * module. @@ -72,18 +91,19 @@ int bt_mesh_dfu_slot_del(const struct bt_mesh_dfu_slot *slot); * * @return 0 on success, or (negative) error code on failure. */ -int bt_mesh_dfu_slot_del_all(void); +void bt_mesh_dfu_slot_del_all(void); -/** @brief Get the DFU image slot at the given index. +/** @brief Get the DFU image slot at the given firmware image list index. * * @param idx DFU image slot index. * * @return The DFU image slot at the given index, or NULL if no slot exists with the * given index. */ -const struct bt_mesh_dfu_slot *bt_mesh_dfu_slot_at(uint16_t idx); +const struct bt_mesh_dfu_slot *bt_mesh_dfu_slot_at(uint16_t img_idx); -/** @brief Get the DFU image slot for the image with the given firmware ID. +/** @brief Get the committed DFU image slot for the image with the given + * firmware ID. * * @param fwid Firmware ID. * @param fwid_len Firmware ID length. @@ -91,16 +111,15 @@ const struct bt_mesh_dfu_slot *bt_mesh_dfu_slot_at(uint16_t idx); * * @return Slot index on success, or negative error code on failure. */ -int bt_mesh_dfu_slot_get(const uint8_t *fwid, size_t fwid_len, - const struct bt_mesh_dfu_slot **slot); +int bt_mesh_dfu_slot_get(const uint8_t *fwid, size_t fwid_len, struct bt_mesh_dfu_slot **slot); -/** @brief Get the DFU image slot index of the given slot. +/** @brief Get the index in the firmware image list for the given slot. * * @param slot Slot to find. * * @return Slot index on success, or negative error code on failure. */ -int bt_mesh_dfu_slot_idx_get(const struct bt_mesh_dfu_slot *slot); +int bt_mesh_dfu_slot_img_idx_get(const struct bt_mesh_dfu_slot *slot); /** @brief Iterate through all DFU image slots. * diff --git a/subsys/bluetooth/mesh/shell/dfd.c b/subsys/bluetooth/mesh/shell/dfd.c index 94d656f3689..b7daf42af1c 100644 --- a/subsys/bluetooth/mesh/shell/dfd.c +++ b/subsys/bluetooth/mesh/shell/dfd.c @@ -43,7 +43,7 @@ static void print_fw_status(const struct shell *sh, enum bt_mesh_dfd_status stat uint16_t idx, const uint8_t *fwid, size_t fwid_len) { shell_fprintf(sh, SHELL_NORMAL, "{ \"status\": %d, \"slot_cnt\": %d, \"idx\": %d", - status, bt_mesh_dfu_slot_foreach(NULL, NULL), idx); + status, bt_mesh_dfu_slot_count(), idx); if (fwid) { shell_fprintf(sh, SHELL_NORMAL, ", \"fwid\": \""); for (size_t i = 0; i < fwid_len; i++) { @@ -325,10 +325,9 @@ static int cmd_dfd_fw_get(const struct shell *sh, size_t argc, char *argv[]) return -EINVAL; } - const struct bt_mesh_dfu_slot *slot; - int idx = bt_mesh_dfu_slot_get(fwid, fwid_len, &slot); + int idx = bt_mesh_dfu_slot_get(fwid, fwid_len, NULL); - if (idx >= 0 && bt_mesh_dfu_slot_is_valid(slot)) { + if (idx >= 0) { print_fw_status(sh, BT_MESH_DFD_SUCCESS, idx, fwid, fwid_len); } else { print_fw_status(sh, BT_MESH_DFD_ERR_FW_NOT_FOUND, 0xffff, fwid, fwid_len); @@ -349,7 +348,7 @@ static int cmd_dfd_fw_get_by_idx(const struct shell *sh, size_t argc, char *argv return err; } - if (slot && bt_mesh_dfu_slot_is_valid(slot)) { + if (slot) { print_fw_status(sh, BT_MESH_DFD_SUCCESS, idx, slot->fwid, slot->fwid_len); } else { print_fw_status(sh, BT_MESH_DFD_ERR_FW_NOT_FOUND, idx, NULL, 0); diff --git a/subsys/bluetooth/mesh/shell/dfu.c b/subsys/bluetooth/mesh/shell/dfu.c index 71d27b158e4..8d7fc96e014 100644 --- a/subsys/bluetooth/mesh/shell/dfu.c +++ b/subsys/bluetooth/mesh/shell/dfu.c @@ -375,13 +375,12 @@ static int cmd_dfu_metadata_encode(const struct shell *sh, size_t argc, char *ar static int cmd_dfu_slot_add(const struct shell *sh, size_t argc, char *argv[]) { - const struct bt_mesh_dfu_slot *slot; + struct bt_mesh_dfu_slot *slot; size_t size; uint8_t fwid[CONFIG_BT_MESH_DFU_FWID_MAXLEN]; size_t fwid_len = 0; uint8_t metadata[CONFIG_BT_MESH_DFU_METADATA_MAXLEN]; size_t metadata_len = 0; - const char *uri = ""; int err = 0; size = shell_strtoul(argv[1], 0, &err); @@ -390,32 +389,33 @@ static int cmd_dfu_slot_add(const struct shell *sh, size_t argc, char *argv[]) return err; } - if (argc > 2) { - fwid_len = hex2bin(argv[2], strlen(argv[2]), fwid, - sizeof(fwid)); + shell_print(sh, "Adding slot (size: %u)", size); + slot = bt_mesh_dfu_slot_reserve(); + + if (!slot) { + shell_print(sh, "Failed to reserve slot."); + return 0; } + fwid_len = hex2bin(argv[2], strlen(argv[2]), fwid, + sizeof(fwid)); + bt_mesh_dfu_slot_fwid_set(slot, fwid, fwid_len); + if (argc > 3) { metadata_len = hex2bin(argv[3], strlen(argv[3]), metadata, sizeof(metadata)); } - if (argc > 4) { - uri = argv[4]; - } + bt_mesh_dfu_slot_info_set(slot, size, metadata, metadata_len); - shell_print(sh, "Adding slot (size: %u)", size); - - slot = bt_mesh_dfu_slot_add(size, fwid, fwid_len, metadata, - metadata_len, uri, strlen(uri)); - if (!slot) { - shell_print(sh, "Failed."); - return 0; + err = bt_mesh_dfu_slot_commit(slot); + if (err) { + shell_print(sh, "Failed to commit slot: %d", err); + bt_mesh_dfu_slot_release(slot); + return err; } - bt_mesh_dfu_slot_valid_set(slot, true); - - shell_print(sh, "Slot added. ID: %u", bt_mesh_dfu_slot_idx_get(slot)); + shell_print(sh, "Slot added. Index: %u", bt_mesh_dfu_slot_img_idx_get(slot)); return 0; } @@ -451,14 +451,7 @@ static int cmd_dfu_slot_del(const struct shell *sh, size_t argc, char *argv[]) static int cmd_dfu_slot_del_all(const struct shell *sh, size_t argc, char *argv[]) { - int err; - - err = bt_mesh_dfu_slot_del_all(); - if (err) { - shell_print(sh, "Failed deleting all slots (err: %d)", err); - return 0; - } - + bt_mesh_dfu_slot_del_all(); shell_print(sh, "All slots deleted."); return 0; } @@ -468,7 +461,6 @@ static void slot_info_print(const struct shell *sh, const struct bt_mesh_dfu_slo { char fwid[2 * CONFIG_BT_MESH_DFU_FWID_MAXLEN + 1]; char metadata[2 * CONFIG_BT_MESH_DFU_METADATA_MAXLEN + 1]; - char uri[CONFIG_BT_MESH_DFU_URI_MAXLEN + 1]; size_t len; len = bin2hex(slot->fwid, slot->fwid_len, fwid, sizeof(fwid)); @@ -476,8 +468,6 @@ static void slot_info_print(const struct shell *sh, const struct bt_mesh_dfu_slo len = bin2hex(slot->metadata, slot->metadata_len, metadata, sizeof(metadata)); metadata[len] = '\0'; - memcpy(uri, slot->uri, slot->uri_len); - uri[slot->uri_len] = '\0'; if (idx != NULL) { shell_print(sh, "Slot %u:", *idx); @@ -487,7 +477,6 @@ static void slot_info_print(const struct shell *sh, const struct bt_mesh_dfu_slo shell_print(sh, "\tSize: %u bytes", slot->size); shell_print(sh, "\tFWID: %s", fwid); shell_print(sh, "\tMetadata: %s", metadata); - shell_print(sh, "\tURI: %s", uri); } static int cmd_dfu_slot_get(const struct shell *sh, size_t argc, char *argv[]) @@ -970,8 +959,8 @@ SHELL_STATIC_SUBCMD_SET_CREATE( SHELL_STATIC_SUBCMD_SET_CREATE( dfu_slot_cmds, SHELL_CMD_ARG(add, NULL, - " [ [ []]]", - cmd_dfu_slot_add, 2, 3), + " []", + cmd_dfu_slot_add, 3, 1), SHELL_CMD_ARG(del, NULL, "", cmd_dfu_slot_del, 2, 0), SHELL_CMD_ARG(del-all, NULL, NULL, cmd_dfu_slot_del_all, 1, 0), SHELL_CMD_ARG(get, NULL, "", cmd_dfu_slot_get, 2, 0), diff --git a/tests/bsim/bluetooth/mesh/prj_mesh1d1.conf b/tests/bsim/bluetooth/mesh/prj_mesh1d1.conf index e870e190481..2e08329b7ef 100644 --- a/tests/bsim/bluetooth/mesh/prj_mesh1d1.conf +++ b/tests/bsim/bluetooth/mesh/prj_mesh1d1.conf @@ -58,7 +58,8 @@ CONFIG_BT_MESH_LARGE_COMP_DATA_SRV=y CONFIG_BT_MESH_DFU_SRV=y CONFIG_BT_MESH_DFU_CLI=y CONFIG_BT_MESH_DFD_SRV=y -CONFIG_BT_MESH_DFU_SLOT_CNT=3 +CONFIG_BT_MESH_DFD_SRV_OOB_UPLOAD=y +CONFIG_BT_MESH_DFU_SLOT_CNT=4 CONFIG_BT_MESH_PRIV_BEACON_SRV=y CONFIG_BT_MESH_PRIV_BEACON_CLI=y CONFIG_BT_MESH_COMP_PAGE_1=y diff --git a/tests/bsim/bluetooth/mesh/src/test_dfu.c b/tests/bsim/bluetooth/mesh/src/test_dfu.c index f7c4ca6f4f0..a235e86eeec 100644 --- a/tests/bsim/bluetooth/mesh/src/test_dfu.c +++ b/tests/bsim/bluetooth/mesh/src/test_dfu.c @@ -434,25 +434,50 @@ static void target_prov_and_conf_default(void) target_prov_and_conf(addr, bind_params, ARRAY_SIZE(bind_params)); } +static struct bt_mesh_dfu_slot *slot_reserve_and_set(size_t size, uint8_t *fwid, size_t fwid_len, + uint8_t *metadata, size_t metadata_len) +{ + struct bt_mesh_dfu_slot *new_slot = bt_mesh_dfu_slot_reserve(); + + if (!new_slot) { + LOG_WRN("Reserving slot failed"); + return NULL; + } + + int err = bt_mesh_dfu_slot_fwid_set(new_slot, fwid, fwid_len); + + if (err) { + return NULL; + } + + err = bt_mesh_dfu_slot_info_set(new_slot, size, metadata, metadata_len); + + if (err) { + return NULL; + } + + return new_slot; +} + static bool slot_add(const struct bt_mesh_dfu_slot **slot) { - const struct bt_mesh_dfu_slot *new_slot; + struct bt_mesh_dfu_slot *new_slot; size_t size = 100; uint8_t fwid[CONFIG_BT_MESH_DFU_FWID_MAXLEN] = { 0xAA, 0xBB, 0xCC, 0xDD }; size_t fwid_len = 4; uint8_t metadata[CONFIG_BT_MESH_DFU_METADATA_MAXLEN] = { 0xAA, 0xBB, 0xCC, 0xDD }; size_t metadata_len = 4; - const char *uri = ""; ASSERT_EQUAL(sizeof(target_fw_ver_new), fwid_len); - new_slot = bt_mesh_dfu_slot_add(size, fwid, fwid_len, metadata, metadata_len, uri, - strlen(uri)); + new_slot = slot_reserve_and_set(size, fwid, fwid_len, metadata, metadata_len); if (!new_slot) { return false; } - bt_mesh_dfu_slot_valid_set(new_slot, true); + if (bt_mesh_dfu_slot_commit(new_slot) != 0) { + return false; + } if (slot) { *slot = new_slot; @@ -568,13 +593,12 @@ static void test_dist_dfu_self_update(void) static void test_dist_dfu_slot_create(void) { - const struct bt_mesh_dfu_slot *slot[3]; + struct bt_mesh_dfu_slot *slot[CONFIG_BT_MESH_DFU_SLOT_CNT]; size_t size = 100; uint8_t fwid[CONFIG_BT_MESH_DFU_FWID_MAXLEN] = { 0 }; size_t fwid_len = 4; uint8_t metadata[CONFIG_BT_MESH_DFU_METADATA_MAXLEN] = { 0 }; size_t metadata_len = 4; - const char *uri = "test"; int err, i; ASSERT_TRUE(CONFIG_BT_MESH_DFU_SLOT_CNT >= 3, @@ -584,36 +608,26 @@ static void test_dist_dfu_slot_create(void) bt_mesh_device_setup(&prov, &dist_comp); dist_prov_and_conf(DIST_ADDR); - for (i = CONFIG_BT_MESH_DFU_SLOT_CNT - 1; i >= 0; i--) { + for (i = 0; i < CONFIG_BT_MESH_DFU_SLOT_CNT; i++) { fwid[0] = i; metadata[0] = i; - slot[i] = bt_mesh_dfu_slot_add(size, fwid, fwid_len, metadata, metadata_len, uri, - strlen(uri)); + slot[i] = slot_reserve_and_set(size, fwid, fwid_len, metadata, metadata_len); ASSERT_FALSE(slot[i] == NULL, "Failed to add slot"); - } - - /* First slot is set as valid */ - err = bt_mesh_dfu_slot_valid_set(slot[0], true); - if (err) { - FAIL("Setting slot to valid state failed (err %d)", err); - return; - } - ASSERT_TRUE(bt_mesh_dfu_slot_is_valid(slot[0])); - /* Second slot is set as invalid */ - err = bt_mesh_dfu_slot_valid_set(slot[1], false); - if (err) { - FAIL("Setting slot to invalid state failed (err %d)", err); - return; + if (i > 0) { + /* All but first slot are committed */ + err = bt_mesh_dfu_slot_commit(slot[i]); + if (err) { + FAIL("Committing slot failed (err %d)", err); + } + } } - ASSERT_TRUE(!bt_mesh_dfu_slot_is_valid(slot[1])); - /* Last slot is deleted */ - err = bt_mesh_dfu_slot_del(slot[CONFIG_BT_MESH_DFU_SLOT_CNT - 1]); + /* Second slot is deleted */ + err = bt_mesh_dfu_slot_del(slot[1]); if (err) { FAIL("Slot delete failed (err %d)", err); - return; } PASS(); @@ -626,20 +640,17 @@ enum bt_mesh_dfu_iter check_slot(const struct bt_mesh_dfu_slot *slot, void *data size_t fwid_len = 4; uint8_t metadata[CONFIG_BT_MESH_DFU_METADATA_MAXLEN] = { 0 }; size_t metadata_len = 4; - const char *uri = "test"; - int idx = bt_mesh_dfu_slot_idx_get(slot); - - ASSERT_TRUE(idx >= 0, "Failed to retrieve slot index"); + int idx = bt_mesh_dfu_slot_img_idx_get(slot); + int *i = data; + ASSERT_EQUAL(idx, (*i)++); ASSERT_EQUAL(size, slot->size); - ASSERT_TRUE(strcmp(uri, slot->uri) == 0); - - fwid[0] = idx; + fwid[0] = idx + 2; ASSERT_EQUAL(fwid_len, slot->fwid_len); ASSERT_TRUE(memcmp(fwid, slot->fwid, fwid_len) == 0); - metadata[0] = idx; + metadata[0] = idx + 2; ASSERT_EQUAL(metadata_len, slot->metadata_len); ASSERT_TRUE(memcmp(metadata, slot->metadata, metadata_len) == 0); @@ -649,13 +660,12 @@ enum bt_mesh_dfu_iter check_slot(const struct bt_mesh_dfu_slot *slot, void *data static void test_dist_dfu_slot_create_recover(void) { size_t slot_count; - const struct bt_mesh_dfu_slot *slot; + struct bt_mesh_dfu_slot *slot; size_t size = 100; uint8_t fwid[CONFIG_BT_MESH_DFU_FWID_MAXLEN] = { 0 }; size_t fwid_len = 4; uint8_t metadata[CONFIG_BT_MESH_DFU_METADATA_MAXLEN] = { 0 }; size_t metadata_len = 4; - const char *uri = "test"; int i, idx; ASSERT_TRUE(CONFIG_BT_MESH_DFU_SLOT_CNT >= 3, @@ -664,26 +674,17 @@ static void test_dist_dfu_slot_create_recover(void) bt_mesh_test_cfg_set(NULL, WAIT_TIME); bt_mesh_device_setup(&prov, &dist_comp); - slot_count = bt_mesh_dfu_slot_foreach(check_slot, NULL); - ASSERT_EQUAL(CONFIG_BT_MESH_DFU_SLOT_CNT - 1, slot_count); - - slot = bt_mesh_dfu_slot_at(0); - ASSERT_EQUAL(true, bt_mesh_dfu_slot_is_valid(slot)); + i = 0; + slot_count = bt_mesh_dfu_slot_foreach(check_slot, &i); + ASSERT_EQUAL(CONFIG_BT_MESH_DFU_SLOT_CNT - 2, slot_count); - slot = bt_mesh_dfu_slot_at(1); - ASSERT_TRUE(slot != NULL); - ASSERT_EQUAL(false, bt_mesh_dfu_slot_is_valid(slot)); - - for (i = 0; i < (CONFIG_BT_MESH_DFU_SLOT_CNT - 1); i++) { + for (i = 2; i < CONFIG_BT_MESH_DFU_SLOT_CNT; i++) { fwid[0] = i; idx = bt_mesh_dfu_slot_get(fwid, fwid_len, &slot); - ASSERT_TRUE(idx >= 0); - ASSERT_EQUAL(idx, bt_mesh_dfu_slot_idx_get(slot)); - + ASSERT_EQUAL(idx, i - 2); ASSERT_EQUAL(size, slot->size); - ASSERT_TRUE(strcmp(uri, slot->uri) == 0); - metadata[0] = idx; + metadata[0] = i; ASSERT_EQUAL(metadata_len, slot->metadata_len); ASSERT_TRUE(memcmp(metadata, slot->metadata, metadata_len) == 0); } @@ -693,7 +694,7 @@ static void test_dist_dfu_slot_create_recover(void) static void check_delete_all(void) { - int i, idx, err; + int i; const struct bt_mesh_dfu_slot *slot; size_t slot_count; @@ -706,14 +707,6 @@ static void check_delete_all(void) for (i = 0; i < CONFIG_BT_MESH_DFU_SLOT_CNT - 1; i++) { slot = bt_mesh_dfu_slot_at(i); ASSERT_TRUE(slot == NULL); - - idx = bt_mesh_dfu_slot_idx_get(slot); - ASSERT_TRUE(idx < 0); - - err = bt_mesh_dfu_slot_valid_set(slot, true); - ASSERT_EQUAL(err, -ENOENT); - - ASSERT_TRUE(!bt_mesh_dfu_slot_is_valid(slot)); } } @@ -726,7 +719,6 @@ static void test_dist_dfu_slot_delete_all(void) bt_mesh_device_setup(&prov, &dist_comp); bt_mesh_dfu_slot_del_all(); - check_delete_all(); PASS(); @@ -742,6 +734,63 @@ static void test_dist_dfu_slot_check_delete_all(void) PASS(); } +static void test_dist_dfu_slot_reservation(void) +{ + int i; + struct bt_mesh_dfu_slot *slots[CONFIG_BT_MESH_DFU_SLOT_CNT]; + + bt_mesh_test_cfg_set(NULL, WAIT_TIME); + bt_mesh_device_setup(&prov, &dist_comp); + + for (i = 0; i < CONFIG_BT_MESH_DFU_SLOT_CNT; i++) { + slots[i] = bt_mesh_dfu_slot_reserve(); + ASSERT_TRUE(slots[i] != NULL); + } + + ASSERT_EQUAL(NULL, bt_mesh_dfu_slot_reserve()); + bt_mesh_dfu_slot_release(slots[0]); + /* Release twice to check idempotency with empty pool */ + bt_mesh_dfu_slot_release(slots[0]); + ASSERT_TRUE(bt_mesh_dfu_slot_reserve() != NULL); + ASSERT_EQUAL(NULL, bt_mesh_dfu_slot_reserve()); + + PASS(); +} + +static void test_dist_dfu_slot_idempotency(void) +{ + uint8_t fwid[CONFIG_BT_MESH_DFU_FWID_MAXLEN] = { 0 }; + size_t fwid_len = 4; + struct bt_mesh_dfu_slot *slot; + + ASSERT_TRUE(CONFIG_BT_MESH_DFU_SLOT_CNT >= 1, + "CONFIG_BT_MESH_DFU_SLOT_CNT must be at least 1"); + + bt_mesh_test_cfg_set(NULL, WAIT_TIME); + bt_mesh_device_setup(&prov, &dist_comp); + dist_prov_and_conf(DIST_ADDR); + + slot = bt_mesh_dfu_slot_reserve(); + ASSERT_TRUE(slot != NULL); + + bt_mesh_dfu_slot_release(slot); + bt_mesh_dfu_slot_release(slot); + + slot = bt_mesh_dfu_slot_reserve(); + ASSERT_TRUE(slot != NULL); + + ASSERT_EQUAL(0, bt_mesh_dfu_slot_fwid_set(slot, fwid, fwid_len)); + ASSERT_EQUAL(0, bt_mesh_dfu_slot_info_set(slot, 100, NULL, 0)); + + ASSERT_EQUAL(0, bt_mesh_dfu_slot_commit(slot)); + ASSERT_EQUAL(-EINVAL, bt_mesh_dfu_slot_commit(slot)); + + ASSERT_EQUAL(0, bt_mesh_dfu_slot_del(slot)); + ASSERT_EQUAL(-EINVAL, bt_mesh_dfu_slot_del(slot)); + + PASS(); +} + static void target_test_effect(enum bt_mesh_dfu_effect effect) { dfu_target_effect = effect; @@ -921,12 +970,14 @@ static void cli_common_fail_on_init(void) static void cli_common_init_recover(void) { - const struct bt_mesh_dfu_slot *slot; + struct bt_mesh_dfu_slot *slot; + uint8_t fwid[CONFIG_BT_MESH_DFU_FWID_MAXLEN] = { 0xAA, 0xBB, 0xCC, 0xDD }; + size_t fwid_len = 4; bt_mesh_test_cfg_set(NULL, 300); bt_mesh_device_setup(&prov, &cli_comp); - ASSERT_TRUE(slot_add(&slot)); + ASSERT_TRUE(bt_mesh_dfu_slot_get(fwid, fwid_len, &slot) >= 0); dfu_cli_inputs_prepare(0); dfu_cli_xfer.xfer.mode = BT_MESH_BLOB_XFER_MODE_PUSH; @@ -1595,6 +1646,10 @@ static const struct bst_test_instance test_dfu[] = { TEST_CASE(dist, dfu_slot_delete_all, "Distributor deletes all image slots"), TEST_CASE(dist, dfu_slot_check_delete_all, "Distributor checks if all slots are removed from persistent storage"), + TEST_CASE(dist, dfu_slot_reservation, + "Distributor checks that the correct number of slots can be reserved"), + TEST_CASE(dist, dfu_slot_idempotency, + "Distributor checks that the the DFU slot APIs are idempotent"), TEST_CASE(cli, stop, "DFU Client stops at configured point of Firmware Distribution"), TEST_CASE(cli, fail_on_persistency, "DFU Client doesn't give up DFU Transfer"), TEST_CASE(cli, all_targets_lost_on_metadata, diff --git a/tests/bsim/bluetooth/mesh/tests_scripts/dfu/dfu_slot_idempotency.sh b/tests/bsim/bluetooth/mesh/tests_scripts/dfu/dfu_slot_idempotency.sh new file mode 100755 index 00000000000..3f18f1a2651 --- /dev/null +++ b/tests/bsim/bluetooth/mesh/tests_scripts/dfu/dfu_slot_idempotency.sh @@ -0,0 +1,14 @@ +#!/usr/bin/env bash +# Copyright 2023 Nordic Semiconductor +# SPDX-License-Identifier: Apache-2.0 + +source $(dirname "${BASH_SOURCE[0]}")/../../_mesh_test.sh + +# Test DFU Slot API. This test tests that the APIs are idempotent. +conf=prj_mesh1d1_conf +overlay=overlay_pst_conf +RunTest dfu_slot_idempotency dfu_dist_dfu_slot_idempotency + +conf=prj_mesh1d1_conf +overlay="overlay_pst_conf_overlay_psa_conf" +RunTest dfu_slot_idempotency_psa dfu_dist_dfu_slot_idempotency diff --git a/tests/bsim/bluetooth/mesh/tests_scripts/dfu/dfu_slot_reservation.sh b/tests/bsim/bluetooth/mesh/tests_scripts/dfu/dfu_slot_reservation.sh new file mode 100755 index 00000000000..ddd7d0123f5 --- /dev/null +++ b/tests/bsim/bluetooth/mesh/tests_scripts/dfu/dfu_slot_reservation.sh @@ -0,0 +1,14 @@ +#!/usr/bin/env bash +# Copyright 2023 Nordic Semiconductor +# SPDX-License-Identifier: Apache-2.0 + +source $(dirname "${BASH_SOURCE[0]}")/../../_mesh_test.sh + +# Test DFU Slot API. This test tests slot reservation APIs. +conf=prj_mesh1d1_conf +overlay=overlay_pst_conf +RunTest dfu_slot_reservation dfu_dist_dfu_slot_reservation + +conf=prj_mesh1d1_conf +overlay="overlay_pst_conf_overlay_psa_conf" +RunTest dfu_slot_reservation_psa dfu_dist_dfu_slot_reservation From 7e3caf9f788b375b0eacf2b3c501606d95038ab0 Mon Sep 17 00:00:00 2001 From: Pavel Vasilyev Date: Fri, 15 Sep 2023 16:02:21 +0200 Subject: [PATCH 148/421] [nrf fromtree] Bluetooth: Mesh: Fix printing device UUID MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit IS_ENABLED was incorrectly used here. Signed-off-by: Pavel Vasilyev (cherry picked from commit ac050455c51e542e6dd852ceaff82c8f58de99c9) Signed-off-by: Alperen Şener (cherry picked from commit 2e3cf5a81536ed97ceffe6b36f322e56852ebaf6) --- subsys/bluetooth/mesh/prov_device.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subsys/bluetooth/mesh/prov_device.c b/subsys/bluetooth/mesh/prov_device.c index 48d852cb1a7..20735f49fa5 100644 --- a/subsys/bluetooth/mesh/prov_device.c +++ b/subsys/bluetooth/mesh/prov_device.c @@ -675,7 +675,7 @@ int bt_mesh_prov_enable(bt_mesh_prov_bearer_t bearers) return -EALREADY; } -#if IS_ENABLED(CONFIG_BT_MESH_PROV_DEVICE_LOG_LEVEL) +#if defined(CONFIG_BT_MESH_PROV_DEVICE_LOG_LEVEL) if (CONFIG_BT_MESH_PROV_DEVICE_LOG_LEVEL > 2) { struct bt_uuid_128 uuid = { .uuid = { BT_UUID_TYPE_128 } }; From cd7dfd7466119b3764545e4af9ae825ee577397e Mon Sep 17 00:00:00 2001 From: Pavel Vasilyev Date: Fri, 15 Sep 2023 14:42:57 +0200 Subject: [PATCH 149/421] [nrf fromtree] Bluetooth: Mesh: Use decimals instead of hex nums in DFD shell cmds MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit JSON doesn't support hexdecimals as numbers. Signed-off-by: Pavel Vasilyev (cherry picked from commit 6267259f91d2561666a97dd836e4ea7e2aabbc3a) Signed-off-by: Alperen Şener (cherry picked from commit e08b07667b533ff7f311d79c037e6dff8b77a0ac) --- subsys/bluetooth/mesh/shell/dfd.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/subsys/bluetooth/mesh/shell/dfd.c b/subsys/bluetooth/mesh/shell/dfd.c index b7daf42af1c..0415929dfec 100644 --- a/subsys/bluetooth/mesh/shell/dfd.c +++ b/subsys/bluetooth/mesh/shell/dfd.c @@ -29,7 +29,7 @@ static void print_dfd_status(const struct shell *sh, struct bt_mesh_dfd_srv *srv srv->phase); if (srv->phase != BT_MESH_DFD_PHASE_IDLE && srv->dfu.xfer.slot) { - shell_fprintf(sh, SHELL_NORMAL, ", \"group\": 0x%04x, \"app_idx\": %d, " + shell_fprintf(sh, SHELL_NORMAL, ", \"group\": %d, \"app_idx\": %d, " "\"ttl\": %d, \"timeout_base\": %d, \"xfer_mode\": %d, " "\"apply\": %d, \"slot_idx\": %d", srv->inputs.group, srv->inputs.app_idx, srv->inputs.ttl, srv->inputs.timeout_base, @@ -165,7 +165,7 @@ static int cmd_dfd_receivers_get(const struct shell *sh, size_t argc, char *argv for (int i = 0; i < cnt; i++) { const struct bt_mesh_dfu_target *t = &dfd_srv->targets[i + first]; - shell_print(sh, "\t\t\"%d\": { \"blob_addr\": 0x%04x, \"phase\": %d, " + shell_print(sh, "\t\t\"%d\": { \"blob_addr\": %d, \"phase\": %d, " "\"status\": %d, \"blob_status\": %d, \"progress\": %d, " "\"img_idx\": %d }%s", i + first, t->blob.addr, t->phase, t->status, t->blob.status, progress, t->img_idx, (i == cnt - 1) ? "" : ","); From efc4e52f347da84ba172e23935f3786d9612a781 Mon Sep 17 00:00:00 2001 From: Aleksandr Khromykh Date: Tue, 26 Sep 2023 12:11:00 +0200 Subject: [PATCH 150/421] [nrf fromtree] Bluetooth: Mesh: fix static oob setting MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit According to specification it is possible to provide static oob value with any length. Mesh should trim or append\prepend by zeroes if it is longer\shorter than required value. Signed-off-by: Aleksandr Khromykh (cherry picked from commit 707d1ed81941e425c77a9fd77db43a68d92f76be) Signed-off-by: Alperen Şener (cherry picked from commit 6b2f413d0dc9509685a9bf14804f37c1c9fbcdbd) --- subsys/bluetooth/mesh/prov_device.c | 11 ++++++++--- subsys/bluetooth/mesh/provisioner.c | 15 +++++++-------- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/subsys/bluetooth/mesh/prov_device.c b/subsys/bluetooth/mesh/prov_device.c index 20735f49fa5..a83ace178db 100644 --- a/subsys/bluetooth/mesh/prov_device.c +++ b/subsys/bluetooth/mesh/prov_device.c @@ -183,9 +183,14 @@ static void prov_start(const uint8_t *data) } if (atomic_test_bit(bt_mesh_prov_link.flags, OOB_STATIC_KEY)) { - memcpy(bt_mesh_prov_link.auth + auth_size - bt_mesh_prov->static_val_len, - bt_mesh_prov->static_val, bt_mesh_prov->static_val_len); - memset(bt_mesh_prov_link.auth, 0, auth_size - bt_mesh_prov->static_val_len); + + uint8_t tail_size = bt_mesh_prov->static_val_len < auth_size + ? auth_size - bt_mesh_prov->static_val_len + : 0; + + memcpy(bt_mesh_prov_link.auth + tail_size, bt_mesh_prov->static_val, + tail_size ? bt_mesh_prov->static_val_len : auth_size); + memset(bt_mesh_prov_link.auth, 0, tail_size); } } diff --git a/subsys/bluetooth/mesh/provisioner.c b/subsys/bluetooth/mesh/provisioner.c index 25f0a299480..673e14578d2 100644 --- a/subsys/bluetooth/mesh/provisioner.c +++ b/subsys/bluetooth/mesh/provisioner.c @@ -254,8 +254,7 @@ static void prov_capabilities(const uint8_t *data) return; } - if (IS_ENABLED(CONFIG_BT_MESH_OOB_AUTH_REQUIRED) && - (caps.oob_type & BT_MESH_OOB_AUTH_REQUIRED)) { + if (caps.oob_type & BT_MESH_OOB_AUTH_REQUIRED) { bool oob_availability = caps.output_size > 0 || caps.input_size > 0 || (caps.oob_type & BT_MESH_STATIC_OOB_AVAILABLE); @@ -752,18 +751,18 @@ int bt_mesh_auth_method_set_output(bt_mesh_output_action_t action, uint8_t size) int bt_mesh_auth_method_set_static(const uint8_t *static_val, uint8_t size) { - uint8_t auth_size = bt_mesh_prov_auth_size_get(); + uint8_t tail_size = size < PROV_AUTH_MAX_LEN ? PROV_AUTH_MAX_LEN - size : 0; - if (!size || !static_val || size > auth_size) { + if (!size || !static_val) { return -EINVAL; } prov_set_method(AUTH_METHOD_STATIC, 0, 0); - memcpy(bt_mesh_prov_link.auth + auth_size - size, static_val, size); - if (size < auth_size) { - (void)memset(bt_mesh_prov_link.auth, 0, auth_size - size); - } + memcpy(bt_mesh_prov_link.auth + tail_size, static_val, + tail_size ? size : PROV_AUTH_MAX_LEN); + memset(bt_mesh_prov_link.auth, 0, tail_size); + return 0; } From 609c593b26ea626d88909f09b7b6df4d26f88363 Mon Sep 17 00:00:00 2001 From: Aleksandr Khromykh Date: Tue, 26 Sep 2023 12:15:40 +0200 Subject: [PATCH 151/421] [nrf fromtree] Bluetooth: Mesh: shell supports 32 bytes static oob MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit adds support of 32 bytes static oob in mesh shell. Signed-off-by: Aleksandr Khromykh (cherry picked from commit 236e3b64db062b7ae9e5c9abfc964ea188345db7) Signed-off-by: Alperen Şener (cherry picked from commit 82f1d7e67edc476bf6e6d75d7f4ae46481b555ce) --- doc/connectivity/bluetooth/api/mesh/shell.rst | 4 ++-- subsys/bluetooth/mesh/shell/shell.c | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/doc/connectivity/bluetooth/api/mesh/shell.rst b/doc/connectivity/bluetooth/api/mesh/shell.rst index e6609f40e5c..6f102b5490f 100644 --- a/doc/connectivity/bluetooth/api/mesh/shell.rst +++ b/doc/connectivity/bluetooth/api/mesh/shell.rst @@ -297,7 +297,7 @@ To allow a device to provision devices over GATT, the :kconfig:option:`CONFIG_BT * ``String``: Unquoted alphanumeric authentication string. -``mesh prov static-oob [Val(1-16 hex)]`` +``mesh prov static-oob [Val(1-32 hex)]`` ---------------------------------------- Set or clear the static OOB authentication value. The static OOB authentication value must be set before provisioning starts to have any effect. The static OOB value must be same on both participants in the provisioning. To enable this command, the :kconfig:option:`BT_MESH_SHELL_PROV_CTX_INSTANCE` option must be enabled. @@ -358,7 +358,7 @@ To allow a device to provision devices over GATT, the :kconfig:option:`CONFIG_BT ------------------------------------------------ From the provisioner device, instruct the unprovisioned device to use static OOB authentication, and use the given static authentication value when provisioning. - * ``Val`` - Static OOB value. Providing a hex-string shorter than 16 bytes will populate the N most significant bytes of the array and zero-pad the rest. + * ``Val`` - Static OOB value. Providing a hex-string shorter than 32 bytes will populate the N most significant bytes of the array and zero-pad the rest. ``mesh prov auth-method none`` ------------------------------ diff --git a/subsys/bluetooth/mesh/shell/shell.c b/subsys/bluetooth/mesh/shell/shell.c index 243166441fe..c5592db02cf 100644 --- a/subsys/bluetooth/mesh/shell/shell.c +++ b/subsys/bluetooth/mesh/shell/shell.c @@ -611,7 +611,7 @@ static void link_close(bt_mesh_prov_bearer_t bearer) shell_print_ctx("Provisioning link closed on %s", bearer2str(bearer)); } -static uint8_t static_val[16]; +static uint8_t static_val[32]; struct bt_mesh_prov bt_mesh_shell_prov = { .uuid = dev_uuid, @@ -645,7 +645,7 @@ static int cmd_static_oob(const struct shell *sh, size_t argc, char *argv[]) bt_mesh_shell_prov.static_val_len = 0U; } else { bt_mesh_shell_prov.static_val_len = hex2bin(argv[1], strlen(argv[1]), - static_val, 16); + static_val, 32); if (bt_mesh_shell_prov.static_val_len) { bt_mesh_shell_prov.static_val = static_val; } else { @@ -886,7 +886,7 @@ static int cmd_auth_method_set_output(const struct shell *sh, size_t argc, char static int cmd_auth_method_set_static(const struct shell *sh, size_t argc, char *argv[]) { size_t len; - uint8_t static_oob_auth[16]; + uint8_t static_oob_auth[32]; int err = 0; len = hex2bin(argv[1], strlen(argv[1]), static_oob_auth, sizeof(static_oob_auth)); From 2ec2e076210bd6c281ead3e1daebbc5ffcb54fc2 Mon Sep 17 00:00:00 2001 From: Aleksandr Khromykh Date: Tue, 26 Sep 2023 12:17:21 +0200 Subject: [PATCH 152/421] [nrf fromtree] Bluetooth: Mesh: refactor mandatory oob for mesh1d1 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Provisioner should be able to manage received capabilities unconditionally. Mandatory oob authentication is the node feature and it is still compile time feature. Split handling of this feature on provisioner and node part. Signed-off-by: Aleksandr Khromykh (cherry picked from commit 0e98a35e39f001d9e5a4c4f0b9f348668bc1451b) Signed-off-by: Alperen Şener (cherry picked from commit 201ce3e031443dd018c642ebcaaab8c7d14405f0) --- subsys/bluetooth/mesh/prov.c | 6 ------ subsys/bluetooth/mesh/prov_device.c | 13 +++++++++++-- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/subsys/bluetooth/mesh/prov.c b/subsys/bluetooth/mesh/prov.c index f44fffde649..fbbcde58185 100644 --- a/subsys/bluetooth/mesh/prov.c +++ b/subsys/bluetooth/mesh/prov.c @@ -181,12 +181,6 @@ int bt_mesh_prov_auth(bool is_provisioner, uint8_t method, uint8_t action, uint8 uint8_t auth_size = bt_mesh_prov_auth_size_get(); int err; - if (IS_ENABLED(CONFIG_BT_MESH_OOB_AUTH_REQUIRED) && - (method == AUTH_METHOD_NO_OOB || - bt_mesh_prov_link.algorithm == BT_MESH_PROV_AUTH_CMAC_AES128_AES_CCM)) { - return -EINVAL; - } - switch (method) { case AUTH_METHOD_NO_OOB: if (action || size) { diff --git a/subsys/bluetooth/mesh/prov_device.c b/subsys/bluetooth/mesh/prov_device.c index a83ace178db..0184463568f 100644 --- a/subsys/bluetooth/mesh/prov_device.c +++ b/subsys/bluetooth/mesh/prov_device.c @@ -94,15 +94,16 @@ static void prov_invite(const uint8_t *data) bt_mesh_prov->input_size > 0 || bt_mesh_prov->static_val; if (IS_ENABLED(CONFIG_BT_MESH_ECDH_P256_HMAC_SHA256_AES_CCM)) { - algorithm_bm |= BIT(BT_MESH_PROV_AUTH_HMAC_SHA256_AES_CCM); + WRITE_BIT(algorithm_bm, BT_MESH_PROV_AUTH_HMAC_SHA256_AES_CCM, 1); } if (IS_ENABLED(CONFIG_BT_MESH_ECDH_P256_CMAC_AES128_AES_CCM)) { - algorithm_bm |= BIT(BT_MESH_PROV_AUTH_CMAC_AES128_AES_CCM); + WRITE_BIT(algorithm_bm, BT_MESH_PROV_AUTH_CMAC_AES128_AES_CCM, 1); } if (oob_availability && IS_ENABLED(CONFIG_BT_MESH_OOB_AUTH_REQUIRED)) { oob_type |= BT_MESH_OOB_AUTH_REQUIRED; + WRITE_BIT(algorithm_bm, BT_MESH_PROV_AUTH_CMAC_AES128_AES_CCM, 0); } /* Supported algorithms */ @@ -176,10 +177,18 @@ static void prov_start(const uint8_t *data) bt_mesh_prov_link.oob_action = data[3]; bt_mesh_prov_link.oob_size = data[4]; + if (IS_ENABLED(CONFIG_BT_MESH_OOB_AUTH_REQUIRED) && + (bt_mesh_prov_link.oob_method == AUTH_METHOD_NO_OOB || + bt_mesh_prov_link.algorithm == BT_MESH_PROV_AUTH_CMAC_AES128_AES_CCM)) { + prov_fail(PROV_ERR_NVAL_FMT); + return; + } + if (bt_mesh_prov_auth(false, data[2], data[3], data[4]) < 0) { LOG_ERR("Invalid authentication method: 0x%02x; " "action: 0x%02x; size: 0x%02x", data[2], data[3], data[4]); prov_fail(PROV_ERR_NVAL_FMT); + return; } if (atomic_test_bit(bt_mesh_prov_link.flags, OOB_STATIC_KEY)) { From b6a8f040d960f817bc4abbb5806aa23d50c4bd07 Mon Sep 17 00:00:00 2001 From: Aleksandr Khromykh Date: Tue, 26 Sep 2023 12:20:28 +0200 Subject: [PATCH 153/421] [nrf fromtree] tests: Bluetooth: tester: fix mesh1d1 EHP pts tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Mesh1d1 uses EHP wth SHA256 algorithm as the main one. This mandates to use 32 bytes static oob if static oob has been chosen. Signed-off-by: Aleksandr Khromykh (cherry picked from commit 4cf78b1e6da90f80bd6449ae01abbcbaccbabbbc) Signed-off-by: Alperen Şener (cherry picked from commit b44b736ef01a0c85727e25fe538acbdd53326a16) --- tests/bluetooth/tester/src/btp/btp_mesh.h | 10 ++++++++-- tests/bluetooth/tester/src/btp_mesh.c | 2 +- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/tests/bluetooth/tester/src/btp/btp_mesh.h b/tests/bluetooth/tester/src/btp/btp_mesh.h index d7d2b2cdc7b..bf73d6839d2 100644 --- a/tests/bluetooth/tester/src/btp/btp_mesh.h +++ b/tests/bluetooth/tester/src/btp/btp_mesh.h @@ -30,9 +30,15 @@ struct btp_mesh_read_supported_commands_rp { #define BTP_MESH_CONFIG_PROVISIONING 0x02 +#if IS_ENABLED(CONFIG_BT_MESH_ECDH_P256_HMAC_SHA256_AES_CCM) +#define BTP_MESH_PROV_AUTH_MAX_LEN 32 +#else +#define BTP_MESH_PROV_AUTH_MAX_LEN 16 +#endif + struct btp_mesh_config_provisioning_cmd { uint8_t uuid[16]; - uint8_t static_auth[16]; + uint8_t static_auth[BTP_MESH_PROV_AUTH_MAX_LEN]; uint8_t out_size; uint16_t out_actions; uint8_t in_size; @@ -41,7 +47,7 @@ struct btp_mesh_config_provisioning_cmd { } __packed; struct btp_mesh_config_provisioning_cmd_v2 { uint8_t uuid[16]; - uint8_t static_auth[16]; + uint8_t static_auth[BTP_MESH_PROV_AUTH_MAX_LEN]; uint8_t out_size; uint16_t out_actions; uint8_t in_size; diff --git a/tests/bluetooth/tester/src/btp_mesh.c b/tests/bluetooth/tester/src/btp_mesh.c index c922c812631..c56c0ff9c1c 100644 --- a/tests/bluetooth/tester/src/btp_mesh.c +++ b/tests/bluetooth/tester/src/btp_mesh.c @@ -43,7 +43,7 @@ static uint8_t priv_key[32]; /* Configured provisioning data */ static uint8_t dev_uuid[16]; -static uint8_t static_auth[16]; +static uint8_t static_auth[BTP_MESH_PROV_AUTH_MAX_LEN]; /* Vendor Model data */ #define VND_MODEL_ID_1 0x1234 From ab1eb73243f14658b3d50ff2b541516a857ace70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Narajowski?= Date: Mon, 16 Nov 2020 12:01:54 +0100 Subject: [PATCH 154/421] [nrf fromtree] Bluetooth: tester: Use Model Receive testing callback MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Send a BTP event to the automation framework that a model message has been received. Signed-off-by: Michal Narajowski (cherry picked from commit 0efc66df5e62078ba9560070c6bafd7e7d122c78) Signed-off-by: Alperen Şener (cherry picked from commit 17f09b553dffd4022567ce0511a6382e5614e04a) --- tests/bluetooth/tester/src/btp/btp_mesh.h | 8 ++++++++ tests/bluetooth/tester/src/btp_mesh.c | 23 +++++++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/tests/bluetooth/tester/src/btp/btp_mesh.h b/tests/bluetooth/tester/src/btp/btp_mesh.h index bf73d6839d2..e17d8481500 100644 --- a/tests/bluetooth/tester/src/btp/btp_mesh.h +++ b/tests/bluetooth/tester/src/btp/btp_mesh.h @@ -864,3 +864,11 @@ struct btp_mesh_prov_node_added_ev { uint8_t uuid[16]; uint8_t num_elems; } __packed; + +#define BTP_MESH_EV_MODEL_RECV 0x8f +struct btp_mesh_model_recv_ev { + uint16_t src; + uint16_t dst; + uint8_t payload_len; + uint8_t payload[]; +} __packed; diff --git a/tests/bluetooth/tester/src/btp_mesh.c b/tests/bluetooth/tester/src/btp_mesh.c index c56c0ff9c1c..2796f6418e4 100644 --- a/tests/bluetooth/tester/src/btp_mesh.c +++ b/tests/bluetooth/tester/src/btp_mesh.c @@ -2963,6 +2963,28 @@ void net_recv_ev(uint8_t ttl, uint8_t ctl, uint16_t src, uint16_t dst, const voi tester_event(BTP_SERVICE_ID_MESH, BTP_MESH_EV_NET_RECV, buf.data, buf.len); } +void model_recv_ev(uint16_t src, uint16_t dst, const void *payload, + size_t payload_len) +{ + NET_BUF_SIMPLE_DEFINE(buf, UINT8_MAX); + struct btp_mesh_model_recv_ev *ev; + + LOG_DBG("src 0x%04x dst 0x%04x payload_len %zu", src, dst, payload_len); + + if (payload_len > net_buf_simple_tailroom(&buf)) { + LOG_ERR("Payload size exceeds buffer size"); + return; + } + + ev = net_buf_simple_add(&buf, sizeof(*ev)); + ev->src = sys_cpu_to_le16(src); + ev->dst = sys_cpu_to_le16(dst); + ev->payload_len = payload_len; + net_buf_simple_add_mem(&buf, payload, payload_len); + + tester_event(BTP_SERVICE_ID_MESH, BTP_MESH_EV_MODEL_RECV, buf.data, buf.len); +} + static void model_bound_cb(uint16_t addr, struct bt_mesh_model *model, uint16_t key_idx) { @@ -3023,6 +3045,7 @@ static void incomp_timer_exp_cb(void) static struct bt_test_cb bt_test_cb = { .mesh_net_recv = net_recv_ev, + .mesh_model_recv = model_recv_ev, .mesh_model_bound = model_bound_cb, .mesh_model_unbound = model_unbound_cb, .mesh_prov_invalid_bearer = invalid_bearer_cb, From 83280e62bcf2d4f9ab18ce82c79ad6103a46cd62 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Narajowski?= Date: Wed, 18 Nov 2020 12:52:59 +0100 Subject: [PATCH 155/421] [nrf fromtree] Bluetooth: tester: Add ttl param to Model Send CMD MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some test cases require more control over transmission parameters used when sending access messages. Signed-off-by: Michal Narajowski (cherry picked from commit 959e55cdc07100bda633aab65f577e572e8dd36d) Signed-off-by: Alperen Şener (cherry picked from commit dd60cb7adb16cd6839da09a0f1debd0559610669) --- tests/bluetooth/tester/src/btp/btp_mesh.h | 1 + tests/bluetooth/tester/src/btp_mesh.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/bluetooth/tester/src/btp/btp_mesh.h b/tests/bluetooth/tester/src/btp/btp_mesh.h index e17d8481500..bd7af172744 100644 --- a/tests/bluetooth/tester/src/btp/btp_mesh.h +++ b/tests/bluetooth/tester/src/btp/btp_mesh.h @@ -127,6 +127,7 @@ struct btp_mesh_lpn_set_cmd { #define BTP_MESH_MODEL_SEND 0x0f struct btp_mesh_model_send_cmd { + uint8_t ttl; uint16_t src; uint16_t dst; uint8_t payload_len; diff --git a/tests/bluetooth/tester/src/btp_mesh.c b/tests/bluetooth/tester/src/btp_mesh.c index 2796f6418e4..b6ac4d91e1c 100644 --- a/tests/bluetooth/tester/src/btp_mesh.c +++ b/tests/bluetooth/tester/src/btp_mesh.c @@ -861,7 +861,7 @@ static uint8_t model_send(const void *cmd, uint16_t cmd_len, .net_idx = net.net_idx, .app_idx = BT_MESH_KEY_DEV, .addr = sys_le16_to_cpu(cp->dst), - .send_ttl = BT_MESH_TTL_DEFAULT, + .send_ttl = cp->ttl, }; if (BT_MESH_ADDR_IS_VIRTUAL(ctx.addr)) { From 4b5500c758e19a5338dc0bc778975ed94024f0d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Narajowski?= Date: Thu, 25 Mar 2021 15:33:18 +0100 Subject: [PATCH 156/421] [nrf fromtree] tester: Add Large Comp Data models MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Adds Large Comp Data Server and Client - Defines some dummy metadata for Health Server Signed-off-by: Michal Narajowski (cherry picked from commit 11bdcb859e921a79e50dc41c30167bc544dcbcda) Signed-off-by: Alperen Şener (cherry picked from commit f7c4008a2c541985bb00c63e0374990b37ebd2d0) --- tests/bluetooth/tester/overlay-mesh.conf | 5 + tests/bluetooth/tester/src/btp/btp_mesh.h | 22 +++++ tests/bluetooth/tester/src/btp_mesh.c | 111 ++++++++++++++++++++-- 3 files changed, 129 insertions(+), 9 deletions(-) diff --git a/tests/bluetooth/tester/overlay-mesh.conf b/tests/bluetooth/tester/overlay-mesh.conf index 840af06c1c0..937f4d1270e 100644 --- a/tests/bluetooth/tester/overlay-mesh.conf +++ b/tests/bluetooth/tester/overlay-mesh.conf @@ -1,4 +1,5 @@ CONFIG_BT_MESH=y +CONFIG_BT_MESH_V1d1=y CONFIG_BT_MESH_RELAY=y CONFIG_BT_MESH_PB_ADV=y CONFIG_BT_MESH_PB_GATT=y @@ -12,6 +13,8 @@ CONFIG_BT_MESH_APP_KEY_COUNT=4 CONFIG_BT_MESH_IV_UPDATE_TEST=y CONFIG_BT_MESH_CFG_CLI=y CONFIG_BT_MESH_HEALTH_CLI=y +CONFIG_BT_MESH_LARGE_COMP_DATA_CLI=y +CONFIG_BT_MESH_LARGE_COMP_DATA_SRV=y CONFIG_BT_MESH_FRIEND=y CONFIG_BT_MESH_FRIEND_QUEUE_SIZE=32 CONFIG_BT_MESH_RX_SEG_MAX=13 @@ -23,3 +26,5 @@ CONFIG_BT_MESH_CDB_NODE_COUNT=3 CONFIG_BT_MESH_PROV_OOB_PUBLIC_KEY=y CONFIG_BT_MESH_MSG_CACHE_SIZE=10 CONFIG_BT_MESH_PROXY_CLIENT=y + +CONFIG_SETTINGS=y diff --git a/tests/bluetooth/tester/src/btp/btp_mesh.h b/tests/bluetooth/tester/src/btp/btp_mesh.h index bd7af172744..63984f0b61f 100644 --- a/tests/bluetooth/tester/src/btp/btp_mesh.h +++ b/tests/bluetooth/tester/src/btp/btp_mesh.h @@ -773,6 +773,28 @@ struct btp_proxy_connect_cmd { uint16_t net_idx; } __packed; +#define BTP_MESH_LARGE_COMP_DATA_GET 0x53 +struct btp_mesh_large_comp_data_get_cmd { + uint16_t net_idx; + uint16_t addr; + uint8_t page; + uint16_t offset; +} __packed; +struct btp_mesh_large_comp_data_get_rp { + uint8_t data[0]; +} __packed; + +#define BTP_MESH_MODELS_METADATA_GET 0x54 +struct btp_mesh_models_metadata_get_cmd { + uint16_t net_idx; + uint16_t addr; + uint8_t page; + uint16_t offset; +} __packed; +struct btp_mesh_models_metadata_get_rp { + uint8_t data[0]; +} __packed; + /* events */ #define BTP_MESH_EV_OUT_NUMBER_ACTION 0x80 struct btp_mesh_out_number_action_ev { diff --git a/tests/bluetooth/tester/src/btp_mesh.c b/tests/bluetooth/tester/src/btp_mesh.c index b6ac4d91e1c..a6ccd319b2d 100644 --- a/tests/bluetooth/tester/src/btp_mesh.c +++ b/tests/bluetooth/tester/src/btp_mesh.c @@ -22,6 +22,8 @@ LOG_MODULE_REGISTER(LOG_MODULE_NAME, CONFIG_BTTESTER_LOG_LEVEL); #include "btp/btp.h" #define CID_LOCAL 0x05F1 +#define COMPANY_ID_LF 0x05F1 +#define COMPANY_ID_NORDIC_SEMI 0x05F9 /* Health server data */ #define CUR_FAULTS_MAX 4 @@ -254,15 +256,6 @@ static const struct bt_mesh_health_srv_cb health_srv_cb = { .fault_test = fault_test, }; -static struct bt_mesh_health_srv health_srv = { - .cb = &health_srv_cb, -}; - -BT_MESH_HEALTH_PUB_DEFINE(health_pub, CUR_FAULTS_MAX); - -static struct bt_mesh_cfg_cli cfg_cli = { -}; - static void show_faults(uint8_t test_id, uint16_t cid, uint8_t *faults, size_t fault_count) { size_t i; @@ -289,15 +282,52 @@ static void health_current_status(struct bt_mesh_health_cli *cli, uint16_t addr, show_faults(test_id, cid, faults, fault_count); } +#if defined(CONFIG_BT_MESH_LARGE_COMP_DATA_CLI) +static struct bt_mesh_large_comp_data_cli lcd_cli = { +}; +#endif + static struct bt_mesh_health_cli health_cli = { .current_status = health_current_status, }; + +#ifdef CONFIG_BT_MESH_LARGE_COMP_DATA_SRV +static uint8_t health_tests[] = { + BT_MESH_HEALTH_TEST_INFO(COMPANY_ID_LF, 6, 0x01, 0x02, 0x03, 0x04, 0x34, + 0x15), + BT_MESH_HEALTH_TEST_INFO(COMPANY_ID_NORDIC_SEMI, 3, 0x01, 0x02, 0x03), +}; + +static struct bt_mesh_models_metadata_entry health_srv_meta[] = { + BT_MESH_HEALTH_TEST_INFO_METADATA(health_tests), + BT_MESH_MODELS_METADATA_END, +}; +#endif + +static struct bt_mesh_health_srv health_srv = { + .cb = &health_srv_cb, +#ifdef CONFIG_BT_MESH_LARGE_COMP_DATA_SRV + .metadata = health_srv_meta, +#endif +}; + +BT_MESH_HEALTH_PUB_DEFINE(health_pub, CUR_FAULTS_MAX); + +static struct bt_mesh_cfg_cli cfg_cli = { +}; + static struct bt_mesh_model root_models[] = { BT_MESH_MODEL_CFG_SRV, BT_MESH_MODEL_CFG_CLI(&cfg_cli), BT_MESH_MODEL_HEALTH_SRV(&health_srv, &health_pub), BT_MESH_MODEL_HEALTH_CLI(&health_cli), +#if defined(CONFIG_BT_MESH_LARGE_COMP_DATA_SRV) + BT_MESH_MODEL_LARGE_COMP_DATA_SRV, +#endif +#if defined(CONFIG_BT_MESH_LARGE_COMP_DATA_CLI) + BT_MESH_MODEL_LARGE_COMP_DATA_CLI(&lcd_cli), +#endif }; static struct bt_mesh_model vnd_models[] = { @@ -986,6 +1016,56 @@ static uint8_t proxy_connect(const void *cmd, uint16_t cmd_len, } #endif +#if defined(CONFIG_BT_MESH_LARGE_COMP_DATA_CLI) +static uint8_t large_comp_data_get(const void *cmd, uint16_t cmd_len, + void *rsp, uint16_t *rsp_len) +{ + const struct btp_mesh_large_comp_data_get_cmd *cp = cmd; + struct btp_mesh_large_comp_data_get_rp *rp = rsp; + int err; + + struct bt_mesh_large_comp_data_rsp comp; + + err = bt_mesh_large_comp_data_get(sys_le16_to_cpu(cp->net_idx), + sys_le16_to_cpu(cp->addr), cp->page, + sys_le16_to_cpu(cp->offset), &comp); + if (err) { + LOG_ERR("Large Composition Data Get failed (err %d)", err); + + return BTP_STATUS_FAILED; + } + + memcpy(rp->data, comp.data->data, comp.data->len); + *rsp_len = comp.data->len; + + return BTP_STATUS_SUCCESS; +} + +static uint8_t models_metadata_get(const void *cmd, uint16_t cmd_len, + void *rsp, uint16_t *rsp_len) +{ + const struct btp_mesh_models_metadata_get_cmd *cp = cmd; + struct btp_mesh_models_metadata_get_rp *rp = rsp; + int err; + + struct bt_mesh_large_comp_data_rsp metadata; + + err = bt_mesh_models_metadata_get(sys_le16_to_cpu(cp->net_idx), + sys_le16_to_cpu(cp->addr), cp->page, + sys_le16_to_cpu(cp->offset), &metadata); + + if (err) { + LOG_ERR("Models Metadata Get failed (err %d)", err); + return BTP_STATUS_FAILED; + } + + memcpy(rp->data, metadata.data->data, metadata.data->len); + *rsp_len = metadata.data->len; + + return BTP_STATUS_SUCCESS; +} +#endif + static uint8_t composition_data_get(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len) { @@ -2936,8 +3016,21 @@ static const struct btp_handler handlers[] = { .func = proxy_connect }, #endif +#if defined(CONFIG_BT_MESH_LARGE_COMP_DATA_CLI) + { + .opcode = BTP_MESH_LARGE_COMP_DATA_GET, + .expect_len = sizeof(struct btp_mesh_large_comp_data_get_cmd), + .func = large_comp_data_get + }, + { + .opcode = BTP_MESH_MODELS_METADATA_GET, + .expect_len = sizeof(struct btp_mesh_models_metadata_get_cmd), + .func = models_metadata_get + }, +#endif }; + void net_recv_ev(uint8_t ttl, uint8_t ctl, uint16_t src, uint16_t dst, const void *payload, size_t payload_len) { From 9c7ac78741416f601ad8f453f76f5edab0b4d110 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Narajowski?= Date: Tue, 31 Jan 2023 14:29:16 +0100 Subject: [PATCH 157/421] [nrf fromtree] Bluetooth: tester: Add Transport SAR Configuration models MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add support for testing the new SAR Configuration models in tester application. Signed-off-by: Michal Narajowski (cherry picked from commit a73727c2fe8c7ac6972b7f2844d2949936ecc5fe) Signed-off-by: Alperen Şener (cherry picked from commit 5e6d6501d8348bcea388e2ef3a903efec1fe1662) --- tests/bluetooth/tester/overlay-mesh.conf | 2 + tests/bluetooth/tester/src/btp/btp_mesh.h | 40 +++++++ tests/bluetooth/tester/src/btp_mesh.c | 133 +++++++++++++++++++++- 3 files changed, 174 insertions(+), 1 deletion(-) diff --git a/tests/bluetooth/tester/overlay-mesh.conf b/tests/bluetooth/tester/overlay-mesh.conf index 937f4d1270e..43e666d0eb3 100644 --- a/tests/bluetooth/tester/overlay-mesh.conf +++ b/tests/bluetooth/tester/overlay-mesh.conf @@ -15,6 +15,8 @@ CONFIG_BT_MESH_CFG_CLI=y CONFIG_BT_MESH_HEALTH_CLI=y CONFIG_BT_MESH_LARGE_COMP_DATA_CLI=y CONFIG_BT_MESH_LARGE_COMP_DATA_SRV=y +CONFIG_BT_MESH_SAR_CFG_SRV=y +CONFIG_BT_MESH_SAR_CFG_CLI=y CONFIG_BT_MESH_FRIEND=y CONFIG_BT_MESH_FRIEND_QUEUE_SIZE=32 CONFIG_BT_MESH_RX_SEG_MAX=13 diff --git a/tests/bluetooth/tester/src/btp/btp_mesh.h b/tests/bluetooth/tester/src/btp/btp_mesh.h index 63984f0b61f..67ce612c2ac 100644 --- a/tests/bluetooth/tester/src/btp/btp_mesh.h +++ b/tests/bluetooth/tester/src/btp/btp_mesh.h @@ -773,6 +773,46 @@ struct btp_proxy_connect_cmd { uint16_t net_idx; } __packed; +struct sar_transmitter { + uint8_t seg_int_step; + uint8_t unicast_retrans_count; + uint8_t unicast_retrans_without_prog_count; + uint8_t unicast_retrans_int_step; + uint8_t unicast_retrans_int_inc; + uint8_t multicast_retrans_count; + uint8_t multicast_retrans_int; +} __packed; + +struct sar_receiver { + uint8_t seg_thresh; + uint8_t ack_delay_inc; + uint8_t ack_retrans_count; + uint8_t discard_timeout; + uint8_t rx_seg_int_step; +} __packed; + +#define BTP_MESH_SAR_TRANSMITTER_GET 0x4f +struct btp_mesh_sar_transmitter_get_cmd { + uint16_t dst; +} __packed; + +#define BTP_MESH_SAR_TRANSMITTER_SET 0x50 +struct btp_mesh_sar_transmitter_set_cmd { + uint16_t dst; + struct sar_transmitter tx; +} __packed; + +#define BTP_MESH_SAR_RECEIVER_GET 0x51 +struct btp_mesh_sar_receiver_get_cmd { + uint16_t dst; +} __packed; + +#define BTP_MESH_SAR_RECEIVER_SET 0x52 +struct btp_mesh_sar_receiver_set_cmd { + uint16_t dst; + struct sar_receiver rx; +} __packed; + #define BTP_MESH_LARGE_COMP_DATA_GET 0x53 struct btp_mesh_large_comp_data_get_cmd { uint16_t net_idx; diff --git a/tests/bluetooth/tester/src/btp_mesh.c b/tests/bluetooth/tester/src/btp_mesh.c index a6ccd319b2d..232e3d7d8b4 100644 --- a/tests/bluetooth/tester/src/btp_mesh.c +++ b/tests/bluetooth/tester/src/btp_mesh.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #define LOG_MODULE_NAME bttester_mesh @@ -317,11 +318,21 @@ BT_MESH_HEALTH_PUB_DEFINE(health_pub, CUR_FAULTS_MAX); static struct bt_mesh_cfg_cli cfg_cli = { }; +#if defined(CONFIG_BT_MESH_SAR_CFG_CLI) +static struct bt_mesh_sar_cfg_cli sar_cfg_cli; +#endif + static struct bt_mesh_model root_models[] = { BT_MESH_MODEL_CFG_SRV, BT_MESH_MODEL_CFG_CLI(&cfg_cli), BT_MESH_MODEL_HEALTH_SRV(&health_srv, &health_pub), BT_MESH_MODEL_HEALTH_CLI(&health_cli), +#if defined(CONFIG_BT_MESH_SAR_CFG_SRV) + BT_MESH_MODEL_SAR_CFG_SRV, +#endif +#if defined(CONFIG_BT_MESH_SAR_CFG_CLI) + BT_MESH_MODEL_SAR_CFG_CLI(&sar_cfg_cli), +#endif #if defined(CONFIG_BT_MESH_LARGE_COMP_DATA_SRV) BT_MESH_MODEL_LARGE_COMP_DATA_SRV, #endif @@ -1016,6 +1027,105 @@ static uint8_t proxy_connect(const void *cmd, uint16_t cmd_len, } #endif +#if defined(CONFIG_BT_MESH_SAR_CFG_CLI) +static uint8_t sar_transmitter_get(const void *cmd, uint16_t cmd_len, + void *rsp, uint16_t *rsp_len) +{ + const struct btp_mesh_sar_transmitter_get_cmd *cp = cmd; + struct bt_mesh_sar_tx tx_rsp; + int err; + + LOG_DBG(""); + + bt_mesh_sar_cfg_cli_timeout_set(5000); + + err = bt_mesh_sar_cfg_cli_transmitter_get( + net_key_idx, sys_le16_to_cpu(cp->dst), &tx_rsp); + if (err) { + LOG_ERR("err=%d", err); + return BTP_STATUS_FAILED; + } + + return BTP_STATUS_SUCCESS; +} + +static uint8_t sar_transmitter_set(const void *cmd, uint16_t cmd_len, + void *rsp, uint16_t *rsp_len) +{ + const struct btp_mesh_sar_transmitter_set_cmd *cp = cmd; + struct bt_mesh_sar_tx set, tx_rsp; + int err; + + LOG_DBG(""); + + bt_mesh_sar_cfg_cli_timeout_set(5000); + + set.seg_int_step = cp->tx.seg_int_step; + set.unicast_retrans_count = cp->tx.unicast_retrans_count; + set.unicast_retrans_int_inc = cp->tx.unicast_retrans_int_inc; + set.unicast_retrans_int_step = cp->tx.unicast_retrans_int_step; + set.unicast_retrans_without_prog_count = + cp->tx.unicast_retrans_without_prog_count; + set.multicast_retrans_count = cp->tx.multicast_retrans_count; + set.multicast_retrans_int = cp->tx.multicast_retrans_int; + + err = bt_mesh_sar_cfg_cli_transmitter_set(net_key_idx, + sys_le16_to_cpu(cp->dst), + &set, &tx_rsp); + if (err) { + LOG_ERR("err=%d", err); + return BTP_STATUS_FAILED; + } + + return BTP_STATUS_SUCCESS; +} + +static uint8_t sar_receiver_get(const void *cmd, uint16_t cmd_len, + void *rsp, uint16_t *rsp_len) +{ + const struct btp_mesh_sar_receiver_get_cmd *cp = cmd; + struct bt_mesh_sar_rx rx_rsp; + int err; + + LOG_DBG(""); + + err = bt_mesh_sar_cfg_cli_receiver_get(net_key_idx, + sys_le16_to_cpu(cp->dst), &rx_rsp); + if (err) { + LOG_ERR("err=%d", err); + return BTP_STATUS_FAILED; + } + + return BTP_STATUS_SUCCESS; +} + +static uint8_t sar_receiver_set(const void *cmd, uint16_t cmd_len, + void *rsp, uint16_t *rsp_len) +{ + const struct btp_mesh_sar_receiver_set_cmd *cp = cmd; + struct bt_mesh_sar_rx set, rx_rsp; + int err; + + LOG_DBG(""); + + set.ack_delay_inc = cp->rx.ack_delay_inc; + set.ack_retrans_count = cp->rx.ack_retrans_count; + set.discard_timeout = cp->rx.discard_timeout; + set.seg_thresh = cp->rx.seg_thresh; + set.rx_seg_int_step = cp->rx.rx_seg_int_step; + + err = bt_mesh_sar_cfg_cli_receiver_set(net_key_idx, + sys_le16_to_cpu(cp->dst), &set, + &rx_rsp); + if (err) { + LOG_ERR("err=%d", err); + return BTP_STATUS_FAILED; + } + + return BTP_STATUS_SUCCESS; +} +#endif + #if defined(CONFIG_BT_MESH_LARGE_COMP_DATA_CLI) static uint8_t large_comp_data_get(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len) @@ -3016,6 +3126,28 @@ static const struct btp_handler handlers[] = { .func = proxy_connect }, #endif +#if defined(CONFIG_BT_MESH_SAR_CFG_CLI) + { + .opcode = BTP_MESH_SAR_TRANSMITTER_GET, + .expect_len = sizeof(struct btp_mesh_sar_transmitter_get_cmd), + .func = sar_transmitter_get + }, + { + .opcode = BTP_MESH_SAR_TRANSMITTER_SET, + .expect_len = sizeof(struct btp_mesh_sar_transmitter_set_cmd), + .func = sar_transmitter_set + }, + { + .opcode = BTP_MESH_SAR_RECEIVER_GET, + .expect_len = sizeof(struct btp_mesh_sar_receiver_get_cmd), + .func = sar_receiver_get + }, + { + .opcode = BTP_MESH_SAR_RECEIVER_SET, + .expect_len = sizeof(struct btp_mesh_sar_receiver_set_cmd), + .func = sar_receiver_set + }, +#endif #if defined(CONFIG_BT_MESH_LARGE_COMP_DATA_CLI) { .opcode = BTP_MESH_LARGE_COMP_DATA_GET, @@ -3030,7 +3162,6 @@ static const struct btp_handler handlers[] = { #endif }; - void net_recv_ev(uint8_t ttl, uint8_t ctl, uint16_t src, uint16_t dst, const void *payload, size_t payload_len) { From 2560e34ef5baf2d9a4c0ddadc36e4037a39d5569 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Fri, 28 Jan 2022 08:03:51 +0100 Subject: [PATCH 158/421] [nrf fromtree] Tests: Bluetooth: tester: enable Remote Provisioning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This enables Remote Provisioning in tester application. Adds basic setup and required structures/functions. add BTP API for Remote Provisioning Client This adds BTP commands for RPR Client API. Signed-off-by: Krzysztof Kopyściński (cherry picked from commit 68928e050f365306d92fc08f3bec91fa0e207cad) Signed-off-by: Alperen Şener (cherry picked from commit bff665d6dcf11c9a461b955be185e58b5d76faf3) --- tests/bluetooth/tester/overlay-mesh.conf | 4 + tests/bluetooth/tester/src/btp/btp_mesh.h | 61 +++ tests/bluetooth/tester/src/btp_mesh.c | 434 +++++++++++++++++++++- 3 files changed, 495 insertions(+), 4 deletions(-) diff --git a/tests/bluetooth/tester/overlay-mesh.conf b/tests/bluetooth/tester/overlay-mesh.conf index 43e666d0eb3..b537ae0001e 100644 --- a/tests/bluetooth/tester/overlay-mesh.conf +++ b/tests/bluetooth/tester/overlay-mesh.conf @@ -28,5 +28,9 @@ CONFIG_BT_MESH_CDB_NODE_COUNT=3 CONFIG_BT_MESH_PROV_OOB_PUBLIC_KEY=y CONFIG_BT_MESH_MSG_CACHE_SIZE=10 CONFIG_BT_MESH_PROXY_CLIENT=y +CONFIG_BT_MESH_PROVISIONER=y +CONFIG_BT_MESH_RPR_SRV=y +CONFIG_BT_MESH_RPR_CLI=y +CONFIG_BT_MESH_RPR_AD_TYPES_MAX=2 CONFIG_SETTINGS=y diff --git a/tests/bluetooth/tester/src/btp/btp_mesh.h b/tests/bluetooth/tester/src/btp/btp_mesh.h index 67ce612c2ac..29523d02d8c 100644 --- a/tests/bluetooth/tester/src/btp/btp_mesh.h +++ b/tests/bluetooth/tester/src/btp/btp_mesh.h @@ -835,6 +835,66 @@ struct btp_mesh_models_metadata_get_rp { uint8_t data[0]; } __packed; +#define BTP_MESH_COMP_CHANGE_PREPARE 0x57 + +#define BTP_MESH_SET_COMP_ALT 0x58 + +#define BTP_MESH_RPR_SCAN_START 0x59 +struct btp_rpr_scan_start_cmd { + uint16_t dst; + uint8_t timeout; + uint8_t uuid[16]; +} __packed; + +#define BTP_MESH_RPR_EXT_SCAN_START 0x5a +struct btp_rpr_ext_scan_start_cmd { + uint16_t dst; + uint8_t timeout; + uint8_t uuid[16]; + uint8_t ad_count; + uint8_t ad_types[]; +} __packed; + +#define BTP_MESH_RPR_SCAN_CAPS_GET 0x5b +struct btp_rpr_scan_caps_get_cmd { + uint16_t dst; +} __packed; + +#define BTP_MESH_RPR_SCAN_GET 0x5c +struct btp_rpr_scan_get_cmd { + uint16_t dst; +} __packed; + +#define BTP_MESH_RPR_SCAN_STOP 0x5d +struct btp_rpr_scan_stop_cmd { + uint16_t dst; +} __packed; + +#define BTP_MESH_RPR_LINK_GET 0x5e +struct btp_rpr_link_get_cmd { + uint16_t dst; +} __packed; + +#define BTP_MESH_RPR_LINK_CLOSE 0x5f +struct btp_rpr_link_close_cmd { + uint16_t dst; +} __packed; + +#define BTP_MESH_RPR_PROV_REMOTE 0x60 +struct btp_rpr_prov_remote_cmd { + uint16_t dst; + uint8_t uuid[16]; + uint16_t net_idx; + uint16_t addr; +} __packed; + +#define BTP_MESH_RPR_REPROV_REMOTE 0x61 +struct btp_rpr_reprov_remote_cmd { + uint16_t dst; + uint16_t addr; + bool comp_change; +} __packed; + /* events */ #define BTP_MESH_EV_OUT_NUMBER_ACTION 0x80 struct btp_mesh_out_number_action_ev { @@ -858,6 +918,7 @@ struct btp_mesh_in_action_ev { #define BTP_MESH_PROV_BEARER_PB_ADV 0x00 #define BTP_MESH_PROV_BEARER_PB_GATT 0x01 +#define BTP_MESH_PROV_BEARER_REMOTE 0x04 #define BTP_MESH_EV_PROV_LINK_OPEN 0x84 struct btp_mesh_prov_link_open_ev { uint8_t bearer; diff --git a/tests/bluetooth/tester/src/btp_mesh.c b/tests/bluetooth/tester/src/btp_mesh.c index 232e3d7d8b4..40ae3a6f038 100644 --- a/tests/bluetooth/tester/src/btp_mesh.c +++ b/tests/bluetooth/tester/src/btp_mesh.c @@ -76,6 +76,7 @@ static struct { .dst = BT_MESH_ADDR_UNASSIGNED, }; +static bool default_comp = true; static uint8_t supported_commands(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len) @@ -322,6 +323,49 @@ static struct bt_mesh_cfg_cli cfg_cli = { static struct bt_mesh_sar_cfg_cli sar_cfg_cli; #endif +#if defined(CONFIG_BT_MESH_RPR_CLI) +static void rpr_scan_report(struct bt_mesh_rpr_cli *cli, + const struct bt_mesh_rpr_node *srv, + struct bt_mesh_rpr_unprov *unprov, + struct net_buf_simple *adv_data) +{ + char uuid_hex_str[32 + 1]; + + bin2hex(unprov->uuid, 16, uuid_hex_str, sizeof(uuid_hex_str)); + + LOG_DBG("Server 0x%04x:\n" + "\tuuid: %s\n" + "\tOOB: 0x%04x", + srv->addr, uuid_hex_str, unprov->oob); + + while (adv_data && adv_data->len > 2) { + uint8_t len, type; + uint8_t data[31]; + + len = net_buf_simple_pull_u8(adv_data) - 1; + type = net_buf_simple_pull_u8(adv_data); + memcpy(data, net_buf_simple_pull_mem(adv_data, len), len); + data[len] = '\0'; + + if (type == BT_DATA_URI) { + LOG_DBG("\tURI: \"\\x%02x%s\"", + data[0], &data[1]); + } else if (type == BT_DATA_NAME_COMPLETE) { + LOG_DBG("\tName: \"%s\"", data); + } else { + char string[64 + 1]; + + bin2hex(data, len, string, sizeof(string)); + LOG_DBG("\t0x%02x: %s", type, string); + } + } +} + +static struct bt_mesh_rpr_cli rpr_cli = { + .scan_report = rpr_scan_report, +}; +#endif + static struct bt_mesh_model root_models[] = { BT_MESH_MODEL_CFG_SRV, BT_MESH_MODEL_CFG_CLI(&cfg_cli), @@ -339,6 +383,12 @@ static struct bt_mesh_model root_models[] = { #if defined(CONFIG_BT_MESH_LARGE_COMP_DATA_CLI) BT_MESH_MODEL_LARGE_COMP_DATA_CLI(&lcd_cli), #endif +#if defined(CONFIG_BT_MESH_RPR_CLI) + BT_MESH_MODEL_RPR_CLI(&rpr_cli), +#endif +#if defined(CONFIG_BT_MESH_RPR_SRV) + BT_MESH_MODEL_RPR_SRV, +#endif }; static struct bt_mesh_model vnd_models[] = { @@ -363,6 +413,9 @@ static void link_open(bt_mesh_prov_bearer_t bearer) case BT_MESH_PROV_GATT: ev.bearer = BTP_MESH_PROV_BEARER_PB_GATT; break; + case BT_MESH_PROV_REMOTE: + ev.bearer = BTP_MESH_PROV_BEARER_REMOTE; + break; default: LOG_ERR("Invalid bearer"); @@ -385,6 +438,9 @@ static void link_close(bt_mesh_prov_bearer_t bearer) case BT_MESH_PROV_GATT: ev.bearer = BTP_MESH_PROV_BEARER_PB_GATT; break; + case BT_MESH_PROV_REMOTE: + ev.bearer = BTP_MESH_PROV_BEARER_REMOTE; + break; default: LOG_ERR("Invalid bearer"); @@ -476,12 +532,24 @@ static void prov_reset(void) LOG_DBG(""); bt_mesh_prov_enable(BT_MESH_PROV_ADV | BT_MESH_PROV_GATT); + + if (IS_ENABLED(CONFIG_BT_MESH_RPR_SRV)) { + bt_mesh_prov_enable(BT_MESH_PROV_REMOTE); + } } static const struct bt_mesh_comp comp = { .cid = CID_LOCAL, .elem = elements, .elem_count = ARRAY_SIZE(elements), + .vid = 1, +}; + +static const struct bt_mesh_comp comp_alt = { + .cid = CID_LOCAL, + .elem = elements, + .elem_count = ARRAY_SIZE(elements), + .vid = 2, }; static struct bt_mesh_prov prov = { @@ -496,6 +564,7 @@ static struct bt_mesh_prov prov = { .complete = prov_complete, .node_added = prov_node_added, .reset = prov_reset, + .uri = "Tester", }; static uint8_t config_prov(const void *cmd, uint16_t cmd_len, @@ -617,19 +686,26 @@ static uint8_t init(const void *cmd, uint16_t cmd_len, LOG_DBG(""); - err = bt_mesh_init(&prov, &comp); - if (err) { - return BTP_STATUS_FAILED; + if (IS_ENABLED(CONFIG_BT_SETTINGS)) { + printk("Loading stored settings\n"); + settings_load(); } if (addr) { err = bt_mesh_provision(net_key, net_key_idx, flags, iv_index, addr, dev_key); - if (err) { + if (err && err != -EALREADY) { return BTP_STATUS_FAILED; } } else { err = bt_mesh_prov_enable(BT_MESH_PROV_ADV | BT_MESH_PROV_GATT); + if (err && err != -EALREADY) { + return BTP_STATUS_FAILED; + } + } + + if (IS_ENABLED(CONFIG_BT_MESH_RPR_SRV)) { + err = bt_mesh_prov_enable(BT_MESH_PROV_REMOTE); if (err) { return BTP_STATUS_FAILED; } @@ -1205,6 +1281,62 @@ static uint8_t composition_data_get(const void *cmd, uint16_t cmd_len, return BTP_STATUS_SUCCESS; } +static uint8_t change_prepare(const void *cmd, uint16_t cmd_len, + void *rsp, uint16_t *rsp_len) +{ + int err; + + LOG_DBG(""); + + err = bt_mesh_comp_change_prepare(); + if (err < 0) { + return BTP_STATUS_FAILED; + } + + return BTP_STATUS_SUCCESS; +} + +#if IS_ENABLED(CONFIG_BT_SETTINGS) +static int comp_alt_set(const char *name, size_t len_rd, + settings_read_cb read_cb, void *store) +{ + ssize_t len; + bool alt_comp_value; + + if (len_rd == 0) { + LOG_DBG("Default composition"); + } + + len = read_cb(store, &alt_comp_value, sizeof(alt_comp_value)); + if (len < 0 || len != len_rd) { + LOG_ERR("Failed to read value (err %zd)", len); + return len; + } + + if (alt_comp_value) { + default_comp = false; + } + + return 0; +} + +SETTINGS_STATIC_HANDLER_DEFINE(tester_comp_alt, "tester/comp_alt", NULL, comp_alt_set, NULL, NULL); +#endif + +static uint8_t set_comp_alt(const void *cmd, uint16_t cmd_len, + void *rsp, uint16_t *rsp_len) +{ +#if !IS_ENABLED(CONFIG_BT_SETTINGS) + return BTP_STATUS_FAILED; +#else + bool comp_alt_val = true; + + settings_save_one("tester/comp_alt", &comp_alt_val, sizeof(comp_alt_val)); + + return BTP_STATUS_SUCCESS; +#endif +} + static uint8_t config_krp_get(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len) { @@ -2730,6 +2862,233 @@ static uint8_t health_attention_set(const void *cmd, uint16_t cmd_len, return BTP_STATUS_SUCCESS; } +#if defined(CONFIG_BT_MESH_RPR_CLI) +static uint8_t rpr_scan_start(const void *cmd, uint16_t cmd_len, + void *rsp, uint16_t *rsp_len) +{ + const struct btp_rpr_scan_start_cmd *cp = cmd; + + struct bt_mesh_rpr_scan_status status; + const struct bt_mesh_rpr_node srv = { + .addr = cp->dst, + .net_idx = net.net_idx, + .ttl = BT_MESH_TTL_DEFAULT, + }; + uint8_t uuid[16] = {0}; + int err; + + err = bt_mesh_rpr_scan_start(&rpr_cli, &srv, + memcmp(uuid, cp->uuid, 16) ? cp->uuid : NULL, + cp->timeout, + BT_MESH_RPR_SCAN_MAX_DEVS_ANY, &status); + + if (err) { + LOG_ERR("Scan start failed: %d", err); + return BTP_STATUS_FAILED; + } + + return BTP_STATUS_SUCCESS; +} + +static uint8_t rpr_ext_scan_start(const void *cmd, uint16_t cmd_len, + void *rsp, uint16_t *rsp_len) +{ + const struct btp_rpr_ext_scan_start_cmd *cp = cmd; + const struct bt_mesh_rpr_node srv = { + .addr = cp->dst, + .net_idx = net.net_idx, + .ttl = BT_MESH_TTL_DEFAULT, + }; + int err; + + err = bt_mesh_rpr_scan_start_ext(&rpr_cli, &srv, cp->uuid, + cp->timeout, cp->ad_types, + cp->ad_count); + if (err) { + LOG_ERR("Scan start failed: %d", err); + return BTP_STATUS_FAILED; + } + + return BTP_STATUS_SUCCESS; +} + +static uint8_t rpr_scan_caps_get(const void *cmd, uint16_t cmd_len, + void *rsp, uint16_t *rsp_len) +{ + const struct btp_rpr_scan_caps_get_cmd *cp = cmd; + struct bt_mesh_rpr_caps caps; + const struct bt_mesh_rpr_node srv = { + .addr = cp->dst, + .net_idx = net.net_idx, + .ttl = BT_MESH_TTL_DEFAULT, + }; + int err; + + err = bt_mesh_rpr_scan_caps_get(&rpr_cli, &srv, &caps); + if (err) { + LOG_ERR("Scan capabilities get failed: %d", err); + return BTP_STATUS_FAILED; + } + + LOG_DBG("Remote Provisioning scan capabilities of 0x%04x:", + net.dst); + LOG_DBG("\tMax devices: %u", caps.max_devs); + LOG_DBG("\tActive scanning: %s", + caps.active_scan ? "true" : "false"); + + return BTP_STATUS_SUCCESS; +} + +static uint8_t rpr_scan_get(const void *cmd, uint16_t cmd_len, + void *rsp, uint16_t *rsp_len) +{ + const struct btp_rpr_scan_get_cmd *cp = cmd; + struct bt_mesh_rpr_scan_status status; + const struct bt_mesh_rpr_node srv = { + .addr = cp->dst, + .net_idx = net.net_idx, + .ttl = BT_MESH_TTL_DEFAULT, + }; + int err; + + err = bt_mesh_rpr_scan_get(&rpr_cli, &srv, &status); + if (err) { + LOG_ERR("Scan get failed: %d", err); + return BTP_STATUS_FAILED; + } + + LOG_DBG("Remote Provisioning scan on 0x%04x:", cp->dst); + LOG_DBG("\tStatus: %u", status.status); + LOG_DBG("\tScan type: %u", status.scan); + LOG_DBG("\tMax devices: %u", status.max_devs); + LOG_DBG("\tRemaining time: %u", status.timeout); + + return BTP_STATUS_SUCCESS; +} + +static uint8_t rpr_scan_stop(const void *cmd, uint16_t cmd_len, + void *rsp, uint16_t *rsp_len) +{ + const struct btp_rpr_scan_stop_cmd *cp = cmd; + struct bt_mesh_rpr_scan_status status; + const struct bt_mesh_rpr_node srv = { + .addr = cp->dst, + .net_idx = net.net_idx, + .ttl = BT_MESH_TTL_DEFAULT, + }; + int err; + + err = bt_mesh_rpr_scan_stop(&rpr_cli, &srv, &status); + if (err || status.status) { + LOG_DBG("Scan stop failed: %d %u", err, status.status); + return BTP_STATUS_FAILED; + } + + LOG_DBG("Remote Provisioning scan on 0x%04x stopped.", + net.dst); + + return BTP_STATUS_SUCCESS; +} + +static uint8_t rpr_link_get(const void *cmd, uint16_t cmd_len, + void *rsp, uint16_t *rsp_len) +{ + const struct btp_rpr_link_get_cmd *cp = cmd; + struct bt_mesh_rpr_link link; + const struct bt_mesh_rpr_node srv = { + .addr = cp->dst, + .net_idx = net.net_idx, + .ttl = BT_MESH_TTL_DEFAULT, + }; + int err; + + err = bt_mesh_rpr_link_get(&rpr_cli, &srv, &link); + if (err) { + LOG_ERR("Link get failed: %d %u", err, link.status); + return BTP_STATUS_FAILED; + } + + LOG_DBG("Remote Provisioning Link on 0x%04x:", cp->dst); + LOG_DBG("\tStatus: %u", link.status); + LOG_DBG("\tState: %u", link.state); + + return BTP_STATUS_SUCCESS; +} + +static uint8_t rpr_link_close(const void *cmd, uint16_t cmd_len, + void *rsp, uint16_t *rsp_len) +{ + const struct btp_rpr_link_close_cmd *cp = cmd; + struct bt_mesh_rpr_link link; + const struct bt_mesh_rpr_node srv = { + .addr = cp->dst, + .net_idx = net.net_idx, + .ttl = BT_MESH_TTL_DEFAULT, + }; + int err; + + err = bt_mesh_rpr_link_close(&rpr_cli, &srv, &link); + if (err) { + LOG_ERR("Link close failed: %d %u", err, link.status); + return BTP_STATUS_FAILED; + } + + LOG_DBG("Remote Provisioning Link on 0x%04x:", cp->dst); + LOG_DBG("\tStatus: %u", link.status); + LOG_DBG("\tState: %u", link.state); + + return BTP_STATUS_SUCCESS; +} + +static uint8_t rpr_prov_remote(const void *cmd, uint16_t cmd_len, + void *rsp, uint16_t *rsp_len) +{ + const struct btp_rpr_prov_remote_cmd *cp = cmd; + struct bt_mesh_rpr_node srv = { + .addr = cp->dst, + .net_idx = net.net_idx, + .ttl = BT_MESH_TTL_DEFAULT, + }; + int err; + + err = bt_mesh_provision_remote(&rpr_cli, &srv, cp->uuid, + cp->net_idx, cp->addr); + if (err) { + LOG_ERR("Prov remote start failed: %d", err); + return BTP_STATUS_FAILED; + } + + return BTP_STATUS_SUCCESS; +} + +static uint8_t rpr_reprov_remote(const void *cmd, uint16_t cmd_len, + void *rsp, uint16_t *rsp_len) +{ + const struct btp_rpr_reprov_remote_cmd *cp = cmd; + struct bt_mesh_rpr_node srv = { + .addr = cp->dst, + .net_idx = net.net_idx, + .ttl = BT_MESH_TTL_DEFAULT, + }; + int err; + + if (!BT_MESH_ADDR_IS_UNICAST(cp->addr)) { + LOG_ERR("Must be a valid unicast address"); + err = -EINVAL; + return BTP_STATUS_FAILED; + } + + err = bt_mesh_reprovision_remote(&rpr_cli, &srv, cp->addr, + cp->comp_change); + if (err) { + LOG_ERR("Reprovisioning failed: %d", err); + return BTP_STATUS_FAILED; + } + + return BTP_STATUS_SUCCESS; +} +#endif + static const struct btp_handler handlers[] = { { .opcode = BTP_MESH_READ_SUPPORTED_COMMANDS, @@ -3160,6 +3519,62 @@ static const struct btp_handler handlers[] = { .func = models_metadata_get }, #endif + { + .opcode = BTP_MESH_COMP_CHANGE_PREPARE, + .expect_len = 0, + .func = change_prepare + }, + { + .opcode = BTP_MESH_SET_COMP_ALT, + .expect_len = 0, + .func = set_comp_alt + }, +#if defined(CONFIG_BT_MESH_RPR_CLI) + { + .opcode = BTP_MESH_RPR_SCAN_START, + .expect_len = sizeof(struct btp_rpr_scan_start_cmd), + .func = rpr_scan_start + }, + { + .opcode = BTP_MESH_RPR_EXT_SCAN_START, + .expect_len = BTP_HANDLER_LENGTH_VARIABLE, + .func = rpr_ext_scan_start + }, + { + .opcode = BTP_MESH_RPR_SCAN_CAPS_GET, + .expect_len = sizeof(struct btp_rpr_scan_caps_get_cmd), + .func = rpr_scan_caps_get + }, + { + .opcode = BTP_MESH_RPR_SCAN_GET, + .expect_len = sizeof(struct btp_rpr_scan_get_cmd), + .func = rpr_scan_get + }, + { + .opcode = BTP_MESH_RPR_SCAN_STOP, + .expect_len = sizeof(struct btp_rpr_scan_stop_cmd), + .func = rpr_scan_stop + }, + { + .opcode = BTP_MESH_RPR_LINK_GET, + .expect_len = sizeof(struct btp_rpr_link_get_cmd), + .func = rpr_link_get + }, + { + .opcode = BTP_MESH_RPR_LINK_CLOSE, + .expect_len = sizeof(struct btp_rpr_link_close_cmd), + .func = rpr_link_close + }, + { + .opcode = BTP_MESH_RPR_PROV_REMOTE, + .expect_len = sizeof(struct btp_rpr_prov_remote_cmd), + .func = rpr_prov_remote + }, + { + .opcode = BTP_MESH_RPR_REPROV_REMOTE, + .expect_len = sizeof(struct btp_rpr_reprov_remote_cmd), + .func = rpr_reprov_remote + }, }; void net_recv_ev(uint8_t ttl, uint8_t ctl, uint16_t src, uint16_t dst, const void *payload, @@ -3345,12 +3760,23 @@ BT_MESH_LPN_CB_DEFINE(lpn_cb) = { uint8_t tester_init_mesh(void) { + int err; + if (IS_ENABLED(CONFIG_BT_TESTING)) { bt_test_cb_register(&bt_test_cb); } tester_register_command_handlers(BTP_SERVICE_ID_MESH, handlers, ARRAY_SIZE(handlers)); + if (default_comp) { + err = bt_mesh_init(&prov, &comp); + } else { + err = bt_mesh_init(&prov, &comp_alt); + } + + if (err) { + return BTP_STATUS_FAILED; + } return BTP_STATUS_SUCCESS; } From 26290321c5f585ca469dd52076fe458045a55d01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Wed, 4 May 2022 08:05:03 +0200 Subject: [PATCH 159/421] [nrf fromtree] Bluetooth: Tester: Add Blob, DFU and DFD tests support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adding support for automatic testing BLOB, DFU and DFD models. Co-authored-by: Agata Ponitka Co-authored-by: Pavel Vasilyev Signed-off-by: Krzysztof Kopyściński Signed-off-by: Pavel Vasilyev (cherry picked from commit 51ec2462d60aded26a5ba4736dde0e17dfc38af1) Signed-off-by: Alperen Şener (cherry picked from commit a4517ed57ebfbfb6c5ca765bdbefac1af492c901) --- tests/bluetooth/tester/overlay-mesh.conf | 8 +- tests/bluetooth/tester/src/btp/btp_mesh.h | 68 ++ tests/bluetooth/tester/src/btp/bttester.h | 3 + tests/bluetooth/tester/src/btp_core.c | 6 + tests/bluetooth/tester/src/btp_mesh.c | 1277 ++++++++++++++++++--- 5 files changed, 1221 insertions(+), 141 deletions(-) diff --git a/tests/bluetooth/tester/overlay-mesh.conf b/tests/bluetooth/tester/overlay-mesh.conf index b537ae0001e..3352e36f3a4 100644 --- a/tests/bluetooth/tester/overlay-mesh.conf +++ b/tests/bluetooth/tester/overlay-mesh.conf @@ -20,7 +20,7 @@ CONFIG_BT_MESH_SAR_CFG_CLI=y CONFIG_BT_MESH_FRIEND=y CONFIG_BT_MESH_FRIEND_QUEUE_SIZE=32 CONFIG_BT_MESH_RX_SEG_MAX=13 -CONFIG_BT_MESH_TX_SEG_MSG_COUNT=3 +CONFIG_BT_MESH_TX_SEG_MSG_COUNT=10 CONFIG_BT_MESH_LPN_POLL_TIMEOUT=100 CONFIG_BT_MESH_PROVISIONER=y CONFIG_BT_MESH_CDB=y @@ -32,5 +32,11 @@ CONFIG_BT_MESH_PROVISIONER=y CONFIG_BT_MESH_RPR_SRV=y CONFIG_BT_MESH_RPR_CLI=y CONFIG_BT_MESH_RPR_AD_TYPES_MAX=2 +CONFIG_BT_MESH_BLOB_CLI=y +CONFIG_BT_MESH_DFU_CLI=y +CONFIG_BT_MESH_BLOB_SRV=y +CONFIG_BT_MESH_DFU_SRV=y +CONFIG_BT_MESH_DFD_SRV=y +CONFIG_BT_MESH_DFU_SLOT_CNT=2 CONFIG_SETTINGS=y diff --git a/tests/bluetooth/tester/src/btp/btp_mesh.h b/tests/bluetooth/tester/src/btp/btp_mesh.h index 29523d02d8c..66a86bbb128 100644 --- a/tests/bluetooth/tester/src/btp/btp_mesh.h +++ b/tests/bluetooth/tester/src/btp/btp_mesh.h @@ -895,6 +895,72 @@ struct btp_rpr_reprov_remote_cmd { bool comp_change; } __packed; +#define BTP_MMDL_DFU_INFO_GET 0x5f +struct btp_mmdl_dfu_info_get_cmd { + uint8_t limit; +} __packed; + +#define BTP_MMDL_BLOB_INFO_GET 0x60 +struct btp_mmdl_blob_info_get_cmd { + uint8_t addr_cnt; + uint8_t addr[]; +} __packed; + +#define BTP_MMDL_DFU_UPDATE_METADATA_CHECK 0x61 +struct btp_mmdl_dfu_metadata_check_cmd { + uint8_t index; + uint8_t slot_idx; + uint8_t slot_size; + uint8_t fwid_len; + uint8_t metadata_len; + uint8_t data[]; +} __packed; + +struct btp_mmdl_dfu_metadata_check_rp { + uint8_t idx; + uint8_t status; + uint8_t effect; +} __packed; + +#define BTP_MMDL_DFU_FIRMWARE_UPDATE_GET 0x62 +#define BTP_MMDL_DFU_FIRMWARE_UPDATE_CANCEL 0x63 +#define BTP_MMDL_DFU_FIRMWARE_UPDATE_START 0x64 +struct btp_mmdl_dfu_firmware_update_cmd { + uint8_t addr_cnt; + uint8_t slot_idx; + uint8_t slot_size; + uint8_t fwid_len; + uint8_t metadata_len; + uint8_t block_size; + uint16_t chunk_size; + uint8_t data[]; +} __packed; + +struct btp_mmdl_dfu_firmware_update_rp { + uint8_t status; +} __packed; + +#define BTP_MMDL_BLOB_SRV_RECV 0x65 +struct btp_mmdl_blob_srv_recv_cmd { + uint64_t id; + uint16_t timeout; +} __packed; + +#define BTP_MMDL_BLOB_TRANSFER_START 0x66 +struct btp_mmdl_blob_transfer_start_cmd { + uint64_t id; + uint16_t size; + uint8_t block_size; + uint16_t chunk_size; + uint16_t timeout; +} __packed; + +#define BTP_MMDL_BLOB_TRANSFER_CANCEL 0x67 +#define BTP_MMDL_BLOB_TRANSFER_GET 0x68 +#define BTP_MMDL_BLOB_SRV_CANCEL 0x69 +#define BTP_MMDL_DFU_FIRMWARE_UPDATE_APPLY 0x6A +#define BTP_MMDL_DFU_SRV_APPLY 0x6B + /* events */ #define BTP_MESH_EV_OUT_NUMBER_ACTION 0x80 struct btp_mesh_out_number_action_ev { @@ -996,3 +1062,5 @@ struct btp_mesh_model_recv_ev { uint8_t payload_len; uint8_t payload[]; } __packed; + +#define MESH_EV_BLOB_LOST_TARGET 0x90 diff --git a/tests/bluetooth/tester/src/btp/bttester.h b/tests/bluetooth/tester/src/btp/bttester.h index b30eee70d44..84d4722a913 100644 --- a/tests/bluetooth/tester/src/btp/bttester.h +++ b/tests/bluetooth/tester/src/btp/bttester.h @@ -73,6 +73,9 @@ uint8_t tester_unregister_vocs(void); uint8_t tester_init_ias(void); uint8_t tester_unregister_ias(void); +uint8_t tester_init_mmdl(void); +uint8_t tester_unregister_mmdl(void); + uint8_t tester_init_gap(void); uint8_t tester_unregister_gap(void); diff --git a/tests/bluetooth/tester/src/btp_core.c b/tests/bluetooth/tester/src/btp_core.c index 36f92619bfc..7ece1224ed0 100644 --- a/tests/bluetooth/tester/src/btp_core.c +++ b/tests/bluetooth/tester/src/btp_core.c @@ -118,6 +118,9 @@ static uint8_t register_service(const void *cmd, uint16_t cmd_len, case BTP_SERVICE_ID_MESH: status = tester_init_mesh(); break; + case BTP_SERVICE_ID_MESH_MDL: + status = tester_init_mmdl(); + break; #endif /* CONFIG_BT_MESH */ #if defined(CONFIG_BT_VCP_VOL_REND) case BTP_SERVICE_ID_VCS: @@ -201,6 +204,9 @@ static uint8_t unregister_service(const void *cmd, uint16_t cmd_len, case BTP_SERVICE_ID_MESH: status = tester_unregister_mesh(); break; + case BTP_SERVICE_ID_MESH_MDL: + status = tester_unregister_mmdl(); + break; #endif /* CONFIG_BT_MESH */ #if defined(CONFIG_BT_VCP_VOL_REND) case BTP_SERVICE_ID_VCS: diff --git a/tests/bluetooth/tester/src/btp_mesh.c b/tests/bluetooth/tester/src/btp_mesh.c index 40ae3a6f038..8c637320a11 100644 --- a/tests/bluetooth/tester/src/btp_mesh.c +++ b/tests/bluetooth/tester/src/btp_mesh.c @@ -12,15 +12,18 @@ #include #include #include +#include #include #include #include +#include #include #define LOG_MODULE_NAME bttester_mesh LOG_MODULE_REGISTER(LOG_MODULE_NAME, CONFIG_BTTESTER_LOG_LEVEL); #include "btp/btp.h" +#include "dfu_slot.h" #define CID_LOCAL 0x05F1 #define COMPANY_ID_LF 0x05F1 @@ -54,7 +57,245 @@ static uint8_t vnd_app_key[16]; static uint16_t vnd_app_key_idx = 0x000f; /* Model send data */ -#define MODEL_BOUNDS_MAX 2 +#define MODEL_BOUNDS_MAX 100 + +#if defined(CONFIG_BT_MESH_BLOB_SRV) || defined(CONFIG_BT_MESH_BLOB_CLI) +/* BLOB Model data*/ +static uint8_t blob_rx_sum; +static bool blob_valid; +static const char *blob_data = "11111111111111111111111111111111"; + +static int blob_io_open(const struct bt_mesh_blob_io *io, + const struct bt_mesh_blob_xfer *xfer, + enum bt_mesh_blob_io_mode mode) +{ + blob_rx_sum = 0; + blob_valid = true; + return 0; +} + +static int blob_chunk_wr(const struct bt_mesh_blob_io *io, + const struct bt_mesh_blob_xfer *xfer, + const struct bt_mesh_blob_block *block, + const struct bt_mesh_blob_chunk *chunk) +{ + for (int i = 0; i < chunk->size; ++i) { + blob_rx_sum += chunk->data[i]; + if (chunk->data[i] != + blob_data[(i + chunk->offset) % strlen(blob_data)]) { + blob_valid = false; + } + } + + return 0; +} + +static int blob_chunk_rd(const struct bt_mesh_blob_io *io, + const struct bt_mesh_blob_xfer *xfer, + const struct bt_mesh_blob_block *block, + const struct bt_mesh_blob_chunk *chunk) +{ + for (int i = 0; i < chunk->size; ++i) { + chunk->data[i] = + blob_data[(i + chunk->offset) % strlen(blob_data)]; + } + + return 0; +} + +static const struct bt_mesh_blob_io dummy_blob_io = { + .open = blob_io_open, + .rd = blob_chunk_rd, + .wr = blob_chunk_wr, +}; +#endif + +#if defined(CONFIG_BT_MESH_DFD_SRV) +/* DFD Model data*/ +static int dfd_srv_recv(struct bt_mesh_dfd_srv *srv, + const struct bt_mesh_dfu_slot *slot, + const struct bt_mesh_blob_io **io) +{ + LOG_DBG("Uploading new firmware image to the distributor."); + + *io = &dummy_blob_io; + + return 0; +} + +static void dfd_srv_del(struct bt_mesh_dfd_srv *srv, + const struct bt_mesh_dfu_slot *slot) +{ + LOG_DBG("Deleting the firmware image from the distributor."); +} + +static int dfd_srv_send(struct bt_mesh_dfd_srv *srv, + const struct bt_mesh_dfu_slot *slot, + const struct bt_mesh_blob_io **io) +{ + LOG_DBG("Starting the firmware distribution."); + + *io = &dummy_blob_io; + + return 0; +} + +static struct bt_mesh_dfd_srv_cb dfd_srv_cb = { + .recv = dfd_srv_recv, + .del = dfd_srv_del, + .send = dfd_srv_send, +}; + +static struct bt_mesh_dfd_srv dfd_srv = BT_MESH_DFD_SRV_INIT(&dfd_srv_cb); +#endif + +#if defined(CONFIG_BT_MESH_BLOB_CLI) && !defined(CONFIG_BT_MESH_DFD_SRV) +static struct { + struct bt_mesh_blob_cli_inputs inputs; + struct bt_mesh_blob_target targets[32]; + struct bt_mesh_blob_target_pull pull[32]; + uint8_t target_count; + struct bt_mesh_blob_xfer xfer; +} blob_cli_xfer; + +static void blob_cli_lost_target(struct bt_mesh_blob_cli *cli, + struct bt_mesh_blob_target *target, + enum bt_mesh_blob_status reason) +{ + LOG_DBG("Mesh Blob: Lost target 0x%04x (reason: %u)", target->addr, + reason); + tester_event(BTP_SERVICE_ID_MESH, MESH_EV_BLOB_LOST_TARGET, NULL, 0); +} + +static void blob_cli_caps(struct bt_mesh_blob_cli *cli, + const struct bt_mesh_blob_cli_caps *caps) +{ + const char *const modes[] = { + "none", + "push", + "pull", + "all", + }; + + if (!caps) { + LOG_DBG("None of the targets can be used for BLOB transfer"); + return; + } + + LOG_DBG("Mesh BLOB: capabilities:"); + LOG_DBG("\tMax BLOB size: %u bytes", caps->max_size); + LOG_DBG("\tBlock size: %u-%u (%u-%u bytes)", caps->min_block_size_log, + caps->max_block_size_log, 1 << caps->min_block_size_log, + 1 << caps->max_block_size_log); + LOG_DBG("\tMax chunks: %u", caps->max_chunks); + LOG_DBG("\tChunk size: %u", caps->max_chunk_size); + LOG_DBG("\tMTU size: %u", caps->mtu_size); + LOG_DBG("\tModes: %s", modes[caps->modes]); +} + +static void blob_cli_end(struct bt_mesh_blob_cli *cli, + const struct bt_mesh_blob_xfer *xfer, bool success) +{ + if (success) { + LOG_DBG("Mesh BLOB transfer complete."); + } else { + LOG_DBG("Mesh BLOB transfer failed."); + } +} + +static const struct bt_mesh_blob_cli_cb blob_cli_handlers = { + .lost_target = blob_cli_lost_target, + .caps = blob_cli_caps, + .end = blob_cli_end, +}; + +static struct bt_mesh_blob_cli blob_cli = { .cb = &blob_cli_handlers }; +#endif + +#if defined(CONFIG_BT_MESH_DFU_SRV) +const char *metadata_data = "1100000000000011"; + +static uint8_t dfu_fwid[] = { + 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +static struct bt_mesh_dfu_img dfu_imgs[] = { { + .fwid = &dfu_fwid, + .fwid_len = sizeof(dfu_fwid), +} }; + +static int dfu_meta_check(struct bt_mesh_dfu_srv *srv, + const struct bt_mesh_dfu_img *img, + struct net_buf_simple *metadata, + enum bt_mesh_dfu_effect *effect) +{ + char string[2 * CONFIG_BT_MESH_DFU_METADATA_MAXLEN + 1]; + int i; + size_t len; + + len = bin2hex(metadata->data, metadata->len, string, sizeof(string)); + string[len] = '\0'; + + for (i = 0; i <= len; i++) { + if (string[i] != metadata_data[i]) { + LOG_ERR("Wrong Firmware Metadata"); + return -EINVAL; + } + } + + return 0; +} + +static int dfu_start(struct bt_mesh_dfu_srv *srv, + const struct bt_mesh_dfu_img *img, + struct net_buf_simple *metadata, + const struct bt_mesh_blob_io **io) +{ + LOG_DBG("DFU setup"); + + *io = &dummy_blob_io; + + return 0; +} + +static void dfu_end(struct bt_mesh_dfu_srv *srv, + const struct bt_mesh_dfu_img *img, bool success) +{ + if (!success) { + LOG_ERR("DFU failed"); + return; + } + + if (!blob_valid) { + bt_mesh_dfu_srv_rejected(srv); + return; + } + + bt_mesh_dfu_srv_verified(srv); +} + +static int dfu_apply(struct bt_mesh_dfu_srv *srv, + const struct bt_mesh_dfu_img *img) +{ + if (!blob_valid) { + return -EINVAL; + } + + LOG_DBG("Applying DFU transfer..."); + + return 0; +} + +static const struct bt_mesh_dfu_srv_cb dfu_handlers = { + .check = dfu_meta_check, + .start = dfu_start, + .end = dfu_end, + .apply = dfu_apply, +}; + +static struct bt_mesh_dfu_srv dfu_srv = + BT_MESH_DFU_SRV_INIT(&dfu_handlers, dfu_imgs, ARRAY_SIZE(dfu_imgs)); +#endif /* CONFIG_BT_MESH_DFU_SRV */ /* Model Authentication Method */ #define AUTH_METHOD_STATIC 0x01 @@ -366,6 +607,16 @@ static struct bt_mesh_rpr_cli rpr_cli = { }; #endif +#if defined(CONFIG_BT_MESH_DFU_SRV) +static uint8_t dfu_srv_apply(const void *cmd, uint16_t cmd_len, + void *rsp, uint16_t *rsp_len) +{ + LOG_DBG("Applying image on server"); + bt_mesh_dfu_srv_applied(&dfu_srv); + return BTP_STATUS_SUCCESS; +} +#endif + static struct bt_mesh_model root_models[] = { BT_MESH_MODEL_CFG_SRV, BT_MESH_MODEL_CFG_CLI(&cfg_cli), @@ -389,8 +640,28 @@ static struct bt_mesh_model root_models[] = { #if defined(CONFIG_BT_MESH_RPR_SRV) BT_MESH_MODEL_RPR_SRV, #endif +#if defined(CONFIG_BT_MESH_DFD_SRV) + BT_MESH_MODEL_DFD_SRV(&dfd_srv), +#endif +#if defined(CONFIG_BT_MESH_DFU_SRV) + BT_MESH_MODEL_DFU_SRV(&dfu_srv), +#endif +#if defined(CONFIG_BT_MESH_BLOB_CLI) && !defined(CONFIG_BT_MESH_DFD_SRV) + BT_MESH_MODEL_BLOB_CLI(&blob_cli), +#endif }; +struct model_data *lookup_model_bound(uint16_t id) +{ + int i; + for (i = 0; i < ARRAY_SIZE(model_bound); i++) { + if (model_bound[i].model && model_bound[i].model->id == id) { + return &model_bound[i]; + } + } + + return NULL; +} static struct bt_mesh_model vnd_models[] = { BT_MESH_MODEL_VND(CID_LOCAL, VND_MODEL_ID_1, BT_MESH_MODEL_NO_OPS, NULL, NULL), @@ -3089,145 +3360,782 @@ static uint8_t rpr_reprov_remote(const void *cmd, uint16_t cmd_len, } #endif -static const struct btp_handler handlers[] = { - { - .opcode = BTP_MESH_READ_SUPPORTED_COMMANDS, - .index = BTP_INDEX_NONE, - .expect_len = 0, - .func = supported_commands, - }, - { - .opcode = BTP_MESH_CONFIG_PROVISIONING, - .expect_len = BTP_HANDLER_LENGTH_VARIABLE, - .func = config_prov, - }, - { - .opcode = BTP_MESH_PROVISION_NODE, - .expect_len = BTP_HANDLER_LENGTH_VARIABLE, - .func = provision_node, - }, - { - .opcode = BTP_MESH_INIT, - .expect_len = 0, - .func = init, - }, - { - .opcode = BTP_MESH_RESET, - .expect_len = 0, - .func = reset, - }, - { - .opcode = BTP_MESH_INPUT_NUMBER, - .expect_len = sizeof(struct btp_mesh_input_number_cmd), - .func = input_number, - }, - { - .opcode = BTP_MESH_INPUT_STRING, - .expect_len = BTP_HANDLER_LENGTH_VARIABLE, - .func = input_string, - }, - { - .opcode = BTP_MESH_IVU_TEST_MODE, - .expect_len = sizeof(struct btp_mesh_ivu_test_mode_cmd), - .func = ivu_test_mode, - }, - { - .opcode = BTP_MESH_IVU_TOGGLE_STATE, - .expect_len = 0, - .func = ivu_toggle_state, - }, - { - .opcode = BTP_MESH_LPN, - .expect_len = sizeof(struct btp_mesh_lpn_set_cmd), - .func = lpn, - }, - { - .opcode = BTP_MESH_LPN_POLL, - .expect_len = 0, - .func = lpn_poll, - }, - { - .opcode = BTP_MESH_NET_SEND, - .expect_len = BTP_HANDLER_LENGTH_VARIABLE, - .func = net_send, - }, - { - .opcode = BTP_MESH_HEALTH_GENERATE_FAULTS, - .expect_len = 0, - .func = health_generate_faults, - }, - { - .opcode = BTP_MESH_HEALTH_CLEAR_FAULTS, - .expect_len = 0, - .func = health_clear_faults, - }, - { - .opcode = BTP_MESH_MODEL_SEND, - .expect_len = BTP_HANDLER_LENGTH_VARIABLE, - .func = model_send, - }, - { - .opcode = BTP_MESH_COMP_DATA_GET, - .expect_len = sizeof(struct btp_mesh_comp_data_get_cmd), - .func = composition_data_get, - }, - { - .opcode = BTP_MESH_CFG_BEACON_GET, - .expect_len = sizeof(struct btp_mesh_cfg_beacon_get_cmd), - .func = config_beacon_get, - }, - { - .opcode = BTP_MESH_CFG_BEACON_SET, - .expect_len = sizeof(struct btp_mesh_cfg_beacon_set_cmd), - .func = config_beacon_set, - }, - { - .opcode = BTP_MESH_CFG_DEFAULT_TTL_GET, - .expect_len = sizeof(struct btp_mesh_cfg_default_ttl_get_cmd), - .func = config_default_ttl_get, - }, - { - .opcode = BTP_MESH_CFG_DEFAULT_TTL_SET, - .expect_len = sizeof(struct btp_mesh_cfg_default_ttl_set_cmd), - .func = config_default_ttl_set, - }, - { - .opcode = BTP_MESH_CFG_GATT_PROXY_GET, - .expect_len = sizeof(struct btp_mesh_cfg_gatt_proxy_get_cmd), - .func = config_gatt_proxy_get, - }, - { - .opcode = BTP_MESH_CFG_GATT_PROXY_SET, - .expect_len = sizeof(struct btp_mesh_cfg_gatt_proxy_set_cmd), - .func = config_gatt_proxy_set, - }, - { - .opcode = BTP_MESH_CFG_FRIEND_GET, - .expect_len = sizeof(struct btp_mesh_cfg_friend_get_cmd), - .func = config_friend_get, - }, - { - .opcode = BTP_MESH_CFG_FRIEND_SET, - .expect_len = sizeof(struct btp_mesh_cfg_friend_set_cmd), - .func = config_friend_set, - }, - { - .opcode = BTP_MESH_CFG_RELAY_GET, - .expect_len = sizeof(struct btp_mesh_cfg_relay_get_cmd), - .func = config_relay_get, - }, - { - .opcode = BTP_MESH_CFG_RELAY_SET, - .expect_len = sizeof(struct btp_mesh_cfg_relay_set_cmd), - .func = config_relay_set, - }, - { - .opcode = BTP_MESH_CFG_MODEL_PUB_GET, - .expect_len = sizeof(struct btp_mesh_cfg_model_pub_get_cmd), - .func = config_mod_pub_get, - }, - { - .opcode = BTP_MESH_CFG_MODEL_PUB_SET, +#if defined(CONFIG_BT_MESH_DFD_SRV) +static struct { + struct bt_mesh_dfu_target targets[32]; + struct bt_mesh_blob_target_pull pull[32]; + size_t target_cnt; + struct bt_mesh_blob_cli_inputs inputs; +} dfu_tx; + +static void dfu_tx_prepare(void) +{ + sys_slist_init(&dfu_tx.inputs.targets); + + for (int i = 0; i < dfu_tx.target_cnt; i++) { + /* Reset target context. */ + uint16_t addr = dfu_tx.targets[i].blob.addr; + + memset(&dfu_tx.targets[i].blob, 0, + sizeof(struct bt_mesh_blob_target)); + memset(&dfu_tx.pull[i], 0, + sizeof(struct bt_mesh_blob_target_pull)); + dfu_tx.targets[i].blob.addr = addr; + dfu_tx.targets[i].blob.pull = &dfu_tx.pull[i]; + + sys_slist_append(&dfu_tx.inputs.targets, + &dfu_tx.targets[i].blob.n); + } +} + +static void dfu_target(uint8_t img_idx, uint16_t addr) +{ + if (dfu_tx.target_cnt == ARRAY_SIZE(dfu_tx.targets)) { + LOG_ERR("No room."); + return; + } + + for (int i = 0; i < dfu_tx.target_cnt; i++) { + if (dfu_tx.targets[i].blob.addr == addr) { + LOG_ERR("Target 0x%04x already exists", addr); + return; + } + } + + dfu_tx.targets[dfu_tx.target_cnt].blob.addr = addr; + dfu_tx.targets[dfu_tx.target_cnt].img_idx = img_idx; + sys_slist_append(&dfu_tx.inputs.targets, + &dfu_tx.targets[dfu_tx.target_cnt].blob.n); + dfu_tx.target_cnt++; + + LOG_DBG("Added target 0x%04x", addr); +} +static void dfu_slot_add(size_t size, uint8_t *fwid, size_t fwid_len, + uint8_t *metadata, size_t metadata_len) +{ + struct bt_mesh_dfu_slot *slot; + int err; + + slot = bt_mesh_dfu_slot_reserve(); + err = bt_mesh_dfu_slot_info_set(slot, size, metadata, metadata_len); + if (err) { + LOG_ERR("Failed to set slot info: %d", err); + return; + } + + err = bt_mesh_dfu_slot_fwid_set(slot, fwid, fwid_len); + if (err) { + LOG_ERR("Failed to set slot fwid: %d", err); + return; + } + + bt_mesh_dfu_slot_commit(slot); + if (err) { + LOG_ERR("Failed to commit slot: %d", err); + return; + } + + LOG_DBG("Slot added."); +} +static enum bt_mesh_dfu_iter dfu_img_cb(struct bt_mesh_dfu_cli *cli, + struct bt_mesh_msg_ctx *ctx, + uint8_t idx, uint8_t total, + const struct bt_mesh_dfu_img *img, + void *cb_data) +{ + char fwid[2 * CONFIG_BT_MESH_DFU_FWID_MAXLEN + 1]; + size_t len; + + idx = 0xff; + + if (img->fwid_len <= sizeof(fwid)) { + len = bin2hex(img->fwid, img->fwid_len, fwid, sizeof(fwid)); + } else { + LOG_ERR("FWID is too big"); + return BT_MESH_DFU_ITER_STOP; + } + + fwid[len] = '\0'; + + LOG_DBG("Image %u:", idx); + LOG_DBG("\tFWID: "); + if (img->uri) { + LOG_DBG("\tURI: "); + } + + return BT_MESH_DFU_ITER_CONTINUE; +} + +static uint8_t dfu_info_get(const void *cmd, uint16_t cmd_len, + void *rsp, uint16_t *rsp_len) +{ + const struct btp_mmdl_dfu_info_get_cmd *cp = cmd; + struct model_data *model_bound; + struct bt_mesh_msg_ctx ctx = { + .net_idx = net.net_idx, + .send_ttl = BT_MESH_TTL_DEFAULT, + }; + uint8_t max_count; + int err = 0; + + LOG_DBG(""); + + model_bound = lookup_model_bound(BT_MESH_MODEL_ID_DFU_CLI); + if (!model_bound) { + LOG_ERR("Model not found"); + return BTP_STATUS_FAILED; + } + ctx.addr = model_bound->addr; + ctx.app_idx = model_bound->appkey_idx; + + max_count = cp->limit; + + err = bt_mesh_dfu_cli_imgs_get(&dfd_srv.dfu, &ctx, dfu_img_cb, NULL, + max_count); + if (err) { + return BTP_STATUS_FAILED; + } + + return BTP_STATUS_SUCCESS; +} + +static uint8_t dfu_update_metadata_check(const void *cmd, uint16_t cmd_len, + void *rsp, uint16_t *rsp_len) +{ + const struct btp_mmdl_dfu_metadata_check_cmd *cp = cmd; + struct btp_mmdl_dfu_metadata_check_rp *rp = rsp; + const struct bt_mesh_dfu_slot *slot; + struct model_data *model_bound; + struct bt_mesh_msg_ctx ctx = { + .net_idx = net.net_idx, + .send_ttl = BT_MESH_TTL_DEFAULT, + }; + struct bt_mesh_dfu_metadata_status rsp_data; + uint8_t img_idx, slot_idx; + size_t size; + size_t fwid_len; + size_t metadata_len; + uint8_t fwid[CONFIG_BT_MESH_DFU_FWID_MAXLEN]; + uint8_t metadata[CONFIG_BT_MESH_DFU_METADATA_MAXLEN]; + int err; + + LOG_DBG(""); + + model_bound = lookup_model_bound(BT_MESH_MODEL_ID_DFU_CLI); + if (!model_bound) { + LOG_ERR("Model not found"); + return BTP_STATUS_FAILED; + } + + ctx.addr = model_bound->addr; + ctx.app_idx = model_bound->appkey_idx; + img_idx = cp->index; + slot_idx = cp->slot_idx; + size = cp->slot_size; + fwid_len = cp->fwid_len; + metadata_len = cp->metadata_len; + + if ((metadata_len > 0) && + (metadata_len < CONFIG_BT_MESH_DFU_METADATA_MAXLEN)) { + memcpy(&metadata, cp->data, metadata_len); + } + + dfu_slot_add(size, fwid, fwid_len, metadata, metadata_len); + + slot = bt_mesh_dfu_slot_at(slot_idx); + if (!slot) { + LOG_ERR("No image in slot %u", slot_idx); + return BTP_STATUS_FAILED; + } + + err = bt_mesh_dfu_cli_metadata_check(&dfd_srv.dfu, &ctx, img_idx, slot, + &rsp_data); + + if (err) { + LOG_ERR("ERR %d", err); + return BTP_STATUS_FAILED; + } + + rp->idx = rsp_data.idx; + rp->status = rsp_data.status; + rp->effect = rsp_data.effect; + + *rsp_len = sizeof(struct btp_mmdl_dfu_metadata_check_rp); + + return BTP_STATUS_SUCCESS; +} + +static uint8_t dfu_firmware_update_get(const void *cmd, uint16_t cmd_len, + void *rsp, uint16_t *rsp_len) +{ + struct model_data *model_bound; + struct bt_mesh_msg_ctx ctx = { + .net_idx = net.net_idx, + .send_ttl = BT_MESH_TTL_DEFAULT, + }; + struct bt_mesh_dfu_target_status rsp_data; + struct btp_mmdl_dfu_firmware_update_rp *rp = rsp; + int err; + + LOG_DBG(""); + + model_bound = lookup_model_bound(BT_MESH_MODEL_ID_DFU_CLI); + if (!model_bound) { + LOG_ERR("Model not found"); + return BTP_STATUS_FAILED; + } + + ctx.addr = model_bound->addr; + ctx.app_idx = model_bound->appkey_idx; + + err = bt_mesh_dfu_cli_status_get(&dfd_srv.dfu, &ctx, &rsp_data); + if (err) { + LOG_ERR("err %d", err); + return BTP_STATUS_FAILED; + } + + rp->status = rsp_data.status; + *rsp_len = sizeof(struct btp_mmdl_dfu_firmware_update_rp); + return BTP_STATUS_SUCCESS; +} + +static uint8_t dfu_firmware_update_cancel(const void *cmd, uint16_t cmd_len, + void *rsp, uint16_t *rsp_len) +{ + struct model_data *model_bound; + struct bt_mesh_msg_ctx ctx = { + .net_idx = net.net_idx, + .send_ttl = BT_MESH_TTL_DEFAULT, + }; + int err; + + LOG_DBG(""); + + model_bound = lookup_model_bound(BT_MESH_MODEL_ID_DFU_CLI); + if (!model_bound) { + LOG_ERR("Model not found"); + return BTP_STATUS_FAILED; + } + + ctx.addr = model_bound->addr; + ctx.app_idx = model_bound->appkey_idx; + + err = bt_mesh_dfu_cli_cancel(&dfd_srv.dfu, &ctx); + if (err) { + LOG_ERR("err %d", err); + return BTP_STATUS_FAILED; + } + + return BTP_STATUS_SUCCESS; +} + +static uint8_t dfu_firmware_update_start(const void *cmd, uint16_t cmd_len, + void *rsp, uint16_t *rsp_len) +{ + const struct btp_mmdl_dfu_firmware_update_cmd *cp = cmd; + struct model_data *model_bound; + struct bt_mesh_dfu_cli_xfer xfer; + uint8_t addr_cnt; + uint16_t addr = BT_MESH_ADDR_UNASSIGNED; + uint8_t slot_idx; + size_t size; + size_t fwid_len; + size_t metadata_len; + uint8_t fwid[CONFIG_BT_MESH_DFU_FWID_MAXLEN]; + uint8_t metadata[CONFIG_BT_MESH_DFU_METADATA_MAXLEN]; + int err = 0; + int i = 0; + + LOG_DBG(""); + + model_bound = lookup_model_bound(BT_MESH_MODEL_ID_DFU_CLI); + if (!model_bound) { + LOG_ERR("Model not found"); + return BTP_STATUS_FAILED; + } + + struct bt_mesh_dfu_cli_xfer_blob_params blob = { + .block_size_log = cp->block_size, + .chunk_size = cp->chunk_size, + }; + + addr_cnt = cp->addr_cnt; + slot_idx = cp->slot_idx; + size = cp->slot_size; + fwid_len = cp->fwid_len; + metadata_len = cp->metadata_len; + xfer.mode = BT_MESH_BLOB_XFER_MODE_PUSH; + xfer.blob_params = &blob; + + if ((metadata_len > 0) && + (metadata_len < CONFIG_BT_MESH_DFU_METADATA_MAXLEN)) { + memcpy(&metadata, cp->data, metadata_len); + } + + bt_mesh_dfu_slot_del_all(); + + dfu_slot_add(size, fwid, fwid_len, metadata, metadata_len); + + xfer.slot = bt_mesh_dfu_slot_at(slot_idx); + if (!xfer.slot) { + LOG_ERR("No image in slot %u", slot_idx); + return BTP_STATUS_FAILED; + } + + for (i = 0; i < addr_cnt; i++) { + addr = cp->data[metadata_len + 1 + i * sizeof(uint16_t)] | + (cp->data[metadata_len + i * sizeof(uint16_t)] << 8); + dfu_target(slot_idx, addr); + } + + dfu_tx_prepare(); + + if (!dfu_tx.target_cnt) { + LOG_ERR("No targets."); + return BTP_STATUS_FAILED; + } + + if (addr_cnt > 1) { + dfu_tx.inputs.group = BT_MESH_ADDR_UNASSIGNED; + } else { + dfu_tx.inputs.group = addr; + } + + dfu_tx.inputs.app_idx = model_bound->appkey_idx; + dfu_tx.inputs.ttl = BT_MESH_TTL_DEFAULT; + + err = bt_mesh_dfu_cli_send(&dfd_srv.dfu, &dfu_tx.inputs, &dummy_blob_io, &xfer); + + if (err) { + LOG_ERR("err %d", err); + return BTP_STATUS_FAILED; + } + + return BTP_STATUS_SUCCESS; +} + +static uint8_t dfu_firmware_update_apply(const void *cmd, uint16_t cmd_len, + void *rsp, uint16_t *rsp_len) +{ + struct model_data *model_bound; + int err; + + LOG_DBG(""); + + model_bound = lookup_model_bound(BT_MESH_MODEL_ID_DFU_CLI); + if (!model_bound) { + LOG_ERR("Model not found"); + return BTP_STATUS_FAILED; + } + + err = bt_mesh_dfu_cli_apply(&dfd_srv.dfu); + if (err) { + LOG_ERR("err %d", err); + return BTP_STATUS_FAILED; + } + + return BTP_STATUS_SUCCESS; +} +#endif + +#if defined(CONFIG_BT_MESH_BLOB_CLI) && !defined(CONFIG_BT_MESH_DFD_SRV) +static void blob_cli_inputs_prepare(uint16_t group, uint16_t app_idx) +{ + int i; + + blob_cli_xfer.inputs.ttl = BT_MESH_TTL_DEFAULT; + blob_cli_xfer.inputs.group = group; + blob_cli_xfer.inputs.app_idx = app_idx; + sys_slist_init(&blob_cli_xfer.inputs.targets); + + for (i = 0; i < blob_cli_xfer.target_count; ++i) { + /* Reset target context. */ + uint16_t addr = blob_cli_xfer.targets[i].addr; + + memset(&blob_cli_xfer.targets[i], 0, + sizeof(struct bt_mesh_blob_target)); + memset(&blob_cli_xfer.pull[i], 0, + sizeof(struct bt_mesh_blob_target_pull)); + blob_cli_xfer.targets[i].addr = addr; + blob_cli_xfer.targets[i].pull = &blob_cli_xfer.pull[i]; + + sys_slist_append(&blob_cli_xfer.inputs.targets, + &blob_cli_xfer.targets[i].n); + } +} + +static int cmd_blob_target(uint16_t addr) +{ + struct bt_mesh_blob_target *t; + + if (blob_cli_xfer.target_count == ARRAY_SIZE(blob_cli_xfer.targets)) { + LOG_ERR("No more room"); + return 0; + } + + t = &blob_cli_xfer.targets[blob_cli_xfer.target_count]; + + t->addr = addr; + + LOG_DBG("Added target 0x%04x", t->addr); + + blob_cli_xfer.target_count++; + return 0; +} + +static uint8_t blob_info_get(const void *cmd, uint16_t cmd_len, + void *rsp, uint16_t *rsp_len) +{ + const struct btp_mmdl_blob_info_get_cmd *cp = cmd; + struct model_data *model_bound; + uint16_t addr = BT_MESH_ADDR_UNASSIGNED; + uint16_t group = BT_MESH_ADDR_UNASSIGNED; + int err; + + LOG_DBG(""); + + model_bound = lookup_model_bound(BT_MESH_MODEL_ID_BLOB_CLI); + if (!model_bound) { + LOG_ERR("Model not found"); + return BTP_STATUS_FAILED; + } + + for (int i = 0; i < cp->addr_cnt; i++) { + addr = cp->addr[1 + i * sizeof(uint16_t)] | + (cp->addr[i * sizeof(uint16_t)] << 8); + err = cmd_blob_target(addr); + if (err) { + LOG_ERR("err target %d", err); + return BTP_STATUS_FAILED; + } + } + + if (cp->addr_cnt > 1) { + group = BT_MESH_ADDR_UNASSIGNED; + } else { + group = addr; + } + + if (!blob_cli_xfer.target_count) { + LOG_ERR("Failed: No targets"); + return BTP_STATUS_FAILED; + } + + blob_cli_inputs_prepare(group, model_bound->appkey_idx); + + err = bt_mesh_blob_cli_caps_get(&blob_cli, &blob_cli_xfer.inputs); + + if (err) { + return BTP_STATUS_FAILED; + } + + return BTP_STATUS_SUCCESS; +} + +static uint8_t blob_transfer_start(const void *cmd, uint16_t cmd_len, + void *rsp, uint16_t *rsp_len) +{ + const struct btp_mmdl_blob_transfer_start_cmd *cp = cmd; + struct model_data *model_bound; + int err = 0; + + LOG_DBG(""); + + model_bound = lookup_model_bound(BT_MESH_MODEL_ID_BLOB_CLI); + if (!model_bound) { + LOG_ERR("Model not found"); + return BTP_STATUS_FAILED; + } + + if (!blob_cli_xfer.target_count) { + LOG_ERR("Failed: No targets"); + return BTP_STATUS_FAILED; + } + blob_cli_xfer.xfer.id = cp->id; + blob_cli_xfer.xfer.size = cp->size; + blob_cli_xfer.xfer.block_size_log = cp->block_size; + blob_cli_xfer.xfer.chunk_size = cp->chunk_size; + + if (blob_cli.caps.modes) { + blob_cli_xfer.xfer.mode = blob_cli.caps.modes; + } else { + blob_cli_xfer.xfer.mode = BT_MESH_BLOB_XFER_MODE_PUSH; + } + + if (cp->timeout) { + blob_cli_xfer.inputs.timeout_base = cp->timeout; + } + + err = bt_mesh_blob_cli_send(&blob_cli, &blob_cli_xfer.inputs, + &blob_cli_xfer.xfer, &dummy_blob_io); + + if (err) { + return BTP_STATUS_FAILED; + } + + return BTP_STATUS_SUCCESS; +} + +static uint8_t blob_transfer_cancel(const void *cmd, uint16_t cmd_len, + void *rsp, uint16_t *rsp_len) +{ + LOG_DBG(""); + + bt_mesh_blob_cli_cancel(&blob_cli); + + return BTP_STATUS_SUCCESS; +} + +static uint8_t blob_transfer_get(const void *cmd, uint16_t cmd_len, + void *rsp, uint16_t *rsp_len) +{ + struct model_data *model_bound; + uint16_t group; + int err; + + LOG_DBG(""); + + model_bound = lookup_model_bound(BT_MESH_MODEL_ID_BLOB_CLI); + if (!model_bound) { + LOG_ERR("Model not found"); + return BTP_STATUS_FAILED; + } + + group = model_bound->addr; + + err = cmd_blob_target(group); + if (err) { + LOG_ERR("err target %d", err); + return BTP_STATUS_FAILED; + } + + if (!blob_cli_xfer.target_count) { + LOG_ERR("Failed: No targets"); + return BTP_STATUS_FAILED; + } + + blob_cli_inputs_prepare(group, model_bound->appkey_idx); + + err = bt_mesh_blob_cli_xfer_progress_get(&blob_cli, &blob_cli_xfer.inputs); + + if (err) { + LOG_ERR("ERR %d", err); + return BTP_STATUS_FAILED; + } + + return BTP_STATUS_SUCCESS; +} +#endif /* CONFIG_BT_MESH_BLOB_CLI */ + +#if defined(CONFIG_BT_MESH_BLOB_SRV) +static uint8_t blob_srv_recv(const void *cmd, uint16_t cmd_len, + void *rsp, uint16_t *rsp_len) +{ + const struct btp_mmdl_blob_srv_recv_cmd *cp = cmd; + struct model_data *model_bound; + int err; + +#if defined(CONFIG_BT_MESH_DFU_SRV) + struct bt_mesh_blob_srv *srv = &dfu_srv.blob; +#elif defined(CONFIG_BT_MESH_DFD_SRV) + struct bt_mesh_blob_srv *srv = &dfd_srv.upload.blob; +#endif + + model_bound = lookup_model_bound(BT_MESH_MODEL_ID_BLOB_SRV); + if (!model_bound) { + LOG_ERR("Model not found"); + return BTP_STATUS_FAILED; + } + + uint16_t timeout_base; + uint64_t id; + + LOG_DBG(""); + + id = cp->id; + timeout_base = cp->timeout; + + err = bt_mesh_blob_srv_recv(srv, id, &dummy_blob_io, BT_MESH_TTL_MAX, + timeout_base); + + if (err) { + LOG_ERR("ERR %d", err); + return BTP_STATUS_FAILED; + } + + return BTP_STATUS_SUCCESS; +} + +static uint8_t blob_srv_cancel(const void *cmd, uint16_t cmd_len, + void *rsp, uint16_t *rsp_len) +{ + struct model_data *model_bound; + int err; + +#if defined(CONFIG_BT_MESH_DFU_SRV) + struct bt_mesh_blob_srv *srv = &dfu_srv.blob; +#elif defined(CONFIG_BT_MESH_DFD_SRV) + struct bt_mesh_blob_srv *srv = &dfd_srv.upload.blob; +#endif + + model_bound = lookup_model_bound(BT_MESH_MODEL_ID_BLOB_SRV); + if (!model_bound) { + LOG_ERR("Model not found"); + return BTP_STATUS_FAILED; + } + + LOG_DBG(""); + + err = bt_mesh_blob_srv_cancel(srv); + + if (err) { + LOG_ERR("ERR %d", err); + return BTP_STATUS_FAILED; + } + + return BTP_STATUS_SUCCESS; +} +#endif + +static const struct btp_handler handlers[] = { + { + .opcode = BTP_MESH_READ_SUPPORTED_COMMANDS, + .index = BTP_INDEX_NONE, + .expect_len = 0, + .func = supported_commands, + }, + { + .opcode = BTP_MESH_CONFIG_PROVISIONING, + .expect_len = BTP_HANDLER_LENGTH_VARIABLE, + .func = config_prov, + }, + { + .opcode = BTP_MESH_PROVISION_NODE, + .expect_len = BTP_HANDLER_LENGTH_VARIABLE, + .func = provision_node, + }, + { + .opcode = BTP_MESH_INIT, + .expect_len = 0, + .func = init, + }, + { + .opcode = BTP_MESH_RESET, + .expect_len = 0, + .func = reset, + }, + { + .opcode = BTP_MESH_INPUT_NUMBER, + .expect_len = sizeof(struct btp_mesh_input_number_cmd), + .func = input_number, + }, + { + .opcode = BTP_MESH_INPUT_STRING, + .expect_len = BTP_HANDLER_LENGTH_VARIABLE, + .func = input_string, + }, + { + .opcode = BTP_MESH_IVU_TEST_MODE, + .expect_len = sizeof(struct btp_mesh_ivu_test_mode_cmd), + .func = ivu_test_mode, + }, + { + .opcode = BTP_MESH_IVU_TOGGLE_STATE, + .expect_len = 0, + .func = ivu_toggle_state, + }, + { + .opcode = BTP_MESH_LPN, + .expect_len = sizeof(struct btp_mesh_lpn_set_cmd), + .func = lpn, + }, + { + .opcode = BTP_MESH_LPN_POLL, + .expect_len = 0, + .func = lpn_poll, + }, + { + .opcode = BTP_MESH_NET_SEND, + .expect_len = BTP_HANDLER_LENGTH_VARIABLE, + .func = net_send, + }, + { + .opcode = BTP_MESH_HEALTH_GENERATE_FAULTS, + .expect_len = 0, + .func = health_generate_faults, + }, + { + .opcode = BTP_MESH_HEALTH_CLEAR_FAULTS, + .expect_len = 0, + .func = health_clear_faults, + }, + { + .opcode = BTP_MESH_MODEL_SEND, + .expect_len = BTP_HANDLER_LENGTH_VARIABLE, + .func = model_send, + }, + { + .opcode = BTP_MESH_COMP_DATA_GET, + .expect_len = sizeof(struct btp_mesh_comp_data_get_cmd), + .func = composition_data_get, + }, + { + .opcode = BTP_MESH_CFG_BEACON_GET, + .expect_len = sizeof(struct btp_mesh_cfg_beacon_get_cmd), + .func = config_beacon_get, + }, + { + .opcode = BTP_MESH_CFG_BEACON_SET, + .expect_len = sizeof(struct btp_mesh_cfg_beacon_set_cmd), + .func = config_beacon_set, + }, + { + .opcode = BTP_MESH_CFG_DEFAULT_TTL_GET, + .expect_len = sizeof(struct btp_mesh_cfg_default_ttl_get_cmd), + .func = config_default_ttl_get, + }, + { + .opcode = BTP_MESH_CFG_DEFAULT_TTL_SET, + .expect_len = sizeof(struct btp_mesh_cfg_default_ttl_set_cmd), + .func = config_default_ttl_set, + }, + { + .opcode = BTP_MESH_CFG_GATT_PROXY_GET, + .expect_len = sizeof(struct btp_mesh_cfg_gatt_proxy_get_cmd), + .func = config_gatt_proxy_get, + }, + { + .opcode = BTP_MESH_CFG_GATT_PROXY_SET, + .expect_len = sizeof(struct btp_mesh_cfg_gatt_proxy_set_cmd), + .func = config_gatt_proxy_set, + }, + { + .opcode = BTP_MESH_CFG_FRIEND_GET, + .expect_len = sizeof(struct btp_mesh_cfg_friend_get_cmd), + .func = config_friend_get, + }, + { + .opcode = BTP_MESH_CFG_FRIEND_SET, + .expect_len = sizeof(struct btp_mesh_cfg_friend_set_cmd), + .func = config_friend_set, + }, + { + .opcode = BTP_MESH_CFG_RELAY_GET, + .expect_len = sizeof(struct btp_mesh_cfg_relay_get_cmd), + .func = config_relay_get, + }, + { + .opcode = BTP_MESH_CFG_RELAY_SET, + .expect_len = sizeof(struct btp_mesh_cfg_relay_set_cmd), + .func = config_relay_set, + }, + { + .opcode = BTP_MESH_CFG_MODEL_PUB_GET, + .expect_len = sizeof(struct btp_mesh_cfg_model_pub_get_cmd), + .func = config_mod_pub_get, + }, + { + .opcode = BTP_MESH_CFG_MODEL_PUB_SET, .expect_len = sizeof(struct btp_mesh_cfg_model_pub_set_cmd), .func = config_mod_pub_set, }, @@ -3577,6 +4485,83 @@ static const struct btp_handler handlers[] = { }, }; + +static const struct btp_handler mdl_handlers[] = { +#if defined(CONFIG_BT_MESH_DFD_SRV) + { + .opcode = BTP_MMDL_DFU_INFO_GET, + .expect_len = sizeof(struct btp_mmdl_dfu_info_get_cmd), + .func = dfu_info_get, + }, + { + .opcode = BTP_MMDL_DFU_UPDATE_METADATA_CHECK, + .expect_len = BTP_HANDLER_LENGTH_VARIABLE, + .func = dfu_update_metadata_check, + }, + { + .opcode = BTP_MMDL_DFU_FIRMWARE_UPDATE_GET, + .expect_len = 0, + .func = dfu_firmware_update_get, + }, + { + .opcode = BTP_MMDL_DFU_FIRMWARE_UPDATE_CANCEL, + .expect_len = 0, + .func = dfu_firmware_update_cancel, + }, + { + .opcode = BTP_MMDL_DFU_FIRMWARE_UPDATE_START, + .expect_len = BTP_HANDLER_LENGTH_VARIABLE, + .func = dfu_firmware_update_start, + }, + { + .opcode = BTP_MMDL_DFU_FIRMWARE_UPDATE_APPLY, + .expect_len = 0, + .func = dfu_firmware_update_apply, + }, +#endif +#if defined(CONFIG_BT_MESH_BLOB_CLI) && !defined(CONFIG_BT_MESH_DFD_SRV) + { + .opcode = BTP_MMDL_BLOB_INFO_GET, + .expect_len = BTP_HANDLER_LENGTH_VARIABLE, + .func = blob_info_get, + }, + { + .opcode = BTP_MMDL_BLOB_TRANSFER_START, + .expect_len = sizeof(struct btp_mmdl_blob_transfer_start_cmd), + .func = blob_transfer_start, + }, + { + .opcode = BTP_MMDL_BLOB_TRANSFER_CANCEL, + .expect_len = 0, + .func = blob_transfer_cancel, + }, + { + .opcode = BTP_MMDL_BLOB_TRANSFER_GET, + .expect_len = 0, + .func = blob_transfer_get, + }, +#endif +#if defined(CONFIG_BT_MESH_BLOB_SRV) + { + .opcode = BTP_MMDL_BLOB_SRV_RECV, + .expect_len = sizeof(struct btp_mmdl_blob_srv_recv_cmd), + .func = blob_srv_recv + }, + { + .opcode = BTP_MMDL_BLOB_SRV_CANCEL, + .expect_len = 0, + .func = blob_srv_cancel + }, +#endif +#if defined(CONFIG_BT_MESH_DFU_SRV) + { + .opcode = BTP_MMDL_DFU_SRV_APPLY, + .expect_len = 0, + .func = dfu_srv_apply + }, +#endif +}; + void net_recv_ev(uint8_t ttl, uint8_t ctl, uint16_t src, uint16_t dst, const void *payload, size_t payload_len) { @@ -3785,3 +4770,15 @@ uint8_t tester_unregister_mesh(void) { return BTP_STATUS_SUCCESS; } + +uint8_t tester_init_mmdl(void) +{ + tester_register_command_handlers(BTP_SERVICE_ID_MESH_MDL, mdl_handlers, + ARRAY_SIZE(mdl_handlers)); + return BTP_STATUS_SUCCESS; +} + +uint8_t tester_unregister_mmdl(void) +{ + return BTP_STATUS_SUCCESS; +} From 14e69effb12eee44178feadc4d8e9d0cac0b9cbd Mon Sep 17 00:00:00 2001 From: Michal Narajowski Date: Mon, 13 Jun 2022 14:09:32 +0200 Subject: [PATCH 160/421] [nrf fromtree] tests: bluetooth: tester: Add Opcodes Aggregator support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add entry for client and server in composition data. - Add Client commands to aggregate and send messages. MESH/SR/AGG/BV-02-C requires more key slots. Signed-off-by: Michal Narajowski (cherry picked from commit 1e5eeb83f41ae2c0dc50062ccfd921101cadaa1b) Signed-off-by: Alperen Şener (cherry picked from commit 05d9c3c2840602ba3c276986e3294482acbeb20a) --- tests/bluetooth/tester/overlay-mesh.conf | 5 + tests/bluetooth/tester/src/btp/btp_mesh.h | 10 ++ tests/bluetooth/tester/src/btp_mesh.c | 115 +++++++++++++++++++--- 3 files changed, 119 insertions(+), 11 deletions(-) diff --git a/tests/bluetooth/tester/overlay-mesh.conf b/tests/bluetooth/tester/overlay-mesh.conf index 3352e36f3a4..60f809f77e5 100644 --- a/tests/bluetooth/tester/overlay-mesh.conf +++ b/tests/bluetooth/tester/overlay-mesh.conf @@ -9,6 +9,11 @@ CONFIG_BT_MESH_GATT_PROXY=y CONFIG_BT_MESH_LABEL_COUNT=2 CONFIG_BT_MESH_SUBNET_COUNT=2 CONFIG_BT_MESH_MODEL_GROUP_COUNT=2 +CONFIG_BT_MESH_OP_AGG_CLI=y +CONFIG_BT_MESH_OP_AGG_SRV=y +# PTS requires more key slots. +# First one is implicitly taken by Device Key. +CONFIG_BT_MESH_MODEL_KEY_COUNT=3 CONFIG_BT_MESH_APP_KEY_COUNT=4 CONFIG_BT_MESH_IV_UPDATE_TEST=y CONFIG_BT_MESH_CFG_CLI=y diff --git a/tests/bluetooth/tester/src/btp/btp_mesh.h b/tests/bluetooth/tester/src/btp/btp_mesh.h index 66a86bbb128..63fb2adcf12 100644 --- a/tests/bluetooth/tester/src/btp/btp_mesh.h +++ b/tests/bluetooth/tester/src/btp/btp_mesh.h @@ -835,6 +835,16 @@ struct btp_mesh_models_metadata_get_rp { uint8_t data[0]; } __packed; +#define BTP_MESH_OPCODES_AGGREGATOR_INIT 0x55 +struct btp_mesh_opcodes_aggregator_init_cmd { + uint16_t net_idx; + uint16_t app_idx; + uint16_t dst; + uint16_t elem_addr; +} __packed; + +#define BTP_MESH_OPCODES_AGGREGATOR_SEND 0x56 + #define BTP_MESH_COMP_CHANGE_PREPARE 0x57 #define BTP_MESH_SET_COMP_ALT 0x58 diff --git a/tests/bluetooth/tester/src/btp_mesh.c b/tests/bluetooth/tester/src/btp_mesh.c index 8c637320a11..4f3d181fd1d 100644 --- a/tests/bluetooth/tester/src/btp_mesh.c +++ b/tests/bluetooth/tester/src/btp_mesh.c @@ -634,6 +634,12 @@ static struct bt_mesh_model root_models[] = { #if defined(CONFIG_BT_MESH_LARGE_COMP_DATA_CLI) BT_MESH_MODEL_LARGE_COMP_DATA_CLI(&lcd_cli), #endif +#if defined(CONFIG_BT_MESH_OP_AGG_SRV) + BT_MESH_MODEL_OP_AGG_SRV, +#endif +#if defined(CONFIG_BT_MESH_OP_AGG_CLI) + BT_MESH_MODEL_OP_AGG_CLI, +#endif #if defined(CONFIG_BT_MESH_RPR_CLI) BT_MESH_MODEL_RPR_CLI(&rpr_cli), #endif @@ -2491,6 +2497,8 @@ static uint8_t config_model_app_bind(const void *cmd, uint16_t cmd_len, LOG_DBG(""); + bt_mesh_cfg_cli_timeout_set(5000); + err = bt_mesh_cfg_cli_mod_app_bind(sys_le16_to_cpu(cp->net_idx), sys_le16_to_cpu(cp->address), sys_le16_to_cpu(cp->elem_address), @@ -2934,7 +2942,7 @@ static uint8_t health_fault_clear(const void *cmd, uint16_t cmd_len, .addr = sys_le16_to_cpu(cp->address), .app_idx = sys_le16_to_cpu(cp->app_idx), }; - uint8_t test_id; + uint8_t test_id = 0; size_t fault_count = 16; uint8_t faults[fault_count]; int err; @@ -2944,7 +2952,20 @@ static uint8_t health_fault_clear(const void *cmd, uint16_t cmd_len, if (cp->ack) { err = bt_mesh_health_cli_fault_clear(&health_cli, &ctx, sys_le16_to_cpu(cp->cid), - &test_id, faults, +#if defined(CONFIG_BT_MESH_OP_AGG_CLI) + bt_mesh_op_agg_cli_seq_is_started() ? + NULL : +#endif + &test_id, +#if defined(CONFIG_BT_MESH_OP_AGG_CLI) + bt_mesh_op_agg_cli_seq_is_started() ? + NULL : +#endif + faults, +#if defined(CONFIG_BT_MESH_OP_AGG_CLI) + bt_mesh_op_agg_cli_seq_is_started() ? + NULL : +#endif &fault_count); } else { err = bt_mesh_health_cli_fault_clear_unack(&health_cli, &ctx, @@ -2977,20 +2998,37 @@ static uint8_t health_fault_test(const void *cmd, uint16_t cmd_len, }; size_t fault_count = 16; uint8_t faults[fault_count]; - uint8_t test_id; - uint16_t cid; int err; LOG_DBG(""); - test_id = cp->test_id; - cid = sys_le16_to_cpu(cp->cid); - if (cp->ack) { - err = bt_mesh_health_cli_fault_test(&health_cli, &ctx, cid, test_id, faults, + err = bt_mesh_health_cli_fault_test(&health_cli, &ctx, + sys_le16_to_cpu(cp->cid), +#if defined(CONFIG_BT_MESH_OP_AGG_CLI) + bt_mesh_op_agg_cli_seq_is_started() ? + 0 : +#endif + cp->test_id, +#if defined(CONFIG_BT_MESH_OP_AGG_CLI) + bt_mesh_op_agg_cli_seq_is_started() ? + NULL : +#endif + faults, +#if defined(CONFIG_BT_MESH_OP_AGG_CLI) + bt_mesh_op_agg_cli_seq_is_started() ? + NULL : +#endif &fault_count); +#if defined(CONFIG_BT_MESH_OP_AGG_CLI) + if (bt_mesh_op_agg_cli_seq_is_started()) { + fault_count = 0; + } +#endif } else { - err = bt_mesh_health_cli_fault_test_unack(&health_cli, &ctx, cid, test_id); + err = bt_mesh_health_cli_fault_test_unack(&health_cli, &ctx, + sys_le16_to_cpu(cp->cid), + cp->test_id); } if (err) { @@ -3001,8 +3039,8 @@ static uint8_t health_fault_test(const void *cmd, uint16_t cmd_len, if (cp->ack) { struct btp_mesh_health_fault_test_rp *rp = rsp; - rp->test_id = test_id; - rp->cid = sys_cpu_to_le16(cid); + rp->test_id = cp->test_id; + rp->cid = cp->cid; (void)memcpy(rp->faults, faults, fault_count); *rsp_len = sizeof(*rp) + fault_count; @@ -3051,6 +3089,10 @@ static uint8_t health_period_set(const void *cmd, uint16_t cmd_len, if (cp->ack) { err = bt_mesh_health_cli_period_set(&health_cli, &ctx, cp->divisor, +#if defined(CONFIG_BT_MESH_OP_AGG_CLI) + bt_mesh_op_agg_cli_seq_is_started() ? + NULL : +#endif &updated_divisor); } else { err = bt_mesh_health_cli_period_set_unack(&health_cli, &ctx, cp->divisor); @@ -3112,6 +3154,10 @@ static uint8_t health_attention_set(const void *cmd, uint16_t cmd_len, if (cp->ack) { err = bt_mesh_health_cli_attention_set(&health_cli, &ctx, cp->attention, +#if defined(CONFIG_BT_MESH_OP_AGG_CLI) + bt_mesh_op_agg_cli_seq_is_started() ? + NULL : +#endif &updated_attention); } else { err = bt_mesh_health_cli_attention_set_unack(&health_cli, &ctx, cp->attention); @@ -3133,6 +3179,41 @@ static uint8_t health_attention_set(const void *cmd, uint16_t cmd_len, return BTP_STATUS_SUCCESS; } +#if defined(CONFIG_BT_MESH_OP_AGG_CLI) +static uint8_t opcodes_aggregator_init(const void *cmd, uint16_t cmd_len, + void *rsp, uint16_t *rsp_len) +{ + const struct btp_mesh_opcodes_aggregator_init_cmd *cp = cmd; + int err; + + LOG_DBG(""); + + err = bt_mesh_op_agg_cli_seq_start(cp->net_idx, cp->app_idx, cp->dst, cp->elem_addr); + if (err) { + LOG_ERR("Failed to init Opcodes Aggregator Context (err %d)", err); + return BTP_STATUS_FAILED; + } + + return BTP_STATUS_SUCCESS; +} + +static uint8_t opcodes_aggregator_send(const void *cmd, uint16_t cmd_len, + void *rsp, uint16_t *rsp_len) +{ + int err; + + LOG_DBG(""); + + err = bt_mesh_op_agg_cli_seq_send(); + if (err) { + LOG_ERR("Failed to send Opcodes Aggregator message (err %d)", err); + return BTP_STATUS_FAILED; + } + + return BTP_STATUS_SUCCESS; +} +#endif + #if defined(CONFIG_BT_MESH_RPR_CLI) static uint8_t rpr_scan_start(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len) @@ -4426,6 +4507,18 @@ static const struct btp_handler handlers[] = { .expect_len = sizeof(struct btp_mesh_models_metadata_get_cmd), .func = models_metadata_get }, +#endif +#if defined(CONFIG_BT_MESH_OP_AGG_CLI) + { + .opcode = BTP_MESH_OPCODES_AGGREGATOR_INIT, + .expect_len = sizeof(struct btp_mesh_opcodes_aggregator_init_cmd), + .func = opcodes_aggregator_init + }, + { + .opcode = BTP_MESH_OPCODES_AGGREGATOR_SEND, + .expect_len = 0, + .func = opcodes_aggregator_send + }, #endif { .opcode = BTP_MESH_COMP_CHANGE_PREPARE, From c77879087eaaae5206ba1274c86636d903ae119c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Thu, 23 Jun 2022 10:32:50 +0200 Subject: [PATCH 161/421] [nrf fromtree] Tests: Bluetooth: Tester: Add BTP command to enable Private NID MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This allows to advertise beacons with Private Node Identity on demand, like was available for regular Node Identity. Signed-off-by: Krzysztof Kopyściński (cherry picked from commit 7b69f8faf0ee6457702fd6a37d020ceec8f9f9bc) Signed-off-by: Alperen Şener (cherry picked from commit f9c487715816b076127acaf0a98a5f37a9b490c5) --- tests/bluetooth/tester/overlay-mesh.conf | 3 + tests/bluetooth/tester/src/btp/btp_mesh.h | 38 +++++ tests/bluetooth/tester/src/btp_mesh.c | 177 ++++++++++++++++++++++ 3 files changed, 218 insertions(+) diff --git a/tests/bluetooth/tester/overlay-mesh.conf b/tests/bluetooth/tester/overlay-mesh.conf index 60f809f77e5..95a61769a1a 100644 --- a/tests/bluetooth/tester/overlay-mesh.conf +++ b/tests/bluetooth/tester/overlay-mesh.conf @@ -43,5 +43,8 @@ CONFIG_BT_MESH_BLOB_SRV=y CONFIG_BT_MESH_DFU_SRV=y CONFIG_BT_MESH_DFD_SRV=y CONFIG_BT_MESH_DFU_SLOT_CNT=2 +CONFIG_BT_MESH_PRIV_BEACONS=y +CONFIG_BT_MESH_PRIV_BEACON_SRV=y +CONFIG_BT_MESH_PRIV_BEACON_CLI=y CONFIG_SETTINGS=y diff --git a/tests/bluetooth/tester/src/btp/btp_mesh.h b/tests/bluetooth/tester/src/btp/btp_mesh.h index 63fb2adcf12..e93c2ceeb3d 100644 --- a/tests/bluetooth/tester/src/btp/btp_mesh.h +++ b/tests/bluetooth/tester/src/btp/btp_mesh.h @@ -971,6 +971,44 @@ struct btp_mmdl_blob_transfer_start_cmd { #define BTP_MMDL_DFU_FIRMWARE_UPDATE_APPLY 0x6A #define BTP_MMDL_DFU_SRV_APPLY 0x6B +#define BTP_MESH_PRIV_BEACON_GET 0x6c +struct btp_priv_beacon_get_cmd { + uint16_t dst; +} __packed; + +#define BTP_MESH_PRIV_BEACON_SET 0x6d +struct btp_priv_beacon_set_cmd { + uint16_t dst; + uint8_t enabled; + uint8_t rand_interval; +} __packed; + +#define BTP_MESH_PRIV_GATT_PROXY_GET 0x6e +struct btp_priv_gatt_proxy_get_cmd { + uint16_t dst; +} __packed; + +#define BTP_MESH_PRIV_GATT_PROXY_SET 0x6f +struct btp_priv_gatt_proxy_set_cmd { + uint16_t dst; + uint8_t state; +} __packed; + +#define BTP_MESH_PRIV_NODE_ID_GET 0x70 +struct btp_priv_node_id_get_cmd { + uint16_t dst; + uint16_t key_net_idx; +} __packed; + +#define BTP_MESH_PRIV_NODE_ID_SET 0x71 +struct btp_priv_node_id_set_cmd { + uint16_t dst; + uint16_t net_idx; + uint8_t state; +} __packed; + +#define BTP_MESH_PROXY_PRIVATE_IDENTITY 0x72 + /* events */ #define BTP_MESH_EV_OUT_NUMBER_ACTION 0x80 struct btp_mesh_out_number_action_ev { diff --git a/tests/bluetooth/tester/src/btp_mesh.c b/tests/bluetooth/tester/src/btp_mesh.c index 4f3d181fd1d..5a7b4bb5fd7 100644 --- a/tests/bluetooth/tester/src/btp_mesh.c +++ b/tests/bluetooth/tester/src/btp_mesh.c @@ -617,6 +617,139 @@ static uint8_t dfu_srv_apply(const void *cmd, uint16_t cmd_len, } #endif +#ifdef CONFIG_BT_MESH_PRIV_BEACON_CLI +static struct bt_mesh_priv_beacon_cli priv_beacon_cli; + +static uint8_t priv_beacon_get(const void *cmd, uint16_t cmd_len, + void *rsp, uint16_t *rsp_len) +{ + const struct btp_priv_beacon_get_cmd *cp = cmd; + + struct bt_mesh_priv_beacon val; + int err; + + err = bt_mesh_priv_beacon_cli_get(net.net_idx, cp->dst, &val); + if (err) { + LOG_ERR("Failed to send Private Beacon Get (err %d)", err); + return BTP_STATUS_FAILED; + } + + LOG_DBG("Private Beacon state: %u, %u", val.enabled, val.rand_interval); + return BTP_STATUS_SUCCESS; +} + +static uint8_t priv_beacon_set(const void *cmd, uint16_t cmd_len, + void *rsp, uint16_t *rsp_len) +{ + const struct btp_priv_beacon_set_cmd *cp = cmd; + struct bt_mesh_priv_beacon val; + int err; + + val.enabled = cp->enabled; + val.rand_interval = cp->rand_interval; + + err = bt_mesh_priv_beacon_cli_set(net.net_idx, cp->dst, &val); + if (err) { + LOG_ERR("Failed to send Private Beacon Set (err %d)", err); + return BTP_STATUS_FAILED; + } + + return BTP_STATUS_SUCCESS; +} + +static uint8_t priv_gatt_proxy_get(const void *cmd, uint16_t cmd_len, + void *rsp, uint16_t *rsp_len) +{ + const struct btp_priv_gatt_proxy_get_cmd *cp = cmd; + + uint8_t state; + int err; + + err = bt_mesh_priv_beacon_cli_gatt_proxy_get(net.net_idx, cp->dst, &state); + if (err) { + LOG_ERR("Failed to send Private GATT Proxy Get (err %d)", err); + return BTP_STATUS_FAILED; + } + + LOG_DBG("Private GATT Proxy state: %u", state); + return BTP_STATUS_SUCCESS; +} + +static uint8_t priv_gatt_proxy_set(const void *cmd, uint16_t cmd_len, + void *rsp, uint16_t *rsp_len) +{ + const struct btp_priv_gatt_proxy_set_cmd *cp = cmd; + + uint8_t state; + int err; + + state = cp->state; + + err = bt_mesh_priv_beacon_cli_gatt_proxy_set(net.net_idx, cp->dst, &state); + if (err) { + LOG_ERR("Failed to send Private GATT Proxy Set (err %d)", err); + return BTP_STATUS_FAILED; + } + + return BTP_STATUS_SUCCESS; +} + +static uint8_t priv_node_id_get(const void *cmd, uint16_t cmd_len, + void *rsp, uint16_t *rsp_len) +{ + const struct btp_priv_node_id_get_cmd *cp = cmd; + struct bt_mesh_priv_node_id val; + uint16_t key_net_idx; + int err; + + key_net_idx = cp->key_net_idx; + + err = bt_mesh_priv_beacon_cli_node_id_get(net.net_idx, cp->dst, key_net_idx, &val); + if (err) { + LOG_ERR("Failed to send Private Node Identity Get (err %d)", err); + return BTP_STATUS_FAILED; + } + + LOG_DBG("Private Node Identity state: %u %u %u", val.net_idx, val.state, val.status); + return BTP_STATUS_SUCCESS; +} + +static uint8_t priv_node_id_set(const void *cmd, uint16_t cmd_len, + void *rsp, uint16_t *rsp_len) +{ + const struct btp_priv_node_id_set_cmd *cp = cmd; + struct bt_mesh_priv_node_id val; + int err; + + val.net_idx = cp->net_idx; + val.state = cp->state; + + err = bt_mesh_priv_beacon_cli_node_id_set(net.net_idx, cp->dst, &val); + if (err) { + LOG_ERR("Failed to send Private Node Identity Set (err %d)", err); + return BTP_STATUS_FAILED; + } + + return BTP_STATUS_SUCCESS; +} + +static uint8_t proxy_private_identity_enable(const void *cmd, uint16_t cmd_len, + void *rsp, uint16_t *rsp_len) +{ + int err; + + LOG_DBG(""); + + err = bt_mesh_proxy_private_identity_enable(); + if (err) { + LOG_ERR("Failed to enable proxy private identity (err %d)", err); + return BTP_STATUS_FAILED; + } + + return BTP_STATUS_SUCCESS; +} +#endif + static struct bt_mesh_model root_models[] = { BT_MESH_MODEL_CFG_SRV, BT_MESH_MODEL_CFG_CLI(&cfg_cli), @@ -655,6 +788,12 @@ static struct bt_mesh_model root_models[] = { #if defined(CONFIG_BT_MESH_BLOB_CLI) && !defined(CONFIG_BT_MESH_DFD_SRV) BT_MESH_MODEL_BLOB_CLI(&blob_cli), #endif +#if defined(CONFIG_BT_MESH_PRIV_BEACON_SRV) + BT_MESH_MODEL_PRIV_BEACON_SRV, +#endif +#if defined(CONFIG_BT_MESH_PRIV_BEACON_CLI) + BT_MESH_MODEL_PRIV_BEACON_CLI(&priv_beacon_cli), +#endif }; struct model_data *lookup_model_bound(uint16_t id) { @@ -4576,6 +4715,44 @@ static const struct btp_handler handlers[] = { .expect_len = sizeof(struct btp_rpr_reprov_remote_cmd), .func = rpr_reprov_remote }, +#endif +#if defined(CONFIG_BT_MESH_PRIV_BEACON_CLI) + { + .opcode = BTP_MESH_PRIV_BEACON_GET, + .expect_len = sizeof(struct btp_priv_beacon_get_cmd), + .func = priv_beacon_get + }, + { + .opcode = BTP_MESH_PRIV_BEACON_SET, + .expect_len = sizeof(struct btp_priv_beacon_set_cmd), + .func = priv_beacon_set + }, + { + .opcode = BTP_MESH_PRIV_GATT_PROXY_GET, + .expect_len = sizeof(struct btp_priv_gatt_proxy_get_cmd), + .func = priv_gatt_proxy_get + }, + { + .opcode = BTP_MESH_PRIV_GATT_PROXY_SET, + .expect_len = sizeof(struct btp_priv_gatt_proxy_set_cmd), + .func = priv_gatt_proxy_set + }, + { + .opcode = BTP_MESH_PRIV_NODE_ID_GET, + .expect_len = sizeof(struct btp_priv_node_id_get_cmd), + .func = priv_node_id_get + }, + { + .opcode = BTP_MESH_PRIV_NODE_ID_SET, + .expect_len = sizeof(struct btp_priv_node_id_set_cmd), + .func = priv_node_id_set + }, + { + .opcode = BTP_MESH_PROXY_PRIVATE_IDENTITY, + .expect_len = 0, + .func = proxy_private_identity_enable + }, +#endif }; From d629e26fb5e4ffc8e70de557700d6f98285a9db4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Fri, 9 Sep 2022 11:40:32 +0200 Subject: [PATCH 162/421] [nrf fromtree] tests: Bluetooth: tester: enable Composition Data Page 1 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This allows to tests this page using BTP protocol. Signed-off-by: Krzysztof Kopyściński (cherry picked from commit 26e697bd04ccb702268949490733d93eeab3a303) Signed-off-by: Alperen Şener (cherry picked from commit 56bcf9cdb405ad62f768b51d057d0eb04eb78b8f) --- tests/bluetooth/tester/overlay-mesh.conf | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/bluetooth/tester/overlay-mesh.conf b/tests/bluetooth/tester/overlay-mesh.conf index 95a61769a1a..fe4c9a62fef 100644 --- a/tests/bluetooth/tester/overlay-mesh.conf +++ b/tests/bluetooth/tester/overlay-mesh.conf @@ -46,5 +46,7 @@ CONFIG_BT_MESH_DFU_SLOT_CNT=2 CONFIG_BT_MESH_PRIV_BEACONS=y CONFIG_BT_MESH_PRIV_BEACON_SRV=y CONFIG_BT_MESH_PRIV_BEACON_CLI=y +CONFIG_BT_MESH_MODEL_EXTENSIONS=y +CONFIG_BT_MESH_COMP_PAGE_1=y CONFIG_SETTINGS=y From 5237cdd07078a0064c3808f31d263e07f1d9ee42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Narajowski?= Date: Tue, 31 Jan 2023 14:44:41 +0100 Subject: [PATCH 163/421] [nrf fromtree] tests: Bluetooth: tester: Add Models Metadata Page 128 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add Models Metadata Page 128 support to tester. Signed-off-by: Michal Narajowski Signed-off-by: Pavel Vasilyev (cherry picked from commit 2ad0eaa9ab548336fd37f064315f5427650a8c4f) Signed-off-by: Alperen Şener (cherry picked from commit c724d4f3a6a4d73e2b9ad8629e7fb4cc79dba1c6) --- tests/bluetooth/tester/src/btp_mesh.c | 33 +++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/tests/bluetooth/tester/src/btp_mesh.c b/tests/bluetooth/tester/src/btp_mesh.c index 5a7b4bb5fd7..2c837bfb198 100644 --- a/tests/bluetooth/tester/src/btp_mesh.c +++ b/tests/bluetooth/tester/src/btp_mesh.c @@ -542,8 +542,31 @@ static uint8_t health_tests[] = { BT_MESH_HEALTH_TEST_INFO(COMPANY_ID_NORDIC_SEMI, 3, 0x01, 0x02, 0x03), }; +static uint8_t zero_metadata[100]; + static struct bt_mesh_models_metadata_entry health_srv_meta[] = { BT_MESH_HEALTH_TEST_INFO_METADATA(health_tests), + { + .len = ARRAY_SIZE(zero_metadata), + .id = 0xABCD, + .data = zero_metadata, + }, + BT_MESH_MODELS_METADATA_END, +}; + +static uint8_t health_tests_alt[] = { + BT_MESH_HEALTH_TEST_INFO(COMPANY_ID_LF, 6, 0x11, 0x22, 0x33, 0x44, 0x55, + 0x66), + BT_MESH_HEALTH_TEST_INFO(COMPANY_ID_NORDIC_SEMI, 3, 0x11, 0x22, 0x33), +}; + +static struct bt_mesh_models_metadata_entry health_srv_meta_alt[] = { + BT_MESH_HEALTH_TEST_INFO_METADATA(health_tests_alt), + { + .len = ARRAY_SIZE(zero_metadata), + .id = 0xFEED, + .data = zero_metadata, + }, BT_MESH_MODELS_METADATA_END, }; #endif @@ -1709,6 +1732,13 @@ static uint8_t change_prepare(const void *cmd, uint16_t cmd_len, return BTP_STATUS_FAILED; } +#if CONFIG_BT_MESH_LARGE_COMP_DATA_SRV + err = bt_mesh_models_metadata_change_prepare(); + if (err < 0) { + return BTP_STATUS_FAILED; + } +#endif + return BTP_STATUS_SUCCESS; } @@ -5026,6 +5056,9 @@ uint8_t tester_init_mesh(void) if (default_comp) { err = bt_mesh_init(&prov, &comp); } else { +#ifdef CONFIG_BT_MESH_LARGE_COMP_DATA_SRV + health_srv.metadata = health_srv_meta_alt; +#endif err = bt_mesh_init(&prov, &comp_alt); } From fd0886b30723ba0a0309fd4d6c0e01442dc7dc4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Fri, 19 May 2023 14:29:50 +0200 Subject: [PATCH 164/421] [nrf fromtree] tests: Bluetooth: tester: add support for Proxy Solicitation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds BTP commands implemantation needed to pass tests for Proxy Solicitation. Signed-off-by: Krzysztof Kopyściński (cherry picked from commit a8334210c1fa59a662a07a8189c7313c9d0af218) Signed-off-by: Alperen Şener (cherry picked from commit 5bc10ca1d9c44d0811d02ac01aaffbe9f9ac6507) --- tests/bluetooth/tester/src/btp/btp_mesh.h | 27 +++++ tests/bluetooth/tester/src/btp_mesh.c | 138 ++++++++++++++++++++++ 2 files changed, 165 insertions(+) diff --git a/tests/bluetooth/tester/src/btp/btp_mesh.h b/tests/bluetooth/tester/src/btp/btp_mesh.h index e93c2ceeb3d..ea5d89de07a 100644 --- a/tests/bluetooth/tester/src/btp/btp_mesh.h +++ b/tests/bluetooth/tester/src/btp/btp_mesh.h @@ -1009,6 +1009,33 @@ struct btp_priv_node_id_set_cmd { #define BTP_MESH_PROXY_PRIVATE_IDENTITY 0x72 +#define BTP_MESH_OD_PRIV_PROXY_GET 0x73 +struct btp_od_priv_proxy_get_cmd { + uint16_t dst; +} __packed; + +#define BTP_MESH_OD_PRIV_PROXY_SET 0x74 + +struct btp_od_priv_proxy_set_cmd { + uint16_t dst; + uint8_t val; +} __packed; + +#define BTP_MESH_SRPL_CLEAR 0x75 + +struct btp_srpl_clear_cmd { + uint16_t dst; + uint16_t range_start; + uint8_t range_len; + uint8_t acked; +} __packed; + +#define BTP_MESH_PROXY_SOLICIT 0x76 + +struct btp_proxy_solicit_cmd { + uint16_t net_idx; +} __packed; + /* events */ #define BTP_MESH_EV_OUT_NUMBER_ACTION 0x80 struct btp_mesh_out_number_action_ev { diff --git a/tests/bluetooth/tester/src/btp_mesh.c b/tests/bluetooth/tester/src/btp_mesh.c index 2c837bfb198..b9297474860 100644 --- a/tests/bluetooth/tester/src/btp_mesh.c +++ b/tests/bluetooth/tester/src/btp_mesh.c @@ -773,6 +773,108 @@ static uint8_t proxy_private_identity_enable(const void *cmd, uint16_t cmd_len, } #endif +#if defined(CONFIG_BT_MESH_SOL_PDU_RPL_CLI) +static struct bt_mesh_sol_pdu_rpl_cli srpl_cli; +#endif + + +#if defined(CONFIG_BT_MESH_OD_PRIV_PROXY_CLI) +static struct bt_mesh_od_priv_proxy_cli od_priv_proxy_cli; + +static uint8_t od_priv_proxy_get(const void *cmd, uint16_t cmd_len, + void *rsp, uint16_t *rsp_len) +{ + const struct btp_od_priv_proxy_get_cmd *cp = cmd; + uint8_t val_rsp; + int err; + + LOG_DBG(""); + + err = bt_mesh_od_priv_proxy_cli_get(net.net_idx, cp->dst, &val_rsp); + if (err) { + LOG_ERR("Failed to get On-Demand Private Proxy state (err %d)", err); + return BTP_STATUS_FAILED; + } + + LOG_DBG("On-Demand Private Proxy state: %u", val_rsp); + + return BTP_STATUS_SUCCESS; +} + +static uint8_t od_priv_proxy_set(const void *cmd, uint16_t cmd_len, + void *rsp, uint16_t *rsp_len) +{ + const struct btp_od_priv_proxy_set_cmd *cp = cmd; + uint8_t val_rsp; + int err; + + LOG_DBG(""); + + err = bt_mesh_od_priv_proxy_cli_set(net.net_idx, cp->dst, cp->val, &val_rsp); + if (err) { + LOG_ERR("Failed to set On-Demand Private Proxy state (err %d)", err); + return BTP_STATUS_FAILED; + } + + LOG_DBG("On-Demand Private Proxy set state: %u", val_rsp); + + return BTP_STATUS_SUCCESS; +} + +#endif + +#if defined(CONFIG_BT_MESH_SOL_PDU_RPL_CLI) +static uint8_t srpl_clear(const void *cmd, uint16_t cmd_len, + void *rsp, uint16_t *rsp_len) +{ + const struct btp_srpl_clear_cmd *cp = cmd; + uint16_t app_idx = BT_MESH_KEY_UNUSED; + uint16_t start_rsp; + uint8_t len_rsp; + int err; + + /* Lookup source address */ + for (int i = 0; i < ARRAY_SIZE(model_bound); i++) { + if (model_bound[i].model->id == BT_MESH_MODEL_ID_SOL_PDU_RPL_CLI) { + app_idx = model_bound[i].appkey_idx; + break; + } + } + + struct bt_mesh_msg_ctx ctx = BT_MESH_MSG_CTX_INIT_APP(app_idx, cp->dst); + + if (cp->acked) { + err = bt_mesh_sol_pdu_rpl_clear(&ctx, cp->range_start, cp->range_len, &start_rsp, + &len_rsp); + } else { + err = bt_mesh_sol_pdu_rpl_clear_unack(&ctx, cp->range_start, cp->range_len); + } + if (err) { + LOG_ERR("Failed to clear SRPL (err %d)", err); + return BTP_STATUS_FAILED; + } + + return BTP_STATUS_SUCCESS; +} +#endif + +#if defined(CONFIG_BT_MESH_PROXY_SOLICITATION) +static uint8_t proxy_solicit(const void *cmd, uint16_t cmd_len, + void *rsp, uint16_t *rsp_len) +{ + const struct btp_proxy_solicit_cmd *cp = cmd; + int err; + + err = bt_mesh_proxy_solicit(cp->net_idx); + if (err) { + LOG_ERR("Failed to advertise solicitation PDU (err %d)", err); + return BTP_STATUS_FAILED; + } + + return BTP_STATUS_SUCCESS; +} +#endif /* CONFIG_BT_MESH_PROXY_SOLICITATION */ + static struct bt_mesh_model root_models[] = { BT_MESH_MODEL_CFG_SRV, BT_MESH_MODEL_CFG_CLI(&cfg_cli), @@ -817,6 +919,16 @@ static struct bt_mesh_model root_models[] = { #if defined(CONFIG_BT_MESH_PRIV_BEACON_CLI) BT_MESH_MODEL_PRIV_BEACON_CLI(&priv_beacon_cli), #endif +#if defined(CONFIG_BT_MESH_OD_PRIV_PROXY_CLI) + BT_MESH_MODEL_OD_PRIV_PROXY_CLI(&od_priv_proxy_cli), +#endif +#if defined(CONFIG_BT_MESH_SOL_PDU_RPL_CLI) + BT_MESH_MODEL_SOL_PDU_RPL_CLI(&srpl_cli), +#endif +#if defined(CONFIG_BT_MESH_OD_PRIV_PROXY_SRV) + BT_MESH_MODEL_OD_PRIV_PROXY_SRV, +#endif + }; struct model_data *lookup_model_bound(uint16_t id) { @@ -4783,6 +4895,32 @@ static const struct btp_handler handlers[] = { .func = proxy_private_identity_enable }, #endif +#if defined(CONFIG_BT_MESH_OD_PRIV_PROXY_CLI) + { + .opcode = BTP_MESH_OD_PRIV_PROXY_GET, + .expect_len = sizeof(struct btp_od_priv_proxy_get_cmd), + .func = od_priv_proxy_get + }, + { + .opcode = BTP_MESH_OD_PRIV_PROXY_SET, + .expect_len = sizeof(struct btp_od_priv_proxy_set_cmd), + .func = od_priv_proxy_set + }, +#endif +#if defined(CONFIG_BT_MESH_SOL_PDU_RPL_CLI) + { + .opcode = BTP_MESH_SRPL_CLEAR, + .expect_len = sizeof(struct btp_srpl_clear_cmd), + .func = srpl_clear + }, +#endif +#if defined(CONFIG_BT_MESH_SOLICITATION) + { + .opcode = BTP_MESH_PROXY_SOLICIT, + .expect_len = sizeof(struct btp_proxy_solicit_cmd), + .func = proxy_solicit + }, +#endif }; From 991f7b9e250d62a4df1e3322b28127e7ff3cd69e Mon Sep 17 00:00:00 2001 From: Pavel Vasilyev Date: Fri, 22 Sep 2023 14:22:42 +0200 Subject: [PATCH 165/421] [nrf fromtree] tests: bluetooth: tester: Move mesh-1.1 features to a separate conf MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This allows to compile mesh tester for 1.0.1 and 1.1 specs sepately. Signed-off-by: Pavel Vasilyev (cherry picked from commit b7579065f95535f16a1b5aaffed14437b51f7520) Signed-off-by: Alperen Şener (cherry picked from commit 0bdbe0cd58d2c7ff87db28c0215f0fb47a7d0c40) --- tests/bluetooth/tester/overlay-mesh-v1d1.conf | 29 +++++++++++++++++++ tests/bluetooth/tester/overlay-mesh.conf | 29 +------------------ tests/bluetooth/tester/testcase.yaml | 9 ++++++ 3 files changed, 39 insertions(+), 28 deletions(-) create mode 100644 tests/bluetooth/tester/overlay-mesh-v1d1.conf diff --git a/tests/bluetooth/tester/overlay-mesh-v1d1.conf b/tests/bluetooth/tester/overlay-mesh-v1d1.conf new file mode 100644 index 00000000000..7a3907cc78c --- /dev/null +++ b/tests/bluetooth/tester/overlay-mesh-v1d1.conf @@ -0,0 +1,29 @@ +CONFIG_ENTROPY_GENERATOR=y + +CONFIG_BT_MESH_V1d1=y +CONFIG_BT_MESH_OP_AGG_CLI=y +CONFIG_BT_MESH_OP_AGG_SRV=y +# PTS requires more key slots. +# First one is implicitly taken by Device Key. +CONFIG_BT_MESH_MODEL_KEY_COUNT=3 +CONFIG_BT_MESH_LARGE_COMP_DATA_CLI=y +CONFIG_BT_MESH_LARGE_COMP_DATA_SRV=y +CONFIG_BT_MESH_SAR_CFG_SRV=y +CONFIG_BT_MESH_SAR_CFG_CLI=y +CONFIG_BT_MESH_TX_SEG_MSG_COUNT=10 +CONFIG_BT_MESH_RPR_SRV=y +CONFIG_BT_MESH_RPR_CLI=y +CONFIG_BT_MESH_RPR_AD_TYPES_MAX=2 +CONFIG_BT_MESH_BLOB_CLI=y +CONFIG_BT_MESH_DFU_CLI=y +CONFIG_BT_MESH_BLOB_SRV=y +CONFIG_BT_MESH_DFU_SRV=y +CONFIG_BT_MESH_DFD_SRV=y +CONFIG_BT_MESH_DFU_SLOT_CNT=2 +CONFIG_BT_MESH_PRIV_BEACONS=y +CONFIG_BT_MESH_PRIV_BEACON_SRV=y +CONFIG_BT_MESH_PRIV_BEACON_CLI=y +CONFIG_BT_MESH_MODEL_EXTENSIONS=y +CONFIG_BT_MESH_COMP_PAGE_1=y + +CONFIG_SETTINGS=y diff --git a/tests/bluetooth/tester/overlay-mesh.conf b/tests/bluetooth/tester/overlay-mesh.conf index fe4c9a62fef..840af06c1c0 100644 --- a/tests/bluetooth/tester/overlay-mesh.conf +++ b/tests/bluetooth/tester/overlay-mesh.conf @@ -1,5 +1,4 @@ CONFIG_BT_MESH=y -CONFIG_BT_MESH_V1d1=y CONFIG_BT_MESH_RELAY=y CONFIG_BT_MESH_PB_ADV=y CONFIG_BT_MESH_PB_GATT=y @@ -9,23 +8,14 @@ CONFIG_BT_MESH_GATT_PROXY=y CONFIG_BT_MESH_LABEL_COUNT=2 CONFIG_BT_MESH_SUBNET_COUNT=2 CONFIG_BT_MESH_MODEL_GROUP_COUNT=2 -CONFIG_BT_MESH_OP_AGG_CLI=y -CONFIG_BT_MESH_OP_AGG_SRV=y -# PTS requires more key slots. -# First one is implicitly taken by Device Key. -CONFIG_BT_MESH_MODEL_KEY_COUNT=3 CONFIG_BT_MESH_APP_KEY_COUNT=4 CONFIG_BT_MESH_IV_UPDATE_TEST=y CONFIG_BT_MESH_CFG_CLI=y CONFIG_BT_MESH_HEALTH_CLI=y -CONFIG_BT_MESH_LARGE_COMP_DATA_CLI=y -CONFIG_BT_MESH_LARGE_COMP_DATA_SRV=y -CONFIG_BT_MESH_SAR_CFG_SRV=y -CONFIG_BT_MESH_SAR_CFG_CLI=y CONFIG_BT_MESH_FRIEND=y CONFIG_BT_MESH_FRIEND_QUEUE_SIZE=32 CONFIG_BT_MESH_RX_SEG_MAX=13 -CONFIG_BT_MESH_TX_SEG_MSG_COUNT=10 +CONFIG_BT_MESH_TX_SEG_MSG_COUNT=3 CONFIG_BT_MESH_LPN_POLL_TIMEOUT=100 CONFIG_BT_MESH_PROVISIONER=y CONFIG_BT_MESH_CDB=y @@ -33,20 +23,3 @@ CONFIG_BT_MESH_CDB_NODE_COUNT=3 CONFIG_BT_MESH_PROV_OOB_PUBLIC_KEY=y CONFIG_BT_MESH_MSG_CACHE_SIZE=10 CONFIG_BT_MESH_PROXY_CLIENT=y -CONFIG_BT_MESH_PROVISIONER=y -CONFIG_BT_MESH_RPR_SRV=y -CONFIG_BT_MESH_RPR_CLI=y -CONFIG_BT_MESH_RPR_AD_TYPES_MAX=2 -CONFIG_BT_MESH_BLOB_CLI=y -CONFIG_BT_MESH_DFU_CLI=y -CONFIG_BT_MESH_BLOB_SRV=y -CONFIG_BT_MESH_DFU_SRV=y -CONFIG_BT_MESH_DFD_SRV=y -CONFIG_BT_MESH_DFU_SLOT_CNT=2 -CONFIG_BT_MESH_PRIV_BEACONS=y -CONFIG_BT_MESH_PRIV_BEACON_SRV=y -CONFIG_BT_MESH_PRIV_BEACON_CLI=y -CONFIG_BT_MESH_MODEL_EXTENSIONS=y -CONFIG_BT_MESH_COMP_PAGE_1=y - -CONFIG_SETTINGS=y diff --git a/tests/bluetooth/tester/testcase.yaml b/tests/bluetooth/tester/testcase.yaml index 65588568994..dba67716af1 100644 --- a/tests/bluetooth/tester/testcase.yaml +++ b/tests/bluetooth/tester/testcase.yaml @@ -25,3 +25,12 @@ tests: extra_args: OVERLAY_CONFIG="overlay-mesh.conf" tags: bluetooth harness: bluetooth + bluetooth.general.tester_mesh_v1d1: + build_only: true + platform_allow: + - qemu_x86 + - native_posix + - nrf52840dk_nrf52840 + extra_args: OVERLAY_CONFIG="overlay-mesh.conf;overlay-mesh-v1d1.conf" + tags: bluetooth + harness: bluetooth From 954d54fef79f1a2f7400098e2a58bf7b64ec9b18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alperen=20=C5=9Eener?= Date: Wed, 6 Sep 2023 18:57:08 +0200 Subject: [PATCH 166/421] [nrf fromtree] tests: bluetooth: tester: add transfer ttl to mbt inputs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit adding transfer ttl ixit value to be used as input for mbt test cases Signed-off-by: Alperen Şener (cherry picked from commit 90fac3045db59585f724fadc63adcaea9fcafd69) Signed-off-by: Alperen Şener (cherry picked from commit 591bc197f08512593a556c27ca1a4ca157f55b34) --- tests/bluetooth/tester/src/btp/btp_mesh.h | 2 ++ tests/bluetooth/tester/src/btp_mesh.c | 8 +++++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/tests/bluetooth/tester/src/btp/btp_mesh.h b/tests/bluetooth/tester/src/btp/btp_mesh.h index ea5d89de07a..6c4a5e90106 100644 --- a/tests/bluetooth/tester/src/btp/btp_mesh.h +++ b/tests/bluetooth/tester/src/btp/btp_mesh.h @@ -954,6 +954,7 @@ struct btp_mmdl_dfu_firmware_update_rp { struct btp_mmdl_blob_srv_recv_cmd { uint64_t id; uint16_t timeout; + uint8_t ttl; } __packed; #define BTP_MMDL_BLOB_TRANSFER_START 0x66 @@ -963,6 +964,7 @@ struct btp_mmdl_blob_transfer_start_cmd { uint8_t block_size; uint16_t chunk_size; uint16_t timeout; + uint8_t ttl; } __packed; #define BTP_MMDL_BLOB_TRANSFER_CANCEL 0x67 diff --git a/tests/bluetooth/tester/src/btp_mesh.c b/tests/bluetooth/tester/src/btp_mesh.c index b9297474860..ffd4b69db84 100644 --- a/tests/bluetooth/tester/src/btp_mesh.c +++ b/tests/bluetooth/tester/src/btp_mesh.c @@ -4228,6 +4228,10 @@ static uint8_t blob_transfer_start(const void *cmd, uint16_t cmd_len, blob_cli_xfer.inputs.timeout_base = cp->timeout; } + if (cp->ttl) { + blob_cli_xfer.inputs.ttl = cp->ttl; + } + err = bt_mesh_blob_cli_send(&blob_cli, &blob_cli_xfer.inputs, &blob_cli_xfer.xfer, &dummy_blob_io); @@ -4311,13 +4315,15 @@ static uint8_t blob_srv_recv(const void *cmd, uint16_t cmd_len, uint16_t timeout_base; uint64_t id; + uint8_t ttl; LOG_DBG(""); id = cp->id; timeout_base = cp->timeout; + ttl = cp->ttl; - err = bt_mesh_blob_srv_recv(srv, id, &dummy_blob_io, BT_MESH_TTL_MAX, + err = bt_mesh_blob_srv_recv(srv, id, &dummy_blob_io, ttl, timeout_base); if (err) { From 0f4ef37e9e32afb8c4a006df4876d3d27146a75e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alperen=20=C5=9Eener?= Date: Sat, 9 Sep 2023 19:41:26 +0200 Subject: [PATCH 167/421] [nrf fromtree] tests: bluetooth: tester: fix improper large comp rsp struct init MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Large composition data response struct should have a data buffer to store the reponse data to Signed-off-by: Alperen Şener (cherry picked from commit a54c18ad31943d113b10bdebfbee7e9928ae7862) Signed-off-by: Alperen Şener (cherry picked from commit 092b4c26095cf34eec03970bfa7adc430ada76a5) --- tests/bluetooth/tester/src/btp_mesh.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/tests/bluetooth/tester/src/btp_mesh.c b/tests/bluetooth/tester/src/btp_mesh.c index ffd4b69db84..f02d51c905a 100644 --- a/tests/bluetooth/tester/src/btp_mesh.c +++ b/tests/bluetooth/tester/src/btp_mesh.c @@ -1761,7 +1761,12 @@ static uint8_t large_comp_data_get(const void *cmd, uint16_t cmd_len, struct btp_mesh_large_comp_data_get_rp *rp = rsp; int err; - struct bt_mesh_large_comp_data_rsp comp; + NET_BUF_SIMPLE_DEFINE(data, 500); + net_buf_simple_init(&data, 0); + + struct bt_mesh_large_comp_data_rsp comp = { + .data = &data, + }; err = bt_mesh_large_comp_data_get(sys_le16_to_cpu(cp->net_idx), sys_le16_to_cpu(cp->addr), cp->page, @@ -1785,7 +1790,12 @@ static uint8_t models_metadata_get(const void *cmd, uint16_t cmd_len, struct btp_mesh_models_metadata_get_rp *rp = rsp; int err; - struct bt_mesh_large_comp_data_rsp metadata; + NET_BUF_SIMPLE_DEFINE(data, 500); + net_buf_simple_init(&data, 0); + + struct bt_mesh_large_comp_data_rsp metadata = { + .data = &data, + }; err = bt_mesh_models_metadata_get(sys_le16_to_cpu(cp->net_idx), sys_le16_to_cpu(cp->addr), cp->page, From 1d3d0be5a5684572f422e1b5c9ee3afabe77c7a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alperen=20=C5=9Eener?= Date: Thu, 28 Sep 2023 15:48:04 +0200 Subject: [PATCH 168/421] [nrf fromtree] bluetooth: mesh: check upload slot before release MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Check if the slot is not reseved, NULL before try to releas it. Signed-off-by: Alperen Şener (cherry picked from commit 05e806d31d8ad7a37d20a07cdc32f7d68b044e5b) Signed-off-by: Alperen Şener (cherry picked from commit fc9b8d8ab912c3df2cd2bbf87b837830f4545496) --- subsys/bluetooth/mesh/dfd_srv.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/subsys/bluetooth/mesh/dfd_srv.c b/subsys/bluetooth/mesh/dfd_srv.c index 54de343c94a..59fe5b830d1 100644 --- a/subsys/bluetooth/mesh/dfd_srv.c +++ b/subsys/bluetooth/mesh/dfd_srv.c @@ -477,7 +477,9 @@ static int handle_upload_start(struct bt_mesh_model *mod, struct bt_mesh_msg_ctx /* This will be a no-op if the slot state isn't RESERVED, which is * what we want. */ - bt_mesh_dfu_slot_release(srv->upload.slot); + if (srv->upload.slot) { + bt_mesh_dfu_slot_release(srv->upload.slot); + } #ifdef CONFIG_BT_MESH_DFD_SRV_OOB_UPLOAD srv->upload.is_oob = false; From cbeb833f4470fa050c5c43429298ec72e7a656b2 Mon Sep 17 00:00:00 2001 From: Andrei Emeltchenko Date: Mon, 2 Oct 2023 18:52:30 +0300 Subject: [PATCH 169/421] [nrf fromtree] tests: btp_mesh: Check correct error code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Check actual error code. Signed-off-by: Andrei Emeltchenko (cherry picked from commit ca1de2fc3961147269cc189c65e99f6f23fee3ce) Signed-off-by: Alperen Şener (cherry picked from commit 6246fab755e3d3cf68d6d5e2b58f35c94d886792) --- tests/bluetooth/tester/src/btp_mesh.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/bluetooth/tester/src/btp_mesh.c b/tests/bluetooth/tester/src/btp_mesh.c index f02d51c905a..1d94eb43cb5 100644 --- a/tests/bluetooth/tester/src/btp_mesh.c +++ b/tests/bluetooth/tester/src/btp_mesh.c @@ -3801,7 +3801,7 @@ static void dfu_slot_add(size_t size, uint8_t *fwid, size_t fwid_len, return; } - bt_mesh_dfu_slot_commit(slot); + err = bt_mesh_dfu_slot_commit(slot); if (err) { LOG_ERR("Failed to commit slot: %d", err); return; From 058c19c5a8644dcb0817d720876bb5265776a7ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alperen=20=C5=9Eener?= Date: Mon, 2 Oct 2023 01:14:16 +0200 Subject: [PATCH 170/421] [nrf fromtree] bluetooth: mesh: fix static oob auth padding MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The remaining bit should be zero if auth is shorter than PROV_AUTH_MAX_LEN and it should be trimmed by removing octets with indexes higher than PROV_AUTH_MAX_LEN. Signed-off-by: Alperen Şener (cherry picked from commit fe6fb0f467c4b47cc33e1ffdd99ea976850d02a0) Signed-off-by: Alperen Şener (cherry picked from commit 6b356f778807f1e39c79ee83c260ff761ef0d5b1) --- subsys/bluetooth/mesh/prov_device.c | 18 ++++++++++-------- subsys/bluetooth/mesh/provisioner.c | 13 ++++++++----- 2 files changed, 18 insertions(+), 13 deletions(-) diff --git a/subsys/bluetooth/mesh/prov_device.c b/subsys/bluetooth/mesh/prov_device.c index 0184463568f..992bf656202 100644 --- a/subsys/bluetooth/mesh/prov_device.c +++ b/subsys/bluetooth/mesh/prov_device.c @@ -192,14 +192,16 @@ static void prov_start(const uint8_t *data) } if (atomic_test_bit(bt_mesh_prov_link.flags, OOB_STATIC_KEY)) { - - uint8_t tail_size = bt_mesh_prov->static_val_len < auth_size - ? auth_size - bt_mesh_prov->static_val_len - : 0; - - memcpy(bt_mesh_prov_link.auth + tail_size, bt_mesh_prov->static_val, - tail_size ? bt_mesh_prov->static_val_len : auth_size); - memset(bt_mesh_prov_link.auth, 0, tail_size); + /* Trim the Auth if it is longer than required length */ + memcpy(bt_mesh_prov_link.auth, bt_mesh_prov->static_val, + bt_mesh_prov->static_val_len > auth_size ? auth_size + : bt_mesh_prov->static_val_len); + + /* Padd with zeros if the Auth is shorter the required length*/ + if (bt_mesh_prov->static_val_len < auth_size) { + memset(bt_mesh_prov_link.auth + bt_mesh_prov->static_val_len, 0, + auth_size - bt_mesh_prov->static_val_len); + } } } diff --git a/subsys/bluetooth/mesh/provisioner.c b/subsys/bluetooth/mesh/provisioner.c index 673e14578d2..361f373cb7b 100644 --- a/subsys/bluetooth/mesh/provisioner.c +++ b/subsys/bluetooth/mesh/provisioner.c @@ -751,17 +751,20 @@ int bt_mesh_auth_method_set_output(bt_mesh_output_action_t action, uint8_t size) int bt_mesh_auth_method_set_static(const uint8_t *static_val, uint8_t size) { - uint8_t tail_size = size < PROV_AUTH_MAX_LEN ? PROV_AUTH_MAX_LEN - size : 0; - if (!size || !static_val) { return -EINVAL; } prov_set_method(AUTH_METHOD_STATIC, 0, 0); - memcpy(bt_mesh_prov_link.auth + tail_size, static_val, - tail_size ? size : PROV_AUTH_MAX_LEN); - memset(bt_mesh_prov_link.auth, 0, tail_size); + /* Trim the Auth if it is longer than required length */ + memcpy(bt_mesh_prov_link.auth, static_val, + size > PROV_AUTH_MAX_LEN ? PROV_AUTH_MAX_LEN : size); + + /* Padd with zeros if the Auth is shorter the required length*/ + if (size < PROV_AUTH_MAX_LEN) { + memset(bt_mesh_prov_link.auth + size, 0, PROV_AUTH_MAX_LEN - size); + } return 0; } From 5cb1ed20ab2c98d0e0856219a355a7e7dd51394c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alperen=20=C5=9Eener?= Date: Fri, 29 Sep 2023 16:49:16 +0200 Subject: [PATCH 171/421] [nrf fromlist] bluetooth: tester: Enable composition data page 2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Enabling the composition data page 2 feature and adding tester support. Upstream PR: https://github.com/zephyrproject-rtos/zephyr/pull/63441 Signed-off-by: Alperen Şener (cherry picked from commit 170558aa94d7f82a8852aea19a83f7dcc5f14ae3) --- tests/bluetooth/tester/overlay-mesh-v1d1.conf | 2 +- tests/bluetooth/tester/src/btp_mesh.c | 20 +++++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/tests/bluetooth/tester/overlay-mesh-v1d1.conf b/tests/bluetooth/tester/overlay-mesh-v1d1.conf index 7a3907cc78c..978d1acd3df 100644 --- a/tests/bluetooth/tester/overlay-mesh-v1d1.conf +++ b/tests/bluetooth/tester/overlay-mesh-v1d1.conf @@ -25,5 +25,5 @@ CONFIG_BT_MESH_PRIV_BEACON_SRV=y CONFIG_BT_MESH_PRIV_BEACON_CLI=y CONFIG_BT_MESH_MODEL_EXTENSIONS=y CONFIG_BT_MESH_COMP_PAGE_1=y - +CONFIG_BT_MESH_COMP_PAGE_2=y CONFIG_SETTINGS=y diff --git a/tests/bluetooth/tester/src/btp_mesh.c b/tests/bluetooth/tester/src/btp_mesh.c index 1d94eb43cb5..af41c1518d5 100644 --- a/tests/bluetooth/tester/src/btp_mesh.c +++ b/tests/bluetooth/tester/src/btp_mesh.c @@ -1103,6 +1103,22 @@ static const struct bt_mesh_comp comp_alt = { .vid = 2, }; +#if defined(CONFIG_BT_MESH_COMP_PAGE_2) +static const uint8_t cmp2_elem_offset[1] = {0}; + +static const struct bt_mesh_comp2_record comp_rec = { + .id = 0x1600, + .version.x = 1, + .version.y = 0, + .version.z = 0, + .elem_offset_cnt = 1, + .elem_offset = cmp2_elem_offset, + .data_len = 0 +}; + +static const struct bt_mesh_comp2 comp_p2 = {.record_cnt = 1, .record = &comp_rec}; +#endif + static struct bt_mesh_prov prov = { .uuid = dev_uuid, .static_val = static_auth, @@ -5205,6 +5221,10 @@ uint8_t tester_init_mesh(void) bt_test_cb_register(&bt_test_cb); } +#if defined(CONFIG_BT_MESH_COMP_PAGE_2) + bt_mesh_comp2_register(&comp_p2); +#endif + tester_register_command_handlers(BTP_SERVICE_ID_MESH, handlers, ARRAY_SIZE(handlers)); if (default_comp) { From 6319f2cfbe21cd9cac956922ad70595b149220a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alperen=20=C5=9Eener?= Date: Fri, 29 Sep 2023 15:10:10 +0200 Subject: [PATCH 172/421] [nrf fromlist] bluetooth: tester: add support for variable static oob size MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adding variable static auth size support to be compatible both mesh 1.0.1 and mesh 1.1. Upstream PR: https://github.com/zephyrproject-rtos/zephyr/pull/63440 Signed-off-by: Alperen Şener (cherry picked from commit cafad7403fb4eaf5939c73db2fdfecff2bf65b11) --- tests/bluetooth/tester/src/btp/btp_mesh.h | 8 +++----- tests/bluetooth/tester/src/btp_mesh.c | 13 +++++++++++-- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/tests/bluetooth/tester/src/btp/btp_mesh.h b/tests/bluetooth/tester/src/btp/btp_mesh.h index 6c4a5e90106..826f0fd0408 100644 --- a/tests/bluetooth/tester/src/btp/btp_mesh.h +++ b/tests/bluetooth/tester/src/btp/btp_mesh.h @@ -30,15 +30,12 @@ struct btp_mesh_read_supported_commands_rp { #define BTP_MESH_CONFIG_PROVISIONING 0x02 -#if IS_ENABLED(CONFIG_BT_MESH_ECDH_P256_HMAC_SHA256_AES_CCM) -#define BTP_MESH_PROV_AUTH_MAX_LEN 32 -#else -#define BTP_MESH_PROV_AUTH_MAX_LEN 16 -#endif +#define BTP_MESH_PROV_AUTH_MAX_LEN 32 struct btp_mesh_config_provisioning_cmd { uint8_t uuid[16]; uint8_t static_auth[BTP_MESH_PROV_AUTH_MAX_LEN]; + uint8_t static_auth_size; uint8_t out_size; uint16_t out_actions; uint8_t in_size; @@ -48,6 +45,7 @@ struct btp_mesh_config_provisioning_cmd { struct btp_mesh_config_provisioning_cmd_v2 { uint8_t uuid[16]; uint8_t static_auth[BTP_MESH_PROV_AUTH_MAX_LEN]; + uint8_t static_auth_size; uint8_t out_size; uint16_t out_actions; uint8_t in_size; diff --git a/tests/bluetooth/tester/src/btp_mesh.c b/tests/bluetooth/tester/src/btp_mesh.c index af41c1518d5..e83f1a67ba1 100644 --- a/tests/bluetooth/tester/src/btp_mesh.c +++ b/tests/bluetooth/tester/src/btp_mesh.c @@ -50,6 +50,7 @@ static uint8_t priv_key[32]; /* Configured provisioning data */ static uint8_t dev_uuid[16]; static uint8_t static_auth[BTP_MESH_PROV_AUTH_MAX_LEN]; +static uint8_t static_auth_size; /* Vendor Model data */ #define VND_MODEL_ID_1 0x1234 @@ -1143,13 +1144,21 @@ static uint8_t config_prov(const void *cmd, uint16_t cmd_len, /* TODO consider fix BTP commands to avoid this */ if (cmd_len != sizeof(*cp) && cmd_len != (sizeof(*cp2))) { + LOG_DBG("wrong cmd size"); return BTP_STATUS_FAILED; } LOG_DBG(""); + static_auth_size = cp->static_auth_size; + + if (static_auth_size > BTP_MESH_PROV_AUTH_MAX_LEN || static_auth_size == 0) { + LOG_DBG("wrong static auth length"); + return BTP_STATUS_FAILED; + } + memcpy(dev_uuid, cp->uuid, sizeof(dev_uuid)); - memcpy(static_auth, cp->static_auth, sizeof(static_auth)); + memcpy(static_auth, cp->static_auth, cp->static_auth_size); prov.output_size = cp->out_size; prov.output_actions = sys_le16_to_cpu(cp->out_actions); @@ -1168,7 +1177,7 @@ static uint8_t config_prov(const void *cmd, uint16_t cmd_len, } else if (cp->auth_method == AUTH_METHOD_INPUT) { err = bt_mesh_auth_method_set_input(prov.input_actions, prov.input_size); } else if (cp->auth_method == AUTH_METHOD_STATIC) { - err = bt_mesh_auth_method_set_static(static_auth, sizeof(static_auth)); + err = bt_mesh_auth_method_set_static(static_auth, static_auth_size); } if (err) { From 27f8c5cbafa199be5c1945ab95bc5cbcff9ab8cd Mon Sep 17 00:00:00 2001 From: Mateusz Kapala Date: Wed, 4 Oct 2023 11:58:46 +0200 Subject: [PATCH 173/421] [nrf fromtree] bluetooth: host: smp: Add runtime check for central-specific path Added run-time BT_CENTRAL role check for the path that was central specific and did not have such check. When multi-role BT device tried to pair without bonding (peripheral role) while already previously bonded with the same device on another Bluetooth identity, pairing failed. It executed central-specific code, which should not be executed in case when the device acts as peripheral (as it is even opt-out from code when CONFIG_BT_CENTRAL is not enabled). Signed-off-by: Mateusz Kapala (cherry picked from commit 7a1b194a97e697578e459535752e6c3b1a75bdd9) (cherry picked from commit bbb68430f9586648b9f47ec01f96e19adf4edeb5) --- subsys/bluetooth/host/smp.c | 1 + 1 file changed, 1 insertion(+) diff --git a/subsys/bluetooth/host/smp.c b/subsys/bluetooth/host/smp.c index add06660bf6..9643982c421 100644 --- a/subsys/bluetooth/host/smp.c +++ b/subsys/bluetooth/host/smp.c @@ -4706,6 +4706,7 @@ static void bt_smp_encrypt_change(struct bt_l2cap_chan *chan, */ if (IS_ENABLED(CONFIG_BT_CENTRAL) && IS_ENABLED(CONFIG_BT_PRIVACY) && + conn->role == BT_HCI_ROLE_CENTRAL && !(smp->remote_dist & BT_SMP_DIST_ID_KEY)) { uint8_t smp_err; From 55f4b17ea515edd707dd2fc3a907911f270e088a Mon Sep 17 00:00:00 2001 From: Mateusz Kapala Date: Wed, 4 Oct 2023 11:59:06 +0200 Subject: [PATCH 174/421] [nrf fromtree] bluetooth: tests: Improve bondable_per_connection bsim test Added fail on pairing_failed callback for both central and peripheral. Added pairing status checks in peripheral. It has been done to test the case when multi-role BT device tried to pair without bonding (peripheral role) while already previously bonded with the same device on another Bluetooth identity as it seems that there was an issue with it previously. Signed-off-by: Mateusz Kapala (cherry picked from commit 3c0c6343407106e6ff4705a464bc93912ca37929) (cherry picked from commit 1f6d361cdbd5e112583cb217267783e9cb294130) --- .../host/security/bond_per_connection/src/bs_bt_utils.c | 6 ++++++ .../host/security/bond_per_connection/src/peripheral.c | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/tests/bsim/bluetooth/host/security/bond_per_connection/src/bs_bt_utils.c b/tests/bsim/bluetooth/host/security/bond_per_connection/src/bs_bt_utils.c index 1523e10d8a5..94b27a50b33 100644 --- a/tests/bsim/bluetooth/host/security/bond_per_connection/src/bs_bt_utils.c +++ b/tests/bsim/bluetooth/host/security/bond_per_connection/src/bs_bt_utils.c @@ -88,6 +88,11 @@ DEFINE_FLAG(flag_pairing_complete); DEFINE_FLAG(flag_bonded); DEFINE_FLAG(flag_not_bonded); +static void pairing_failed(struct bt_conn *conn, enum bt_security_err reason) +{ + FAIL("Pairing failed (unexpected): reason %u\n", reason); +} + static void pairing_complete(struct bt_conn *conn, bool bonded) { SET_FLAG(flag_pairing_complete); @@ -100,6 +105,7 @@ static void pairing_complete(struct bt_conn *conn, bool bonded) } static struct bt_conn_auth_info_cb bt_conn_auth_info_cb = { + .pairing_failed = pairing_failed, .pairing_complete = pairing_complete, }; diff --git a/tests/bsim/bluetooth/host/security/bond_per_connection/src/peripheral.c b/tests/bsim/bluetooth/host/security/bond_per_connection/src/peripheral.c index 5e11d6ac712..01956d251df 100644 --- a/tests/bsim/bluetooth/host/security/bond_per_connection/src/peripheral.c +++ b/tests/bsim/bluetooth/host/security/bond_per_connection/src/peripheral.c @@ -33,6 +33,8 @@ void peripheral(void) wait_connected(); /* Central should bond here and trigger a disconnect. */ wait_disconnected(); + TAKE_FLAG(flag_pairing_complete); + TAKE_FLAG(flag_bonded); unpair(id_a); clear_g_conn(); @@ -43,6 +45,8 @@ void peripheral(void) wait_connected(); /* Central should bond here and trigger a disconnect. */ wait_disconnected(); + TAKE_FLAG(flag_pairing_complete); + TAKE_FLAG(flag_bonded); clear_g_conn(); printk("== Bonding id b - bond per-connection false ==\n"); @@ -51,6 +55,8 @@ void peripheral(void) wait_connected(); /* Central should pair without bond here and trigger a disconnect. */ wait_disconnected(); + TAKE_FLAG(flag_pairing_complete); + TAKE_FLAG(flag_not_bonded); PASS("PASS\n"); } From d73788b2457d22003d435da88143ee67881bdc43 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Thu, 28 Sep 2023 11:39:32 +0000 Subject: [PATCH 175/421] [nrf fromtree] modules/MCUboot: Add overwrite mode for MCUboot Add MCUBOOT_BOOTLOADER_MODE_OVERWRITE_ONLY mode. (cherry picked from commit 5d28fdea63b513582b975a276a20b2d5faff7a7a) Signed-off-by: Dominik Ermel (cherry picked from commit 0d08e4d5f29c903c619b0b74dcff3ba830b778fb) --- modules/Kconfig.mcuboot | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/modules/Kconfig.mcuboot b/modules/Kconfig.mcuboot index 1679bfeb8a9..8df4bde8829 100644 --- a/modules/Kconfig.mcuboot +++ b/modules/Kconfig.mcuboot @@ -175,6 +175,18 @@ config MCUBOOT_BOOTLOADER_MODE_SWAP_SCRATCH MCUBOOT_BOOTLOADER_NO_DOWNGRADE should also be selected if MCUboot has been built with MCUBOOT_DOWNGRADE_PREVENTION. +config MCUBOOT_BOOTLOADER_MODE_OVERWRITE_ONLY + bool "MCUboot has been configured to just overwrite primary slot" + select MCUBOOT_BOOTLOADER_MODE_HAS_NO_DOWNGRADE + help + MCUboot will take contents of secondary slot of an image and will + overwrite primary slot with it. + In this mode it is not possible to revert back to previous version + as it is not stored in the secondary slot. + This mode supports MCUBOOT_BOOTLOADER_NO_DOWNGRADE which means + that the overwrite will not happen unless the version of secondary + slot is higher than the version in primary slot. + config MCUBOOT_BOOTLOADER_MODE_DIRECT_XIP bool "MCUboot has been configured for DirectXIP operation" select MCUBOOT_BOOTLOADER_MODE_HAS_NO_DOWNGRADE From 3d0052713f45333aa094a8c6d8896bd3b9c051ce Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Thu, 11 May 2023 15:15:08 +0000 Subject: [PATCH 176/421] [nrf fromtree] doc/services/device_mgmt: Bootloader info request definition Specification for MCUmgr OS group command allowing to query for bootloader information. Provide information on supported MCUboot parameters query by MCUmgr group OS. (cherry picked from commit 7668b4fbb35b98ca1c61029aedf72ff544b70236) Signed-off-by: Dominik Ermel (cherry picked from commit ccae85c1d48469cb22bd4f19cea322de502adc5f) --- .../device_mgmt/smp_groups/smp_group_0.rst | 211 +++++++++++++++++- 1 file changed, 208 insertions(+), 3 deletions(-) diff --git a/doc/services/device_mgmt/smp_groups/smp_group_0.rst b/doc/services/device_mgmt/smp_groups/smp_group_0.rst index 839b0e06be3..53907f33bcc 100644 --- a/doc/services/device_mgmt/smp_groups/smp_group_0.rst +++ b/doc/services/device_mgmt/smp_groups/smp_group_0.rst @@ -28,6 +28,8 @@ OS management group defines following commands: +-------------------+-----------------------------------------------+ | ``7`` | OS/Application info | +-------------------+-----------------------------------------------+ + | ``8`` | Bootloader information | + +-------------------+-----------------------------------------------+ Echo command ************ @@ -660,12 +662,215 @@ CBOR data of response: where: +.. table:: + :align: center + + +------------------+-------------------------------------------------------------------------+ + | "output" | Text response including requested parameters. | + +------------------+-------------------------------------------------------------------------+ + | "err" -> "group" | :c:enum:`mcumgr_group_t` group of the group-based error code. Only | + | | appears if an error is returned when using SMP version 2. | + +------------------+-------------------------------------------------------------------------+ + | "err" -> "rc" | contains the index of the group-based error code. Only appears if | + | | non-zero (error condition) when using SMP version 2. | + +------------------+-------------------------------------------------------------------------+ + | "rc" | :c:enum:`mcumgr_err_t` only appears if non-zero (error condition) when | + | | using SMP version 1 or for SMP errors when using SMP version 2. | + +------------------+-------------------------------------------------------------------------+ + +Bootloader Information +********************** + +Allows retrieving information about the on-board bootloader and its parameters. + +Bootloader Information Request +============================== + +Bootloader information request header: + +.. table:: + :align: center + + +--------+--------------+----------------+ + | ``OP`` | ``Group ID`` | ``Command ID`` | + +========+==============+================+ + | ``0`` | ``0`` | ``8`` | + +--------+--------------+----------------+ + +CBOR data of request: + +.. code-block:: none + + { + (str,opt)"query" : (str) + } + +where: + .. table:: :align: center +--------------+-----------------------------------------------+ - | "output" | Text response including requested parameters. | + | "query" | Is string representing query for parameters, | + | | with no restrictions how the query looks like | + | | as processing of query is left for bootloader | + | | backend. | + | | If there is no query, then response will | + | | return string identifying the bootloader. | +--------------+-----------------------------------------------+ - | "rc" | :c:enum:`mcumgr_err_t` | - | | only appears if non-zero (error condition). | + +Bootloader Information Response +=============================== + +Bootloader information response header: + +.. table:: + :align: center + + +--------+--------------+----------------+ + | ``OP`` | ``Group ID`` | ``Command ID`` | + +========+==============+================+ + | ``1`` | ``0`` | ``8`` | + +--------+--------------+----------------+ + +In case when no "query" has been provided in request, +CBOR data of response: + +.. code-block:: none + + { + (str)"bootloader" : (str) + } + +where: + +.. table:: + :align: center + + +--------------+-----------------------------------------------+ + | "bootloader" | String representing bootloader name | +--------------+-----------------------------------------------+ + +In case when "query" is provided: + +.. code-block:: none + + { + (str,opt) : () + ... + } + +where: + +.. table:: + :align: center + + +------------------+-------------------------------------------------------------------------+ + | | Response to "query". This is optional and may be left out in case when | + | | query yields no response, SMP version 2 error code of | + | | `OS_MGMT_ERR_QUERY_YIELDS_NO_ANSWER` is expected. | + | | Response may have more than one parameter reported back or it may be | + | | a map, that is dependent on bootloader backednd and query. | + +------------------+-------------------------------------------------------------------------+ + | ... | Parameter characteristic information. | + +------------------+-------------------------------------------------------------------------+ + +Parameter may be accompanied by additional, parameter specific, information keywords with +assigned values. + +In case of error the CBOR data takes the form: + +.. tabs:: + + .. group-tab:: SMP version 2 + + .. code-block:: none + + { + (str)"err" : { + (str)"group" : (uint) + (str)"rc" : (uint) + } + } + + .. group-tab:: SMP version 1 (and non-group SMP version 2) + + .. code-block:: none + + { + (str)"rc" : (int) + } + +where: + +.. table:: + :align: center + + +------------------+-------------------------------------------------------------------------+ + | "err" -> "group" | :c:enum:`mcumgr_group_t` group of the group-based error code. Only | + | | appears if an error is returned when using SMP version 2. | + +------------------+-------------------------------------------------------------------------+ + | "err" -> "rc" | contains the index of the group-based error code. Only appears if | + | | non-zero (error condition) when using SMP version 2. | + +------------------+-------------------------------------------------------------------------+ + | "rc" | :c:enum:`mcumgr_err_t` only appears if non-zero (error condition) when | + | | using SMP version 1 or for SMP errors when using SMP version 2. | + +------------------+-------------------------------------------------------------------------+ + +Bootloader Information: MCUboot +=============================== + +In case when MCUboot is application bootloader empty request will +be responded with: + +.. code-block:: none + + { + (str)"bootloader" : (str)"MCUboot" + } + +Currently "MCUboot" supports querying for mode of operation: + +.. code-block:: none + + { + (str)"query" : (str)"mode" + } + +Response to "mode" is: + +.. code-block:: none + + { + (str)"mode" : (int) + (str,opt)"no-downgrade" : (bool) + } + +where "mode" is one of: + +.. table:: + :align: center + + +-----+-----------------------------------------------------+ + | -1 | Unknown mode of MCUboot. | + +-----+-----------------------------------------------------+ + | 0 | MCUboot is in single application mode. | + +-----+-----------------------------------------------------+ + | 1 | MCUboot is in swap using scratch partition mode. | + +-----+-----------------------------------------------------+ + | 2 | MCUboot is in overwrite (upgrade-only) mode. | + +-----+-----------------------------------------------------+ + | 3 | MCUboot is in swap without scratch mode. | + +-----+-----------------------------------------------------+ + | 4 | MCUboot is in DirectXIP without revert mode. | + +-----+-----------------------------------------------------+ + | 5 | MCUboot is in DirectXIP with revert mode. | + +-----+-----------------------------------------------------+ + | 6 | MCUboot is in RAM loader mode. | + +-----+-----------------------------------------------------+ + +The "no-downgrade" is a flag, which is always sent when true, indicating that +mode has downgrade prevention enabled; downgrade prevention means that +if uploaded image has lower version than running, it will notbe taken +for exectuion by MCUboot. +MCUmgr may reject image with lower version in that MCUboot configuration. From b1ab980959dac1486bd6d781ec8b9c80bba21fac Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Thu, 28 Sep 2023 11:44:39 +0000 Subject: [PATCH 177/421] [nrf fromtree] doc/release-notes: MCUboot overwrite mode Kconfig info Note on CONFIG_MCUBOOT_BOOTLOADER_MODE_OVERWRITE_ONLY. (cherry picked from commit 83d69f50ada1fb22bee848a501e82a1683fc0aef) Signed-off-by: Dominik Ermel (cherry picked from commit 58706ac8d24d55d67c5e6c1427e3c36fe0839274) --- doc/releases/release-notes-3.5.rst | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/doc/releases/release-notes-3.5.rst b/doc/releases/release-notes-3.5.rst index d22978d8a84..82d2698849b 100644 --- a/doc/releases/release-notes-3.5.rst +++ b/doc/releases/release-notes-3.5.rst @@ -344,6 +344,11 @@ MCUboot with downgrade prevention enabled. This option is automatically selected for DirectXIP mode and is available for both swap modes. + * Added :kconfig:option:`CONFIG_MCUBOOT_BOOTLOADER_MODE_OVERWRITE_ONLY` + that allows to inform application that the on-board MCUboot will overwrite + the primary slot with secondary slot contents, without saving the original + image in primary slot. + Storage ******* From 8bef82541c679398d9886f211db6a8eb34f34760 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Mon, 15 May 2023 12:48:14 +0000 Subject: [PATCH 178/421] [nrf fromtree] mgmt/MCUmgr/grp/os: Add booloader info support Adds command allowing to query information on bootloader. In this case support is provided to query MCUboot information. (cherry picked from commit e48354455acbea481c102cf97be46d0abc720268) Signed-off-by: Dominik Ermel (cherry picked from commit cbe3d5fb40a7a737e4d17d81864335c7e1623508) --- .../zephyr/mgmt/mcumgr/grp/os_mgmt/os_mgmt.h | 4 ++ subsys/mgmt/mcumgr/grp/os_mgmt/CMakeLists.txt | 8 ++- subsys/mgmt/mcumgr/grp/os_mgmt/Kconfig | 10 +++ subsys/mgmt/mcumgr/grp/os_mgmt/src/os_mgmt.c | 70 ++++++++++++++++++- 4 files changed, 90 insertions(+), 2 deletions(-) diff --git a/include/zephyr/mgmt/mcumgr/grp/os_mgmt/os_mgmt.h b/include/zephyr/mgmt/mcumgr/grp/os_mgmt/os_mgmt.h index 9c541e11c29..e1ac45e6389 100644 --- a/include/zephyr/mgmt/mcumgr/grp/os_mgmt/os_mgmt.h +++ b/include/zephyr/mgmt/mcumgr/grp/os_mgmt/os_mgmt.h @@ -24,6 +24,7 @@ extern "C" { #define OS_MGMT_ID_RESET 5 #define OS_MGMT_ID_MCUMGR_PARAMS 6 #define OS_MGMT_ID_INFO 7 +#define OS_MGMT_ID_BOOTLOADER_INFO 8 /** * Command result codes for OS management group. @@ -37,6 +38,9 @@ enum os_mgmt_err_code_t { /** The provided format value is not valid. */ OS_MGMT_ERR_INVALID_FORMAT, + + /** Query was not recognized. */ + OS_MGMT_ERR_QUERY_YIELDS_NO_ANSWER, }; /* Bitmask values used by the os info command handler. Note that the width of this variable is diff --git a/subsys/mgmt/mcumgr/grp/os_mgmt/CMakeLists.txt b/subsys/mgmt/mcumgr/grp/os_mgmt/CMakeLists.txt index e712acf6e94..35123fa1159 100644 --- a/subsys/mgmt/mcumgr/grp/os_mgmt/CMakeLists.txt +++ b/subsys/mgmt/mcumgr/grp/os_mgmt/CMakeLists.txt @@ -1,6 +1,6 @@ # # Copyright (c) 2018-2021 mcumgr authors -# Copyright (c) 2022 Nordic Semiconductor ASA +# Copyright (c) 2022-2023 Nordic Semiconductor ASA # # SPDX-License-Identifier: Apache-2.0 # @@ -12,6 +12,12 @@ zephyr_library_sources(src/os_mgmt.c) zephyr_library_include_directories(include) +if (CONFIG_MCUMGR_GRP_OS_BOOTLOADER_INFO) + zephyr_include_directories( + ${ZEPHYR_MCUBOOT_MODULE_DIR}/boot/bootutil/include + ) +endif() + if(DEFINED CONFIG_MCUMGR_GRP_OS_INFO_BUILD_DATE_TIME) set(MCUMGR_GRP_OS_INFO_BUILD_DATE_TIME_DIR ${PROJECT_BINARY_DIR}/os_mgmt_auto) file(MAKE_DIRECTORY ${MCUMGR_GRP_OS_INFO_BUILD_DATE_TIME_DIR}) diff --git a/subsys/mgmt/mcumgr/grp/os_mgmt/Kconfig b/subsys/mgmt/mcumgr/grp/os_mgmt/Kconfig index 897db735982..fa743b53caf 100644 --- a/subsys/mgmt/mcumgr/grp/os_mgmt/Kconfig +++ b/subsys/mgmt/mcumgr/grp/os_mgmt/Kconfig @@ -173,6 +173,16 @@ config MCUMGR_GRP_OS_INFO_BUILD_DATE_TIME endif +if BOOTLOADER_MCUBOOT + +config MCUMGR_GRP_OS_BOOTLOADER_INFO + bool "Bootloader information" + help + Allows to query MCUmgr about bootloader used by device and various bootloader + parameters. + +endif # BOOTLOADER_MCUBOOT + module = MCUMGR_GRP_OS module-str = mcumgr_grp_os source "subsys/logging/Kconfig.template.log_config" diff --git a/subsys/mgmt/mcumgr/grp/os_mgmt/src/os_mgmt.c b/subsys/mgmt/mcumgr/grp/os_mgmt/src/os_mgmt.c index 55a6fa81564..a42e2f4022f 100644 --- a/subsys/mgmt/mcumgr/grp/os_mgmt/src/os_mgmt.c +++ b/subsys/mgmt/mcumgr/grp/os_mgmt/src/os_mgmt.c @@ -33,10 +33,15 @@ #include #endif -#ifdef CONFIG_MCUMGR_GRP_OS_INFO +#if defined(CONFIG_MCUMGR_GRP_OS_INFO) || defined(CONFIG_MCUMGR_GRP_OS_BOOTLOADER_INFO) #include #include +#if defined(CONFIG_MCUMGR_GRP_OS_INFO) #include +#endif +#if defined(CONFIG_MCUMGR_GRP_OS_BOOTLOADER_INFO) +#include +#endif #include #if defined(CONFIG_NET_HOSTNAME_ENABLE) #include @@ -370,6 +375,64 @@ os_mgmt_mcumgr_params(struct smp_streamer *ctxt) } #endif +#if defined(CONFIG_MCUMGR_GRP_OS_BOOTLOADER_INFO) + +#if IS_ENABLED(CONFIG_MCUBOOT_BOOTLOADER_MODE_SINGLE_APP) +#define BOOTLOADER_MODE MCUBOOT_MODE_SINGLE_SLOT +#elif IS_ENABLED(CONFIG_MCUBOOT_BOOTLOADER_MODE_SWAP_SCRATCH) +#define BOOTLOADER_MODE MCUBOOT_MODE_SWAP_USING_SCRATCH +#elif IS_ENABLED(CONFIG_MCUBOOT_BOOTLOADER_MODE_OVERWRITE_ONLY) +#define BOOTLOADER_MODE MCUBOOT_MODE_UPGRADE_ONLY +#elif IS_ENABLED(CONFIG_MCUBOOT_BOOTLOADER_MODE_SWAP_WITHOUT_SCRATCH) +#define BOOTLOADER_MODE MCUBOOT_MODE_SWAP_USING_MOVE +#elif IS_ENABLED(CONFIG_MCUBOOT_BOOTLOADER_MODE_DIRECT_XIP) +#define BOOTLOADER_MODE MCUBOOT_MODE_DIRECT_XIP +#elif IS_ENABLED(CONFIG_MCUBOOT_BOOTLOADER_MODE_DIRECT_XIP_WITH_REVERT) +#define BOOTLOADER_MODE MCUBOOT_MODE_DIRECT_XIP_WITH_REVERT +#else +#define BOOTLOADER_MODE -1 +#endif + +static int +os_mgmt_bootloader_info(struct smp_streamer *ctxt) +{ + zcbor_state_t *zse = ctxt->writer->zs; + zcbor_state_t *zsd = ctxt->reader->zs; + struct zcbor_string query = { 0 }; + size_t decoded; + bool ok; + + struct zcbor_map_decode_key_val bootloader_info[] = { + ZCBOR_MAP_DECODE_KEY_DECODER("query", zcbor_tstr_decode, &query), + }; + + if (zcbor_map_decode_bulk(zsd, bootloader_info, ARRAY_SIZE(bootloader_info), &decoded)) { + return MGMT_ERR_EINVAL; + } + + /* If no parameter is recognized then just introduce the bootloader. */ + if (decoded == 0) { + ok = zcbor_tstr_put_lit(zse, "bootloader") && + zcbor_tstr_put_lit(zse, "MCUboot"); + } else if (zcbor_map_decode_bulk_key_found(bootloader_info, ARRAY_SIZE(bootloader_info), + "query") && + (sizeof("mode") - 1) == query.len && + memcmp("mode", query.value, query.len) == 0) { + + ok = zcbor_tstr_put_lit(zse, "mode") && + zcbor_int32_put(zse, BOOTLOADER_MODE); +#if IS_ENABLED(MCUBOOT_BOOTLOADER_NO_DOWNGRADE) + ok = zcbor_tstr_put_lit(zse, "no-downgrade") && + zcbor_bool_encode(zse, true); +#endif + } else { + return OS_MGMT_ERR_QUERY_YIELDS_NO_ANSWER; + } + + return ok ? MGMT_ERR_EOK : MGMT_ERR_EMSGSIZE; +} +#endif + #ifdef CONFIG_MCUMGR_GRP_OS_INFO /** * Command handler: os info @@ -733,6 +796,11 @@ static const struct mgmt_handler os_mgmt_group_handlers[] = { os_mgmt_info, NULL }, #endif +#ifdef CONFIG_MCUMGR_GRP_OS_BOOTLOADER_INFO + [OS_MGMT_ID_BOOTLOADER_INFO] = { + os_mgmt_bootloader_info, NULL + }, +#endif }; #define OS_MGMT_GROUP_SZ ARRAY_SIZE(os_mgmt_group_handlers) From 7d27517258a04103755733c102e74f11841a1318 Mon Sep 17 00:00:00 2001 From: Andrzej Kuros Date: Fri, 6 Oct 2023 08:41:49 +0200 Subject: [PATCH 179/421] [nrf fromlist] nrf53: fix RTC pretick power usage for events on RTC0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For RTC0 events the RTC1 pretick event was not cleared what caused the WDT to be not stopped. This resulted in increased power usage. Upstream PR: https://github.com/zephyrproject-rtos/zephyr/pull/63597 Signed-off-by: Andrzej Kuroś (cherry picked from commit 6b30e02121a9852c98ba0c7600e041da24b2c1fd) --- soc/arm/nordic_nrf/nrf53/soc.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/soc/arm/nordic_nrf/nrf53/soc.c b/soc/arm/nordic_nrf/nrf53/soc.c index aa93dfd4b54..c18228ac4fa 100644 --- a/soc/arm/nordic_nrf/nrf53/soc.c +++ b/soc/arm/nordic_nrf/nrf53/soc.c @@ -410,6 +410,8 @@ static void rtc_pretick_rtc_isr_hook(void) { NRF_IPC->PUBLISH_RECEIVE[CONFIG_SOC_NRF53_RTC_PRETICK_IPC_CH_TO_NET] &= ~IPC_PUBLISH_RECEIVE_EN_Msk; + + nrf_rtc_event_clear(NRF_RTC1, NRF_RTC_CHANNEL_EVENT_ADDR(RTC1_PRETICK_CC_CHAN)); } void rtc_pretick_rtc0_isr_hook(void) @@ -420,10 +422,6 @@ void rtc_pretick_rtc0_isr_hook(void) void rtc_pretick_rtc1_isr_hook(void) { rtc_pretick_rtc_isr_hook(); - - if (IS_ENABLED(CONFIG_SOC_NRF53_RTC_PRETICK)) { - nrf_rtc_event_clear(NRF_RTC1, NRF_RTC_CHANNEL_EVENT_ADDR(RTC1_PRETICK_CC_CHAN)); - } } static int rtc_pretick_cpunet_init(void) From aa88cae57f098f7caf7ed4aac6ba2abafbf0afe0 Mon Sep 17 00:00:00 2001 From: Gerard Marull-Paretas Date: Thu, 14 Sep 2023 14:25:18 +0200 Subject: [PATCH 180/421] [nrf fromtree] dts: bindings: arm: nordic,nrf-uicr add nfct-pins-as-gpios Allow configuring NFCT pins as GPIOs from devicetree. This setting is part of the UICR. Signed-off-by: Gerard Marull-Paretas (cherry picked from commit 1213ed4e8fdaf75a3d8eb3e9f9dc7b4d69d83722) (cherry picked from commit 8e6fa5754d9b77f0a68b7ffd8d3465561c6793cf) --- dts/bindings/arm/nordic,nrf-uicr.yaml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/dts/bindings/arm/nordic,nrf-uicr.yaml b/dts/bindings/arm/nordic,nrf-uicr.yaml index 82ac8fc2089..dbbb34e1265 100644 --- a/dts/bindings/arm/nordic,nrf-uicr.yaml +++ b/dts/bindings/arm/nordic,nrf-uicr.yaml @@ -7,3 +7,15 @@ include: base.yaml properties: reg: required: true + + nfct-pins-as-gpios: + type: boolean + description: | + When enabled this property will configure pins dedicated to NFCT + peripheral as regular GPIOs. + + NFC pins in nRF52 series: P0.09 and P0.10 + NFC pins in nRF5340: P0.02 and P0.03 + + This setting, once applied, can only be unset by erasing the UICR + registers. Refer to the reference manual for more details. From 6f482d8e6f99115d9bd09d94855f76f491afc03c Mon Sep 17 00:00:00 2001 From: Gerard Marull-Paretas Date: Thu, 14 Sep 2023 14:32:51 +0200 Subject: [PATCH 181/421] [nrf fromtree] modules: hal_nordic: inject CONFIG_NFCT_PINS_AS_GPIOS If the users configures this option in devicetree, ie, ``` &uicr { nfct-pins-as-gpios; }; ``` CMake will inject the HAL-specific CONFIG_NFCT_PINS_AS_GPIOS definition, so that the necessary operations are performed during system init. Signed-off-by: Gerard Marull-Paretas (cherry picked from commit e43c2f3eb58cb98b0fcdbde3dba810a501747200) (cherry picked from commit 0e3c0a4d50aad34f045f228fc30da217f3a3ed92) --- modules/hal_nordic/nrfx/CMakeLists.txt | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/modules/hal_nordic/nrfx/CMakeLists.txt b/modules/hal_nordic/nrfx/CMakeLists.txt index 5842ae45ad5..98ba1961396 100644 --- a/modules/hal_nordic/nrfx/CMakeLists.txt +++ b/modules/hal_nordic/nrfx/CMakeLists.txt @@ -109,3 +109,16 @@ zephyr_library_sources_ifdef(CONFIG_NRFX_WDT ${SRC_DIR}/nrfx_wdt.c) if(CONFIG_NRFX_TWI OR CONFIG_NRFX_TWIM) zephyr_library_sources(${SRC_DIR}/nrfx_twi_twim.c) endif() + +# Inject HAL "CONFIG_NFCT_PINS_AS_GPIOS" definition if user requests to +# configure the NFCT pins as GPIOS. This way, the HAL will take care of doing +# the proper configuration sequence during system init + +dt_nodelabel(uicr_path NODELABEL "uicr") +if(${uicr_path}) + dt_prop(nfct_pins_as_gpios PATH ${uicr_path} PROPERTY "nfct-pins-as-gpios") + + if(${nfct_pins_as_gpios}) + zephyr_library_compile_definitions(CONFIG_NFCT_PINS_AS_GPIOS) + endif() +endif() From dda4a3bf0be6c10a1c48516f579b1ae5d6b9ff98 Mon Sep 17 00:00:00 2001 From: Gerard Marull-Paretas Date: Thu, 14 Sep 2023 14:39:01 +0200 Subject: [PATCH 182/421] [nrf fromtree] boards: arm: nrf: use UICR nfc-pins-as-gpios devicetree property Instead of CONFIG_NFCT_PINS_AS_GPIOS (about to be deprecated). Signed-off-by: Gerard Marull-Paretas (cherry picked from commit dd568d01b89eb9e021027df140ae148144830663) (cherry picked from commit 848f5bf88c400b401a62779fb1993e5a5c853c39) --- boards/arm/bt610/bt610.dts | 4 ++++ boards/arm/bt610/bt610_defconfig | 1 - .../arm/nrf52840_mdk_usb_dongle/nrf52840_mdk_usb_dongle.dts | 4 ++++ .../nrf52840_mdk_usb_dongle/nrf52840_mdk_usb_dongle_defconfig | 1 - .../arm/nrf52840dongle_nrf52840/nrf52840dongle_nrf52840.dts | 4 ++++ .../nrf52840dongle_nrf52840/nrf52840dongle_nrf52840_defconfig | 1 - .../nrf5340_audio_dk_nrf5340_cpuapp.dts | 4 ++++ .../nrf5340_audio_dk_nrf5340_cpuapp_defconfig | 1 - boards/arm/pinetime_devkit0/pinetime_devkit0.dts | 4 ++++ boards/arm/pinetime_devkit0/pinetime_devkit0_defconfig | 3 --- 10 files changed, 20 insertions(+), 7 deletions(-) diff --git a/boards/arm/bt610/bt610.dts b/boards/arm/bt610/bt610.dts index 3c047a50fcd..6bbe8d57fe3 100644 --- a/boards/arm/bt610/bt610.dts +++ b/boards/arm/bt610/bt610.dts @@ -143,6 +143,10 @@ status = "okay"; }; +&uicr { + nfct-pins-as-gpios; +}; + &gpio0 { status = "okay"; }; diff --git a/boards/arm/bt610/bt610_defconfig b/boards/arm/bt610/bt610_defconfig index 64f0fcb85ed..1c77ed9e37b 100644 --- a/boards/arm/bt610/bt610_defconfig +++ b/boards/arm/bt610/bt610_defconfig @@ -9,7 +9,6 @@ CONFIG_ARM_MPU=y # Enable GPIO CONFIG_GPIO=y -CONFIG_NFCT_PINS_AS_GPIOS=y # Enable uart driver CONFIG_SERIAL=y diff --git a/boards/arm/nrf52840_mdk_usb_dongle/nrf52840_mdk_usb_dongle.dts b/boards/arm/nrf52840_mdk_usb_dongle/nrf52840_mdk_usb_dongle.dts index 616af71443c..8e835597c78 100644 --- a/boards/arm/nrf52840_mdk_usb_dongle/nrf52840_mdk_usb_dongle.dts +++ b/boards/arm/nrf52840_mdk_usb_dongle/nrf52840_mdk_usb_dongle.dts @@ -87,6 +87,10 @@ status = "okay"; }; +&uicr { + nfct-pins-as-gpios; +}; + &gpio0 { status = "okay"; }; diff --git a/boards/arm/nrf52840_mdk_usb_dongle/nrf52840_mdk_usb_dongle_defconfig b/boards/arm/nrf52840_mdk_usb_dongle/nrf52840_mdk_usb_dongle_defconfig index 92ec1dc7885..90850c10e0a 100644 --- a/boards/arm/nrf52840_mdk_usb_dongle/nrf52840_mdk_usb_dongle_defconfig +++ b/boards/arm/nrf52840_mdk_usb_dongle/nrf52840_mdk_usb_dongle_defconfig @@ -15,6 +15,5 @@ CONFIG_GPIO=y # additional board options CONFIG_GPIO_AS_PINRESET=y -CONFIG_NFCT_PINS_AS_GPIOS=y CONFIG_PINCTRL=y diff --git a/boards/arm/nrf52840dongle_nrf52840/nrf52840dongle_nrf52840.dts b/boards/arm/nrf52840dongle_nrf52840/nrf52840dongle_nrf52840.dts index f17ecb8e18a..93b59baa920 100644 --- a/boards/arm/nrf52840dongle_nrf52840/nrf52840dongle_nrf52840.dts +++ b/boards/arm/nrf52840dongle_nrf52840/nrf52840dongle_nrf52840.dts @@ -99,6 +99,10 @@ status = "okay"; }; +&uicr { + nfct-pins-as-gpios; +}; + &gpio0 { status = "okay"; }; diff --git a/boards/arm/nrf52840dongle_nrf52840/nrf52840dongle_nrf52840_defconfig b/boards/arm/nrf52840dongle_nrf52840/nrf52840dongle_nrf52840_defconfig index f38880961d5..32a9d03b44e 100644 --- a/boards/arm/nrf52840dongle_nrf52840/nrf52840dongle_nrf52840_defconfig +++ b/boards/arm/nrf52840dongle_nrf52840/nrf52840dongle_nrf52840_defconfig @@ -15,7 +15,6 @@ CONFIG_GPIO=y # additional board options CONFIG_GPIO_AS_PINRESET=y -CONFIG_NFCT_PINS_AS_GPIOS=y CONFIG_PINCTRL=y diff --git a/boards/arm/nrf5340_audio_dk_nrf5340/nrf5340_audio_dk_nrf5340_cpuapp.dts b/boards/arm/nrf5340_audio_dk_nrf5340/nrf5340_audio_dk_nrf5340_cpuapp.dts index 8fe46bdd7a3..be871800332 100644 --- a/boards/arm/nrf5340_audio_dk_nrf5340/nrf5340_audio_dk_nrf5340_cpuapp.dts +++ b/boards/arm/nrf5340_audio_dk_nrf5340/nrf5340_audio_dk_nrf5340_cpuapp.dts @@ -20,3 +20,7 @@ zephyr,sram-non-secure-partition = &sram0_ns; }; }; + +&uicr { + nfct-pins-as-gpios; +}; diff --git a/boards/arm/nrf5340_audio_dk_nrf5340/nrf5340_audio_dk_nrf5340_cpuapp_defconfig b/boards/arm/nrf5340_audio_dk_nrf5340/nrf5340_audio_dk_nrf5340_cpuapp_defconfig index 0f5f1991b6d..d1b5f551c9b 100644 --- a/boards/arm/nrf5340_audio_dk_nrf5340/nrf5340_audio_dk_nrf5340_cpuapp_defconfig +++ b/boards/arm/nrf5340_audio_dk_nrf5340/nrf5340_audio_dk_nrf5340_cpuapp_defconfig @@ -12,7 +12,6 @@ CONFIG_HW_STACK_PROTECTION=y CONFIG_ARM_TRUSTZONE_M=y CONFIG_GPIO=y -CONFIG_NFCT_PINS_AS_GPIOS=y CONFIG_SERIAL=y diff --git a/boards/arm/pinetime_devkit0/pinetime_devkit0.dts b/boards/arm/pinetime_devkit0/pinetime_devkit0.dts index baad177740c..fb377fd89e1 100644 --- a/boards/arm/pinetime_devkit0/pinetime_devkit0.dts +++ b/boards/arm/pinetime_devkit0/pinetime_devkit0.dts @@ -87,6 +87,10 @@ status = "okay"; }; +&uicr { + nfct-pins-as-gpios; +}; + &gpio0 { status = "okay"; diff --git a/boards/arm/pinetime_devkit0/pinetime_devkit0_defconfig b/boards/arm/pinetime_devkit0/pinetime_devkit0_defconfig index 4e48c259730..ad7442afe0d 100644 --- a/boards/arm/pinetime_devkit0/pinetime_devkit0_defconfig +++ b/boards/arm/pinetime_devkit0/pinetime_devkit0_defconfig @@ -13,9 +13,6 @@ CONFIG_SERIAL=y CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y -# use P0.09 and P0.10 as GPIOs -CONFIG_NFCT_PINS_AS_GPIOS=y - # use P0.21 as RST CONFIG_GPIO_AS_PINRESET=y From f18175381579045b4cf9ef9a9cb3d09c33832c70 Mon Sep 17 00:00:00 2001 From: Gerard Marull-Paretas Date: Thu, 14 Sep 2023 14:40:59 +0200 Subject: [PATCH 183/421] [nrf fromtree] soc: arm: nordic_nrf: deprecate CONFIG_NFCT_PINS_AS_GPIOS In favor of the new UICR nfct-pins-as-gpios devicetree property. Signed-off-by: Gerard Marull-Paretas (cherry picked from commit 0762008586976290d7a2f23b39489227b088e1fa) (cherry picked from commit 9332b9bbcaac7cfc8c34081da173548cf2498d54) --- soc/arm/nordic_nrf/Kconfig | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/soc/arm/nordic_nrf/Kconfig b/soc/arm/nordic_nrf/Kconfig index 2c386f99a53..c2129db64b3 100644 --- a/soc/arm/nordic_nrf/Kconfig +++ b/soc/arm/nordic_nrf/Kconfig @@ -47,8 +47,9 @@ config NRF_ACL_FLASH_REGION_SIZE FLASH region size for the NRF_ACL peripheral. config NFCT_PINS_AS_GPIOS - bool "NFCT pins as GPIOs" + bool "[DEPRECATED] NFCT pins as GPIOs" depends on $(dt_has_compat,$(DT_COMPAT_NORDIC_NRF_NFCT)) + select DEPRECATED help Two pins are usually reserved for NFC in SoCs that implement the NFCT peripheral. This option switches them to normal GPIO mode. @@ -60,6 +61,13 @@ config NFCT_PINS_AS_GPIOS NFC pins in nRF52 series: P0.09 and P0.10 NFC pins in nRF5340: P0.02 and P0.03 + This option is deprecated, please use devicetree to configure NFCT + pins as GPIOS like this: + + &uicr { + nfct-pins-as-gpios; + }; + choice NRF_APPROTECT_HANDLING bool "APPROTECT handling" depends on SOC_SERIES_NRF52X || SOC_NRF5340_CPUNET || \ From d2aacb763ce42db6b11a46d7617e9a8f9fc5f745 Mon Sep 17 00:00:00 2001 From: Gerard Marull-Paretas Date: Thu, 14 Sep 2023 14:45:33 +0200 Subject: [PATCH 184/421] [nrf fromtree] doc: migration-guide: add notes on CONFIG_NFCT_PINS_AS_GPIOS changes So that users know how to migrate to the new option. Signed-off-by: Gerard Marull-Paretas (cherry picked from commit c0bf310ac87e5339978e7d4072e2b93652830c7a) (cherry picked from commit 008212f5475b450f61b064313b85b571e2384a95) --- doc/releases/migration-guide-3.5.rst | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/doc/releases/migration-guide-3.5.rst b/doc/releases/migration-guide-3.5.rst index 7ffb16319d1..3f367ec5e35 100644 --- a/doc/releases/migration-guide-3.5.rst +++ b/doc/releases/migration-guide-3.5.rst @@ -42,3 +42,14 @@ Recommended Changes :kconfig:option:`CONFIG_GIC_V3` directly in Kconfig has been deprecated. The GIC version should now be specified by adding the appropriate compatible, for example :dtcompatible:`arm,gic-v2`, to the GIC node in the device tree. + +* Nordic nRF based boards using :kconfig:option:`CONFIG_NFCT_PINS_AS_GPIOS` + to configure NFCT pins as GPIOs, should instead set the new UICR + ``nfct-pins-as-gpios`` property in devicetree. It can be set like this in the + board devicetree files: + + .. code-block:: devicetree + + &uicr { + nfct-pins-as-gpios; + }; From 9fd2a0dff20d7b02531259295db889590566996e Mon Sep 17 00:00:00 2001 From: Gerard Marull-Paretas Date: Mon, 18 Sep 2023 10:59:27 +0200 Subject: [PATCH 185/421] [nrf fromtree] dts: bindings: arm: nordic,nrf-uicr: add gpio-as-nreset So that the reset GPIO can be configured as nRESET from devicetree. Signed-off-by: Gerard Marull-Paretas (cherry picked from commit 55ec77cac7a8fc0e6b859c260812ef81b7d4d911) (cherry picked from commit 2cc08226dc04b2a08e456635c1f9e9e1fc14d253) --- dts/bindings/arm/nordic,nrf-uicr.yaml | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/dts/bindings/arm/nordic,nrf-uicr.yaml b/dts/bindings/arm/nordic,nrf-uicr.yaml index dbbb34e1265..b39a6ed6855 100644 --- a/dts/bindings/arm/nordic,nrf-uicr.yaml +++ b/dts/bindings/arm/nordic,nrf-uicr.yaml @@ -19,3 +19,14 @@ properties: This setting, once applied, can only be unset by erasing the UICR registers. Refer to the reference manual for more details. + + gpio-as-nreset: + type: boolean + description: | + When enabled, this property will configure the reset GPIO as nRESET. + + nRESET pin in nRF52805/52810/52811/52832 series: P0.21 + nRESET pin in nRF52820/52833/52840 series: P0.18 + + This setting, once applied, can only be unset by erasing the UICR + registers. Refer to the reference manual for more details. From 23001717f6451eb5b14588a044525bc7dd7f07a5 Mon Sep 17 00:00:00 2001 From: Gerard Marull-Paretas Date: Mon, 18 Sep 2023 11:06:23 +0200 Subject: [PATCH 186/421] [nrf fromtree] modules: hal_nordic: nrfx: add support for 'gpio-as-nreset' So that the HAL's system init function configures the reset GPIO as nRESET if requested by the user. Signed-off-by: Gerard Marull-Paretas (cherry picked from commit 4d7d5ce226951d7bd54af38d7613e07b30641f09) (cherry picked from commit b8209dd8bb1a48dce10b34f33ca0aedf7f9b7dc6) --- modules/hal_nordic/nrfx/CMakeLists.txt | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/modules/hal_nordic/nrfx/CMakeLists.txt b/modules/hal_nordic/nrfx/CMakeLists.txt index 98ba1961396..e98db561906 100644 --- a/modules/hal_nordic/nrfx/CMakeLists.txt +++ b/modules/hal_nordic/nrfx/CMakeLists.txt @@ -111,14 +111,19 @@ if(CONFIG_NRFX_TWI OR CONFIG_NRFX_TWIM) endif() # Inject HAL "CONFIG_NFCT_PINS_AS_GPIOS" definition if user requests to -# configure the NFCT pins as GPIOS. This way, the HAL will take care of doing -# the proper configuration sequence during system init +# configure the NFCT pins as GPIOS. Do the same with "CONFIG_GPIO_AS_PINRESET" +# to configure the reset GPIO as nRESET. This way, the HAL will take care of +# doing the proper configuration sequence during system init dt_nodelabel(uicr_path NODELABEL "uicr") if(${uicr_path}) dt_prop(nfct_pins_as_gpios PATH ${uicr_path} PROPERTY "nfct-pins-as-gpios") - if(${nfct_pins_as_gpios}) zephyr_library_compile_definitions(CONFIG_NFCT_PINS_AS_GPIOS) endif() + + dt_prop(gpio_as_nreset PATH ${uicr_path} PROPERTY "gpio-as-nreset") + if(${gpio_as_nreset}) + zephyr_library_compile_definitions(CONFIG_GPIO_AS_PINRESET) + endif() endif() From 8c4003eacd144e0d1e593dd333d5bfa6c7a4d473 Mon Sep 17 00:00:00 2001 From: Gerard Marull-Paretas Date: Mon, 18 Sep 2023 11:34:15 +0200 Subject: [PATCH 187/421] [nrf fromtree] boards: arm: nrf-based: move all boards to gpio-as-nreset dt property Instead of using the about to be deprecated CONFIG_GPIO_AS_PINRESET option. Signed-off-by: Gerard Marull-Paretas (cherry picked from commit 012fa5c5ef2b314c92bf4f31634d71560d81d081) (cherry picked from commit 0a37f20794ee515d580c5d28e9b63555b945a7fe) --- boards/arm/96b_nitrogen/96b_nitrogen.dts | 4 ++++ boards/arm/96b_nitrogen/96b_nitrogen_defconfig | 3 --- boards/arm/acn52832/acn52832.dts | 4 ++++ boards/arm/acn52832/acn52832_defconfig | 3 --- .../adafruit_feather_nrf52840/adafruit_feather_nrf52840.dts | 4 ++++ .../adafruit_feather_nrf52840_defconfig | 3 --- .../adafruit_itsybitsy_nrf52840.dts | 4 ++++ .../adafruit_itsybitsy_nrf52840_defconfig | 2 -- .../arm/arduino_nano_33_ble/arduino_nano_33_ble-common.dtsi | 4 ++++ boards/arm/arduino_nano_33_ble/arduino_nano_33_ble_defconfig | 3 --- .../arduino_nano_33_ble/arduino_nano_33_ble_sense_defconfig | 3 --- boards/arm/arduino_nicla_sense_me/arduino_nicla_sense_me.dts | 4 ++++ .../arduino_nicla_sense_me/arduino_nicla_sense_me_defconfig | 3 --- boards/arm/bl652_dvk/bl652_dvk.dts | 4 ++++ boards/arm/bl652_dvk/bl652_dvk_defconfig | 3 --- boards/arm/bl653_dvk/bl653_dvk.dts | 4 ++++ boards/arm/bl653_dvk/bl653_dvk_defconfig | 3 --- boards/arm/bl654_dvk/bl654_dvk.dts | 4 ++++ boards/arm/bl654_dvk/bl654_dvk_defconfig | 3 --- boards/arm/bl654_sensor_board/bl654_sensor_board.dts | 4 ++++ boards/arm/bl654_sensor_board/bl654_sensor_board_defconfig | 3 --- boards/arm/bl654_usb/bl654_usb.dts | 4 ++++ boards/arm/bl654_usb/bl654_usb_defconfig | 3 --- .../blueclover_plt_demo_v2_nrf52832.dts | 4 ++++ .../blueclover_plt_demo_v2_nrf52832_defconfig | 3 --- boards/arm/bt510/bt510.dts | 4 ++++ boards/arm/bt510/bt510_defconfig | 3 --- boards/arm/bt610/bt610.dts | 1 + boards/arm/bt610/bt610_defconfig | 3 --- .../contextualelectronics_abc/contextualelectronics_abc.dts | 4 ++++ .../contextualelectronics_abc_defconfig | 3 --- boards/arm/decawave_dwm1001_dev/decawave_dwm1001_dev.dts | 4 ++++ .../arm/decawave_dwm1001_dev/decawave_dwm1001_dev_defconfig | 3 --- boards/arm/degu_evk/degu_evk.dts | 4 ++++ boards/arm/degu_evk/degu_evk_defconfig | 1 - boards/arm/ebyte_e73_tbb_nrf52832/ebyte_e73_tbb_nrf52832.dts | 4 ++++ .../ebyte_e73_tbb_nrf52832/ebyte_e73_tbb_nrf52832_defconfig | 3 --- boards/arm/mg100/mg100.dts | 4 ++++ boards/arm/mg100/mg100_defconfig | 3 --- boards/arm/nrf21540dk_nrf52840/nrf21540dk_nrf52840.dts | 4 ++++ boards/arm/nrf21540dk_nrf52840/nrf21540dk_nrf52840_defconfig | 3 --- boards/arm/nrf52832_mdk/nrf52832_mdk.dts | 4 ++++ boards/arm/nrf52832_mdk/nrf52832_mdk_defconfig | 3 --- boards/arm/nrf52833dk_nrf52820/nrf52833dk_nrf52820.dts | 4 ++++ boards/arm/nrf52833dk_nrf52820/nrf52833dk_nrf52820_defconfig | 3 --- boards/arm/nrf52833dk_nrf52833/nrf52833dk_nrf52833.dts | 4 ++++ boards/arm/nrf52833dk_nrf52833/nrf52833dk_nrf52833_defconfig | 3 --- boards/arm/nrf52840_blip/nrf52840_blip.dts | 4 ++++ boards/arm/nrf52840_blip/nrf52840_blip_defconfig | 3 --- boards/arm/nrf52840_mdk/nrf52840_mdk.dts | 4 ++++ boards/arm/nrf52840_mdk/nrf52840_mdk_defconfig | 3 --- .../arm/nrf52840_mdk_usb_dongle/nrf52840_mdk_usb_dongle.dts | 1 + .../nrf52840_mdk_usb_dongle/nrf52840_mdk_usb_dongle_defconfig | 3 --- boards/arm/nrf52840_papyr/nrf52840_papyr.dts | 4 ++++ boards/arm/nrf52840_papyr/nrf52840_papyr_defconfig | 3 --- boards/arm/nrf52840dk_nrf52811/nrf52840dk_nrf52811.dts | 4 ++++ boards/arm/nrf52840dk_nrf52811/nrf52840dk_nrf52811_defconfig | 3 --- boards/arm/nrf52840dk_nrf52840/nrf52840dk_nrf52840.dts | 4 ++++ boards/arm/nrf52840dk_nrf52840/nrf52840dk_nrf52840_defconfig | 3 --- .../arm/nrf52840dongle_nrf52840/nrf52840dongle_nrf52840.dts | 1 + .../nrf52840dongle_nrf52840/nrf52840dongle_nrf52840_defconfig | 3 --- boards/arm/nrf52_adafruit_feather/nrf52_adafruit_feather.dts | 4 ++++ .../nrf52_adafruit_feather/nrf52_adafruit_feather_defconfig | 3 --- boards/arm/nrf52_sparkfun/nrf52_sparkfun.dts | 4 ++++ boards/arm/nrf52_sparkfun/nrf52_sparkfun_defconfig | 3 --- boards/arm/nrf52_vbluno52/nrf52_vbluno52.dts | 4 ++++ boards/arm/nrf52_vbluno52/nrf52_vbluno52_defconfig | 3 --- boards/arm/nrf52dk_nrf52805/nrf52dk_nrf52805.dts | 4 ++++ boards/arm/nrf52dk_nrf52805/nrf52dk_nrf52805_defconfig | 3 --- boards/arm/nrf52dk_nrf52810/nrf52dk_nrf52810.dts | 4 ++++ boards/arm/nrf52dk_nrf52810/nrf52dk_nrf52810_defconfig | 3 --- boards/arm/nrf52dk_nrf52832/nrf52dk_nrf52832.dts | 4 ++++ boards/arm/nrf52dk_nrf52832/nrf52dk_nrf52832_defconfig | 3 --- boards/arm/nrf9160dk_nrf52840/nrf9160dk_nrf52840.dts | 4 ++++ boards/arm/nrf9160dk_nrf52840/nrf9160dk_nrf52840_defconfig | 3 --- boards/arm/pan1770_evb/pan1770_evb.dts | 4 ++++ boards/arm/pan1770_evb/pan1770_evb_defconfig | 3 --- boards/arm/pan1780_evb/pan1780_evb.dts | 4 ++++ boards/arm/pan1780_evb/pan1780_evb_defconfig | 3 --- boards/arm/pan1781_evb/pan1781_evb.dts | 4 ++++ boards/arm/pan1781_evb/pan1781_evb_defconfig | 3 --- boards/arm/pan1782_evb/pan1782_evb.dts | 4 ++++ boards/arm/pan1782_evb/pan1782_evb_defconfig | 3 --- boards/arm/particle_argon/particle_argon.dts | 4 ++++ boards/arm/particle_argon/particle_argon_defconfig | 3 --- boards/arm/particle_boron/particle_boron.dts | 4 ++++ boards/arm/particle_boron/particle_boron_defconfig | 3 --- boards/arm/particle_xenon/particle_xenon.dts | 4 ++++ boards/arm/particle_xenon/particle_xenon_defconfig | 3 --- boards/arm/pinetime_devkit0/pinetime_devkit0.dts | 4 ++++ boards/arm/pinetime_devkit0/pinetime_devkit0_defconfig | 3 --- boards/arm/pinnacle_100_dvk/pinnacle_100_dvk.dts | 4 ++++ boards/arm/pinnacle_100_dvk/pinnacle_100_dvk_defconfig | 3 --- boards/arm/rak4631_nrf52840/rak4631_nrf52840.dts | 4 ++++ boards/arm/rak4631_nrf52840/rak4631_nrf52840_defconfig | 3 --- .../raytac_mdbt50q_db_33_nrf52833.dts | 4 ++++ .../raytac_mdbt50q_db_33_nrf52833_defconfig | 3 --- .../raytac_mdbt50q_db_40_nrf52840.dts | 4 ++++ .../raytac_mdbt50q_db_40_nrf52840_defconfig | 3 --- boards/arm/reel_board/dts/reel_board.dtsi | 4 ++++ boards/arm/reel_board/reel_board_defconfig | 3 --- boards/arm/reel_board/reel_board_v2_defconfig | 3 --- .../arm/ubx_bmd300eval_nrf52832/ubx_bmd300eval_nrf52832.dts | 4 ++++ .../ubx_bmd300eval_nrf52832/ubx_bmd300eval_nrf52832_defconfig | 3 --- .../arm/ubx_bmd330eval_nrf52810/ubx_bmd330eval_nrf52810.dts | 4 ++++ .../ubx_bmd330eval_nrf52810/ubx_bmd330eval_nrf52810_defconfig | 3 --- .../arm/ubx_bmd340eval_nrf52840/ubx_bmd340eval_nrf52840.dts | 4 ++++ .../ubx_bmd340eval_nrf52840/ubx_bmd340eval_nrf52840_defconfig | 3 --- .../arm/ubx_bmd345eval_nrf52840/ubx_bmd345eval_nrf52840.dts | 4 ++++ .../ubx_bmd345eval_nrf52840/ubx_bmd345eval_nrf52840_defconfig | 3 --- .../arm/ubx_bmd360eval_nrf52811/ubx_bmd360eval_nrf52811.dts | 4 ++++ .../ubx_bmd360eval_nrf52811/ubx_bmd360eval_nrf52811_defconfig | 3 --- .../arm/ubx_bmd380eval_nrf52840/ubx_bmd380eval_nrf52840.dts | 4 ++++ .../ubx_bmd380eval_nrf52840/ubx_bmd380eval_nrf52840_defconfig | 3 --- boards/arm/ubx_evkannab1_nrf52832/ubx_evkannab1_nrf52832.dts | 4 ++++ .../ubx_evkannab1_nrf52832/ubx_evkannab1_nrf52832_defconfig | 3 --- boards/arm/ubx_evkninab1_nrf52832/ubx_evkninab1_nrf52832.dts | 4 ++++ .../ubx_evkninab1_nrf52832/ubx_evkninab1_nrf52832_defconfig | 3 --- boards/arm/ubx_evkninab3_nrf52840/ubx_evkninab3_nrf52840.dts | 4 ++++ .../ubx_evkninab3_nrf52840/ubx_evkninab3_nrf52840_defconfig | 3 --- boards/arm/ubx_evkninab4_nrf52833/ubx_evkninab4_nrf52833.dts | 4 ++++ .../ubx_evkninab4_nrf52833/ubx_evkninab4_nrf52833_defconfig | 3 --- boards/arm/we_ophelia1ev_nrf52805/we_ophelia1ev_nrf52805.dts | 4 ++++ .../we_ophelia1ev_nrf52805/we_ophelia1ev_nrf52805_defconfig | 3 --- boards/arm/we_proteus2ev_nrf52832/we_proteus2ev_nrf52832.dts | 4 ++++ .../we_proteus2ev_nrf52832/we_proteus2ev_nrf52832_defconfig | 3 --- boards/arm/we_proteus3ev_nrf52840/we_proteus3ev_nrf52840.dts | 4 ++++ .../we_proteus3ev_nrf52840/we_proteus3ev_nrf52840_defconfig | 3 --- boards/arm/xiao_ble/xiao_ble_common.dtsi | 4 ++++ boards/arm/xiao_ble/xiao_ble_defconfig | 3 --- boards/arm/xiao_ble/xiao_ble_sense_defconfig | 3 --- 131 files changed, 247 insertions(+), 198 deletions(-) diff --git a/boards/arm/96b_nitrogen/96b_nitrogen.dts b/boards/arm/96b_nitrogen/96b_nitrogen.dts index d5bac1cd6d3..69148a032d7 100644 --- a/boards/arm/96b_nitrogen/96b_nitrogen.dts +++ b/boards/arm/96b_nitrogen/96b_nitrogen.dts @@ -58,6 +58,10 @@ }; }; +&uicr { + gpio-as-nreset; +}; + &gpiote { status = "okay"; }; diff --git a/boards/arm/96b_nitrogen/96b_nitrogen_defconfig b/boards/arm/96b_nitrogen/96b_nitrogen_defconfig index 500c469813b..e804b43da5c 100644 --- a/boards/arm/96b_nitrogen/96b_nitrogen_defconfig +++ b/boards/arm/96b_nitrogen/96b_nitrogen_defconfig @@ -16,7 +16,4 @@ CONFIG_SERIAL=y CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y -# additional board options -CONFIG_GPIO_AS_PINRESET=y - CONFIG_PINCTRL=y diff --git a/boards/arm/acn52832/acn52832.dts b/boards/arm/acn52832/acn52832.dts index 1e01221f652..ca9f5046fba 100644 --- a/boards/arm/acn52832/acn52832.dts +++ b/boards/arm/acn52832/acn52832.dts @@ -45,6 +45,10 @@ }; }; +&uicr { + gpio-as-nreset; +}; + &gpiote { status = "okay"; }; diff --git a/boards/arm/acn52832/acn52832_defconfig b/boards/arm/acn52832/acn52832_defconfig index 6b1ae1a7ba7..2bb13882f8c 100644 --- a/boards/arm/acn52832/acn52832_defconfig +++ b/boards/arm/acn52832/acn52832_defconfig @@ -17,7 +17,4 @@ CONFIG_SERIAL=y CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y -# Enable P0_21 as RST -CONFIG_GPIO_AS_PINRESET=y - CONFIG_PINCTRL=y diff --git a/boards/arm/adafruit_feather_nrf52840/adafruit_feather_nrf52840.dts b/boards/arm/adafruit_feather_nrf52840/adafruit_feather_nrf52840.dts index 5024f43fd81..284a4d24542 100644 --- a/boards/arm/adafruit_feather_nrf52840/adafruit_feather_nrf52840.dts +++ b/boards/arm/adafruit_feather_nrf52840/adafruit_feather_nrf52840.dts @@ -61,6 +61,10 @@ status = "okay"; }; +&uicr { + gpio-as-nreset; +}; + &gpiote { status = "okay"; }; diff --git a/boards/arm/adafruit_feather_nrf52840/adafruit_feather_nrf52840_defconfig b/boards/arm/adafruit_feather_nrf52840/adafruit_feather_nrf52840_defconfig index 8d892db30f2..1f42d1a0aa4 100644 --- a/boards/arm/adafruit_feather_nrf52840/adafruit_feather_nrf52840_defconfig +++ b/boards/arm/adafruit_feather_nrf52840/adafruit_feather_nrf52840_defconfig @@ -17,7 +17,4 @@ CONFIG_SERIAL=y CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y -# additional board options -CONFIG_GPIO_AS_PINRESET=y - CONFIG_PINCTRL=y diff --git a/boards/arm/adafruit_itsybitsy_nrf52840/adafruit_itsybitsy_nrf52840.dts b/boards/arm/adafruit_itsybitsy_nrf52840/adafruit_itsybitsy_nrf52840.dts index 6e827388aef..103e18d8328 100644 --- a/boards/arm/adafruit_itsybitsy_nrf52840/adafruit_itsybitsy_nrf52840.dts +++ b/boards/arm/adafruit_itsybitsy_nrf52840/adafruit_itsybitsy_nrf52840.dts @@ -55,6 +55,10 @@ status = "okay"; }; +&uicr { + gpio-as-nreset; +}; + &gpiote { status = "okay"; }; diff --git a/boards/arm/adafruit_itsybitsy_nrf52840/adafruit_itsybitsy_nrf52840_defconfig b/boards/arm/adafruit_itsybitsy_nrf52840/adafruit_itsybitsy_nrf52840_defconfig index bc27efcdd29..e5a88c27fb3 100644 --- a/boards/arm/adafruit_itsybitsy_nrf52840/adafruit_itsybitsy_nrf52840_defconfig +++ b/boards/arm/adafruit_itsybitsy_nrf52840/adafruit_itsybitsy_nrf52840_defconfig @@ -17,8 +17,6 @@ CONFIG_SERIAL=y CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y -# additional board options -CONFIG_GPIO_AS_PINRESET=y CONFIG_PINCTRL=y # Flashing diff --git a/boards/arm/arduino_nano_33_ble/arduino_nano_33_ble-common.dtsi b/boards/arm/arduino_nano_33_ble/arduino_nano_33_ble-common.dtsi index 60c0d63920c..200db7f94c7 100644 --- a/boards/arm/arduino_nano_33_ble/arduino_nano_33_ble-common.dtsi +++ b/boards/arm/arduino_nano_33_ble/arduino_nano_33_ble-common.dtsi @@ -177,6 +177,10 @@ arduino_spi: &spi2 { pinctrl-names = "default", "sleep"; }; +&uicr { + gpio-as-nreset; +}; + &gpio0 { status = "okay"; }; diff --git a/boards/arm/arduino_nano_33_ble/arduino_nano_33_ble_defconfig b/boards/arm/arduino_nano_33_ble/arduino_nano_33_ble_defconfig index 2d91725aaf9..dcdc0c8a836 100644 --- a/boards/arm/arduino_nano_33_ble/arduino_nano_33_ble_defconfig +++ b/boards/arm/arduino_nano_33_ble/arduino_nano_33_ble_defconfig @@ -20,7 +20,4 @@ CONFIG_UART_CONSOLE=y CONFIG_BOOTLOADER_BOSSA=y CONFIG_BOOTLOADER_BOSSA_LEGACY=y -# additional board options -CONFIG_GPIO_AS_PINRESET=y - CONFIG_PINCTRL=y diff --git a/boards/arm/arduino_nano_33_ble/arduino_nano_33_ble_sense_defconfig b/boards/arm/arduino_nano_33_ble/arduino_nano_33_ble_sense_defconfig index 8ef8ece861c..4604c6bf386 100644 --- a/boards/arm/arduino_nano_33_ble/arduino_nano_33_ble_sense_defconfig +++ b/boards/arm/arduino_nano_33_ble/arduino_nano_33_ble_sense_defconfig @@ -20,7 +20,4 @@ CONFIG_UART_CONSOLE=y CONFIG_BOOTLOADER_BOSSA=y CONFIG_BOOTLOADER_BOSSA_LEGACY=y -# additional board options -CONFIG_GPIO_AS_PINRESET=y - CONFIG_PINCTRL=y diff --git a/boards/arm/arduino_nicla_sense_me/arduino_nicla_sense_me.dts b/boards/arm/arduino_nicla_sense_me/arduino_nicla_sense_me.dts index ada4c76441c..2329853a1a3 100644 --- a/boards/arm/arduino_nicla_sense_me/arduino_nicla_sense_me.dts +++ b/boards/arm/arduino_nicla_sense_me/arduino_nicla_sense_me.dts @@ -45,6 +45,10 @@ status = "okay"; }; +&uicr { + gpio-as-nreset; +}; + &gpiote { status = "okay"; }; diff --git a/boards/arm/arduino_nicla_sense_me/arduino_nicla_sense_me_defconfig b/boards/arm/arduino_nicla_sense_me/arduino_nicla_sense_me_defconfig index 396d37d36e0..c2f2b95cc72 100644 --- a/boards/arm/arduino_nicla_sense_me/arduino_nicla_sense_me_defconfig +++ b/boards/arm/arduino_nicla_sense_me/arduino_nicla_sense_me_defconfig @@ -18,8 +18,5 @@ CONFIG_SERIAL=y CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y -# additional board options -CONFIG_GPIO_AS_PINRESET=y - # enable pin controller CONFIG_PINCTRL=y diff --git a/boards/arm/bl652_dvk/bl652_dvk.dts b/boards/arm/bl652_dvk/bl652_dvk.dts index 5569f1323c0..f2cffbd819b 100644 --- a/boards/arm/bl652_dvk/bl652_dvk.dts +++ b/boards/arm/bl652_dvk/bl652_dvk.dts @@ -68,6 +68,10 @@ status = "okay"; }; +&uicr { + gpio-as-nreset; +}; + &gpiote { status = "okay"; }; diff --git a/boards/arm/bl652_dvk/bl652_dvk_defconfig b/boards/arm/bl652_dvk/bl652_dvk_defconfig index 1ca971e2546..5302fa8d53f 100644 --- a/boards/arm/bl652_dvk/bl652_dvk_defconfig +++ b/boards/arm/bl652_dvk/bl652_dvk_defconfig @@ -21,9 +21,6 @@ CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y CONFIG_RTT_CONSOLE=y -# additional board options -CONFIG_GPIO_AS_PINRESET=y - # 32kHz clock source CONFIG_CLOCK_CONTROL_NRF_K32SRC_RC=y CONFIG_CLOCK_CONTROL_NRF_K32SRC_500PPM=y diff --git a/boards/arm/bl653_dvk/bl653_dvk.dts b/boards/arm/bl653_dvk/bl653_dvk.dts index ceb91aeb96f..ba8fa3658d2 100644 --- a/boards/arm/bl653_dvk/bl653_dvk.dts +++ b/boards/arm/bl653_dvk/bl653_dvk.dts @@ -91,6 +91,10 @@ status = "okay"; }; +&uicr { + gpio-as-nreset; +}; + &gpiote { status = "okay"; }; diff --git a/boards/arm/bl653_dvk/bl653_dvk_defconfig b/boards/arm/bl653_dvk/bl653_dvk_defconfig index 4933055c93c..83b73ef4435 100644 --- a/boards/arm/bl653_dvk/bl653_dvk_defconfig +++ b/boards/arm/bl653_dvk/bl653_dvk_defconfig @@ -20,9 +20,6 @@ CONFIG_SERIAL=y CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y -# additional board options -CONFIG_GPIO_AS_PINRESET=y - # 32kHz clock source CONFIG_CLOCK_CONTROL_NRF_K32SRC_RC=y CONFIG_CLOCK_CONTROL_NRF_K32SRC_500PPM=y diff --git a/boards/arm/bl654_dvk/bl654_dvk.dts b/boards/arm/bl654_dvk/bl654_dvk.dts index b99435696d1..7ede69427de 100644 --- a/boards/arm/bl654_dvk/bl654_dvk.dts +++ b/boards/arm/bl654_dvk/bl654_dvk.dts @@ -91,6 +91,10 @@ status = "okay"; }; +&uicr { + gpio-as-nreset; +}; + &gpiote { status = "okay"; }; diff --git a/boards/arm/bl654_dvk/bl654_dvk_defconfig b/boards/arm/bl654_dvk/bl654_dvk_defconfig index aa2238cda87..976495f7e88 100644 --- a/boards/arm/bl654_dvk/bl654_dvk_defconfig +++ b/boards/arm/bl654_dvk/bl654_dvk_defconfig @@ -21,9 +21,6 @@ CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y CONFIG_RTT_CONSOLE=y -# additional board options -CONFIG_GPIO_AS_PINRESET=y - # 32kHz clock source CONFIG_CLOCK_CONTROL_NRF_K32SRC_RC=y CONFIG_CLOCK_CONTROL_NRF_K32SRC_500PPM=y diff --git a/boards/arm/bl654_sensor_board/bl654_sensor_board.dts b/boards/arm/bl654_sensor_board/bl654_sensor_board.dts index 1c2949ee2e8..c43354f2705 100644 --- a/boards/arm/bl654_sensor_board/bl654_sensor_board.dts +++ b/boards/arm/bl654_sensor_board/bl654_sensor_board.dts @@ -56,6 +56,10 @@ status = "okay"; }; +&uicr { + gpio-as-nreset; +}; + &gpiote { status = "okay"; }; diff --git a/boards/arm/bl654_sensor_board/bl654_sensor_board_defconfig b/boards/arm/bl654_sensor_board/bl654_sensor_board_defconfig index 259fac9d309..e92c2c4005f 100644 --- a/boards/arm/bl654_sensor_board/bl654_sensor_board_defconfig +++ b/boards/arm/bl654_sensor_board/bl654_sensor_board_defconfig @@ -17,9 +17,6 @@ CONFIG_SERIAL=y CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y -# Additional board options -CONFIG_GPIO_AS_PINRESET=y - # 32KHz clock source CONFIG_CLOCK_CONTROL_NRF_K32SRC_XTAL=y CONFIG_CLOCK_CONTROL_NRF_K32SRC_150PPM=y diff --git a/boards/arm/bl654_usb/bl654_usb.dts b/boards/arm/bl654_usb/bl654_usb.dts index 2cc6850a468..80600290dbf 100644 --- a/boards/arm/bl654_usb/bl654_usb.dts +++ b/boards/arm/bl654_usb/bl654_usb.dts @@ -47,6 +47,10 @@ }; }; +&uicr { + gpio-as-nreset; +}; + &gpio0 { status = "okay"; }; diff --git a/boards/arm/bl654_usb/bl654_usb_defconfig b/boards/arm/bl654_usb/bl654_usb_defconfig index 59c26ddb4d7..983150c35d9 100644 --- a/boards/arm/bl654_usb/bl654_usb_defconfig +++ b/boards/arm/bl654_usb/bl654_usb_defconfig @@ -19,9 +19,6 @@ CONFIG_GPIO=y # Enable USB CONFIG_USB_DEVICE_STACK=y -# Additional board options -CONFIG_GPIO_AS_PINRESET=y - # 32KHz clock source CONFIG_CLOCK_CONTROL_NRF_K32SRC_XTAL=y CONFIG_CLOCK_CONTROL_NRF_K32SRC_150PPM=y diff --git a/boards/arm/blueclover_plt_demo_v2_nrf52832/blueclover_plt_demo_v2_nrf52832.dts b/boards/arm/blueclover_plt_demo_v2_nrf52832/blueclover_plt_demo_v2_nrf52832.dts index cf7dd7a52de..4c49979bb0a 100644 --- a/boards/arm/blueclover_plt_demo_v2_nrf52832/blueclover_plt_demo_v2_nrf52832.dts +++ b/boards/arm/blueclover_plt_demo_v2_nrf52832/blueclover_plt_demo_v2_nrf52832.dts @@ -48,6 +48,10 @@ }; }; +&uicr { + gpio-as-nreset; +}; + &gpiote { status ="okay"; }; diff --git a/boards/arm/blueclover_plt_demo_v2_nrf52832/blueclover_plt_demo_v2_nrf52832_defconfig b/boards/arm/blueclover_plt_demo_v2_nrf52832/blueclover_plt_demo_v2_nrf52832_defconfig index 52f089ba0d6..301a23af362 100644 --- a/boards/arm/blueclover_plt_demo_v2_nrf52832/blueclover_plt_demo_v2_nrf52832_defconfig +++ b/boards/arm/blueclover_plt_demo_v2_nrf52832/blueclover_plt_demo_v2_nrf52832_defconfig @@ -24,7 +24,4 @@ CONFIG_SERIAL=y CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y -# additional board options -CONFIG_GPIO_AS_PINRESET=y - CONFIG_PINCTRL=y diff --git a/boards/arm/bt510/bt510.dts b/boards/arm/bt510/bt510.dts index 74818be0d7c..984b098e5d5 100644 --- a/boards/arm/bt510/bt510.dts +++ b/boards/arm/bt510/bt510.dts @@ -72,6 +72,10 @@ status = "okay"; }; +&uicr { + gpio-as-nreset; +}; + &gpiote { status = "okay"; }; diff --git a/boards/arm/bt510/bt510_defconfig b/boards/arm/bt510/bt510_defconfig index fd86ea3f0f2..eb769cc9465 100644 --- a/boards/arm/bt510/bt510_defconfig +++ b/boards/arm/bt510/bt510_defconfig @@ -17,9 +17,6 @@ CONFIG_SERIAL=y CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y -# Additional board options -CONFIG_GPIO_AS_PINRESET=y - # 32KHz clock source CONFIG_CLOCK_CONTROL_NRF_K32SRC_XTAL=y CONFIG_CLOCK_CONTROL_NRF_K32SRC_150PPM=y diff --git a/boards/arm/bt610/bt610.dts b/boards/arm/bt610/bt610.dts index 6bbe8d57fe3..489401a5fb3 100644 --- a/boards/arm/bt610/bt610.dts +++ b/boards/arm/bt610/bt610.dts @@ -145,6 +145,7 @@ &uicr { nfct-pins-as-gpios; + gpio-as-nreset; }; &gpio0 { diff --git a/boards/arm/bt610/bt610_defconfig b/boards/arm/bt610/bt610_defconfig index 1c77ed9e37b..d1d7226fade 100644 --- a/boards/arm/bt610/bt610_defconfig +++ b/boards/arm/bt610/bt610_defconfig @@ -17,9 +17,6 @@ CONFIG_SERIAL=y CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y -# Additional board options -CONFIG_GPIO_AS_PINRESET=y - # Enable hardware stack protection CONFIG_HW_STACK_PROTECTION=y diff --git a/boards/arm/contextualelectronics_abc/contextualelectronics_abc.dts b/boards/arm/contextualelectronics_abc/contextualelectronics_abc.dts index ebc866afeff..6f60b1ddfed 100644 --- a/boards/arm/contextualelectronics_abc/contextualelectronics_abc.dts +++ b/boards/arm/contextualelectronics_abc/contextualelectronics_abc.dts @@ -25,6 +25,10 @@ }; }; +&uicr { + gpio-as-nreset; +}; + &gpiote { status = "okay"; }; diff --git a/boards/arm/contextualelectronics_abc/contextualelectronics_abc_defconfig b/boards/arm/contextualelectronics_abc/contextualelectronics_abc_defconfig index bb841469339..7a3055b9c82 100644 --- a/boards/arm/contextualelectronics_abc/contextualelectronics_abc_defconfig +++ b/boards/arm/contextualelectronics_abc/contextualelectronics_abc_defconfig @@ -20,7 +20,4 @@ CONFIG_SERIAL=y CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y -# Additional board options -CONFIG_GPIO_AS_PINRESET=y - CONFIG_PINCTRL=y diff --git a/boards/arm/decawave_dwm1001_dev/decawave_dwm1001_dev.dts b/boards/arm/decawave_dwm1001_dev/decawave_dwm1001_dev.dts index 75510faf4a6..a1c415fc299 100644 --- a/boards/arm/decawave_dwm1001_dev/decawave_dwm1001_dev.dts +++ b/boards/arm/decawave_dwm1001_dev/decawave_dwm1001_dev.dts @@ -84,6 +84,10 @@ status = "okay"; }; +&uicr { + gpio-as-nreset; +}; + &gpiote { status = "okay"; }; diff --git a/boards/arm/decawave_dwm1001_dev/decawave_dwm1001_dev_defconfig b/boards/arm/decawave_dwm1001_dev/decawave_dwm1001_dev_defconfig index 89d31bfd45b..4cb6022e7ae 100644 --- a/boards/arm/decawave_dwm1001_dev/decawave_dwm1001_dev_defconfig +++ b/boards/arm/decawave_dwm1001_dev/decawave_dwm1001_dev_defconfig @@ -21,7 +21,4 @@ CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y CONFIG_RTT_CONSOLE=y -# additional board options -CONFIG_GPIO_AS_PINRESET=y - CONFIG_PINCTRL=y diff --git a/boards/arm/degu_evk/degu_evk.dts b/boards/arm/degu_evk/degu_evk.dts index caa134752e0..eb3329726e9 100644 --- a/boards/arm/degu_evk/degu_evk.dts +++ b/boards/arm/degu_evk/degu_evk.dts @@ -92,6 +92,10 @@ status ="okay"; }; +&uicr { + gpio-as-nreset; +}; + &gpiote { status ="okay"; }; diff --git a/boards/arm/degu_evk/degu_evk_defconfig b/boards/arm/degu_evk/degu_evk_defconfig index 7b9d7737481..e003438c3dc 100644 --- a/boards/arm/degu_evk/degu_evk_defconfig +++ b/boards/arm/degu_evk/degu_evk_defconfig @@ -17,7 +17,6 @@ CONFIG_USB_DEVICE_STACK=y # additional board options CONFIG_GPIO=y -CONFIG_GPIO_AS_PINRESET=y # required to enable 3V3 power rail and Vin1 monitor CONFIG_REGULATOR=y diff --git a/boards/arm/ebyte_e73_tbb_nrf52832/ebyte_e73_tbb_nrf52832.dts b/boards/arm/ebyte_e73_tbb_nrf52832/ebyte_e73_tbb_nrf52832.dts index 9fa240cb5ae..31eb0cc7524 100644 --- a/boards/arm/ebyte_e73_tbb_nrf52832/ebyte_e73_tbb_nrf52832.dts +++ b/boards/arm/ebyte_e73_tbb_nrf52832/ebyte_e73_tbb_nrf52832.dts @@ -75,6 +75,10 @@ status = "okay"; }; +&uicr { + gpio-as-nreset; +}; + &gpiote { status = "okay"; }; diff --git a/boards/arm/ebyte_e73_tbb_nrf52832/ebyte_e73_tbb_nrf52832_defconfig b/boards/arm/ebyte_e73_tbb_nrf52832/ebyte_e73_tbb_nrf52832_defconfig index 3e1778de525..05acf2ca945 100644 --- a/boards/arm/ebyte_e73_tbb_nrf52832/ebyte_e73_tbb_nrf52832_defconfig +++ b/boards/arm/ebyte_e73_tbb_nrf52832/ebyte_e73_tbb_nrf52832_defconfig @@ -23,7 +23,4 @@ CONFIG_SERIAL=y CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y -# Additional board options -CONFIG_GPIO_AS_PINRESET=y - CONFIG_PINCTRL=y diff --git a/boards/arm/mg100/mg100.dts b/boards/arm/mg100/mg100.dts index 512ca901010..0d33fd32151 100644 --- a/boards/arm/mg100/mg100.dts +++ b/boards/arm/mg100/mg100.dts @@ -65,6 +65,10 @@ status = "okay"; }; +&uicr { + gpio-as-nreset; +}; + &gpiote { status = "okay"; }; diff --git a/boards/arm/mg100/mg100_defconfig b/boards/arm/mg100/mg100_defconfig index 93f55f3d0a4..bb7d09dabf2 100644 --- a/boards/arm/mg100/mg100_defconfig +++ b/boards/arm/mg100/mg100_defconfig @@ -18,9 +18,6 @@ CONFIG_SERIAL=y CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y -# Additional board options -CONFIG_GPIO_AS_PINRESET=y - # 32KHz clock source CONFIG_CLOCK_CONTROL_NRF_K32SRC_XTAL=y CONFIG_CLOCK_CONTROL_NRF_K32SRC_150PPM=y diff --git a/boards/arm/nrf21540dk_nrf52840/nrf21540dk_nrf52840.dts b/boards/arm/nrf21540dk_nrf52840/nrf21540dk_nrf52840.dts index 077eb4a1657..af0ea59794c 100644 --- a/boards/arm/nrf21540dk_nrf52840/nrf21540dk_nrf52840.dts +++ b/boards/arm/nrf21540dk_nrf52840/nrf21540dk_nrf52840.dts @@ -150,6 +150,10 @@ status = "okay"; }; +&uicr { + gpio-as-nreset; +}; + &gpiote { status = "okay"; }; diff --git a/boards/arm/nrf21540dk_nrf52840/nrf21540dk_nrf52840_defconfig b/boards/arm/nrf21540dk_nrf52840/nrf21540dk_nrf52840_defconfig index 56d8497b43a..af230adb18a 100644 --- a/boards/arm/nrf21540dk_nrf52840/nrf21540dk_nrf52840_defconfig +++ b/boards/arm/nrf21540dk_nrf52840/nrf21540dk_nrf52840_defconfig @@ -23,7 +23,4 @@ CONFIG_SERIAL=y CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y -# additional board options -CONFIG_GPIO_AS_PINRESET=y - CONFIG_PINCTRL=y diff --git a/boards/arm/nrf52832_mdk/nrf52832_mdk.dts b/boards/arm/nrf52832_mdk/nrf52832_mdk.dts index 348a5b79745..c51002c6497 100644 --- a/boards/arm/nrf52832_mdk/nrf52832_mdk.dts +++ b/boards/arm/nrf52832_mdk/nrf52832_mdk.dts @@ -86,6 +86,10 @@ }; +&uicr { + gpio-as-nreset; +}; + &gpiote { status = "okay"; }; diff --git a/boards/arm/nrf52832_mdk/nrf52832_mdk_defconfig b/boards/arm/nrf52832_mdk/nrf52832_mdk_defconfig index 2c283bda97e..8993b59f938 100644 --- a/boards/arm/nrf52832_mdk/nrf52832_mdk_defconfig +++ b/boards/arm/nrf52832_mdk/nrf52832_mdk_defconfig @@ -17,7 +17,4 @@ CONFIG_SERIAL=y CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y -# additional board options -CONFIG_GPIO_AS_PINRESET=y - CONFIG_PINCTRL=y diff --git a/boards/arm/nrf52833dk_nrf52820/nrf52833dk_nrf52820.dts b/boards/arm/nrf52833dk_nrf52820/nrf52833dk_nrf52820.dts index f70d6649aa8..4942dd6daa0 100644 --- a/boards/arm/nrf52833dk_nrf52820/nrf52833dk_nrf52820.dts +++ b/boards/arm/nrf52833dk_nrf52820/nrf52833dk_nrf52820.dts @@ -99,6 +99,10 @@ clock-prescaler = <8>; }; +&uicr { + gpio-as-nreset; +}; + &gpiote { status = "okay"; }; diff --git a/boards/arm/nrf52833dk_nrf52820/nrf52833dk_nrf52820_defconfig b/boards/arm/nrf52833dk_nrf52820/nrf52833dk_nrf52820_defconfig index 9bbc4da98cb..9ef66860ab3 100644 --- a/boards/arm/nrf52833dk_nrf52820/nrf52833dk_nrf52820_defconfig +++ b/boards/arm/nrf52833dk_nrf52820/nrf52833dk_nrf52820_defconfig @@ -23,7 +23,4 @@ CONFIG_SERIAL=y CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y -# additional board options -CONFIG_GPIO_AS_PINRESET=y - CONFIG_PINCTRL=y diff --git a/boards/arm/nrf52833dk_nrf52833/nrf52833dk_nrf52833.dts b/boards/arm/nrf52833dk_nrf52833/nrf52833dk_nrf52833.dts index 0d1725d5bbb..b488b5d1ff3 100644 --- a/boards/arm/nrf52833dk_nrf52833/nrf52833dk_nrf52833.dts +++ b/boards/arm/nrf52833dk_nrf52833/nrf52833dk_nrf52833.dts @@ -127,6 +127,10 @@ status = "okay"; }; +&uicr { + gpio-as-nreset; +}; + &gpiote { status = "okay"; }; diff --git a/boards/arm/nrf52833dk_nrf52833/nrf52833dk_nrf52833_defconfig b/boards/arm/nrf52833dk_nrf52833/nrf52833dk_nrf52833_defconfig index 7fe9f4e480c..9cbee72b2e7 100644 --- a/boards/arm/nrf52833dk_nrf52833/nrf52833dk_nrf52833_defconfig +++ b/boards/arm/nrf52833dk_nrf52833/nrf52833dk_nrf52833_defconfig @@ -23,7 +23,4 @@ CONFIG_SERIAL=y CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y -# additional board options -CONFIG_GPIO_AS_PINRESET=y - CONFIG_PINCTRL=y diff --git a/boards/arm/nrf52840_blip/nrf52840_blip.dts b/boards/arm/nrf52840_blip/nrf52840_blip.dts index 112d22799bc..e641c60bd1f 100644 --- a/boards/arm/nrf52840_blip/nrf52840_blip.dts +++ b/boards/arm/nrf52840_blip/nrf52840_blip.dts @@ -66,6 +66,10 @@ status = "okay"; }; +&uicr { + gpio-as-nreset; +}; + &gpiote { status = "okay"; }; diff --git a/boards/arm/nrf52840_blip/nrf52840_blip_defconfig b/boards/arm/nrf52840_blip/nrf52840_blip_defconfig index 82c0146ecf1..811a88de939 100644 --- a/boards/arm/nrf52840_blip/nrf52840_blip_defconfig +++ b/boards/arm/nrf52840_blip/nrf52840_blip_defconfig @@ -17,7 +17,4 @@ CONFIG_SERIAL=y CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y -# additional board options -CONFIG_GPIO_AS_PINRESET=y - CONFIG_PINCTRL=y diff --git a/boards/arm/nrf52840_mdk/nrf52840_mdk.dts b/boards/arm/nrf52840_mdk/nrf52840_mdk.dts index 0ed4addb069..2439b0c2aca 100644 --- a/boards/arm/nrf52840_mdk/nrf52840_mdk.dts +++ b/boards/arm/nrf52840_mdk/nrf52840_mdk.dts @@ -90,6 +90,10 @@ status = "okay"; }; +&uicr { + gpio-as-nreset; +}; + &gpiote { status = "okay"; }; diff --git a/boards/arm/nrf52840_mdk/nrf52840_mdk_defconfig b/boards/arm/nrf52840_mdk/nrf52840_mdk_defconfig index f0ed2a2fbad..e4c79a2bf88 100644 --- a/boards/arm/nrf52840_mdk/nrf52840_mdk_defconfig +++ b/boards/arm/nrf52840_mdk/nrf52840_mdk_defconfig @@ -17,7 +17,4 @@ CONFIG_SERIAL=y CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y -# additional board options -CONFIG_GPIO_AS_PINRESET=y - CONFIG_PINCTRL=y diff --git a/boards/arm/nrf52840_mdk_usb_dongle/nrf52840_mdk_usb_dongle.dts b/boards/arm/nrf52840_mdk_usb_dongle/nrf52840_mdk_usb_dongle.dts index 8e835597c78..4e13783d656 100644 --- a/boards/arm/nrf52840_mdk_usb_dongle/nrf52840_mdk_usb_dongle.dts +++ b/boards/arm/nrf52840_mdk_usb_dongle/nrf52840_mdk_usb_dongle.dts @@ -89,6 +89,7 @@ &uicr { nfct-pins-as-gpios; + gpio-as-nreset; }; &gpio0 { diff --git a/boards/arm/nrf52840_mdk_usb_dongle/nrf52840_mdk_usb_dongle_defconfig b/boards/arm/nrf52840_mdk_usb_dongle/nrf52840_mdk_usb_dongle_defconfig index 90850c10e0a..8701863e99a 100644 --- a/boards/arm/nrf52840_mdk_usb_dongle/nrf52840_mdk_usb_dongle_defconfig +++ b/boards/arm/nrf52840_mdk_usb_dongle/nrf52840_mdk_usb_dongle_defconfig @@ -13,7 +13,4 @@ CONFIG_HW_STACK_PROTECTION=y # enable GPIO CONFIG_GPIO=y -# additional board options -CONFIG_GPIO_AS_PINRESET=y - CONFIG_PINCTRL=y diff --git a/boards/arm/nrf52840_papyr/nrf52840_papyr.dts b/boards/arm/nrf52840_papyr/nrf52840_papyr.dts index acbb09d2df2..0a9d8ff4724 100644 --- a/boards/arm/nrf52840_papyr/nrf52840_papyr.dts +++ b/boards/arm/nrf52840_papyr/nrf52840_papyr.dts @@ -85,6 +85,10 @@ status = "okay"; }; +&uicr { + gpio-as-nreset; +}; + &gpiote { status = "okay"; }; diff --git a/boards/arm/nrf52840_papyr/nrf52840_papyr_defconfig b/boards/arm/nrf52840_papyr/nrf52840_papyr_defconfig index 0ad48d7f940..4a5e737cd14 100644 --- a/boards/arm/nrf52840_papyr/nrf52840_papyr_defconfig +++ b/boards/arm/nrf52840_papyr/nrf52840_papyr_defconfig @@ -17,7 +17,4 @@ CONFIG_SERIAL=y CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y -# additional board options -CONFIG_GPIO_AS_PINRESET=y - CONFIG_PINCTRL=y diff --git a/boards/arm/nrf52840dk_nrf52811/nrf52840dk_nrf52811.dts b/boards/arm/nrf52840dk_nrf52811/nrf52840dk_nrf52811.dts index eb99beca22f..a53a174be15 100644 --- a/boards/arm/nrf52840dk_nrf52811/nrf52840dk_nrf52811.dts +++ b/boards/arm/nrf52840dk_nrf52811/nrf52840dk_nrf52811.dts @@ -97,6 +97,10 @@ status = "okay"; }; +&uicr { + gpio-as-nreset; +}; + &gpiote { status = "okay"; }; diff --git a/boards/arm/nrf52840dk_nrf52811/nrf52840dk_nrf52811_defconfig b/boards/arm/nrf52840dk_nrf52811/nrf52840dk_nrf52811_defconfig index 36553a757eb..2c6b7f2fc82 100644 --- a/boards/arm/nrf52840dk_nrf52811/nrf52840dk_nrf52811_defconfig +++ b/boards/arm/nrf52840dk_nrf52811/nrf52840dk_nrf52811_defconfig @@ -22,9 +22,6 @@ CONFIG_UART_CONSOLE=y # enable GPIO CONFIG_GPIO=y -# additional board options -CONFIG_GPIO_AS_PINRESET=y - # Bluetooth not enabled by default on nRF52811 due to RAM limitations when # running the default set of kernel tests. # Enable this on your prj.conf to include Bluetooth support diff --git a/boards/arm/nrf52840dk_nrf52840/nrf52840dk_nrf52840.dts b/boards/arm/nrf52840dk_nrf52840/nrf52840dk_nrf52840.dts index ba5d94738a6..96006ec4722 100644 --- a/boards/arm/nrf52840dk_nrf52840/nrf52840dk_nrf52840.dts +++ b/boards/arm/nrf52840dk_nrf52840/nrf52840dk_nrf52840.dts @@ -139,6 +139,10 @@ status = "okay"; }; +&uicr { + gpio-as-nreset; +}; + &gpiote { status = "okay"; }; diff --git a/boards/arm/nrf52840dk_nrf52840/nrf52840dk_nrf52840_defconfig b/boards/arm/nrf52840dk_nrf52840/nrf52840dk_nrf52840_defconfig index 100d91ed320..9f1232a8f0a 100644 --- a/boards/arm/nrf52840dk_nrf52840/nrf52840dk_nrf52840_defconfig +++ b/boards/arm/nrf52840dk_nrf52840/nrf52840dk_nrf52840_defconfig @@ -23,7 +23,4 @@ CONFIG_SERIAL=y CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y -# additional board options -CONFIG_GPIO_AS_PINRESET=y - CONFIG_PINCTRL=y diff --git a/boards/arm/nrf52840dongle_nrf52840/nrf52840dongle_nrf52840.dts b/boards/arm/nrf52840dongle_nrf52840/nrf52840dongle_nrf52840.dts index 93b59baa920..dcf9fb690d1 100644 --- a/boards/arm/nrf52840dongle_nrf52840/nrf52840dongle_nrf52840.dts +++ b/boards/arm/nrf52840dongle_nrf52840/nrf52840dongle_nrf52840.dts @@ -101,6 +101,7 @@ &uicr { nfct-pins-as-gpios; + gpio-as-nreset; }; &gpio0 { diff --git a/boards/arm/nrf52840dongle_nrf52840/nrf52840dongle_nrf52840_defconfig b/boards/arm/nrf52840dongle_nrf52840/nrf52840dongle_nrf52840_defconfig index 32a9d03b44e..c367a90d5ef 100644 --- a/boards/arm/nrf52840dongle_nrf52840/nrf52840dongle_nrf52840_defconfig +++ b/boards/arm/nrf52840dongle_nrf52840/nrf52840dongle_nrf52840_defconfig @@ -13,9 +13,6 @@ CONFIG_HW_STACK_PROTECTION=y # enable GPIO CONFIG_GPIO=y -# additional board options -CONFIG_GPIO_AS_PINRESET=y - CONFIG_PINCTRL=y # Board Kconfig.defconfig enables USB CDC ACM and should disable USB remote diff --git a/boards/arm/nrf52_adafruit_feather/nrf52_adafruit_feather.dts b/boards/arm/nrf52_adafruit_feather/nrf52_adafruit_feather.dts index 4412d3c492d..c29ca8000dc 100644 --- a/boards/arm/nrf52_adafruit_feather/nrf52_adafruit_feather.dts +++ b/boards/arm/nrf52_adafruit_feather/nrf52_adafruit_feather.dts @@ -70,6 +70,10 @@ }; }; +&uicr { + gpio-as-nreset; +}; + &gpiote { status = "okay"; }; diff --git a/boards/arm/nrf52_adafruit_feather/nrf52_adafruit_feather_defconfig b/boards/arm/nrf52_adafruit_feather/nrf52_adafruit_feather_defconfig index 42948633b2f..19aaa3825d1 100644 --- a/boards/arm/nrf52_adafruit_feather/nrf52_adafruit_feather_defconfig +++ b/boards/arm/nrf52_adafruit_feather/nrf52_adafruit_feather_defconfig @@ -17,7 +17,4 @@ CONFIG_SERIAL=y CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y -# additional board options -CONFIG_GPIO_AS_PINRESET=y - CONFIG_PINCTRL=y diff --git a/boards/arm/nrf52_sparkfun/nrf52_sparkfun.dts b/boards/arm/nrf52_sparkfun/nrf52_sparkfun.dts index 618bd670ad1..60de01f0bb0 100644 --- a/boards/arm/nrf52_sparkfun/nrf52_sparkfun.dts +++ b/boards/arm/nrf52_sparkfun/nrf52_sparkfun.dts @@ -50,6 +50,10 @@ }; }; +&uicr { + gpio-as-nreset; +}; + &gpiote { status = "okay"; }; diff --git a/boards/arm/nrf52_sparkfun/nrf52_sparkfun_defconfig b/boards/arm/nrf52_sparkfun/nrf52_sparkfun_defconfig index 944fc20b9c8..2a21dc07192 100644 --- a/boards/arm/nrf52_sparkfun/nrf52_sparkfun_defconfig +++ b/boards/arm/nrf52_sparkfun/nrf52_sparkfun_defconfig @@ -17,7 +17,4 @@ CONFIG_SERIAL=y CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y -# Enable P0_21 as RST -CONFIG_GPIO_AS_PINRESET=y - CONFIG_PINCTRL=y diff --git a/boards/arm/nrf52_vbluno52/nrf52_vbluno52.dts b/boards/arm/nrf52_vbluno52/nrf52_vbluno52.dts index 8b276c5fed7..b622a1a23ea 100644 --- a/boards/arm/nrf52_vbluno52/nrf52_vbluno52.dts +++ b/boards/arm/nrf52_vbluno52/nrf52_vbluno52.dts @@ -49,6 +49,10 @@ }; }; +&uicr { + gpio-as-nreset; +}; + &gpiote { status = "okay"; }; diff --git a/boards/arm/nrf52_vbluno52/nrf52_vbluno52_defconfig b/boards/arm/nrf52_vbluno52/nrf52_vbluno52_defconfig index 97f4efbc236..fac5419e6f6 100644 --- a/boards/arm/nrf52_vbluno52/nrf52_vbluno52_defconfig +++ b/boards/arm/nrf52_vbluno52/nrf52_vbluno52_defconfig @@ -17,7 +17,4 @@ CONFIG_SERIAL=y CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y -# additional board options -CONFIG_GPIO_AS_PINRESET=y - CONFIG_PINCTRL=y diff --git a/boards/arm/nrf52dk_nrf52805/nrf52dk_nrf52805.dts b/boards/arm/nrf52dk_nrf52805/nrf52dk_nrf52805.dts index 29257e7a0b2..e0eaa911a06 100644 --- a/boards/arm/nrf52dk_nrf52805/nrf52dk_nrf52805.dts +++ b/boards/arm/nrf52dk_nrf52805/nrf52dk_nrf52805.dts @@ -89,6 +89,10 @@ status = "okay"; }; +&uicr { + gpio-as-nreset; +}; + &gpio0 { status = "okay"; }; diff --git a/boards/arm/nrf52dk_nrf52805/nrf52dk_nrf52805_defconfig b/boards/arm/nrf52dk_nrf52805/nrf52dk_nrf52805_defconfig index 31571f10fb4..6e275e63f35 100644 --- a/boards/arm/nrf52dk_nrf52805/nrf52dk_nrf52805_defconfig +++ b/boards/arm/nrf52dk_nrf52805/nrf52dk_nrf52805_defconfig @@ -20,9 +20,6 @@ CONFIG_SERIAL=y CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y -# Additional board options -CONFIG_GPIO_AS_PINRESET=y - # Bluetooth not enabled by default on nRF52805 due to RAM limitations when # running the default set of kernel tests. diff --git a/boards/arm/nrf52dk_nrf52810/nrf52dk_nrf52810.dts b/boards/arm/nrf52dk_nrf52810/nrf52dk_nrf52810.dts index 823a3db7f7e..4d4600f1222 100644 --- a/boards/arm/nrf52dk_nrf52810/nrf52dk_nrf52810.dts +++ b/boards/arm/nrf52dk_nrf52810/nrf52dk_nrf52810.dts @@ -91,6 +91,10 @@ status = "okay"; }; +&uicr { + gpio-as-nreset; +}; + &gpiote { status = "okay"; }; diff --git a/boards/arm/nrf52dk_nrf52810/nrf52dk_nrf52810_defconfig b/boards/arm/nrf52dk_nrf52810/nrf52dk_nrf52810_defconfig index 5873f1d2e9a..93706e89d0a 100644 --- a/boards/arm/nrf52dk_nrf52810/nrf52dk_nrf52810_defconfig +++ b/boards/arm/nrf52dk_nrf52810/nrf52dk_nrf52810_defconfig @@ -20,9 +20,6 @@ CONFIG_SERIAL=y CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y -# additional board options -CONFIG_GPIO_AS_PINRESET=y - # Bluetooth not enabled by default on nRF52810 due to RAM limitations when # running the default set of kernel tests. # Enable this on your prj.conf to include Bluetooth support diff --git a/boards/arm/nrf52dk_nrf52832/nrf52dk_nrf52832.dts b/boards/arm/nrf52dk_nrf52832/nrf52dk_nrf52832.dts index 3002a1841c9..687bba9254a 100644 --- a/boards/arm/nrf52dk_nrf52832/nrf52dk_nrf52832.dts +++ b/boards/arm/nrf52dk_nrf52832/nrf52dk_nrf52832.dts @@ -138,6 +138,10 @@ status = "okay"; }; +&uicr { + gpio-as-nreset; +}; + &gpiote { status = "okay"; }; diff --git a/boards/arm/nrf52dk_nrf52832/nrf52dk_nrf52832_defconfig b/boards/arm/nrf52dk_nrf52832/nrf52dk_nrf52832_defconfig index 547ff67c348..23e1f4c249a 100644 --- a/boards/arm/nrf52dk_nrf52832/nrf52dk_nrf52832_defconfig +++ b/boards/arm/nrf52dk_nrf52832/nrf52dk_nrf52832_defconfig @@ -23,7 +23,4 @@ CONFIG_SERIAL=y CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y -# additional board options -CONFIG_GPIO_AS_PINRESET=y - CONFIG_PINCTRL=y diff --git a/boards/arm/nrf9160dk_nrf52840/nrf9160dk_nrf52840.dts b/boards/arm/nrf9160dk_nrf52840/nrf9160dk_nrf52840.dts index c8cc706750c..07dc648b853 100644 --- a/boards/arm/nrf9160dk_nrf52840/nrf9160dk_nrf52840.dts +++ b/boards/arm/nrf9160dk_nrf52840/nrf9160dk_nrf52840.dts @@ -141,6 +141,10 @@ }; }; +&uicr { + gpio-as-nreset; +}; + &gpiote { status = "okay"; }; diff --git a/boards/arm/nrf9160dk_nrf52840/nrf9160dk_nrf52840_defconfig b/boards/arm/nrf9160dk_nrf52840/nrf9160dk_nrf52840_defconfig index c15e39669ea..073409dbba1 100644 --- a/boards/arm/nrf9160dk_nrf52840/nrf9160dk_nrf52840_defconfig +++ b/boards/arm/nrf9160dk_nrf52840/nrf9160dk_nrf52840_defconfig @@ -17,7 +17,4 @@ CONFIG_SERIAL=y CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y -# additional board options -CONFIG_GPIO_AS_PINRESET=y - CONFIG_PINCTRL=y diff --git a/boards/arm/pan1770_evb/pan1770_evb.dts b/boards/arm/pan1770_evb/pan1770_evb.dts index d8fbe8fe9df..2b2a9d561a7 100644 --- a/boards/arm/pan1770_evb/pan1770_evb.dts +++ b/boards/arm/pan1770_evb/pan1770_evb.dts @@ -137,6 +137,10 @@ status = "okay"; }; +&uicr { + gpio-as-nreset; +}; + &gpiote { status = "okay"; }; diff --git a/boards/arm/pan1770_evb/pan1770_evb_defconfig b/boards/arm/pan1770_evb/pan1770_evb_defconfig index 1192aca064e..1d90cb82c25 100644 --- a/boards/arm/pan1770_evb/pan1770_evb_defconfig +++ b/boards/arm/pan1770_evb/pan1770_evb_defconfig @@ -26,8 +26,5 @@ CONFIG_SERIAL=y CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y -# additional board options -CONFIG_GPIO_AS_PINRESET=y - # using pinctrl CONFIG_PINCTRL=y diff --git a/boards/arm/pan1780_evb/pan1780_evb.dts b/boards/arm/pan1780_evb/pan1780_evb.dts index 4f4dbca98ac..da9a7e7fdb8 100644 --- a/boards/arm/pan1780_evb/pan1780_evb.dts +++ b/boards/arm/pan1780_evb/pan1780_evb.dts @@ -137,6 +137,10 @@ status = "okay"; }; +&uicr { + gpio-as-nreset; +}; + &gpiote { status = "okay"; }; diff --git a/boards/arm/pan1780_evb/pan1780_evb_defconfig b/boards/arm/pan1780_evb/pan1780_evb_defconfig index 0c459f39aac..ca1a58c3b74 100644 --- a/boards/arm/pan1780_evb/pan1780_evb_defconfig +++ b/boards/arm/pan1780_evb/pan1780_evb_defconfig @@ -26,8 +26,5 @@ CONFIG_SERIAL=y CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y -# additional board options -CONFIG_GPIO_AS_PINRESET=y - # using pinctrl CONFIG_PINCTRL=y diff --git a/boards/arm/pan1781_evb/pan1781_evb.dts b/boards/arm/pan1781_evb/pan1781_evb.dts index 7d9b7028e35..8ab6af51ea9 100644 --- a/boards/arm/pan1781_evb/pan1781_evb.dts +++ b/boards/arm/pan1781_evb/pan1781_evb.dts @@ -98,6 +98,10 @@ clock-prescaler = <8>; }; +&uicr { + gpio-as-nreset; +}; + &gpiote { status = "okay"; }; diff --git a/boards/arm/pan1781_evb/pan1781_evb_defconfig b/boards/arm/pan1781_evb/pan1781_evb_defconfig index 76436dd2ccd..dacffd42175 100644 --- a/boards/arm/pan1781_evb/pan1781_evb_defconfig +++ b/boards/arm/pan1781_evb/pan1781_evb_defconfig @@ -26,8 +26,5 @@ CONFIG_SERIAL=y CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y -# additional board options -CONFIG_GPIO_AS_PINRESET=y - # using pinctrl CONFIG_PINCTRL=y diff --git a/boards/arm/pan1782_evb/pan1782_evb.dts b/boards/arm/pan1782_evb/pan1782_evb.dts index cf169e41d87..fdc86f792ec 100644 --- a/boards/arm/pan1782_evb/pan1782_evb.dts +++ b/boards/arm/pan1782_evb/pan1782_evb.dts @@ -98,6 +98,10 @@ status = "okay"; }; +&uicr { + gpio-as-nreset; +}; + &gpiote { status = "okay"; }; diff --git a/boards/arm/pan1782_evb/pan1782_evb_defconfig b/boards/arm/pan1782_evb/pan1782_evb_defconfig index 0bdeb9d9127..e6a6cc1d4a5 100644 --- a/boards/arm/pan1782_evb/pan1782_evb_defconfig +++ b/boards/arm/pan1782_evb/pan1782_evb_defconfig @@ -26,9 +26,6 @@ CONFIG_SERIAL=y CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y -# additional board options -CONFIG_GPIO_AS_PINRESET=y - # using pinctrl CONFIG_PINCTRL=y diff --git a/boards/arm/particle_argon/particle_argon.dts b/boards/arm/particle_argon/particle_argon.dts index fa2314b6fb2..a88199fe40b 100644 --- a/boards/arm/particle_argon/particle_argon.dts +++ b/boards/arm/particle_argon/particle_argon.dts @@ -32,6 +32,10 @@ }; }; +&uicr { + gpio-as-nreset; +}; + &uart1 { /* ESP32 */ compatible = "nordic,nrf-uarte"; current-speed = <921600>; diff --git a/boards/arm/particle_argon/particle_argon_defconfig b/boards/arm/particle_argon/particle_argon_defconfig index 784364e9edc..c29f62babd4 100644 --- a/boards/arm/particle_argon/particle_argon_defconfig +++ b/boards/arm/particle_argon/particle_argon_defconfig @@ -21,7 +21,4 @@ CONFIG_SERIAL=y CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y -# additional board options -CONFIG_GPIO_AS_PINRESET=y - CONFIG_PINCTRL=y diff --git a/boards/arm/particle_boron/particle_boron.dts b/boards/arm/particle_boron/particle_boron.dts index 3e20eddb94f..06e75a5a52e 100644 --- a/boards/arm/particle_boron/particle_boron.dts +++ b/boards/arm/particle_boron/particle_boron.dts @@ -36,6 +36,10 @@ }; }; +&uicr { + gpio-as-nreset; +}; + &i2c1 { /* power monitoring */ compatible = "nordic,nrf-twi"; status = "okay"; diff --git a/boards/arm/particle_boron/particle_boron_defconfig b/boards/arm/particle_boron/particle_boron_defconfig index 6963e9d9393..622a3169073 100644 --- a/boards/arm/particle_boron/particle_boron_defconfig +++ b/boards/arm/particle_boron/particle_boron_defconfig @@ -20,9 +20,6 @@ CONFIG_SERIAL=y CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y -# additional board options -CONFIG_GPIO_AS_PINRESET=y - CONFIG_PINCTRL=y # Fix the priority to enable the modem line's serial buffer diff --git a/boards/arm/particle_xenon/particle_xenon.dts b/boards/arm/particle_xenon/particle_xenon.dts index 22252c077f3..2d64ba119b2 100644 --- a/boards/arm/particle_xenon/particle_xenon.dts +++ b/boards/arm/particle_xenon/particle_xenon.dts @@ -33,6 +33,10 @@ }; }; +&uicr { + gpio-as-nreset; +}; + &uart1 { /* feather UART2 */ compatible = "nordic,nrf-uarte"; current-speed = <115200>; diff --git a/boards/arm/particle_xenon/particle_xenon_defconfig b/boards/arm/particle_xenon/particle_xenon_defconfig index 5f90beabba0..2495d886b41 100644 --- a/boards/arm/particle_xenon/particle_xenon_defconfig +++ b/boards/arm/particle_xenon/particle_xenon_defconfig @@ -20,7 +20,4 @@ CONFIG_SERIAL=y CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y -# additional board options -CONFIG_GPIO_AS_PINRESET=y - CONFIG_PINCTRL=y diff --git a/boards/arm/pinetime_devkit0/pinetime_devkit0.dts b/boards/arm/pinetime_devkit0/pinetime_devkit0.dts index fb377fd89e1..207c8934880 100644 --- a/boards/arm/pinetime_devkit0/pinetime_devkit0.dts +++ b/boards/arm/pinetime_devkit0/pinetime_devkit0.dts @@ -83,6 +83,10 @@ status = "okay"; }; +&uicr { + gpio-as-nreset; +}; + &gpiote { status = "okay"; }; diff --git a/boards/arm/pinetime_devkit0/pinetime_devkit0_defconfig b/boards/arm/pinetime_devkit0/pinetime_devkit0_defconfig index ad7442afe0d..fc8f45eceaa 100644 --- a/boards/arm/pinetime_devkit0/pinetime_devkit0_defconfig +++ b/boards/arm/pinetime_devkit0/pinetime_devkit0_defconfig @@ -13,7 +13,4 @@ CONFIG_SERIAL=y CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y -# use P0.21 as RST -CONFIG_GPIO_AS_PINRESET=y - CONFIG_PINCTRL=y diff --git a/boards/arm/pinnacle_100_dvk/pinnacle_100_dvk.dts b/boards/arm/pinnacle_100_dvk/pinnacle_100_dvk.dts index 62664e67b5e..19f9e6ff41e 100644 --- a/boards/arm/pinnacle_100_dvk/pinnacle_100_dvk.dts +++ b/boards/arm/pinnacle_100_dvk/pinnacle_100_dvk.dts @@ -88,6 +88,10 @@ status ="okay"; }; +&uicr { + gpio-as-nreset; +}; + &gpiote { status ="okay"; }; diff --git a/boards/arm/pinnacle_100_dvk/pinnacle_100_dvk_defconfig b/boards/arm/pinnacle_100_dvk/pinnacle_100_dvk_defconfig index 7f11757ab5d..010c72e8c07 100644 --- a/boards/arm/pinnacle_100_dvk/pinnacle_100_dvk_defconfig +++ b/boards/arm/pinnacle_100_dvk/pinnacle_100_dvk_defconfig @@ -22,9 +22,6 @@ CONFIG_SERIAL=y CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y -# Additional board options -CONFIG_GPIO_AS_PINRESET=y - # 32KHz clock source CONFIG_CLOCK_CONTROL_NRF_K32SRC_XTAL=y CONFIG_CLOCK_CONTROL_NRF_K32SRC_150PPM=y diff --git a/boards/arm/rak4631_nrf52840/rak4631_nrf52840.dts b/boards/arm/rak4631_nrf52840/rak4631_nrf52840.dts index 43b2dd0de28..454c4bb84b1 100644 --- a/boards/arm/rak4631_nrf52840/rak4631_nrf52840.dts +++ b/boards/arm/rak4631_nrf52840/rak4631_nrf52840.dts @@ -48,6 +48,10 @@ status = "okay"; }; +&uicr { + gpio-as-nreset; +}; + &gpiote { status = "okay"; }; diff --git a/boards/arm/rak4631_nrf52840/rak4631_nrf52840_defconfig b/boards/arm/rak4631_nrf52840/rak4631_nrf52840_defconfig index 80da4e05041..4cc2863efab 100644 --- a/boards/arm/rak4631_nrf52840/rak4631_nrf52840_defconfig +++ b/boards/arm/rak4631_nrf52840/rak4631_nrf52840_defconfig @@ -22,7 +22,4 @@ CONFIG_SERIAL=y CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y -# additional board options -CONFIG_GPIO_AS_PINRESET=y - CONFIG_PINCTRL=y diff --git a/boards/arm/raytac_mdbt50q_db_33_nrf52833/raytac_mdbt50q_db_33_nrf52833.dts b/boards/arm/raytac_mdbt50q_db_33_nrf52833/raytac_mdbt50q_db_33_nrf52833.dts index 6a530e687f6..a3ada26e811 100644 --- a/boards/arm/raytac_mdbt50q_db_33_nrf52833/raytac_mdbt50q_db_33_nrf52833.dts +++ b/boards/arm/raytac_mdbt50q_db_33_nrf52833/raytac_mdbt50q_db_33_nrf52833.dts @@ -93,6 +93,10 @@ status = "okay"; }; +&uicr { + gpio-as-nreset; +}; + &gpiote { status = "okay"; }; diff --git a/boards/arm/raytac_mdbt50q_db_33_nrf52833/raytac_mdbt50q_db_33_nrf52833_defconfig b/boards/arm/raytac_mdbt50q_db_33_nrf52833/raytac_mdbt50q_db_33_nrf52833_defconfig index 7ed9a1ffe8b..1212ba8928f 100644 --- a/boards/arm/raytac_mdbt50q_db_33_nrf52833/raytac_mdbt50q_db_33_nrf52833_defconfig +++ b/boards/arm/raytac_mdbt50q_db_33_nrf52833/raytac_mdbt50q_db_33_nrf52833_defconfig @@ -26,7 +26,4 @@ CONFIG_SERIAL=y CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y -# additional board options -CONFIG_GPIO_AS_PINRESET=y - CONFIG_PINCTRL=y diff --git a/boards/arm/raytac_mdbt50q_db_40_nrf52840/raytac_mdbt50q_db_40_nrf52840.dts b/boards/arm/raytac_mdbt50q_db_40_nrf52840/raytac_mdbt50q_db_40_nrf52840.dts index 2414b8ea517..bd1a2f06855 100644 --- a/boards/arm/raytac_mdbt50q_db_40_nrf52840/raytac_mdbt50q_db_40_nrf52840.dts +++ b/boards/arm/raytac_mdbt50q_db_40_nrf52840/raytac_mdbt50q_db_40_nrf52840.dts @@ -93,6 +93,10 @@ status = "okay"; }; +&uicr { + gpio-as-nreset; +}; + &gpiote { status = "okay"; }; diff --git a/boards/arm/raytac_mdbt50q_db_40_nrf52840/raytac_mdbt50q_db_40_nrf52840_defconfig b/boards/arm/raytac_mdbt50q_db_40_nrf52840/raytac_mdbt50q_db_40_nrf52840_defconfig index 973b83c9d62..438343c6d9b 100644 --- a/boards/arm/raytac_mdbt50q_db_40_nrf52840/raytac_mdbt50q_db_40_nrf52840_defconfig +++ b/boards/arm/raytac_mdbt50q_db_40_nrf52840/raytac_mdbt50q_db_40_nrf52840_defconfig @@ -26,7 +26,4 @@ CONFIG_SERIAL=y CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y -# additional board options -CONFIG_GPIO_AS_PINRESET=y - CONFIG_PINCTRL=y diff --git a/boards/arm/reel_board/dts/reel_board.dtsi b/boards/arm/reel_board/dts/reel_board.dtsi index 6289cf0ec6d..028a5d86a78 100644 --- a/boards/arm/reel_board/dts/reel_board.dtsi +++ b/boards/arm/reel_board/dts/reel_board.dtsi @@ -94,6 +94,10 @@ }; }; +&uicr { + gpio-as-nreset; +}; + &gpiote { status = "okay"; }; diff --git a/boards/arm/reel_board/reel_board_defconfig b/boards/arm/reel_board/reel_board_defconfig index 7ec7b36871b..850506692ba 100644 --- a/boards/arm/reel_board/reel_board_defconfig +++ b/boards/arm/reel_board/reel_board_defconfig @@ -17,7 +17,4 @@ CONFIG_SERIAL=y CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y -# additional board options -CONFIG_GPIO_AS_PINRESET=y - CONFIG_PINCTRL=y diff --git a/boards/arm/reel_board/reel_board_v2_defconfig b/boards/arm/reel_board/reel_board_v2_defconfig index a7f80f970e8..2ac0610f78c 100644 --- a/boards/arm/reel_board/reel_board_v2_defconfig +++ b/boards/arm/reel_board/reel_board_v2_defconfig @@ -17,7 +17,4 @@ CONFIG_SERIAL=y CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y -# additional board options -CONFIG_GPIO_AS_PINRESET=y - CONFIG_PINCTRL=y diff --git a/boards/arm/ubx_bmd300eval_nrf52832/ubx_bmd300eval_nrf52832.dts b/boards/arm/ubx_bmd300eval_nrf52832/ubx_bmd300eval_nrf52832.dts index a248d8f650e..9594b760488 100644 --- a/boards/arm/ubx_bmd300eval_nrf52832/ubx_bmd300eval_nrf52832.dts +++ b/boards/arm/ubx_bmd300eval_nrf52832/ubx_bmd300eval_nrf52832.dts @@ -137,6 +137,10 @@ status = "okay"; }; +&uicr { + gpio-as-nreset; +}; + &gpiote { status = "okay"; }; diff --git a/boards/arm/ubx_bmd300eval_nrf52832/ubx_bmd300eval_nrf52832_defconfig b/boards/arm/ubx_bmd300eval_nrf52832/ubx_bmd300eval_nrf52832_defconfig index 769e28f5846..801393790fe 100644 --- a/boards/arm/ubx_bmd300eval_nrf52832/ubx_bmd300eval_nrf52832_defconfig +++ b/boards/arm/ubx_bmd300eval_nrf52832/ubx_bmd300eval_nrf52832_defconfig @@ -23,7 +23,4 @@ CONFIG_SERIAL=y CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y -# additional board options -CONFIG_GPIO_AS_PINRESET=y - CONFIG_PINCTRL=y diff --git a/boards/arm/ubx_bmd330eval_nrf52810/ubx_bmd330eval_nrf52810.dts b/boards/arm/ubx_bmd330eval_nrf52810/ubx_bmd330eval_nrf52810.dts index 5afd4960694..c65221eb38c 100644 --- a/boards/arm/ubx_bmd330eval_nrf52810/ubx_bmd330eval_nrf52810.dts +++ b/boards/arm/ubx_bmd330eval_nrf52810/ubx_bmd330eval_nrf52810.dts @@ -137,6 +137,10 @@ status = "okay"; }; +&uicr { + gpio-as-nreset; +}; + &gpiote { status = "okay"; }; diff --git a/boards/arm/ubx_bmd330eval_nrf52810/ubx_bmd330eval_nrf52810_defconfig b/boards/arm/ubx_bmd330eval_nrf52810/ubx_bmd330eval_nrf52810_defconfig index 6fd69454784..4f8a5c5a8da 100644 --- a/boards/arm/ubx_bmd330eval_nrf52810/ubx_bmd330eval_nrf52810_defconfig +++ b/boards/arm/ubx_bmd330eval_nrf52810/ubx_bmd330eval_nrf52810_defconfig @@ -26,7 +26,4 @@ CONFIG_SERIAL=y CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y -# additional board options -CONFIG_GPIO_AS_PINRESET=y - CONFIG_PINCTRL=y diff --git a/boards/arm/ubx_bmd340eval_nrf52840/ubx_bmd340eval_nrf52840.dts b/boards/arm/ubx_bmd340eval_nrf52840/ubx_bmd340eval_nrf52840.dts index f7fbee05909..070730c69d2 100644 --- a/boards/arm/ubx_bmd340eval_nrf52840/ubx_bmd340eval_nrf52840.dts +++ b/boards/arm/ubx_bmd340eval_nrf52840/ubx_bmd340eval_nrf52840.dts @@ -136,6 +136,10 @@ status = "okay"; }; +&uicr { + gpio-as-nreset; +}; + &gpiote { status = "okay"; }; diff --git a/boards/arm/ubx_bmd340eval_nrf52840/ubx_bmd340eval_nrf52840_defconfig b/boards/arm/ubx_bmd340eval_nrf52840/ubx_bmd340eval_nrf52840_defconfig index 4a1d3a6075c..37271c2ce81 100644 --- a/boards/arm/ubx_bmd340eval_nrf52840/ubx_bmd340eval_nrf52840_defconfig +++ b/boards/arm/ubx_bmd340eval_nrf52840/ubx_bmd340eval_nrf52840_defconfig @@ -26,7 +26,4 @@ CONFIG_SERIAL=y CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y -# additional board options -CONFIG_GPIO_AS_PINRESET=y - CONFIG_PINCTRL=y diff --git a/boards/arm/ubx_bmd345eval_nrf52840/ubx_bmd345eval_nrf52840.dts b/boards/arm/ubx_bmd345eval_nrf52840/ubx_bmd345eval_nrf52840.dts index 2db4e005b04..68b3755123b 100644 --- a/boards/arm/ubx_bmd345eval_nrf52840/ubx_bmd345eval_nrf52840.dts +++ b/boards/arm/ubx_bmd345eval_nrf52840/ubx_bmd345eval_nrf52840.dts @@ -152,6 +152,10 @@ status = "okay"; }; +&uicr { + gpio-as-nreset; +}; + &gpiote { status = "okay"; }; diff --git a/boards/arm/ubx_bmd345eval_nrf52840/ubx_bmd345eval_nrf52840_defconfig b/boards/arm/ubx_bmd345eval_nrf52840/ubx_bmd345eval_nrf52840_defconfig index 6a6d80f1b2b..4a35f6e612f 100644 --- a/boards/arm/ubx_bmd345eval_nrf52840/ubx_bmd345eval_nrf52840_defconfig +++ b/boards/arm/ubx_bmd345eval_nrf52840/ubx_bmd345eval_nrf52840_defconfig @@ -26,7 +26,4 @@ CONFIG_SERIAL=y CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y -# additional board options -CONFIG_GPIO_AS_PINRESET=y - CONFIG_PINCTRL=y diff --git a/boards/arm/ubx_bmd360eval_nrf52811/ubx_bmd360eval_nrf52811.dts b/boards/arm/ubx_bmd360eval_nrf52811/ubx_bmd360eval_nrf52811.dts index 842c882ac7f..5b8679cc065 100644 --- a/boards/arm/ubx_bmd360eval_nrf52811/ubx_bmd360eval_nrf52811.dts +++ b/boards/arm/ubx_bmd360eval_nrf52811/ubx_bmd360eval_nrf52811.dts @@ -137,6 +137,10 @@ status = "okay"; }; +&uicr { + gpio-as-nreset; +}; + &gpiote { status = "okay"; }; diff --git a/boards/arm/ubx_bmd360eval_nrf52811/ubx_bmd360eval_nrf52811_defconfig b/boards/arm/ubx_bmd360eval_nrf52811/ubx_bmd360eval_nrf52811_defconfig index b2996dba82d..7a63bc69bf2 100644 --- a/boards/arm/ubx_bmd360eval_nrf52811/ubx_bmd360eval_nrf52811_defconfig +++ b/boards/arm/ubx_bmd360eval_nrf52811/ubx_bmd360eval_nrf52811_defconfig @@ -26,7 +26,4 @@ CONFIG_SERIAL=y CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y -# additional board options -CONFIG_GPIO_AS_PINRESET=y - CONFIG_PINCTRL=y diff --git a/boards/arm/ubx_bmd380eval_nrf52840/ubx_bmd380eval_nrf52840.dts b/boards/arm/ubx_bmd380eval_nrf52840/ubx_bmd380eval_nrf52840.dts index 1c4623b52fe..d7a21c98b44 100644 --- a/boards/arm/ubx_bmd380eval_nrf52840/ubx_bmd380eval_nrf52840.dts +++ b/boards/arm/ubx_bmd380eval_nrf52840/ubx_bmd380eval_nrf52840.dts @@ -97,6 +97,10 @@ status = "okay"; }; +&uicr { + gpio-as-nreset; +}; + &gpiote { status = "okay"; }; diff --git a/boards/arm/ubx_bmd380eval_nrf52840/ubx_bmd380eval_nrf52840_defconfig b/boards/arm/ubx_bmd380eval_nrf52840/ubx_bmd380eval_nrf52840_defconfig index d0a583edbe8..c20dc6fe9f3 100644 --- a/boards/arm/ubx_bmd380eval_nrf52840/ubx_bmd380eval_nrf52840_defconfig +++ b/boards/arm/ubx_bmd380eval_nrf52840/ubx_bmd380eval_nrf52840_defconfig @@ -27,7 +27,4 @@ CONFIG_SERIAL=y CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y -# additional board options -CONFIG_GPIO_AS_PINRESET=y - CONFIG_PINCTRL=y diff --git a/boards/arm/ubx_evkannab1_nrf52832/ubx_evkannab1_nrf52832.dts b/boards/arm/ubx_evkannab1_nrf52832/ubx_evkannab1_nrf52832.dts index b183b17bc41..2c0f051d25f 100644 --- a/boards/arm/ubx_evkannab1_nrf52832/ubx_evkannab1_nrf52832.dts +++ b/boards/arm/ubx_evkannab1_nrf52832/ubx_evkannab1_nrf52832.dts @@ -133,6 +133,10 @@ status = "okay"; }; +&uicr { + gpio-as-nreset; +}; + &gpiote { status = "okay"; }; diff --git a/boards/arm/ubx_evkannab1_nrf52832/ubx_evkannab1_nrf52832_defconfig b/boards/arm/ubx_evkannab1_nrf52832/ubx_evkannab1_nrf52832_defconfig index 4a289cc2597..93127beefef 100644 --- a/boards/arm/ubx_evkannab1_nrf52832/ubx_evkannab1_nrf52832_defconfig +++ b/boards/arm/ubx_evkannab1_nrf52832/ubx_evkannab1_nrf52832_defconfig @@ -26,7 +26,4 @@ CONFIG_SERIAL=y CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y -# additional board options -CONFIG_GPIO_AS_PINRESET=y - CONFIG_PINCTRL=y diff --git a/boards/arm/ubx_evkninab1_nrf52832/ubx_evkninab1_nrf52832.dts b/boards/arm/ubx_evkninab1_nrf52832/ubx_evkninab1_nrf52832.dts index 691705b3a91..849c96c5e6f 100644 --- a/boards/arm/ubx_evkninab1_nrf52832/ubx_evkninab1_nrf52832.dts +++ b/boards/arm/ubx_evkninab1_nrf52832/ubx_evkninab1_nrf52832.dts @@ -133,6 +133,10 @@ status = "okay"; }; +&uicr { + gpio-as-nreset; +}; + &gpiote { status = "okay"; }; diff --git a/boards/arm/ubx_evkninab1_nrf52832/ubx_evkninab1_nrf52832_defconfig b/boards/arm/ubx_evkninab1_nrf52832/ubx_evkninab1_nrf52832_defconfig index b7064633b25..b44e54e3d18 100644 --- a/boards/arm/ubx_evkninab1_nrf52832/ubx_evkninab1_nrf52832_defconfig +++ b/boards/arm/ubx_evkninab1_nrf52832/ubx_evkninab1_nrf52832_defconfig @@ -26,7 +26,4 @@ CONFIG_SERIAL=y CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y -# additional board options -CONFIG_GPIO_AS_PINRESET=y - CONFIG_PINCTRL=y diff --git a/boards/arm/ubx_evkninab3_nrf52840/ubx_evkninab3_nrf52840.dts b/boards/arm/ubx_evkninab3_nrf52840/ubx_evkninab3_nrf52840.dts index 19b4e25a5af..5e15c5cc232 100644 --- a/boards/arm/ubx_evkninab3_nrf52840/ubx_evkninab3_nrf52840.dts +++ b/boards/arm/ubx_evkninab3_nrf52840/ubx_evkninab3_nrf52840.dts @@ -129,6 +129,10 @@ status = "okay"; }; +&uicr { + gpio-as-nreset; +}; + &gpiote { status = "okay"; }; diff --git a/boards/arm/ubx_evkninab3_nrf52840/ubx_evkninab3_nrf52840_defconfig b/boards/arm/ubx_evkninab3_nrf52840/ubx_evkninab3_nrf52840_defconfig index ca03d00a8e7..f9cabe94b4a 100644 --- a/boards/arm/ubx_evkninab3_nrf52840/ubx_evkninab3_nrf52840_defconfig +++ b/boards/arm/ubx_evkninab3_nrf52840/ubx_evkninab3_nrf52840_defconfig @@ -26,7 +26,4 @@ CONFIG_SERIAL=y CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y -# additional board options -CONFIG_GPIO_AS_PINRESET=y - CONFIG_PINCTRL=y diff --git a/boards/arm/ubx_evkninab4_nrf52833/ubx_evkninab4_nrf52833.dts b/boards/arm/ubx_evkninab4_nrf52833/ubx_evkninab4_nrf52833.dts index 783d69b4788..521f9f6aa9e 100644 --- a/boards/arm/ubx_evkninab4_nrf52833/ubx_evkninab4_nrf52833.dts +++ b/boards/arm/ubx_evkninab4_nrf52833/ubx_evkninab4_nrf52833.dts @@ -134,6 +134,10 @@ status = "okay"; }; +&uicr { + gpio-as-nreset; +}; + &gpiote { status = "okay"; }; diff --git a/boards/arm/ubx_evkninab4_nrf52833/ubx_evkninab4_nrf52833_defconfig b/boards/arm/ubx_evkninab4_nrf52833/ubx_evkninab4_nrf52833_defconfig index 96d99738526..c06ad795868 100644 --- a/boards/arm/ubx_evkninab4_nrf52833/ubx_evkninab4_nrf52833_defconfig +++ b/boards/arm/ubx_evkninab4_nrf52833/ubx_evkninab4_nrf52833_defconfig @@ -26,7 +26,4 @@ CONFIG_SERIAL=y CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y -# additional board options -CONFIG_GPIO_AS_PINRESET=y - CONFIG_PINCTRL=y diff --git a/boards/arm/we_ophelia1ev_nrf52805/we_ophelia1ev_nrf52805.dts b/boards/arm/we_ophelia1ev_nrf52805/we_ophelia1ev_nrf52805.dts index b9b9bfcedb2..4d7c3d8cc0b 100644 --- a/boards/arm/we_ophelia1ev_nrf52805/we_ophelia1ev_nrf52805.dts +++ b/boards/arm/we_ophelia1ev_nrf52805/we_ophelia1ev_nrf52805.dts @@ -61,6 +61,10 @@ status = "okay"; }; +&uicr { + gpio-as-nreset; +}; + &gpio0 { status = "okay"; }; diff --git a/boards/arm/we_ophelia1ev_nrf52805/we_ophelia1ev_nrf52805_defconfig b/boards/arm/we_ophelia1ev_nrf52805/we_ophelia1ev_nrf52805_defconfig index d1a44910ced..88c4ddb2023 100644 --- a/boards/arm/we_ophelia1ev_nrf52805/we_ophelia1ev_nrf52805_defconfig +++ b/boards/arm/we_ophelia1ev_nrf52805/we_ophelia1ev_nrf52805_defconfig @@ -21,9 +21,6 @@ CONFIG_SERIAL=y CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y -# Additional board options -CONFIG_GPIO_AS_PINRESET=y - # Use internal oscillator CONFIG_CLOCK_CONTROL_NRF_K32SRC_RC=y diff --git a/boards/arm/we_proteus2ev_nrf52832/we_proteus2ev_nrf52832.dts b/boards/arm/we_proteus2ev_nrf52832/we_proteus2ev_nrf52832.dts index 4cd193c4162..ef7eede1f75 100644 --- a/boards/arm/we_proteus2ev_nrf52832/we_proteus2ev_nrf52832.dts +++ b/boards/arm/we_proteus2ev_nrf52832/we_proteus2ev_nrf52832.dts @@ -56,6 +56,10 @@ status = "okay"; }; +&uicr { + gpio-as-nreset; +}; + &gpiote { status = "okay"; }; diff --git a/boards/arm/we_proteus2ev_nrf52832/we_proteus2ev_nrf52832_defconfig b/boards/arm/we_proteus2ev_nrf52832/we_proteus2ev_nrf52832_defconfig index ab2356cf412..249c4a8e394 100644 --- a/boards/arm/we_proteus2ev_nrf52832/we_proteus2ev_nrf52832_defconfig +++ b/boards/arm/we_proteus2ev_nrf52832/we_proteus2ev_nrf52832_defconfig @@ -24,9 +24,6 @@ CONFIG_SERIAL=y CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y -# additional board options -CONFIG_GPIO_AS_PINRESET=y - # Use internal oscillator CONFIG_CLOCK_CONTROL_NRF_K32SRC_RC=y diff --git a/boards/arm/we_proteus3ev_nrf52840/we_proteus3ev_nrf52840.dts b/boards/arm/we_proteus3ev_nrf52840/we_proteus3ev_nrf52840.dts index 4c64bcaa4d0..62cecf7066e 100644 --- a/boards/arm/we_proteus3ev_nrf52840/we_proteus3ev_nrf52840.dts +++ b/boards/arm/we_proteus3ev_nrf52840/we_proteus3ev_nrf52840.dts @@ -57,6 +57,10 @@ status = "okay"; }; +&uicr { + gpio-as-nreset; +}; + &gpiote { status = "okay"; }; diff --git a/boards/arm/we_proteus3ev_nrf52840/we_proteus3ev_nrf52840_defconfig b/boards/arm/we_proteus3ev_nrf52840/we_proteus3ev_nrf52840_defconfig index b232a355e40..cca27094e6a 100644 --- a/boards/arm/we_proteus3ev_nrf52840/we_proteus3ev_nrf52840_defconfig +++ b/boards/arm/we_proteus3ev_nrf52840/we_proteus3ev_nrf52840_defconfig @@ -24,9 +24,6 @@ CONFIG_SERIAL=y CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y -# additional board options -CONFIG_GPIO_AS_PINRESET=y - # Use internal oscillator CONFIG_CLOCK_CONTROL_NRF_K32SRC_RC=y diff --git a/boards/arm/xiao_ble/xiao_ble_common.dtsi b/boards/arm/xiao_ble/xiao_ble_common.dtsi index 588f381868a..d031ce4b5b3 100644 --- a/boards/arm/xiao_ble/xiao_ble_common.dtsi +++ b/boards/arm/xiao_ble/xiao_ble_common.dtsi @@ -62,6 +62,10 @@ status = "okay"; }; +&uicr { + gpio-as-nreset; +}; + &gpiote { status = "okay"; }; diff --git a/boards/arm/xiao_ble/xiao_ble_defconfig b/boards/arm/xiao_ble/xiao_ble_defconfig index faef5befa1f..6b6aa3168ec 100644 --- a/boards/arm/xiao_ble/xiao_ble_defconfig +++ b/boards/arm/xiao_ble/xiao_ble_defconfig @@ -29,7 +29,4 @@ CONFIG_USB_DEVICE_STACK=y CONFIG_BUILD_OUTPUT_UF2=y CONFIG_USE_DT_CODE_PARTITION=y -# additional board options -CONFIG_GPIO_AS_PINRESET=y - CONFIG_PINCTRL=y diff --git a/boards/arm/xiao_ble/xiao_ble_sense_defconfig b/boards/arm/xiao_ble/xiao_ble_sense_defconfig index f549e4173dc..269f6f7915b 100644 --- a/boards/arm/xiao_ble/xiao_ble_sense_defconfig +++ b/boards/arm/xiao_ble/xiao_ble_sense_defconfig @@ -29,9 +29,6 @@ CONFIG_USB_DEVICE_STACK=y CONFIG_BUILD_OUTPUT_UF2=y CONFIG_USE_DT_CODE_PARTITION=y -# additional board options -CONFIG_GPIO_AS_PINRESET=y - CONFIG_PINCTRL=y # required to enable LSM6DS3TR-C power From 11cbd4dd27bdabd5191901422a694a273a4afc53 Mon Sep 17 00:00:00 2001 From: Gerard Marull-Paretas Date: Mon, 18 Sep 2023 11:37:32 +0200 Subject: [PATCH 188/421] [nrf fromtree] boards: arm: nrf9160dk_nrf52840: use UICR gpio-as-nreset property Instead of the about to be deprecated GPIO_AS_PINRESET. Signed-off-by: Gerard Marull-Paretas (cherry picked from commit 5d6d6f5b65ca5696dd27d1c266d6eb4f257d7a45) (cherry picked from commit 4b28e8dbfd7465bce59348851e729476a2356897) --- boards/arm/nrf9160dk_nrf52840/board.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/boards/arm/nrf9160dk_nrf52840/board.c b/boards/arm/nrf9160dk_nrf52840/board.c index e01b8eb64e7..cdf00f8f3dd 100644 --- a/boards/arm/nrf9160dk_nrf52840/board.c +++ b/boards/arm/nrf9160dk_nrf52840/board.c @@ -27,7 +27,7 @@ LOG_MODULE_REGISTER(board_control, CONFIG_BOARD_NRF9160DK_LOG_LEVEL); * exposes the nRESET function (P0.18 in nRF52840), there is no need to * provide any additional GPIO configuration for it. */ -#define RESET_INPUT_IS_PINRESET (IS_ENABLED(CONFIG_GPIO_AS_PINRESET) && \ +#define RESET_INPUT_IS_PINRESET (DT_PROP(DT_NODELABEL(uicr), gpio_as_nreset) && \ GET_PORT(reset_input, gpios, 0) == 0 && \ GET_PIN(reset_input, gpios, 0) == 18) #define USE_RESET_GPIO \ From 4c425de49697cf8629615c7f7b25feee45180cf6 Mon Sep 17 00:00:00 2001 From: Gerard Marull-Paretas Date: Mon, 18 Sep 2023 11:02:25 +0200 Subject: [PATCH 189/421] [nrf fromtree] soc: arm: nordic_nrf: nrf52: deprecate GPIO_AS_PINRESET In favor of devicetree property in the UICR node. Signed-off-by: Gerard Marull-Paretas (cherry picked from commit efb8408ba2e9a2cb1de638441ec60de495ee0f0d) (cherry picked from commit 03d992d8f6f5c59992e12777b82d31900d4720c4) --- soc/arm/nordic_nrf/nrf52/Kconfig.soc | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/soc/arm/nordic_nrf/nrf52/Kconfig.soc b/soc/arm/nordic_nrf/nrf52/Kconfig.soc index 13a2fef932b..b2a915f168e 100644 --- a/soc/arm/nordic_nrf/nrf52/Kconfig.soc +++ b/soc/arm/nordic_nrf/nrf52/Kconfig.soc @@ -94,8 +94,15 @@ config SOC_DCDC_NRF52X_HV Enable nRF52 series System on Chip High Voltage DC/DC converter. config GPIO_AS_PINRESET - bool "GPIO as pin reset (reset button)" - default y + bool "[DEPRECATED] GPIO as pin reset (reset button)" + select DEPRECATED + help + This option is deprecated, use devicetree instead. Example + configuration: + + &uicr { + gpio-as-nreset; + }; config NRF_ENABLE_ICACHE bool "The instruction cache (I-Cache)" From 12bfbfc7d6751e17c63cf190e8bce8eac056c29f Mon Sep 17 00:00:00 2001 From: Gerard Marull-Paretas Date: Mon, 18 Sep 2023 11:38:09 +0200 Subject: [PATCH 190/421] [nrf fromtree] boards: arm: nrf-based: remove redundant GPIO_AS_PINRESET=n Because the option is disabled by default now that it is deprecated. Signed-off-by: Gerard Marull-Paretas (cherry picked from commit c572228aa0fc157197207841250ca5e71696b05a) (cherry picked from commit 23975f1397f1a3202be17f44c9b7dbd61a31d426) --- boards/arm/holyiot_yj16019/Kconfig.defconfig | 3 --- boards/arm/ruuvi_ruuvitag/ruuvi_ruuvitag_defconfig | 4 ---- 2 files changed, 7 deletions(-) diff --git a/boards/arm/holyiot_yj16019/Kconfig.defconfig b/boards/arm/holyiot_yj16019/Kconfig.defconfig index 99373ad286a..de2d63ad7c8 100644 --- a/boards/arm/holyiot_yj16019/Kconfig.defconfig +++ b/boards/arm/holyiot_yj16019/Kconfig.defconfig @@ -8,9 +8,6 @@ if BOARD_HOLYIOT_YJ16019 config BOARD default "holyiot_yj16019" -config GPIO_AS_PINRESET - default n - config BT_CTLR default BT diff --git a/boards/arm/ruuvi_ruuvitag/ruuvi_ruuvitag_defconfig b/boards/arm/ruuvi_ruuvitag/ruuvi_ruuvitag_defconfig index bd247788458..7e28dde8423 100644 --- a/boards/arm/ruuvi_ruuvitag/ruuvi_ruuvitag_defconfig +++ b/boards/arm/ruuvi_ruuvitag/ruuvi_ruuvitag_defconfig @@ -14,8 +14,4 @@ CONFIG_USE_SEGGER_RTT=y # Enable GPIO CONFIG_GPIO=y -# additional board options -# set y to disable R button -CONFIG_GPIO_AS_PINRESET=n - CONFIG_PINCTRL=y From 532564650101b3c9a9ccbde8ceb3afe4973fc096 Mon Sep 17 00:00:00 2001 From: Gerard Marull-Paretas Date: Mon, 18 Sep 2023 11:41:42 +0200 Subject: [PATCH 191/421] [nrf fromtree] doc: migration-guide: inform about GPIO_AS_PINRESET deprecation In favor of the new devicetree 'gpio-as-nreset' property. Signed-off-by: Gerard Marull-Paretas (cherry picked from commit 9019e468392a22e274282517a037c079ab1592c0) (cherry picked from commit eabe4393f184a797044e3f7e52a23e1a4428e17d) --- doc/releases/migration-guide-3.5.rst | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/doc/releases/migration-guide-3.5.rst b/doc/releases/migration-guide-3.5.rst index 3f367ec5e35..8c059b630c6 100644 --- a/doc/releases/migration-guide-3.5.rst +++ b/doc/releases/migration-guide-3.5.rst @@ -53,3 +53,14 @@ Recommended Changes &uicr { nfct-pins-as-gpios; }; + +* Nordic nRF based boards using :kconfig:option:`CONFIG_GPIO_AS_PINRESET` + to configure reset GPIO as nRESET, should instead set the new UICR + ``gpio-as-nreset`` property in devicetree. It can be set like this in the + board devicetree files: + + .. code-block:: devicetree + + &uicr { + gpio-as-nreset; + }; From f25764149e1e0ce62254cd1759909641077becb5 Mon Sep 17 00:00:00 2001 From: Maciej Baczmanski Date: Tue, 5 Sep 2023 07:32:03 +0200 Subject: [PATCH 192/421] [nrf fromtree] modules: openthread: fix unused variable during `otPlatCryptoInit` If asserts are disabled, there is a warning in 'otPlatCryptoInit' regarding unused variable `err`. This commit fixes that. Signed-off-by: Maciej Baczmanski (cherry picked from commit d2495b14f25a49b7247d1d325bd97ecb5530851c) (cherry picked from commit 9f513ec4ec1520912f65e7d7d938e373b5e04bcd) --- modules/openthread/platform/crypto_psa.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/modules/openthread/platform/crypto_psa.c b/modules/openthread/platform/crypto_psa.c index e61177ef4c4..e5b234ce030 100644 --- a/modules/openthread/platform/crypto_psa.c +++ b/modules/openthread/platform/crypto_psa.c @@ -137,9 +137,8 @@ void otPlatCryptoInit(void) * PSA with emulated TFM, Settings have to be initialized at the end of otPlatCryptoInit(), * to be available before storing Network Key. */ - int err = settings_subsys_init(); - - __ASSERT(!err, "Failed to initialize settings"); + __ASSERT_EVAL((void) settings_subsys_init(), int err = settings_subsys_init(), + !err, "Failed to initialize settings"); #endif } From 860096c05abbb93e27d3ca0c3a14518cd3a69c5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20Battrel?= Date: Fri, 15 Sep 2023 10:57:38 +0200 Subject: [PATCH 193/421] [nrf fromtree] Bluetooth: Test: SC Indication MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Test that SC Indication is correctly sent when the client reconnect and the server updated the GATT database since last connection. Test that the indication is sent even if the bond is not restored. Signed-off-by: Théo Battrel (cherry picked from commit 888a8c644cc955e55d6b4ce4bbedf0e006e0f9d8) (cherry picked from commit e1762127cf123f5cba94939d30c8f42506be1b69) --- tests/bsim/bluetooth/host/compile.sh | 1 + .../host/gatt/sc_indicate/CMakeLists.txt | 25 +++ .../bluetooth/host/gatt/sc_indicate/prj.conf | 20 ++ .../host/gatt/sc_indicate/src/bs_bt_utils.c | 182 ++++++++++++++++ .../host/gatt/sc_indicate/src/bs_bt_utils.h | 67 ++++++ .../host/gatt/sc_indicate/src/central.c | 195 ++++++++++++++++++ .../host/gatt/sc_indicate/src/main.c | 58 ++++++ .../host/gatt/sc_indicate/src/peripheral.c | 86 ++++++++ .../gatt/sc_indicate/test_scripts/_compile.sh | 18 ++ .../sc_indicate/test_scripts/sc_indicate.sh | 24 +++ 10 files changed, 676 insertions(+) create mode 100644 tests/bsim/bluetooth/host/gatt/sc_indicate/CMakeLists.txt create mode 100644 tests/bsim/bluetooth/host/gatt/sc_indicate/prj.conf create mode 100644 tests/bsim/bluetooth/host/gatt/sc_indicate/src/bs_bt_utils.c create mode 100644 tests/bsim/bluetooth/host/gatt/sc_indicate/src/bs_bt_utils.h create mode 100644 tests/bsim/bluetooth/host/gatt/sc_indicate/src/central.c create mode 100644 tests/bsim/bluetooth/host/gatt/sc_indicate/src/main.c create mode 100644 tests/bsim/bluetooth/host/gatt/sc_indicate/src/peripheral.c create mode 100755 tests/bsim/bluetooth/host/gatt/sc_indicate/test_scripts/_compile.sh create mode 100755 tests/bsim/bluetooth/host/gatt/sc_indicate/test_scripts/sc_indicate.sh diff --git a/tests/bsim/bluetooth/host/compile.sh b/tests/bsim/bluetooth/host/compile.sh index a54dbd26507..98d6c79e3ef 100755 --- a/tests/bsim/bluetooth/host/compile.sh +++ b/tests/bsim/bluetooth/host/compile.sh @@ -44,6 +44,7 @@ app=tests/bsim/bluetooth/host/gatt/settings compile app=tests/bsim/bluetooth/host/gatt/settings conf_file=prj_2.conf compile app=tests/bsim/bluetooth/host/gatt/ccc_store compile app=tests/bsim/bluetooth/host/gatt/ccc_store conf_file=prj_2.conf compile +app=tests/bsim/bluetooth/host/gatt/sc_indicate compile app=tests/bsim/bluetooth/host/l2cap/general compile app=tests/bsim/bluetooth/host/l2cap/userdata compile diff --git a/tests/bsim/bluetooth/host/gatt/sc_indicate/CMakeLists.txt b/tests/bsim/bluetooth/host/gatt/sc_indicate/CMakeLists.txt new file mode 100644 index 00000000000..d734b3c054e --- /dev/null +++ b/tests/bsim/bluetooth/host/gatt/sc_indicate/CMakeLists.txt @@ -0,0 +1,25 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) + +if (NOT DEFINED ENV{BSIM_COMPONENTS_PATH}) + message(FATAL_ERROR "This test requires the BabbleSim simulator. Please set \ + the environment variable BSIM_COMPONENTS_PATH to point to its \ + components folder. More information can be found in \ + https://babblesim.github.io/folder_structure_and_env.html") +endif() + +find_package(Zephyr HINTS $ENV{ZEPHYR_BASE}) +project(bsim_test_auto_seq_req) + +target_sources(app PRIVATE + src/main.c + src/central.c + src/peripheral.c + src/bs_bt_utils.c +) + +zephyr_include_directories( + $ENV{BSIM_COMPONENTS_PATH}/libUtilv1/src/ + $ENV{BSIM_COMPONENTS_PATH}/libPhyComv1/src/ +) diff --git a/tests/bsim/bluetooth/host/gatt/sc_indicate/prj.conf b/tests/bsim/bluetooth/host/gatt/sc_indicate/prj.conf new file mode 100644 index 00000000000..7edaf36d10e --- /dev/null +++ b/tests/bsim/bluetooth/host/gatt/sc_indicate/prj.conf @@ -0,0 +1,20 @@ +CONFIG_BT=y +CONFIG_BT_CENTRAL=y +CONFIG_BT_PERIPHERAL=y +CONFIG_BT_DEVICE_NAME="SC Indication Test" + +CONFIG_LOG=y +CONFIG_BT_EXT_ADV=y + +CONFIG_BT_SMP=y +CONFIG_BT_GATT_CLIENT=y + +CONFIG_SETTINGS=y +CONFIG_BT_SETTINGS=y +CONFIG_FLASH=y +CONFIG_FLASH_PAGE_LAYOUT=y +CONFIG_NVS=y +CONFIG_FLASH_MAP=y +CONFIG_SETTINGS_NVS=y + +CONFIG_BT_GATT_DYNAMIC_DB=y diff --git a/tests/bsim/bluetooth/host/gatt/sc_indicate/src/bs_bt_utils.c b/tests/bsim/bluetooth/host/gatt/sc_indicate/src/bs_bt_utils.c new file mode 100644 index 00000000000..31952cbe330 --- /dev/null +++ b/tests/bsim/bluetooth/host/gatt/sc_indicate/src/bs_bt_utils.c @@ -0,0 +1,182 @@ +/** + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +#include +#include +#include +#include + +#include +LOG_MODULE_REGISTER(test_utils, LOG_LEVEL_DBG); + +#include "bs_bt_utils.h" + +struct bt_conn *g_conn; +DEFINE_FLAG(flag_is_connected); + +void wait_connected(void) +{ + LOG_DBG("Wait for connection..."); + WAIT_FOR_FLAG(flag_is_connected); +} + +void wait_disconnected(void) +{ + LOG_DBG("Wait for disconnection..."); + WAIT_FOR_FLAG_UNSET(flag_is_connected); +} + +static void security_changed(struct bt_conn *conn, bt_security_t level, enum bt_security_err err) +{ + LOG_DBG("security changed"); +} + +static void disconnected(struct bt_conn *conn, uint8_t reason) +{ + UNSET_FLAG(flag_is_connected); +} + +struct bt_conn *get_g_conn(void) +{ + return g_conn; +} + +void clear_g_conn(void) +{ + struct bt_conn *conn; + + conn = g_conn; + g_conn = NULL; + BSIM_ASSERT(conn, "Test error: no g_conn!\n"); + bt_conn_unref(conn); +} + +static void connected(struct bt_conn *conn, uint8_t err) +{ + BSIM_ASSERT((!g_conn || (conn == g_conn)), "Unexpected new connection."); + + if (!g_conn) { + g_conn = bt_conn_ref(conn); + } + + if (err != 0) { + clear_g_conn(); + return; + } + + SET_FLAG(flag_is_connected); +} + +BT_CONN_CB_DEFINE(conn_callbacks) = { + .connected = connected, + .disconnected = disconnected, + .security_changed = security_changed, +}; + +static void stop_scan_and_connect(const bt_addr_le_t *addr, + int8_t rssi, + uint8_t type, + struct net_buf_simple *ad) +{ + char addr_str[BT_ADDR_LE_STR_LEN]; + int err; + + if (g_conn != NULL) { + return; + } + + bt_addr_le_to_str(addr, addr_str, sizeof(addr_str)); + printk("Got scan result, connecting.. dst %s, RSSI %d\n", addr_str, rssi); + + err = bt_le_scan_stop(); + BSIM_ASSERT(!err, "Err bt_le_scan_stop %d", err); + + err = bt_conn_le_create(addr, BT_CONN_LE_CREATE_CONN, BT_LE_CONN_PARAM_DEFAULT, &g_conn); + BSIM_ASSERT(!err, "Err bt_conn_le_create %d", err); +} + +void scan_connect_to_first_result(void) +{ + int err; + + err = bt_le_scan_start(BT_LE_SCAN_PASSIVE, stop_scan_and_connect); + BSIM_ASSERT(!err, "Err bt_le_scan_start %d", err); +} + +void disconnect(void) +{ + int err; + + err = bt_conn_disconnect(g_conn, BT_HCI_ERR_REMOTE_USER_TERM_CONN); + BSIM_ASSERT(!err, "bt_conn_disconnect failed (%d)\n", err); +} + +void set_security(bt_security_t sec) +{ + int err; + + err = bt_conn_set_security(g_conn, sec); + BSIM_ASSERT(!err, "Err bt_conn_set_security %d", err); +} + +void create_adv(struct bt_le_ext_adv **adv) +{ + int err; + struct bt_le_adv_param params = {}; + + params.options |= BT_LE_ADV_OPT_CONNECTABLE; + params.options |= BT_LE_ADV_OPT_EXT_ADV; + + params.id = BT_ID_DEFAULT; + params.sid = 0; + params.interval_min = BT_GAP_ADV_FAST_INT_MIN_2; + params.interval_max = BT_GAP_ADV_FAST_INT_MAX_2; + + err = bt_le_ext_adv_create(¶ms, NULL, adv); + BSIM_ASSERT(!err, "bt_le_ext_adv_create failed (%d)\n", err); +} + +void start_adv(struct bt_le_ext_adv *adv) +{ + int err; + + err = bt_le_ext_adv_start(adv, BT_LE_EXT_ADV_START_DEFAULT); + BSIM_ASSERT(!err, "bt_le_ext_adv_start failed (%d)\n", err); +} + +void stop_adv(struct bt_le_ext_adv *adv) +{ + int err; + + err = bt_le_ext_adv_stop(adv); + BSIM_ASSERT(!err, "bt_le_ext_adv_stop failed (%d)\n", err); +} + +/* The following flags are raised by events and lowered by test code. */ +DEFINE_FLAG(flag_pairing_complete); +DEFINE_FLAG(flag_bonded); +DEFINE_FLAG(flag_not_bonded); + +void pairing_complete(struct bt_conn *conn, bool bonded) +{ + LOG_DBG("pairing complete"); + SET_FLAG(flag_pairing_complete); + + if (bonded) { + SET_FLAG(flag_bonded); + LOG_DBG("Bonded status: true"); + } else { + SET_FLAG(flag_not_bonded); + LOG_DBG("Bonded status: false"); + } +} + +void pairing_failed(struct bt_conn *conn, enum bt_security_err err) +{ + FAIL("Pairing failed\n"); +} diff --git a/tests/bsim/bluetooth/host/gatt/sc_indicate/src/bs_bt_utils.h b/tests/bsim/bluetooth/host/gatt/sc_indicate/src/bs_bt_utils.h new file mode 100644 index 00000000000..5ec34005e9f --- /dev/null +++ b/tests/bsim/bluetooth/host/gatt/sc_indicate/src/bs_bt_utils.h @@ -0,0 +1,67 @@ +/** + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "bstests.h" +#include "bs_tracing.h" + +#include +#include + +extern enum bst_result_t bst_result; + +#define DECLARE_FLAG(flag) extern atomic_t flag +#define DEFINE_FLAG(flag) atomic_t flag = (atomic_t) false +#define SET_FLAG(flag) (void)atomic_set(&flag, (atomic_t) true) +#define UNSET_FLAG(flag) (void)atomic_set(&flag, (atomic_t) false) +#define WAIT_FOR_FLAG(flag) \ + while (!(bool)atomic_get(&flag)) { \ + (void)k_sleep(K_MSEC(1)); \ + } +#define WAIT_FOR_FLAG_UNSET(flag) \ + while ((bool)atomic_get(&flag)) { \ + (void)k_sleep(K_MSEC(1)); \ + } +#define TAKE_FLAG(flag) \ + while (!(bool)atomic_cas(&flag, true, false)) { \ + (void)k_sleep(K_MSEC(1)); \ + } +#define GET_FLAG(flag) (bool)atomic_get(&flag) + +#define BSIM_ASSERT(expr, ...) \ + do { \ + if (!(expr)) { \ + FAIL(__VA_ARGS__); \ + } \ + } while (0) + +#define FAIL(...) \ + do { \ + bst_result = Failed; \ + bs_trace_error_time_line(__VA_ARGS__); \ + } while (0) + +#define PASS(...) \ + do { \ + bst_result = Passed; \ + bs_trace_info_time(1, __VA_ARGS__); \ + } while (0) + +DECLARE_FLAG(flag_pairing_complete); +DECLARE_FLAG(flag_bonded); +DECLARE_FLAG(flag_not_bonded); + +void scan_connect_to_first_result(void); +struct bt_conn *get_g_conn(void); +void clear_g_conn(void); +void disconnect(void); +void wait_connected(void); +void wait_disconnected(void); +void create_adv(struct bt_le_ext_adv **adv); +void start_adv(struct bt_le_ext_adv *adv); +void stop_adv(struct bt_le_ext_adv *adv); +void set_security(bt_security_t sec); +void pairing_complete(struct bt_conn *conn, bool bonded); +void pairing_failed(struct bt_conn *conn, enum bt_security_err err); diff --git a/tests/bsim/bluetooth/host/gatt/sc_indicate/src/central.c b/tests/bsim/bluetooth/host/gatt/sc_indicate/src/central.c new file mode 100644 index 00000000000..ca45874e9cb --- /dev/null +++ b/tests/bsim/bluetooth/host/gatt/sc_indicate/src/central.c @@ -0,0 +1,195 @@ +/** + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + * + */ + +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include +LOG_MODULE_REGISTER(test_central, LOG_LEVEL_DBG); + +#include "bs_bt_utils.h" + +DEFINE_FLAG(flag_discovered); +DEFINE_FLAG(flag_subscribed); +DEFINE_FLAG(flag_indicated); + +enum GATT_HANDLES { + SC, + CCC, + NUM_HANDLES, +}; + +static uint16_t gatt_handles[NUM_HANDLES] = {0}; + +static struct bt_gatt_subscribe_params subscribe_params; + +static void sc_subscribed(struct bt_conn *conn, + uint8_t err, + struct bt_gatt_subscribe_params *params) +{ + LOG_DBG("subscribed"); + SET_FLAG(flag_subscribed); +} + +static uint8_t sc_indicated(struct bt_conn *conn, + struct bt_gatt_subscribe_params *params, + const void *data, + uint16_t length) +{ + LOG_DBG("indication received"); + + SET_FLAG(flag_indicated); + + return BT_GATT_ITER_CONTINUE; +} + +static void subscribe(void) +{ + int err; + + subscribe_params.ccc_handle = gatt_handles[CCC]; + subscribe_params.value_handle = gatt_handles[SC]; + subscribe_params.value = BT_GATT_CCC_INDICATE; + subscribe_params.subscribe = sc_subscribed; + subscribe_params.notify = sc_indicated; + + err = bt_gatt_subscribe(get_g_conn(), &subscribe_params); + BSIM_ASSERT(!err, "bt_gatt_subscribe failed (%d)\n", err); + + WAIT_FOR_FLAG(flag_subscribed); +} + +static uint8_t discover_func(struct bt_conn *conn, + const struct bt_gatt_attr *attr, + struct bt_gatt_discover_params *params) +{ + if (attr == NULL) { + for (size_t i = 0U; i < ARRAY_SIZE(gatt_handles); i++) { + LOG_DBG("handle[%d] = 0x%x", i, gatt_handles[i]); + BSIM_ASSERT(gatt_handles[i] != 0, "did not find all handles\n"); + } + + (void)memset(params, 0, sizeof(*params)); + SET_FLAG(flag_discovered); + + return BT_GATT_ITER_STOP; + } + + if (params->type == BT_GATT_DISCOVER_CHARACTERISTIC) { + const struct bt_gatt_chrc *chrc = (struct bt_gatt_chrc *)attr->user_data; + static const struct bt_uuid_16 ccc_uuid = BT_UUID_INIT_16(BT_UUID_GATT_CCC_VAL); + + if (bt_uuid_cmp(chrc->uuid, BT_UUID_GATT_SC) == 0) { + int err; + + LOG_DBG("found sc"); + gatt_handles[SC] = chrc->value_handle; + + params->uuid = &ccc_uuid.uuid; + params->start_handle = attr->handle + 2; + params->type = BT_GATT_DISCOVER_DESCRIPTOR; + + err = bt_gatt_discover(conn, params); + BSIM_ASSERT(!err, "bt_gatt_discover failed (%d)\n", err); + + return BT_GATT_ITER_STOP; + } + + } else if (params->type == BT_GATT_DISCOVER_DESCRIPTOR && + bt_uuid_cmp(params->uuid, BT_UUID_GATT_CCC) == 0) { + LOG_DBG("found ccc"); + gatt_handles[CCC] = attr->handle; + SET_FLAG(flag_discovered); + + return BT_GATT_ITER_STOP; + } + + return BT_GATT_ITER_CONTINUE; +} + +static void gatt_discover(void) +{ + int err; + static struct bt_gatt_discover_params discover_params; + + discover_params.uuid = NULL; + discover_params.func = discover_func; + discover_params.start_handle = BT_ATT_FIRST_ATTRIBUTE_HANDLE; + discover_params.end_handle = BT_ATT_LAST_ATTRIBUTE_HANDLE; + discover_params.type = BT_GATT_DISCOVER_CHARACTERISTIC; + + err = bt_gatt_discover(get_g_conn(), &discover_params); + BSIM_ASSERT(!err, "bt_gatt_discover failed (%d)\n", err); + + WAIT_FOR_FLAG(flag_discovered); + + LOG_DBG("sc handle: %d", gatt_handles[SC]); + LOG_DBG("ccc handle: %d", gatt_handles[CCC]); +} + +void central(void) +{ + /* + * test goal: check that service changed indication is sent on + * reconnection when the server's GATT database has been updated since + * last connection + * + * the central will connect, bond with the peripheral and then + * disconnect after doing that, the central will try to connect again, + * this time it will not elevate the security + * + * to pass the test, the central will wait to receive the service + * changed indication + */ + + int err; + struct bt_conn_auth_info_cb bt_conn_auth_info_cb = { + .pairing_failed = pairing_failed, + .pairing_complete = pairing_complete, + }; + + err = bt_enable(NULL); + BSIM_ASSERT(!err, "bt_enable failed (%d)\n", err); + + err = bt_conn_auth_info_cb_register(&bt_conn_auth_info_cb); + BSIM_ASSERT(!err, "bt_conn_auth_info_cb_register failed.\n"); + + err = settings_load(); + BSIM_ASSERT(!err, "settings_load failed (%d)\n", err); + + scan_connect_to_first_result(); + wait_connected(); + + set_security(BT_SECURITY_L2); + + TAKE_FLAG(flag_pairing_complete); + TAKE_FLAG(flag_bonded); + + /* subscribe to the service changed indication */ + gatt_discover(); + subscribe(); + + disconnect(); + wait_disconnected(); + clear_g_conn(); + + scan_connect_to_first_result(); + wait_connected(); + + /* wait for service change indication */ + WAIT_FOR_FLAG(flag_indicated); + + PASS("PASS\n"); +} diff --git a/tests/bsim/bluetooth/host/gatt/sc_indicate/src/main.c b/tests/bsim/bluetooth/host/gatt/sc_indicate/src/main.c new file mode 100644 index 00000000000..f5ffbbc4677 --- /dev/null +++ b/tests/bsim/bluetooth/host/gatt/sc_indicate/src/main.c @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "bstests.h" +#include "bs_bt_utils.h" + +#define BS_SECONDS_TO_US(dur_sec) ((bs_time_t)dur_sec * USEC_PER_SEC) +#define TEST_TIMEOUT_SIMULATED BS_SECONDS_TO_US(60) + +extern void central(void); +extern void peripheral(void); + +static void test_tick(bs_time_t HW_device_time) +{ + bs_trace_debug_time(0, "Simulation ends now.\n"); + if (bst_result != Passed) { + bst_result = Failed; + bs_trace_error("Test did not pass before simulation ended.\n"); + } +} + +static void test_init(void) +{ + bst_ticker_set_next_tick_absolute(TEST_TIMEOUT_SIMULATED); + bst_result = In_progress; +} + +static const struct bst_test_instance test_to_add[] = { + { + .test_id = "central", + .test_post_init_f = test_init, + .test_tick_f = test_tick, + .test_main_f = central, + }, + { + .test_id = "peripheral", + .test_post_init_f = test_init, + .test_tick_f = test_tick, + .test_main_f = peripheral, + }, + BSTEST_END_MARKER, +}; + +static struct bst_test_list *install(struct bst_test_list *tests) +{ + return bst_add_tests(tests, test_to_add); +}; + +bst_test_install_t test_installers[] = {install, NULL}; + +int main(void) +{ + bst_main(); + return 0; +} diff --git a/tests/bsim/bluetooth/host/gatt/sc_indicate/src/peripheral.c b/tests/bsim/bluetooth/host/gatt/sc_indicate/src/peripheral.c new file mode 100644 index 00000000000..e15c00b60d7 --- /dev/null +++ b/tests/bsim/bluetooth/host/gatt/sc_indicate/src/peripheral.c @@ -0,0 +1,86 @@ +/** + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + * + */ + +#include + +#include +#include +#include +#include +#include +#include + +#include +LOG_MODULE_REGISTER(test_peripheral, LOG_LEVEL_DBG); + +#include "bs_bt_utils.h" + +#define UUID_1 BT_UUID_DECLARE_128(0xdb, 0x1f, 0xe2, 0x52, 0xf3, 0xc6, 0x43, 0x66, \ + 0xb3, 0x92, 0x5d, 0xc6, 0xe7, 0xc9, 0x59, 0x9d) +#define UUID_2 BT_UUID_DECLARE_128(0x3f, 0xa4, 0x7f, 0x44, 0x2e, 0x2a, 0x43, 0x05, \ + 0xab, 0x38, 0x07, 0x8d, 0x16, 0xbf, 0x99, 0xf1) + +static void new_svc_ccc_cfg_changed(const struct bt_gatt_attr *attr, uint16_t value) +{ + ARG_UNUSED(attr); + + bool notif_enabled = (value == BT_GATT_CCC_NOTIFY); + + LOG_DBG("CCC Update: notification %s", notif_enabled ? "enabled" : "disabled"); +} + +static struct bt_gatt_attr attrs[] = { + BT_GATT_PRIMARY_SERVICE(UUID_1), + BT_GATT_CHARACTERISTIC(UUID_2, BT_GATT_CHRC_NOTIFY, BT_GATT_PERM_NONE, NULL, NULL, NULL), + BT_GATT_CCC(new_svc_ccc_cfg_changed, BT_GATT_PERM_READ | BT_GATT_PERM_WRITE), +}; + +static struct bt_gatt_service svc = { + .attrs = attrs, + .attr_count = ARRAY_SIZE(attrs), +}; + +void peripheral(void) +{ + /* + * test goal: check that service changed indication is sent on + * reconnection when the server's GATT database has been updated since + * last connection + * + * the peripheral will wait for connection/disconnection, when + * disconnected it will register a new service, when reconnecting, the + * central should receive an indication + */ + + int err; + struct bt_le_ext_adv *adv = NULL; + + err = bt_enable(NULL); + BSIM_ASSERT(!err, "bt_enable failed (%d)\n", err); + + err = settings_load(); + BSIM_ASSERT(!err, "settings_load failed (%d)\n", err); + + create_adv(&adv); + start_adv(adv); + wait_connected(); + + stop_adv(adv); + + wait_disconnected(); + clear_g_conn(); + + /* add a new service to trigger the service changed indication */ + err = bt_gatt_service_register(&svc); + BSIM_ASSERT(!err, "bt_gatt_service_register failed (%d)\n", err); + LOG_DBG("New service added"); + + start_adv(adv); + wait_connected(); + + PASS("Done\n"); +} diff --git a/tests/bsim/bluetooth/host/gatt/sc_indicate/test_scripts/_compile.sh b/tests/bsim/bluetooth/host/gatt/sc_indicate/test_scripts/_compile.sh new file mode 100755 index 00000000000..b07577a9878 --- /dev/null +++ b/tests/bsim/bluetooth/host/gatt/sc_indicate/test_scripts/_compile.sh @@ -0,0 +1,18 @@ +#!/bin/env bash +# Copyright 2023 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +set -eu + +# Terminate running simulations (if any) +${BSIM_COMPONENTS_PATH}/common/stop_bsim.sh + +test_name='sc_indicate' + +: "${BSIM_OUT_PATH:?BSIM_OUT_PATH must be defined}" +bsim_bin="${BSIM_OUT_PATH}/bin" +BOARD="${BOARD:-nrf52_bsim}" +test_exe="${bsim_bin}/bs_${BOARD}_tests_bsim_bluetooth_host_gatt_${test_name}_prj_conf" + +west build -b nrf52_bsim -d build && \ + cp -v build/zephyr/zephyr.exe "${test_exe}" diff --git a/tests/bsim/bluetooth/host/gatt/sc_indicate/test_scripts/sc_indicate.sh b/tests/bsim/bluetooth/host/gatt/sc_indicate/test_scripts/sc_indicate.sh new file mode 100755 index 00000000000..b46ae13929c --- /dev/null +++ b/tests/bsim/bluetooth/host/gatt/sc_indicate/test_scripts/sc_indicate.sh @@ -0,0 +1,24 @@ +#!/bin/env bash +# Copyright 2023 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +source ${ZEPHYR_BASE}/tests/bsim/sh_common.source + +test_name='sc_indicate' +test_exe="bs_${BOARD}_tests_bsim_bluetooth_host_gatt_${test_name}_prj_conf" +simulation_id="${test_name}" +verbosity_level=2 +EXECUTE_TIMEOUT=30 + +cd ${BSIM_OUT_PATH}/bin + +Execute "./${test_exe}" \ + -v=${verbosity_level} -s=${simulation_id} -d=0 -testid=central + +Execute "./${test_exe}" \ + -v=${verbosity_level} -s=${simulation_id} -d=1 -testid=peripheral + +Execute ./bs_2G4_phy_v1 -v=${verbosity_level} -s=${simulation_id} \ + -D=2 -sim_length=60e6 + +wait_for_background_jobs From c33d528a791c5aa4995e998b07ed8921ac2c04b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20Battrel?= Date: Mon, 18 Sep 2023 13:59:45 +0200 Subject: [PATCH 194/421] [nrf fromtree] Revert "Bluetooth: Host: Fix GATT server handling of CCC" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit cfd368fef1b72e9468626ee03ed1992ceb1e8965. Signed-off-by: Théo Battrel (cherry picked from commit c2b99c0123b4bbb8e70843604e855c5e8fd0211c) (cherry picked from commit 72d67fbaee7d4173e37513309d9f4b8d534da77b) --- include/zephyr/bluetooth/gatt.h | 5 ---- subsys/bluetooth/host/gatt.c | 43 ++++++--------------------------- 2 files changed, 7 insertions(+), 41 deletions(-) diff --git a/include/zephyr/bluetooth/gatt.h b/include/zephyr/bluetooth/gatt.h index e4aae4e4d41..f0ee8d5981a 100644 --- a/include/zephyr/bluetooth/gatt.h +++ b/include/zephyr/bluetooth/gatt.h @@ -736,11 +736,6 @@ struct bt_gatt_ccc_cfg { uint8_t id; /** Remote peer address. */ bt_addr_le_t peer; - /** - * Separate storage for encrypted and unencrypted context. This - * indicate that the link was encrypted when the CCC was written. - */ - bool link_encrypted; /** Configuration value. */ uint16_t value; }; diff --git a/subsys/bluetooth/host/gatt.c b/subsys/bluetooth/host/gatt.c index 39f01bc45b4..93dfe555580 100644 --- a/subsys/bluetooth/host/gatt.c +++ b/subsys/bluetooth/host/gatt.c @@ -1318,7 +1318,6 @@ static void clear_ccc_cfg(struct bt_gatt_ccc_cfg *cfg) bt_addr_le_copy(&cfg->peer, BT_ADDR_LE_ANY); cfg->id = 0U; cfg->value = 0U; - cfg->link_encrypted = false; } static void gatt_store_ccc_cf(uint8_t id, const bt_addr_le_t *peer_addr); @@ -2050,34 +2049,6 @@ struct bt_gatt_attr *bt_gatt_attr_next(const struct bt_gatt_attr *attr) return next; } -static bool bt_gatt_ccc_cfg_is_matching_conn(const struct bt_conn *conn, - const struct bt_gatt_ccc_cfg *cfg) -{ - bool conn_encrypted = bt_conn_get_security(conn) >= BT_SECURITY_L2; - - if (cfg->link_encrypted && !conn_encrypted) { - return false; - } - - return bt_conn_is_peer_addr_le(conn, cfg->id, &cfg->peer); -} - -static struct bt_conn *bt_gatt_ccc_cfg_conn_lookup(const struct bt_gatt_ccc_cfg *cfg) -{ - struct bt_conn *conn; - - conn = bt_conn_lookup_addr_le(cfg->id, &cfg->peer); - if (conn) { - if (bt_gatt_ccc_cfg_is_matching_conn(conn, cfg)) { - return conn; - } - - bt_conn_unref(conn); - } - - return NULL; -} - static struct bt_gatt_ccc_cfg *find_ccc_cfg(const struct bt_conn *conn, struct _bt_gatt_ccc *ccc) { @@ -2085,7 +2056,8 @@ static struct bt_gatt_ccc_cfg *find_ccc_cfg(const struct bt_conn *conn, struct bt_gatt_ccc_cfg *cfg = &ccc->cfg[i]; if (conn) { - if (bt_gatt_ccc_cfg_is_matching_conn(conn, cfg)) { + if (bt_conn_is_peer_addr_le(conn, cfg->id, + &cfg->peer)) { return cfg; } } else if (bt_addr_le_eq(&cfg->peer, BT_ADDR_LE_ANY)) { @@ -2179,7 +2151,6 @@ ssize_t bt_gatt_attr_write_ccc(struct bt_conn *conn, bt_addr_le_copy(&cfg->peer, &conn->le.dst); cfg->id = conn->id; - cfg->link_encrypted = (bt_conn_get_security(conn) >= BT_SECURITY_L2); } /* Confirm write if cfg is managed by application */ @@ -3259,7 +3230,8 @@ static uint8_t update_ccc(const struct bt_gatt_attr *attr, uint16_t handle, struct bt_gatt_ccc_cfg *cfg = &ccc->cfg[i]; /* Ignore configuration for different peer or not active */ - if (!cfg->value || !bt_gatt_ccc_cfg_is_matching_conn(conn, cfg)) { + if (!cfg->value || + !bt_conn_is_peer_addr_le(conn, cfg->id, &cfg->peer)) { continue; } @@ -3333,11 +3305,11 @@ static uint8_t disconnected_cb(const struct bt_gatt_attr *attr, uint16_t handle, continue; } - if (!bt_gatt_ccc_cfg_is_matching_conn(conn, cfg)) { + if (!bt_conn_is_peer_addr_le(conn, cfg->id, &cfg->peer)) { struct bt_conn *tmp; /* Skip if there is another peer connected */ - tmp = bt_gatt_ccc_cfg_conn_lookup(cfg); + tmp = bt_conn_lookup_addr_le(cfg->id, &cfg->peer); if (tmp) { if (tmp->state == BT_CONN_CONNECTED) { value_used = true; @@ -3427,7 +3399,7 @@ bool bt_gatt_is_subscribed(struct bt_conn *conn, for (size_t i = 0; i < BT_GATT_CCC_MAX; i++) { const struct bt_gatt_ccc_cfg *cfg = &ccc->cfg[i]; - if (bt_gatt_ccc_cfg_is_matching_conn(conn, cfg) && + if (bt_conn_is_peer_addr_le(conn, cfg->id, &cfg->peer) && (ccc_type & ccc->cfg[i].value)) { return true; } @@ -5578,7 +5550,6 @@ static uint8_t ccc_load(const struct bt_gatt_attr *attr, uint16_t handle, } bt_addr_le_copy(&cfg->peer, load->addr_with_id.addr); cfg->id = load->addr_with_id.id; - cfg->link_encrypted = true; } cfg->value = load->entry->value; From c65b964187a631bd6bce52995599b29ba455b8dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20Battrel?= Date: Fri, 22 Sep 2023 13:16:37 +0200 Subject: [PATCH 195/421] [nrf fromtree] Bluetooth: Test: Update `security/ccc_update` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previous commit reverted the `link_encrypted` filed of CCC config. Update the test to match the new expected behavior. Signed-off-by: Théo Battrel (cherry picked from commit 2e13802a38469d5cb9a7fbbca8c029a9ce9e9f6b) (cherry picked from commit c991ee360e64a82bb0f396d3c731654905239e02) --- .../host/security/ccc_update/src/central.c | 9 ++---- .../host/security/ccc_update/src/peripheral.c | 28 ++++++++++++------- 2 files changed, 21 insertions(+), 16 deletions(-) diff --git a/tests/bsim/bluetooth/host/security/ccc_update/src/central.c b/tests/bsim/bluetooth/host/security/ccc_update/src/central.c index fbdf7ee0108..8f2d2c17dd4 100644 --- a/tests/bsim/bluetooth/host/security/ccc_update/src/central.c +++ b/tests/bsim/bluetooth/host/security/ccc_update/src/central.c @@ -248,7 +248,7 @@ static void connect_unsubscribe(void) backchannel_sync_wait(SERVER_CLIENT_CHAN, SERVER_ID); } -static void connect_restore_sec_unsubscribe(void) +static void connect_restore_sec(void) { int err; @@ -270,10 +270,7 @@ static void connect_restore_sec_unsubscribe(void) /* wait for server to check that the subscribtion has been restored */ backchannel_sync_wait(SERVER_CLIENT_CHAN, SERVER_ID); - /* send unsubscribtion request */ - ccc_unsubscribe(); - - /* wait for server to check that the unsubscribtion has been well registered */ + /* wait for server to check that the subscription no longer exist */ backchannel_sync_send(SERVER_CLIENT_CHAN, SERVER_ID); } @@ -347,7 +344,7 @@ void run_central(void) backchannel_sync_send(CLIENT_CLIENT_CHAN, BAD_CLIENT_ID); backchannel_sync_wait(CLIENT_CLIENT_CHAN, BAD_CLIENT_ID); - connect_restore_sec_unsubscribe(); + connect_restore_sec(); disconnect(); PASS("Central test passed\n"); diff --git a/tests/bsim/bluetooth/host/security/ccc_update/src/peripheral.c b/tests/bsim/bluetooth/host/security/ccc_update/src/peripheral.c index b9070361577..ac6307dae6a 100644 --- a/tests/bsim/bluetooth/host/security/ccc_update/src/peripheral.c +++ b/tests/bsim/bluetooth/host/security/ccc_update/src/peripheral.c @@ -194,9 +194,9 @@ static void connect_wait_unsubscribtion(struct bt_le_ext_adv *adv) stop_adv(adv); - /* check that subscribtion is not restored for bad client */ - if (is_peer_subscribed(default_conn)) { - FAIL("Subscribtion has been restored for bad client\n"); + /* check that subscribtion is restored for bad client */ + if (!is_peer_subscribed(default_conn)) { + FAIL("Subscribtion has not been restored for bad client\n"); } /* confirm to bad client that the subscribtion had not been restored */ @@ -204,12 +204,12 @@ static void connect_wait_unsubscribtion(struct bt_le_ext_adv *adv) /* wait for confirmation that bad client requested unsubscribtion */ backchannel_sync_wait(BAD_CLIENT_CHAN, BAD_CLIENT_ID); - /* check that unsubscribtion request failed */ - if (GET_FLAG(ccc_cfg_changed_flag)) { - FAIL("Bad client updated CCC config\n"); + /* check that unsubscribtion request didn't fail */ + if (!GET_FLAG(ccc_cfg_changed_flag)) { + FAIL("Bad client didn't manage to update CCC config\n"); } - /* confirm to bad client that unsubscribtion request has been ignored */ + /* confirm to bad client that unsubscribtion request has been well registered */ backchannel_sync_send(BAD_CLIENT_CHAN, BAD_CLIENT_ID); } @@ -225,9 +225,9 @@ static void connect_restore_sec_check_subscribtion(struct bt_le_ext_adv *adv) /* wait for good client end of security update */ backchannel_sync_wait(GOOD_CLIENT_CHAN, GOOD_CLIENT_ID); - /* check that subscribtion has been restored */ - if (!is_peer_subscribed(default_conn)) { - FAIL("Good client is not subscribed\n"); + /* check that subscribtion hasn't been restored */ + if (is_peer_subscribed(default_conn)) { + FAIL("Good client is subscribed\n"); } /* confirm to good client that the subscribtion has been well restored */ @@ -285,6 +285,14 @@ static void check_ccc_handle(void) void run_peripheral(void) { + /* + * test goal: demonstrate the expected behavior of the GATT server when + * a non-bonded peer try to unsubscribe from a previously subscription + * done in a bonded context + * + * test pass if the bad client manage to unsubscribe + */ + int err; struct bt_le_ext_adv *adv = NULL; From 33a728fe359097894cd94598f2f09f7d883f6b8e Mon Sep 17 00:00:00 2001 From: Maximilian Deubel Date: Fri, 15 Sep 2023 10:50:13 +0200 Subject: [PATCH 196/421] [nrf fromtree] boards: arm: nrf9161dk: update SPI flash This patch updates the SPI flash to the one currently used in the latest board version. Since these are still 0.X.X board versions, old configurations are not explicitly supported. (cherry picked from commit 3a34840957a186fe5956c5714eda4072b469a707) Signed-off-by: Maximilian Deubel (cherry picked from commit 04666ef4578116e692ae4ae038f8ff46941b609e) --- .../nrf9161dk_nrf9161_common.dtsi | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/boards/arm/nrf9161dk_nrf9161/nrf9161dk_nrf9161_common.dtsi b/boards/arm/nrf9161dk_nrf9161/nrf9161dk_nrf9161_common.dtsi index 1dee5b1b1a3..a6aeccf34b9 100644 --- a/boards/arm/nrf9161dk_nrf9161/nrf9161dk_nrf9161_common.dtsi +++ b/boards/arm/nrf9161dk_nrf9161/nrf9161dk_nrf9161_common.dtsi @@ -128,7 +128,7 @@ mcuboot-button0 = &button0; mcuboot-led0 = &led0; watchdog0 = &wdt0; - spi-flash0 = &gd25lb256; + spi-flash0 = &gd25wb256; }; }; @@ -195,22 +195,22 @@ arduino_spi: &spi3 { pinctrl-1 = <&spi3_sleep>; pinctrl-names = "default", "sleep"; - gd25lb256: gd25lb256e3ir@1 { + gd25wb256: gd25wb256e3ir@1 { compatible = "jedec,spi-nor"; status = "disabled"; reg = <1>; - spi-max-frequency = <60000000>; - jedec-id = [c8 67 19]; - sfdp-bfp = [ - e5 20 ea ff ff ff ff 0f 44 eb 08 6b 00 3b 00 bb - fe ff ff ff ff ff 00 ff ff ff 44 eb 0c 20 0f 52 - 10 d8 00 ff d5 31 b1 fe 82 e4 14 4c ec 60 06 33 - 7a 75 7a 75 04 bd d5 5c 29 06 74 00 08 50 00 01 - ]; + spi-max-frequency = <8000000>; size = <268435456>; has-dpd; t-enter-dpd = <3000>; - t-exit-dpd = <30000>; + t-exit-dpd = <40000>; + sfdp-bfp = [ + e5 20 f3 ff ff ff ff 0f 44 eb 08 6b 08 3b 42 bb + ee ff ff ff ff ff 00 ff ff ff 00 ff 0c 20 0f 52 + 10 d8 00 ff 44 7a c9 fe 83 67 26 62 ec 82 18 44 + 7a 75 7a 75 04 c4 d5 5c 00 06 74 00 08 50 00 01 + ]; + jedec-id = [c8 65 19]; }; }; From 10b0106a4e8771c99908d2b9c783fd9eee2e40bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eivind=20J=C3=B8lsgard?= Date: Wed, 4 Oct 2023 09:41:33 +0200 Subject: [PATCH 197/421] =?UTF-8?q?[nrf=20fromtree]=C2=A0boards:=20arm:=20?= =?UTF-8?q?nrf9161dk=5Fnrf9161:=20Add=20ext=20flash=20support=20for=200.7.?= =?UTF-8?q?0=20version?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add support for external flash on the 0.7.0 DK version. (cherry picked from commit 8203646cc48c5bfe224b5b5dd2e7dec78e0b1b45) Signed-off-by: Eivind Jølsgard (cherry picked from commit 8c7463b5230ce09b74d75e1b963d0c262d92fa73) --- .../nrf9161dk_nrf9161_0_7_0.overlay | 7 +++++ .../nrf9161dk_nrf9161_common_0_7_0.dtsi | 31 +++++++++++++++++++ .../nrf9161dk_nrf9161_ns_0_7_0.overlay | 7 +++++ boards/arm/nrf9161dk_nrf9161/revision.cmake | 8 +++++ 4 files changed, 53 insertions(+) create mode 100644 boards/arm/nrf9161dk_nrf9161/nrf9161dk_nrf9161_0_7_0.overlay create mode 100644 boards/arm/nrf9161dk_nrf9161/nrf9161dk_nrf9161_common_0_7_0.dtsi create mode 100644 boards/arm/nrf9161dk_nrf9161/nrf9161dk_nrf9161_ns_0_7_0.overlay create mode 100644 boards/arm/nrf9161dk_nrf9161/revision.cmake diff --git a/boards/arm/nrf9161dk_nrf9161/nrf9161dk_nrf9161_0_7_0.overlay b/boards/arm/nrf9161dk_nrf9161/nrf9161dk_nrf9161_0_7_0.overlay new file mode 100644 index 00000000000..22e9f970dab --- /dev/null +++ b/boards/arm/nrf9161dk_nrf9161/nrf9161dk_nrf9161_0_7_0.overlay @@ -0,0 +1,7 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "nrf9161dk_nrf9161_common_0_7_0.dtsi" diff --git a/boards/arm/nrf9161dk_nrf9161/nrf9161dk_nrf9161_common_0_7_0.dtsi b/boards/arm/nrf9161dk_nrf9161/nrf9161dk_nrf9161_common_0_7_0.dtsi new file mode 100644 index 00000000000..ae67df77b22 --- /dev/null +++ b/boards/arm/nrf9161dk_nrf9161/nrf9161dk_nrf9161_common_0_7_0.dtsi @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&spi3 { + gd25lb256: gd25lb256e3ir@1 { + compatible = "jedec,spi-nor"; + status = "okay"; + reg = <1>; + spi-max-frequency = <60000000>; + jedec-id = [c8 67 19]; + sfdp-bfp = [ + e5 20 ea ff ff ff ff 0f 44 eb 08 6b 00 3b 00 bb + fe ff ff ff ff ff 00 ff ff ff 44 eb 0c 20 0f 52 + 10 d8 00 ff d5 31 b1 fe 82 e4 14 4c ec 60 06 33 + 7a 75 7a 75 04 bd d5 5c 29 06 74 00 08 50 00 01 + ]; + size = <268435456>; + has-dpd; + t-enter-dpd = <3000>; + t-exit-dpd = <30000>; + }; +}; + +/ { + aliases { + spi-flash0 = &gd25lb256; + }; +}; diff --git a/boards/arm/nrf9161dk_nrf9161/nrf9161dk_nrf9161_ns_0_7_0.overlay b/boards/arm/nrf9161dk_nrf9161/nrf9161dk_nrf9161_ns_0_7_0.overlay new file mode 100644 index 00000000000..22e9f970dab --- /dev/null +++ b/boards/arm/nrf9161dk_nrf9161/nrf9161dk_nrf9161_ns_0_7_0.overlay @@ -0,0 +1,7 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "nrf9161dk_nrf9161_common_0_7_0.dtsi" diff --git a/boards/arm/nrf9161dk_nrf9161/revision.cmake b/boards/arm/nrf9161dk_nrf9161/revision.cmake new file mode 100644 index 00000000000..2a899f61a83 --- /dev/null +++ b/boards/arm/nrf9161dk_nrf9161/revision.cmake @@ -0,0 +1,8 @@ +# Copyright (c) 2023 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +board_check_revision( + FORMAT MAJOR.MINOR.PATCH + DEFAULT_REVISION 0.9.0 + VALID_REVISIONS 0.7.0 0.9.0 +) From 7bc30a2760c9c536cd24b1ebe040d1cdcbed6f08 Mon Sep 17 00:00:00 2001 From: Aleksandr Khromykh Date: Wed, 4 Oct 2023 16:41:39 +0200 Subject: [PATCH 198/421] [nrf fromtree] Bluetooth: Mesh: fix settings work queue size for rpr MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If RPR server is used then Mesh settings work queue requires more size during provisioning procedure. Signed-off-by: Aleksandr Khromykh (cherry picked from commit 0ba6e80a12b94aa09d47889e3cb0b08024a9cde6) Signed-off-by: Alperen Şener (cherry picked from commit f825ca8452fee34aac58d79656f51afd9a3fc121) --- subsys/bluetooth/mesh/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/subsys/bluetooth/mesh/Kconfig b/subsys/bluetooth/mesh/Kconfig index 2dfc125b8fd..9f24ff81975 100644 --- a/subsys/bluetooth/mesh/Kconfig +++ b/subsys/bluetooth/mesh/Kconfig @@ -1718,6 +1718,7 @@ config BT_MESH_SETTINGS_WORKQ_PRIO config BT_MESH_SETTINGS_WORKQ_STACK_SIZE int "Stack size of the settings workq" + default 1200 if BT_MESH_RPR_SRV default 880 help Size of the settings workqueue stack. From b0b28e641a6591433abfdff68770fac327995e35 Mon Sep 17 00:00:00 2001 From: Pavel Vasilyev Date: Wed, 4 Oct 2023 15:29:10 +0200 Subject: [PATCH 199/421] [nrf fromtree] tests: bluetooth: tester: Move bt_mesh_init call to BTP_MESH_INIT cmd MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In some RPR tests we need to pass alternative composition data when testing CDP128. When bt_mesh_init is called from mesh service registration callback, we can't pass any arguments. Therefore we need to move bt_mesh_init call out from mesh service registration to BTP_MESH_INIT command. Signed-off-by: Pavel Vasilyev (cherry picked from commit 2445e55cd4ddaa2b3863bdedb4dca520a93e1b93) Signed-off-by: Alperen Şener (cherry picked from commit 0d70886943e83a250b9aea92e31932fa4f372410) --- tests/bluetooth/tester/src/btp/btp_mesh.h | 4 +++ tests/bluetooth/tester/src/btp_mesh.c | 32 ++++++++++++----------- 2 files changed, 21 insertions(+), 15 deletions(-) diff --git a/tests/bluetooth/tester/src/btp/btp_mesh.h b/tests/bluetooth/tester/src/btp/btp_mesh.h index 826f0fd0408..bb26524246e 100644 --- a/tests/bluetooth/tester/src/btp/btp_mesh.h +++ b/tests/bluetooth/tester/src/btp/btp_mesh.h @@ -77,6 +77,10 @@ struct btp_mesh_provision_node_cmd_v2 { } __packed; #define BTP_MESH_INIT 0x04 +struct btp_mesh_init_cmd { + bool comp_alt; +} __packed; + #define BTP_MESH_RESET 0x05 #define BTP_MESH_INPUT_NUMBER 0x06 struct btp_mesh_input_number_cmd { diff --git a/tests/bluetooth/tester/src/btp_mesh.c b/tests/bluetooth/tester/src/btp_mesh.c index e83f1a67ba1..eea03b0936e 100644 --- a/tests/bluetooth/tester/src/btp_mesh.c +++ b/tests/bluetooth/tester/src/btp_mesh.c @@ -1258,8 +1258,24 @@ static uint8_t provision_adv(const void *cmd, uint16_t cmd_len, static uint8_t init(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len) { + const struct btp_mesh_init_cmd *cp = cmd; int err; + if (!cp->comp_alt) { + LOG_WRN("Loading default comp data"); + err = bt_mesh_init(&prov, &comp); + } else { + LOG_WRN("Loading alternative comp data"); +#ifdef CONFIG_BT_MESH_LARGE_COMP_DATA_SRV + health_srv.metadata = health_srv_meta_alt; +#endif + err = bt_mesh_init(&prov, &comp_alt); + } + + if (err) { + return BTP_STATUS_FAILED; + } + LOG_DBG(""); if (IS_ENABLED(CONFIG_BT_SETTINGS)) { @@ -4419,7 +4435,7 @@ static const struct btp_handler handlers[] = { }, { .opcode = BTP_MESH_INIT, - .expect_len = 0, + .expect_len = sizeof(struct btp_mesh_init_cmd), .func = init, }, { @@ -5224,8 +5240,6 @@ BT_MESH_LPN_CB_DEFINE(lpn_cb) = { uint8_t tester_init_mesh(void) { - int err; - if (IS_ENABLED(CONFIG_BT_TESTING)) { bt_test_cb_register(&bt_test_cb); } @@ -5236,18 +5250,6 @@ uint8_t tester_init_mesh(void) tester_register_command_handlers(BTP_SERVICE_ID_MESH, handlers, ARRAY_SIZE(handlers)); - if (default_comp) { - err = bt_mesh_init(&prov, &comp); - } else { -#ifdef CONFIG_BT_MESH_LARGE_COMP_DATA_SRV - health_srv.metadata = health_srv_meta_alt; -#endif - err = bt_mesh_init(&prov, &comp_alt); - } - - if (err) { - return BTP_STATUS_FAILED; - } return BTP_STATUS_SUCCESS; } From 2814689b0005730341054fb7b7de91c0488f320a Mon Sep 17 00:00:00 2001 From: Pavel Vasilyev Date: Wed, 4 Oct 2023 15:32:28 +0200 Subject: [PATCH 200/421] [nrf fromtree] tests: bluetooth: tester: Remove comp_alt_set command MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove this command as composition can only be set in bt_mesh_init call which is called before settings are loaded. Signed-off-by: Pavel Vasilyev (cherry picked from commit bd82ff245a92ea15a4d938621c4c977d11c07177) Signed-off-by: Alperen Şener (cherry picked from commit 630017033c61fd3148e099035b82113a540c640b) --- tests/bluetooth/tester/src/btp/btp_mesh.h | 2 - tests/bluetooth/tester/src/btp_mesh.c | 48 ----------------------- 2 files changed, 50 deletions(-) diff --git a/tests/bluetooth/tester/src/btp/btp_mesh.h b/tests/bluetooth/tester/src/btp/btp_mesh.h index bb26524246e..6b58d1515dc 100644 --- a/tests/bluetooth/tester/src/btp/btp_mesh.h +++ b/tests/bluetooth/tester/src/btp/btp_mesh.h @@ -849,8 +849,6 @@ struct btp_mesh_opcodes_aggregator_init_cmd { #define BTP_MESH_COMP_CHANGE_PREPARE 0x57 -#define BTP_MESH_SET_COMP_ALT 0x58 - #define BTP_MESH_RPR_SCAN_START 0x59 struct btp_rpr_scan_start_cmd { uint16_t dst; diff --git a/tests/bluetooth/tester/src/btp_mesh.c b/tests/bluetooth/tester/src/btp_mesh.c index eea03b0936e..dd16e98367b 100644 --- a/tests/bluetooth/tester/src/btp_mesh.c +++ b/tests/bluetooth/tester/src/btp_mesh.c @@ -318,8 +318,6 @@ static struct { .dst = BT_MESH_ADDR_UNASSIGNED, }; -static bool default_comp = true; - static uint8_t supported_commands(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len) { @@ -1905,47 +1903,6 @@ static uint8_t change_prepare(const void *cmd, uint16_t cmd_len, return BTP_STATUS_SUCCESS; } -#if IS_ENABLED(CONFIG_BT_SETTINGS) -static int comp_alt_set(const char *name, size_t len_rd, - settings_read_cb read_cb, void *store) -{ - ssize_t len; - bool alt_comp_value; - - if (len_rd == 0) { - LOG_DBG("Default composition"); - } - - len = read_cb(store, &alt_comp_value, sizeof(alt_comp_value)); - if (len < 0 || len != len_rd) { - LOG_ERR("Failed to read value (err %zd)", len); - return len; - } - - if (alt_comp_value) { - default_comp = false; - } - - return 0; -} - -SETTINGS_STATIC_HANDLER_DEFINE(tester_comp_alt, "tester/comp_alt", NULL, comp_alt_set, NULL, NULL); -#endif - -static uint8_t set_comp_alt(const void *cmd, uint16_t cmd_len, - void *rsp, uint16_t *rsp_len) -{ -#if !IS_ENABLED(CONFIG_BT_SETTINGS) - return BTP_STATUS_FAILED; -#else - bool comp_alt_val = true; - - settings_save_one("tester/comp_alt", &comp_alt_val, sizeof(comp_alt_val)); - - return BTP_STATUS_SUCCESS; -#endif -} - static uint8_t config_krp_get(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len) { @@ -4863,11 +4820,6 @@ static const struct btp_handler handlers[] = { .expect_len = 0, .func = change_prepare }, - { - .opcode = BTP_MESH_SET_COMP_ALT, - .expect_len = 0, - .func = set_comp_alt - }, #if defined(CONFIG_BT_MESH_RPR_CLI) { .opcode = BTP_MESH_RPR_SCAN_START, From 0d5459354aa7383a99c7c7681fea795166061817 Mon Sep 17 00:00:00 2001 From: Pavel Vasilyev Date: Thu, 5 Oct 2023 11:20:45 +0200 Subject: [PATCH 201/421] [nrf fromtree] tests: bluetooth: tester: Allow to pass int instead of bool in comp cmd MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This will allow to choose more variants of cdp in future if needed. Signed-off-by: Pavel Vasilyev (cherry picked from commit 8b4994f22fe9185cafff84fae33d392837f6d81e) Signed-off-by: Alperen Şener (cherry picked from commit 247c268c6e90316c361fcc4b1f57656515452f4d) --- tests/bluetooth/tester/src/btp/btp_mesh.h | 2 +- tests/bluetooth/tester/src/btp_mesh.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/bluetooth/tester/src/btp/btp_mesh.h b/tests/bluetooth/tester/src/btp/btp_mesh.h index 6b58d1515dc..c2636d1445d 100644 --- a/tests/bluetooth/tester/src/btp/btp_mesh.h +++ b/tests/bluetooth/tester/src/btp/btp_mesh.h @@ -78,7 +78,7 @@ struct btp_mesh_provision_node_cmd_v2 { #define BTP_MESH_INIT 0x04 struct btp_mesh_init_cmd { - bool comp_alt; + uint8_t comp; } __packed; #define BTP_MESH_RESET 0x05 diff --git a/tests/bluetooth/tester/src/btp_mesh.c b/tests/bluetooth/tester/src/btp_mesh.c index dd16e98367b..2a74bb03828 100644 --- a/tests/bluetooth/tester/src/btp_mesh.c +++ b/tests/bluetooth/tester/src/btp_mesh.c @@ -1259,7 +1259,7 @@ static uint8_t init(const void *cmd, uint16_t cmd_len, const struct btp_mesh_init_cmd *cp = cmd; int err; - if (!cp->comp_alt) { + if (cp->comp == 0) { LOG_WRN("Loading default comp data"); err = bt_mesh_init(&prov, &comp); } else { From b043570e6e1a2721b9c4ac566a5f768366196f80 Mon Sep 17 00:00:00 2001 From: Ingar Kulbrandstad Date: Mon, 2 Oct 2023 17:41:31 +0200 Subject: [PATCH 202/421] [nrf fromtree] Bluetooth: Mesh: Fixed issue with RPR server and client. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixed issue when reprovisioning is done on a device with both RPR client and server on the same device. Signed-off-by: Ingar Kulbrandstad (cherry picked from commit a5d15ec01737e9f555c370533f358847877cbb94) Signed-off-by: Alperen Şener (cherry picked from commit 327e3899d585342bd99c1e7d988ac1a707b6d800) --- subsys/bluetooth/mesh/provisioner.c | 71 +++ .../bsim/bluetooth/mesh/src/test_provision.c | 490 +++++++++++++----- .../pb_remote_client_server_same_dev.sh | 32 ++ 3 files changed, 470 insertions(+), 123 deletions(-) create mode 100755 tests/bsim/bluetooth/mesh/tests_scripts/provision/pb_remote_client_server_same_dev.sh diff --git a/subsys/bluetooth/mesh/provisioner.c b/subsys/bluetooth/mesh/provisioner.c index 361f373cb7b..717cdbee610 100644 --- a/subsys/bluetooth/mesh/provisioner.c +++ b/subsys/bluetooth/mesh/provisioner.c @@ -857,6 +857,72 @@ int bt_mesh_pb_remote_open(struct bt_mesh_rpr_cli *cli, return link_open(uuid, &pb_remote_cli, net_idx, addr, 0, &ctx, 0); } +/* Remote Provision done where client and server is on same node, skip open link + * and sending of reprovision message, just execute reprovisioning on it self. + */ +static int reprovision_local_client_server(uint16_t addr) +{ + int err; + const uint8_t *pub_key; + const uint8_t *priv_key = NULL; + + if (atomic_test_and_set_bit(bt_mesh_prov_link.flags, LINK_ACTIVE)) { + return -EBUSY; + } + + LOG_DBG("net_idx %u iv_index 0x%08x, addr 0x%04x", + prov_device.node->net_idx, bt_mesh_cdb.iv_index, addr); + + atomic_set_bit(bt_mesh_prov_link.flags, REPROVISION); + atomic_set_bit(bt_mesh_prov_link.flags, PROVISIONER); + bt_mesh_prov_link.addr = addr; + bt_mesh_prov_link.bearer = &pb_remote_cli; + bt_mesh_prov_link.role = &role_provisioner; + prov_device.net_idx = prov_device.node->net_idx; + prov_device.attention_duration = 0; + + if (IS_ENABLED(CONFIG_BT_MESH_PROV_OOB_PUBLIC_KEY) && + bt_mesh_prov->public_key_be && bt_mesh_prov->private_key_be) { + LOG_DBG("Use OOB Public and Private key"); + pub_key = bt_mesh_prov->public_key_be; + priv_key = bt_mesh_prov->private_key_be; + } else { + pub_key = bt_mesh_pub_key_get(); + } + + if (!pub_key) { + LOG_ERR("No public key available"); + return -ENOEXEC; + } + + if (bt_mesh_dhkey_gen(pub_key, priv_key, bt_mesh_prov_link.dhkey)) { + LOG_ERR("Failed to generate DHKey"); + return -ENOEXEC; + } + LOG_DBG("DHkey: %s", bt_hex(bt_mesh_prov_link.dhkey, DH_KEY_SIZE)); + + err = bt_mesh_dev_key(bt_mesh_prov_link.dhkey, + bt_mesh_prov_link.prov_salt, prov_device.new_dev_key); + if (err) { + LOG_ERR("Unable to generate device key"); + return err; + } + + bt_mesh_dev_key_cand(prov_device.new_dev_key); + /* Mark the link that was never opened as closed. */ + atomic_set_bit(bt_mesh_prov_link.flags, COMPLETE); + bt_mesh_reprovision(addr); + bt_mesh_dev_key_cand_activate(); + + if (bt_mesh_prov->reprovisioned) { + LOG_DBG("Application reprovisioned callback 0x%04x", bt_mesh_primary_addr()); + bt_mesh_prov->reprovisioned(bt_mesh_primary_addr()); + } + + prov_link_closed(PROV_BEARER_LINK_STATUS_SUCCESS); + return 0; +} + int bt_mesh_pb_remote_open_node(struct bt_mesh_rpr_cli *cli, struct bt_mesh_rpr_node *srv, uint16_t addr, bool composition_change) @@ -877,6 +943,11 @@ int bt_mesh_pb_remote_open_node(struct bt_mesh_rpr_cli *cli, return -ENOENT; } + /* Check if server is on same device as client */ + if (IS_ENABLED(CONFIG_BT_MESH_RPR_SRV) && bt_mesh_has_addr(srv->addr)) { + return reprovision_local_client_server(addr); + } + return link_open(NULL, &pb_remote_cli, prov_device.node->net_idx, addr, 0, &ctx, 0); } diff --git a/tests/bsim/bluetooth/mesh/src/test_provision.c b/tests/bsim/bluetooth/mesh/src/test_provision.c index 171f8cccbbd..c78fe8dc87d 100644 --- a/tests/bsim/bluetooth/mesh/src/test_provision.c +++ b/tests/bsim/bluetooth/mesh/src/test_provision.c @@ -139,6 +139,19 @@ static const struct bt_mesh_comp rpr_srv_comp = { .elem_count = 1, }; +static const struct bt_mesh_comp rpr_cli_srv_comp = { + .elem = + (struct bt_mesh_elem[]){ + BT_MESH_ELEM(1, + MODEL_LIST(BT_MESH_MODEL_CFG_SRV, + BT_MESH_MODEL_CFG_CLI(&(struct bt_mesh_cfg_cli){}), + BT_MESH_MODEL_RPR_CLI(&rpr_cli), + BT_MESH_MODEL_RPR_SRV), + BT_MESH_MODEL_NONE), + }, + .elem_count = 1, +}; + static int mock_pdu_send(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -1043,18 +1056,127 @@ static void test_provisioner_pb_remote_client_provision_timeout(void) PASS(); } +static void reprovision_remote_devkey_client(struct bt_mesh_rpr_node *srv, + struct bt_mesh_cdb_node *node) +{ + uint8_t status; + uint8_t prev_node_dev_key[16]; + + ASSERT_OK_MSG(bt_mesh_cdb_node_key_export(node, prev_node_dev_key), + "Can't export device key from cdb"); + + bt_mesh_reprovision_remote(&rpr_cli, srv, current_dev_addr, false); + + ASSERT_OK(k_sem_take(&reprov_sem, K_SECONDS(20))); + + /* Check that CDB has updated Device Key for the node. */ + ASSERT_TRUE(bt_mesh_key_compare(prev_node_dev_key, &node->dev_key)); + ASSERT_OK_MSG(bt_mesh_cdb_node_key_export(node, prev_node_dev_key), + "Can't export device key from cdb"); + + /* Check device key by adding appkey. */ + ASSERT_OK(bt_mesh_cfg_cli_app_key_add(0, current_dev_addr, 0, 0, test_app_key, + &status)); + ASSERT_OK(status); + + /* Let RPR Server verify Device Key. */ + k_sleep(K_SECONDS(2)); +} + +static void reprovision_remote_comp_data_client(struct bt_mesh_rpr_node *srv, + struct bt_mesh_cdb_node *node, + struct net_buf_simple *dev_comp) +{ + NET_BUF_SIMPLE_DEFINE(new_dev_comp, BT_MESH_RX_SDU_MAX); + uint8_t prev_node_dev_key[16]; + uint8_t page; + + ASSERT_OK_MSG(bt_mesh_cdb_node_key_export(node, prev_node_dev_key), + "Can't export device key from cdb"); + + bt_mesh_reprovision_remote(&rpr_cli, srv, current_dev_addr, true); + + ASSERT_OK(k_sem_take(&reprov_sem, K_SECONDS(20))); + + /* Check that CDB has updated Device Key for the node. */ + ASSERT_TRUE(bt_mesh_key_compare(prev_node_dev_key, &node->dev_key)); + ASSERT_OK_MSG(bt_mesh_cdb_node_key_export(node, prev_node_dev_key), + "Can't export device key from cdb"); + + /* Check that Composition Data Page 128 is now Page 0. */ + net_buf_simple_reset(&new_dev_comp); + ASSERT_OK(bt_mesh_cfg_cli_comp_data_get(0, current_dev_addr, 0, &page, + &new_dev_comp)); + + ASSERT_EQUAL(0, page); + ASSERT_EQUAL(dev_comp->len, new_dev_comp.len); + if (memcmp(dev_comp->data, new_dev_comp.data, dev_comp->len)) { + FAIL("Wrong composition data page 0"); + } + + /* Let RPR Server verify Device Key. */ + k_sleep(K_SECONDS(2)); +} + +static void reprovision_remote_address_client(struct bt_mesh_rpr_node *srv, + struct bt_mesh_cdb_node *node) +{ + uint8_t status; + uint8_t prev_node_dev_key[16]; + + ASSERT_OK_MSG(bt_mesh_cdb_node_key_export(node, prev_node_dev_key), + "Can't export device key from cdb"); + + bt_mesh_reprovision_remote(&rpr_cli, srv, current_dev_addr + 1, false); + + ASSERT_OK(k_sem_take(&reprov_sem, K_SECONDS(20))); + + current_dev_addr++; + srv->addr++; + + /* Check that device doesn't respond to old address with old and new device key. */ + struct bt_mesh_cdb_node *prev_node; + uint8_t tmp[16]; + + prev_node = bt_mesh_cdb_node_alloc((uint8_t[16]) {}, current_dev_addr - 1, 1, 0); + ASSERT_TRUE(node); + ASSERT_OK_MSG(bt_mesh_cdb_node_key_import(prev_node, prev_node_dev_key), + "Can't import device key into cdb"); + ASSERT_EQUAL(-ETIMEDOUT, bt_mesh_cfg_cli_app_key_add(0, current_dev_addr - 1, 0, 0, + test_app_key, &status)); + ASSERT_OK_MSG(bt_mesh_cdb_node_key_export(node, tmp), + "Can't export device key from cdb"); + ASSERT_OK_MSG(bt_mesh_cdb_node_key_import(prev_node, tmp), + "Can't import device key into cdb"); + ASSERT_EQUAL(-ETIMEDOUT, bt_mesh_cfg_cli_app_key_add(0, current_dev_addr - 1, 0, 0, + test_app_key, &status)); + bt_mesh_cdb_node_del(prev_node, false); + + /* Check that CDB has updated Device Key for the node. */ + ASSERT_TRUE(bt_mesh_key_compare(prev_node_dev_key, &node->dev_key)); + ASSERT_OK_MSG(bt_mesh_cdb_node_key_export(node, prev_node_dev_key), + "Can't export device key from cdb"); + + /* Check new device address by adding appkey. */ + ASSERT_OK(bt_mesh_cfg_cli_app_key_add(0, current_dev_addr, 0, 0, test_app_key, + &status)); + ASSERT_OK(status); + + /* Let RPR Server verify Device Key. */ + k_sleep(K_SECONDS(2)); + +} + /** @brief Verify robustness of NPPI procedures on a RPR Client by running Device Key Refresh, * Node Composition Refresh and Node Address Refresh procedures. */ static void test_provisioner_pb_remote_client_nppi_robustness(void) { NET_BUF_SIMPLE_DEFINE(dev_comp, BT_MESH_RX_SDU_MAX); - NET_BUF_SIMPLE_DEFINE(new_dev_comp, BT_MESH_RX_SDU_MAX); uint8_t page; uint16_t pb_remote_server_addr; uint8_t status; struct bt_mesh_cdb_node *node; - uint8_t prev_node_dev_key[16]; provisioner_pb_remote_client_setup(); @@ -1082,96 +1204,23 @@ static void test_provisioner_pb_remote_client_nppi_robustness(void) node = bt_mesh_cdb_node_get(current_dev_addr); ASSERT_TRUE(node); - ASSERT_OK_MSG(bt_mesh_cdb_node_key_export(node, prev_node_dev_key), - "Can't export device key from cdb"); LOG_INF("Testing DevKey refresh..."); for (int i = 0; i < PROV_REPROV_COUNT; i++) { LOG_INF("Refreshing device key #%d...\n", i); - bt_mesh_reprovision_remote(&rpr_cli, &srv, current_dev_addr, false); - - ASSERT_OK(k_sem_take(&reprov_sem, K_SECONDS(20))); - - /* Check that CDB has updated Device Key for the node. */ - ASSERT_TRUE(bt_mesh_key_compare(prev_node_dev_key, &node->dev_key)); - ASSERT_OK_MSG(bt_mesh_cdb_node_key_export(node, prev_node_dev_key), - "Can't export device key from cdb"); - - /* Check device key by adding appkey. */ - ASSERT_OK(bt_mesh_cfg_cli_app_key_add(0, current_dev_addr, 0, 0, test_app_key, - &status)); - ASSERT_OK(status); - - /* Let RPR Server verify Device Key. */ - k_sleep(K_SECONDS(2)); + reprovision_remote_devkey_client(&srv, node); } LOG_INF("Testing Composition Data refresh..."); for (int i = 0; i < PROV_REPROV_COUNT; i++) { LOG_INF("Changing Composition Data #%d...\n", i); - bt_mesh_reprovision_remote(&rpr_cli, &srv, current_dev_addr, true); - - ASSERT_OK(k_sem_take(&reprov_sem, K_SECONDS(20))); - - /* Check that CDB has updated Device Key for the node. */ - ASSERT_TRUE(bt_mesh_key_compare(prev_node_dev_key, &node->dev_key)); - ASSERT_OK_MSG(bt_mesh_cdb_node_key_export(node, prev_node_dev_key), - "Can't export device key from cdb"); - - /* Check that Composition Data Page 128 is now Page 0. */ - net_buf_simple_reset(&new_dev_comp); - ASSERT_OK(bt_mesh_cfg_cli_comp_data_get(0, current_dev_addr, 0, &page, - &new_dev_comp)); - ASSERT_EQUAL(0, page); - ASSERT_EQUAL(dev_comp.len, new_dev_comp.len); - if (memcmp(dev_comp.data, new_dev_comp.data, dev_comp.len)) { - FAIL("Wrong composition data page 0"); - } - - /* Let RPR Server verify Device Key. */ - k_sleep(K_SECONDS(2)); + reprovision_remote_comp_data_client(&srv, node, &dev_comp); } LOG_INF("Testing address refresh..."); for (int i = 0; i < PROV_REPROV_COUNT; i++) { LOG_INF("Changing address #%d...\n", i); - bt_mesh_reprovision_remote(&rpr_cli, &srv, current_dev_addr + 1, false); - - ASSERT_OK(k_sem_take(&reprov_sem, K_SECONDS(20))); - - current_dev_addr++; - srv.addr++; - - /* Check that device doesn't respond to old address with old and new device key. */ - struct bt_mesh_cdb_node *prev_node; - uint8_t tmp[16]; - - prev_node = bt_mesh_cdb_node_alloc((uint8_t[16]) {}, current_dev_addr - 1, 1, 0); - ASSERT_TRUE(node); - ASSERT_OK_MSG(bt_mesh_cdb_node_key_import(prev_node, prev_node_dev_key), - "Can't import device key into cdb"); - ASSERT_EQUAL(-ETIMEDOUT, bt_mesh_cfg_cli_app_key_add(0, current_dev_addr - 1, 0, 0, - test_app_key, &status)); - ASSERT_OK_MSG(bt_mesh_cdb_node_key_export(node, tmp), - "Can't export device key from cdb"); - ASSERT_OK_MSG(bt_mesh_cdb_node_key_import(prev_node, tmp), - "Can't import device key into cdb"); - ASSERT_EQUAL(-ETIMEDOUT, bt_mesh_cfg_cli_app_key_add(0, current_dev_addr - 1, 0, 0, - test_app_key, &status)); - bt_mesh_cdb_node_del(prev_node, false); - - /* Check that CDB has updated Device Key for the node. */ - ASSERT_TRUE(bt_mesh_key_compare(prev_node_dev_key, &node->dev_key)); - ASSERT_OK_MSG(bt_mesh_cdb_node_key_export(node, prev_node_dev_key), - "Can't export device key from cdb"); - - /* Check new device address by adding appkey. */ - ASSERT_OK(bt_mesh_cfg_cli_app_key_add(0, current_dev_addr, 0, 0, test_app_key, - &status)); - ASSERT_OK(status); - - /* Let RPR Server verify Device Key. */ - k_sleep(K_SECONDS(2)); + reprovision_remote_address_client(&srv, node); } PASS(); @@ -1211,13 +1260,78 @@ static void test_device_pb_remote_server_proved(void) PASS(); } +static void reprovision_remote_devkey_server(const uint16_t initial_addr) +{ + uint8_t prev_dev_key[16]; + uint8_t dev_key[16]; + + ASSERT_OK(bt_mesh_key_export(prev_dev_key, &bt_mesh.dev_key)); + + ASSERT_OK(k_sem_take(&reprov_sem, K_SECONDS(30))); + ASSERT_EQUAL(initial_addr, bt_mesh_primary_addr()); + + /* Let Configuration Client activate the new Device Key and verify that it has + * been changed. + */ + k_sleep(K_SECONDS(2)); + ASSERT_OK(bt_mesh_key_export(dev_key, &bt_mesh.dev_key)); + ASSERT_TRUE(memcmp(&prev_dev_key, dev_key, sizeof(dev_key))); +} + +static void reprovision_remote_comp_data_server(const uint16_t initial_addr) +{ + u_int8_t prev_dev_key[16]; + u_int8_t dev_key[16]; + + /* The RPR Server won't let to run Node Composition Refresh procedure without first + * setting the BT_MESH_COMP_DIRTY flag. The flag is set on a boot if there is a + * "bt/mesh/cmp" entry in settings. The entry is added by the + * `bt_mesh_comp_change_prepare() call. The test suite is not compiled + * with CONFIG_BT_SETTINGS, so the flag will never be set. Since the purpose of the + * test is to check RPR Server behavior, but not the actual swap of the Composition + * Data, the flag is toggled directly from the test. + */ + atomic_set_bit(bt_mesh.flags, BT_MESH_COMP_DIRTY); + ASSERT_OK(bt_mesh_key_export(prev_dev_key, &bt_mesh.dev_key)); + + ASSERT_OK(k_sem_take(&reprov_sem, K_SECONDS(30))); + + /* Drop the flag manually as CONFIG_BT_SETTINGS is not enabled. */ + atomic_clear_bit(bt_mesh.flags, BT_MESH_COMP_DIRTY); + + ASSERT_EQUAL(initial_addr, bt_mesh_primary_addr()); + + /* Let Configuration Client activate the new Device Key and verify that it has + * been changed. + */ + k_sleep(K_SECONDS(2)); + ASSERT_OK(bt_mesh_key_export(dev_key, &bt_mesh.dev_key)); + ASSERT_TRUE(memcmp(prev_dev_key, dev_key, sizeof(dev_key))); +} + +static void reprovision_remote_address_server(const uint16_t initial_addr) +{ + uint8_t prev_dev_key[16]; + uint8_t dev_key[16]; + + ASSERT_OK(bt_mesh_key_export(prev_dev_key, &bt_mesh.dev_key)); + + ASSERT_OK(k_sem_take(&reprov_sem, K_SECONDS(30))); + ASSERT_EQUAL(initial_addr + 1, bt_mesh_primary_addr()); + + /* Let Configuration Client activate the new Device Key and verify that it has + * been changed. + */ + k_sleep(K_SECONDS(2)); + ASSERT_OK(bt_mesh_key_export(dev_key, &bt_mesh.dev_key)); + ASSERT_TRUE(memcmp(prev_dev_key, dev_key, sizeof(dev_key))); +} + /** @brief Verify robustness of NPPI procedures on a RPR Server by running Device Key Refresh, * Node Composition Refresh and Node Address Refresh procedures multiple times each. */ static void test_device_pb_remote_server_nppi_robustness(void) { - struct bt_mesh_key prev_dev_key; - k_sem_init(&prov_sem, 0, 1); k_sem_init(&reprov_sem, 0, 1); @@ -1230,65 +1344,25 @@ static void test_device_pb_remote_server_nppi_robustness(void) ASSERT_OK(k_sem_take(&prov_sem, K_SECONDS(20))); const uint16_t initial_addr = bt_mesh_primary_addr(); - memcpy(&prev_dev_key, &bt_mesh.dev_key, sizeof(struct bt_mesh_key)); - LOG_INF("Enabling PB-Remote server"); ASSERT_OK(bt_mesh_prov_enable(BT_MESH_PROV_REMOTE)); /* Test Device Key Refresh procedure robustness. */ for (int i = 0; i < PROV_REPROV_COUNT; i++) { LOG_INF("Devkey refresh loop #%d, waiting for being reprov ...\n", i); - ASSERT_OK(k_sem_take(&reprov_sem, K_SECONDS(30))); - ASSERT_EQUAL(initial_addr, bt_mesh_primary_addr()); - - /* Let Configuration Client activate the new Device Key and verify that it has - * been changed. - */ - k_sleep(K_SECONDS(2)); - ASSERT_TRUE(memcmp(&prev_dev_key, &bt_mesh.dev_key, sizeof(struct bt_mesh_key))); - memcpy(&prev_dev_key, &bt_mesh.dev_key, sizeof(struct bt_mesh_key)); + reprovision_remote_devkey_server(initial_addr); } /* Test Node Composition Refresh procedure robustness. */ for (int i = 0; i < PROV_REPROV_COUNT; i++) { - /* The RPR Server won't let to run Node Composition Refresh procedure without first - * setting the BT_MESH_COMP_DIRTY flag. The flag is set on a boot if there is a - * "bt/mesh/cmp" entry in settings. The entry is added by the - * `bt_mesh_comp_change_prepare() call. The test suite is not compiled - * with CONFIG_BT_SETTINGS, so the flag will never be set. Since the purpose of the - * test is to check RPR Server behavior, but not the actual swap of the Composition - * Data, the flag is toggled directly from the test. - */ - atomic_set_bit(bt_mesh.flags, BT_MESH_COMP_DIRTY); - LOG_INF("Composition data refresh loop #%d, waiting for being reprov ...\n", i); - ASSERT_OK(k_sem_take(&reprov_sem, K_SECONDS(30))); - - /* Drop the flag manually as CONFIG_BT_SETTINGS is not enabled. */ - atomic_clear_bit(bt_mesh.flags, BT_MESH_COMP_DIRTY); - - ASSERT_EQUAL(initial_addr, bt_mesh_primary_addr()); - - /* Let Configuration Client activate the new Device Key and verify that it has - * been changed. - */ - k_sleep(K_SECONDS(2)); - ASSERT_TRUE(memcmp(&prev_dev_key, &bt_mesh.dev_key, sizeof(struct bt_mesh_key))); - memcpy(&prev_dev_key, &bt_mesh.dev_key, sizeof(struct bt_mesh_key)); + reprovision_remote_comp_data_server(initial_addr); } /* Node Address Refresh robustness. */ for (int i = 0; i < PROV_REPROV_COUNT; i++) { LOG_INF("Address refresh loop #%d, waiting for being reprov ...\n", i); - ASSERT_OK(k_sem_take(&reprov_sem, K_SECONDS(30))); - ASSERT_EQUAL(initial_addr + 1 + i, bt_mesh_primary_addr()); - - /* Let Configuration Client activate the new Device Key and verify that it has - * been changed. - */ - k_sleep(K_SECONDS(2)); - ASSERT_TRUE(memcmp(&prev_dev_key, &bt_mesh.dev_key, sizeof(struct bt_mesh_key))); - memcpy(&prev_dev_key, &bt_mesh.dev_key, sizeof(struct bt_mesh_key)); + reprovision_remote_address_server(initial_addr+i); } PASS(); @@ -1325,6 +1399,172 @@ static void test_provisioner_pb_remote_client_ncrp_provision(void) PASS(); } +/** @brief A device running a Remote Provisioning client and server that is used to reprovision + * another device and it self with the client. + */ +static void test_device_pb_remote_client_server_same_dev(void) +{ + NET_BUF_SIMPLE_DEFINE(dev_comp, BT_MESH_RX_SDU_MAX); + uint8_t status; + struct bt_mesh_cdb_node *node; + uint8_t page; + uint8_t prev_dev_key[16]; + uint16_t test_vector[] = { 0x0002, 0x0001 }; + + k_sem_init(&prov_sem, 0, 1); + k_sem_init(&reprov_sem, 0, 1); + + bt_mesh_device_setup(&prov, &rpr_cli_srv_comp); + + ASSERT_OK(bt_mesh_cdb_create(test_net_key)); + ASSERT_OK(bt_mesh_provision(test_net_key, 0, 0, 0, 0x0001, dev_key)); + + LOG_INF("Enabling PB-Remote server"); + ASSERT_OK(bt_mesh_prov_enable(BT_MESH_PROV_REMOTE)); + + /* Provision a remote device with RPR Client and Server with local RPR Server. */ + current_dev_addr = 0x0001; + struct bt_mesh_rpr_node srv = { + .addr = current_dev_addr, + .net_idx = 0, + .ttl = 3, + }; + + LOG_INF("Provisioner prov, waiting for prov ...\n"); + ASSERT_OK(provision_remote(&srv, 1, &srv.addr)); + + ASSERT_OK(k_sem_take(&prov_sem, K_SECONDS(20))); + + /* Check device key by adding bt_mesh_reprovision_remote appkey. */ + ASSERT_OK(bt_mesh_cfg_cli_app_key_add(0, current_dev_addr, 0, 0, test_app_key, &status)); + ASSERT_OK(status); + + /* Swap callback to catch when device reprovisioned. */ + prov.node_added = prov_node_added_rpr; + + /* Reprovision a device with both RPR Client and Server. */ + for (int i = 0; i < ARRAY_SIZE(test_vector); i++) { + current_dev_addr = test_vector[i]; + srv.addr = current_dev_addr; + bool self_reprov = (bool)(current_dev_addr == bt_mesh_primary_addr()); + + /* Store initial Composition Data Page 0. */ + net_buf_simple_reset(&dev_comp); + ASSERT_OK(bt_mesh_cfg_cli_comp_data_get(0, current_dev_addr, 0, &page, &dev_comp)); + + node = bt_mesh_cdb_node_get(current_dev_addr); + ASSERT_TRUE(node); + + LOG_INF("Refreshing 0x%04x device key ...\n", srv.addr); + ASSERT_OK(bt_mesh_key_export(prev_dev_key, &bt_mesh.dev_key)); + reprovision_remote_devkey_client(&srv, node); + if (self_reprov) { + uint8_t dev_key[16]; + + ASSERT_EQUAL(current_dev_addr, bt_mesh_primary_addr()); + + /* Let Configuration Client activate the new Device Key + * and verify that it has been changed. + */ + ASSERT_OK(bt_mesh_key_export(dev_key, &bt_mesh.dev_key)); + ASSERT_TRUE(memcmp(prev_dev_key, dev_key, sizeof(dev_key))); + } + + LOG_INF("Changing 0x%04x Composition Data ...\n", srv.addr); + ASSERT_OK(bt_mesh_key_export(prev_dev_key, &bt_mesh.dev_key)); + reprovision_remote_comp_data_client(&srv, node, &dev_comp); + if (self_reprov) { + uint8_t dev_key[16]; + + ASSERT_EQUAL(current_dev_addr, bt_mesh_primary_addr()); + + /* Let Configuration Client activate the new Device Key + * and verify that it has been changed. + */ + ASSERT_OK(bt_mesh_key_export(dev_key, &bt_mesh.dev_key)); + ASSERT_TRUE(memcmp(prev_dev_key, dev_key, sizeof(struct bt_mesh_key))); + } + + LOG_INF("Changing 0x%04x address ...\n", srv.addr); + ASSERT_OK(bt_mesh_key_export(prev_dev_key, &bt_mesh.dev_key)); + reprovision_remote_address_client(&srv, node); + if (self_reprov) { + uint8_t dev_key[16]; + + ASSERT_EQUAL(current_dev_addr, bt_mesh_primary_addr()); + + /* Let Configuration Client activate the new Device Key + * and verify that it has been changed. + */ + ASSERT_OK(bt_mesh_key_export(dev_key, &bt_mesh.dev_key)); + ASSERT_TRUE(memcmp(prev_dev_key, dev_key, sizeof(dev_key))); + } + } + + PASS(); +} + +/** @brief Verify that the Remote Provisioning client and server is able to be reprovision + * by another device with a Remote Provisioning client and server. + */ +static void test_device_pb_remote_server_same_dev(void) +{ + k_sem_init(&prov_sem, 0, 1); + k_sem_init(&reprov_sem, 0, 1); + + bt_mesh_device_setup(&prov, &rpr_cli_srv_comp); + + ASSERT_OK(bt_mesh_prov_enable(BT_MESH_PROV_ADV)); + + LOG_INF("Waiting for being provisioned..."); + ASSERT_OK(k_sem_take(&prov_sem, K_SECONDS(20))); + + LOG_INF("Enabling PB-Remote server"); + ASSERT_OK(bt_mesh_prov_enable(BT_MESH_PROV_REMOTE)); + + /* Swap callback to catch when device reprovisioned. */ + prov.node_added = prov_node_added_rpr; + + const uint16_t initial_addr = bt_mesh_primary_addr(); + + LOG_INF("Devkey refresh, waiting for being reprov ...\n"); + reprovision_remote_devkey_server(initial_addr); + + LOG_INF("Composition data refresh, waiting for being reprov ...\n"); + reprovision_remote_comp_data_server(initial_addr); + + LOG_INF("Address refresh, waiting for being reprov ...\n"); + reprovision_remote_address_server(initial_addr); + + PASS(); +} + +static void comp_data_get(uint16_t server_addr, uint8_t page, struct net_buf_simple *comp) +{ + uint8_t page_rsp; + + net_buf_simple_reset(comp); + ASSERT_OK(bt_mesh_cfg_cli_comp_data_get(0, server_addr, page, &page_rsp, comp)); + ASSERT_EQUAL(page, page_rsp); +} + +static void comp_data_compare(struct net_buf_simple *comp1, struct net_buf_simple *comp2, + bool expect_equal) +{ + if (expect_equal) { + ASSERT_EQUAL(comp1->len, comp2->len); + if (memcmp(comp1->data, comp2->data, comp1->len)) { + FAIL("Composition data is not equal"); + } + } else { + if (comp1->len == comp2->len) { + if (!memcmp(comp1->data, comp2->data, comp1->len)) { + FAIL("Composition data is equal"); + } + } + } +} + /** @brief Test Node Composition Refresh procedure on Remote Provisioning client: * - initiate Node Composition Refresh procedure on a 3rd device. */ @@ -1543,6 +1783,10 @@ static const struct bst_test_instance test_connect[] = { "Device: pb-remote reprovisioning, NPPI robustness"), TEST_CASE(device, pb_remote_server_unproved_unresponsive, "Device: used for remote provisioning, starts unprovisioned, stops responding"), + TEST_CASE(device, pb_remote_client_server_same_dev, + "Device: used for remote provisioning, with both client and server"), + TEST_CASE(device, pb_remote_server_same_dev, + "Device: used for remote reprovisioning, with both client and server"), #endif TEST_CASE(provisioner, pb_adv_no_oob, diff --git a/tests/bsim/bluetooth/mesh/tests_scripts/provision/pb_remote_client_server_same_dev.sh b/tests/bsim/bluetooth/mesh/tests_scripts/provision/pb_remote_client_server_same_dev.sh new file mode 100755 index 00000000000..33de74370e1 --- /dev/null +++ b/tests/bsim/bluetooth/mesh/tests_scripts/provision/pb_remote_client_server_same_dev.sh @@ -0,0 +1,32 @@ +#!/usr/bin/env bash +# Copyright 2023 Nordic Semiconductor +# SPDX-License-Identifier: Apache-2.0 + +source $(dirname "${BASH_SOURCE[0]}")/../../_mesh_test.sh + +# Test a node re-provisioning through Remote Provisioning models. Procedure: +# 1. Device (prov_device_pb_remote_client_server_same_dev) provisions it self +# and start scanning for an upprovisioned device, and provisions the the +# second device (prov_device_pb_remote_server_same_dev) with local RPR server. +# 2. The first device (prov_device_pb_remote_client_server_same_dev) execute +# device key refresh procedure the second device (prov_device_pb_remote_server_same_dev). +# 3. The first device (prov_device_pb_remote_client_server_same_dev) execute +# composition refresh procedure the second device (prov_device_pb_remote_server_same_dev). +# 4. The first device (prov_device_pb_remote_client_server_same_dev) execute +# address refresh procedure the second device (prov_device_pb_remote_server_same_dev). +# 5. The first device (prov_device_pb_remote_client_server_same_dev) execute +# device key refresh procedure on it self with local RPR client and server. +# 6. The first device (prov_device_pb_remote_client_server_same_dev) execute +# composition refresh procedure on it self with local RPR client and server. +# 7. The first device (prov_device_pb_remote_client_server_same_dev) execute +# address refresh procedure on it self with local RPR client and server. +conf=prj_mesh1d1_conf +RunTest mesh_prov_pb_remote_client_server_same_dev \ + prov_device_pb_remote_client_server_same_dev \ + prov_device_pb_remote_server_same_dev + +conf=prj_mesh1d1_conf +overlay=overlay_psa_conf +RunTest mesh_prov_pb_remote_client_server_same_dev \ + prov_device_pb_remote_client_server_same_dev \ + prov_device_pb_remote_server_same_dev From 60dc14e371af10a1f549fb3541b5be922217e524 Mon Sep 17 00:00:00 2001 From: Pavel Vasilyev Date: Fri, 6 Oct 2023 14:12:18 +0200 Subject: [PATCH 203/421] [nrf fromtree] tests: bluetooth: tester: Fix self-update test DFU/SR/FD/BV-59-C MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit DFU/SR/FD/BV-59-C tests Distributor self-update. Because the actuall firmware swapping doesn't happen, we need to just simulate the swapping by setting new Firmware ID sent by LT. We use slot to take firmware id as by procedure, Fw Update Server doesn't know about it. Signed-off-by: Pavel Vasilyev (cherry picked from commit 0eb027ab7cc2f372d969f7c5a1fbac39294163e8) Signed-off-by: Alperen Şener (cherry picked from commit 6ae93608a6e001dd1563740855afdda1bad45dce) --- tests/bluetooth/tester/src/btp_mesh.c | 33 ++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/tests/bluetooth/tester/src/btp_mesh.c b/tests/bluetooth/tester/src/btp_mesh.c index 2a74bb03828..c191ed54568 100644 --- a/tests/bluetooth/tester/src/btp_mesh.c +++ b/tests/bluetooth/tester/src/btp_mesh.c @@ -17,6 +17,7 @@ #include #include #include +#include "mesh/access.h" #include #define LOG_MODULE_NAME bttester_mesh @@ -112,6 +113,19 @@ static const struct bt_mesh_blob_io dummy_blob_io = { #endif #if defined(CONFIG_BT_MESH_DFD_SRV) +static const struct bt_mesh_dfu_slot *dfu_self_update_slot; + +static bool is_self_update(struct bt_mesh_dfd_srv *srv) +{ + for (int i = 0; i < ARRAY_SIZE(srv->targets); i++) { + if (bt_mesh_has_addr(srv->targets[i].blob.addr)) { + return true; + } + } + + return false; +} + /* DFD Model data*/ static int dfd_srv_recv(struct bt_mesh_dfd_srv *srv, const struct bt_mesh_dfu_slot *slot, @@ -138,6 +152,13 @@ static int dfd_srv_send(struct bt_mesh_dfd_srv *srv, *io = &dummy_blob_io; + dfu_self_update_slot = NULL; + + if (is_self_update(srv)) { + LOG_DBG("DFD server starts self-update..."); + dfu_self_update_slot = slot; + } + return 0; } @@ -216,7 +237,7 @@ static struct bt_mesh_blob_cli blob_cli = { .cb = &blob_cli_handlers }; #if defined(CONFIG_BT_MESH_DFU_SRV) const char *metadata_data = "1100000000000011"; -static uint8_t dfu_fwid[] = { +static uint8_t dfu_fwid[CONFIG_BT_MESH_DFU_FWID_MAXLEN] = { 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; @@ -284,6 +305,16 @@ static int dfu_apply(struct bt_mesh_dfu_srv *srv, LOG_DBG("Applying DFU transfer..."); +#if defined(CONFIG_BT_MESH_DFD_SRV) + if (is_self_update(&dfd_srv) && dfu_self_update_slot != NULL) { + LOG_DBG("Swapping fwid for self-update"); + /* Simulate self-update by swapping fwid. */ + memcpy(&dfu_fwid[0], dfu_self_update_slot->fwid, dfu_self_update_slot->fwid_len); + dfu_imgs[0].fwid_len = dfu_self_update_slot->fwid_len; + } + +#endif + return 0; } From 14095d899da44030014ce550dcc2b7fb4b910d08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anders=20Storr=C3=B8?= Date: Thu, 5 Oct 2023 13:19:51 +0200 Subject: [PATCH 204/421] [nrf fromtree] Bluetooth: Mesh: Add missing comp pages to LCD mod MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds support for all composition data pages to the Large Composition Data model. Signed-off-by: Anders Storrø (cherry picked from commit 57cb1b1ccb11a47c911772678b05cb309c9dcaf4) Signed-off-by: Alperen Şener (cherry picked from commit b8ebbe98e0b36b736fb4dac722d390dd5da23a13) --- subsys/bluetooth/mesh/Kconfig | 10 + subsys/bluetooth/mesh/access.c | 228 ++++++++++++-------- subsys/bluetooth/mesh/access.h | 2 +- subsys/bluetooth/mesh/large_comp_data_srv.c | 53 ++++- 4 files changed, 199 insertions(+), 94 deletions(-) diff --git a/subsys/bluetooth/mesh/Kconfig b/subsys/bluetooth/mesh/Kconfig index 9f24ff81975..605e4608be7 100644 --- a/subsys/bluetooth/mesh/Kconfig +++ b/subsys/bluetooth/mesh/Kconfig @@ -1375,6 +1375,16 @@ config BT_MESH_PRIV_BEACON_CLI endif # BT_MESH_PRIV_BEACONS +config BT_MESH_COMP_PST_BUF_SIZE + int "Composition Data Page persistence buffer size" + default 100 + help + Stack allocated buffer used to temporarily hold Composition + Data Pages during flash operations. Should reflect the size + of the largest Composition Data Page present in the application. + Note that this buffer should still be large enough to restore previously stored + pages after a performed device firmware update. + config BT_MESH_COMP_PAGE_1 bool "Support for Composition Data Page 1" depends on BT_MESH_MODEL_EXTENSIONS diff --git a/subsys/bluetooth/mesh/access.c b/subsys/bluetooth/mesh/access.c index b6dab2d67a7..24259165e05 100644 --- a/subsys/bluetooth/mesh/access.c +++ b/subsys/bluetooth/mesh/access.c @@ -173,6 +173,18 @@ static void data_buf_add_le16_offset(struct net_buf_simple *buf, } } +static void data_buf_add_mem_offset(struct net_buf_simple *buf, uint8_t *data, size_t len, + size_t *offset) +{ + if (*offset >= len) { + *offset -= len; + return; + } + + net_buf_simple_add_mem(buf, data + *offset, len - *offset); + *offset = 0; +} + static void comp_add_model(struct bt_mesh_model *mod, struct bt_mesh_elem *elem, bool vnd, void *user_data) { @@ -187,20 +199,6 @@ static void comp_add_model(struct bt_mesh_model *mod, struct bt_mesh_elem *elem, } #if defined(CONFIG_BT_MESH_LARGE_COMP_DATA_SRV) -static void data_buf_add_mem_offset(struct net_buf_simple *buf, - const void *mem, size_t len, - size_t *offset) -{ - if (*offset >= len) { - *offset -= len; - return; - } else if (*offset > 0) { - net_buf_simple_add_mem(buf, ((uint8_t *)mem), (len - *offset)); - - } else { - net_buf_simple_add_mem(buf, mem, len); - } -} static size_t metadata_model_size(struct bt_mesh_model *mod, struct bt_mesh_elem *elem, bool vnd) @@ -366,23 +364,6 @@ int bt_mesh_metadata_get_page_0(struct net_buf_simple *buf, size_t offset) } #endif -size_t bt_mesh_comp_page_0_size(void) -{ - const struct bt_mesh_comp *comp; - const struct bt_mesh_elem *elem; - size_t size = 10; - int i; - - comp = bt_mesh_comp_get(); - - for (i = 0; i < comp->elem_count; i++) { - elem = &comp->elem[i]; - size += bt_mesh_comp_elem_size(elem); - } - - return size; -} - static int comp_add_elem(struct net_buf_simple *buf, struct bt_mesh_elem *elem, size_t *offset) { @@ -398,7 +379,7 @@ static int comp_add_elem(struct net_buf_simple *buf, struct bt_mesh_elem *elem, return 0; } - if (net_buf_simple_tailroom(buf) < (elem_size + BT_MESH_MIC_SHORT)) { + if (net_buf_simple_tailroom(buf) < ((elem_size - *offset) + BT_MESH_MIC_SHORT)) { if (IS_ENABLED(CONFIG_BT_MESH_LARGE_COMP_DATA_SRV)) { /* Mesh Profile 1.1 Section 4.4.1.2.2: * If the complete list of models does not fit in the Data field, @@ -516,8 +497,8 @@ static bool is_cor_present(struct bt_mesh_model *mod, uint8_t *cor_id) return false; } -static void prep_model_item_header(struct bt_mesh_model *mod, uint8_t *cor_id, - uint8_t *mod_cnt, struct net_buf_simple *buf) +static void prep_model_item_header(struct bt_mesh_model *mod, uint8_t *cor_id, uint8_t *mod_cnt, + struct net_buf_simple *buf, size_t *offset) { uint8_t ext_mod_cnt; bool cor_present; @@ -536,41 +517,41 @@ static void prep_model_item_header(struct bt_mesh_model *mod, uint8_t *cor_id, if (cor_present) { mod_elem_info |= BIT(0); } - net_buf_simple_add_u8(buf, mod_elem_info); + data_buf_add_u8_offset(buf, mod_elem_info, offset); if (cor_present) { - net_buf_simple_add_u8(buf, *cor_id); + data_buf_add_u8_offset(buf, *cor_id, offset); } memset(mod_cnt, ext_mod_cnt, sizeof(uint8_t)); } static void add_items_to_page(struct net_buf_simple *buf, struct bt_mesh_model *mod, - uint8_t ext_mod_cnt) + uint8_t ext_mod_cnt, size_t *offset) { - int i, offset; + int i, elem_offset; uint8_t mod_idx; MOD_REL_LIST_FOR_EACH(i) { if (IS_MOD_EXTENSION(mod, i)) { - offset = mod->elem_idx - mod_rel_list[i].elem_base; + elem_offset = mod->elem_idx - mod_rel_list[i].elem_base; mod_idx = mod_rel_list[i].idx_base; if (ext_mod_cnt < 32 && - offset < 4 && - offset > -5) { + elem_offset < 4 && + elem_offset > -5) { /* short format */ - if (offset < 0) { - offset += 8; + if (elem_offset < 0) { + elem_offset += 8; } - offset |= mod_idx << 3; - net_buf_simple_add_u8(buf, offset); + elem_offset |= mod_idx << 3; + data_buf_add_u8_offset(buf, elem_offset, offset); } else { /* long format */ - if (offset < 0) { - offset += 256; + if (elem_offset < 0) { + elem_offset += 256; } - net_buf_simple_add_u8(buf, offset); - net_buf_simple_add_u8(buf, mod_idx); + data_buf_add_u8_offset(buf, elem_offset, offset); + data_buf_add_u8_offset(buf, mod_idx, offset); } } } @@ -613,7 +594,7 @@ static size_t page1_elem_size(struct bt_mesh_elem *elem) return temp_size; } -static int bt_mesh_comp_data_get_page_1(struct net_buf_simple *buf) +static int bt_mesh_comp_data_get_page_1(struct net_buf_simple *buf, size_t offset) { const struct bt_mesh_comp *comp; uint8_t cor_id = 0; @@ -623,8 +604,14 @@ static int bt_mesh_comp_data_get_page_1(struct net_buf_simple *buf) comp = bt_mesh_comp_get(); for (i = 0; i < comp->elem_count; i++) { - if (net_buf_simple_tailroom(buf) < - (page1_elem_size(&comp->elem[i]) + BT_MESH_MIC_SHORT)) { + size_t elem_size = page1_elem_size(&comp->elem[i]); + + if (offset >= elem_size) { + offset -= elem_size; + continue; + } + + if (net_buf_simple_tailroom(buf) < ((elem_size - offset) + BT_MESH_MIC_SHORT)) { if (IS_ENABLED(CONFIG_BT_MESH_LARGE_COMP_DATA_SRV)) { /* Mesh Profile 1.1 Section 4.4.1.2.2: * If the complete list of models does not fit in the Data field, @@ -639,49 +626,53 @@ static int bt_mesh_comp_data_get_page_1(struct net_buf_simple *buf) return -E2BIG; } - net_buf_simple_add_u8(buf, comp->elem[i].model_count); - net_buf_simple_add_u8(buf, comp->elem[i].vnd_model_count); + data_buf_add_u8_offset(buf, comp->elem[i].model_count, &offset); + data_buf_add_u8_offset(buf, comp->elem[i].vnd_model_count, &offset); for (j = 0; j < comp->elem[i].model_count; j++) { - prep_model_item_header(&comp->elem[i].models[j], - &cor_id, &ext_mod_cnt, buf); + prep_model_item_header(&comp->elem[i].models[j], &cor_id, &ext_mod_cnt, buf, + &offset); if (ext_mod_cnt != 0) { - add_items_to_page(buf, - &comp->elem[i].models[j], - ext_mod_cnt); + add_items_to_page(buf, &comp->elem[i].models[j], ext_mod_cnt, + &offset); } } for (j = 0; j < comp->elem[i].vnd_model_count; j++) { - prep_model_item_header(&comp->elem[i].vnd_models[j], - &cor_id, &ext_mod_cnt, buf); + prep_model_item_header(&comp->elem[i].vnd_models[j], &cor_id, &ext_mod_cnt, + buf, &offset); if (ext_mod_cnt != 0) { - add_items_to_page(buf, - &comp->elem[i].vnd_models[j], - ext_mod_cnt); + add_items_to_page(buf, &comp->elem[i].vnd_models[j], ext_mod_cnt, + &offset); } } } return 0; } -static int bt_mesh_comp_data_get_page_2(struct net_buf_simple *buf) +static int bt_mesh_comp_data_get_page_2(struct net_buf_simple *buf, size_t offset) { if (!dev_comp2) { LOG_ERR("Composition data P2 not registered"); return -ENODEV; } + size_t elem_size; + for (int i = 0; i < dev_comp2->record_cnt; i++) { - if (net_buf_simple_tailroom(buf) < - (8 + dev_comp2->record[i].elem_offset_cnt + dev_comp2->record[i].data_len + - BT_MESH_MIC_SHORT)) { + elem_size = + 8 + dev_comp2->record[i].elem_offset_cnt + dev_comp2->record[i].data_len; + if (offset >= elem_size) { + offset -= elem_size; + continue; + } + + if (net_buf_simple_tailroom(buf) < ((elem_size - offset) + BT_MESH_MIC_SHORT)) { if (IS_ENABLED(CONFIG_BT_MESH_LARGE_COMP_DATA_SRV)) { /* Mesh Profile 1.1 Section 4.4.1.2.2: * If the complete list of models does not fit in the Data field, * the element shall not be reported. */ - LOG_DBG("Record 0x%04x didn't fit in the Data field", - i); + LOG_DBG("Record 0x%04x didn't fit in the Data field", i); return 0; } @@ -689,20 +680,20 @@ static int bt_mesh_comp_data_get_page_2(struct net_buf_simple *buf) return -E2BIG; } - net_buf_simple_add_le16(buf, dev_comp2->record[i].id); - net_buf_simple_add_u8(buf, dev_comp2->record[i].version.x); - net_buf_simple_add_u8(buf, dev_comp2->record[i].version.y); - net_buf_simple_add_u8(buf, dev_comp2->record[i].version.z); - net_buf_simple_add_u8(buf, dev_comp2->record[i].elem_offset_cnt); + data_buf_add_le16_offset(buf, dev_comp2->record[i].id, &offset); + data_buf_add_u8_offset(buf, dev_comp2->record[i].version.x, &offset); + data_buf_add_u8_offset(buf, dev_comp2->record[i].version.y, &offset); + data_buf_add_u8_offset(buf, dev_comp2->record[i].version.z, &offset); + data_buf_add_u8_offset(buf, dev_comp2->record[i].elem_offset_cnt, &offset); if (dev_comp2->record[i].elem_offset_cnt) { - net_buf_simple_add_mem(buf, dev_comp2->record[i].elem_offset, - dev_comp2->record[i].elem_offset_cnt); + data_buf_add_mem_offset(buf, (uint8_t *)dev_comp2->record[i].elem_offset, + dev_comp2->record[i].elem_offset_cnt, &offset); } - net_buf_simple_add_le16(buf, dev_comp2->record[i].data_len); + data_buf_add_le16_offset(buf, dev_comp2->record[i].data_len, &offset); if (dev_comp2->record[i].data_len) { - net_buf_simple_add_mem(buf, dev_comp2->record[i].data, - dev_comp2->record[i].data_len); + data_buf_add_mem_offset(buf, (uint8_t *)dev_comp2->record[i].data, + dev_comp2->record[i].data_len, &offset); } } @@ -2212,20 +2203,89 @@ int bt_mesh_comp_data_get_page(struct net_buf_simple *buf, size_t page, size_t o if (page == 0 || page == 128) { return bt_mesh_comp_data_get_page_0(buf, offset); } else if (IS_ENABLED(CONFIG_BT_MESH_COMP_PAGE_1) && (page == 1 || page == 129)) { - return bt_mesh_comp_data_get_page_1(buf); + return bt_mesh_comp_data_get_page_1(buf, offset); } else if (IS_ENABLED(CONFIG_BT_MESH_COMP_PAGE_2) && (page == 2 || page == 130)) { - return bt_mesh_comp_data_get_page_2(buf); + return bt_mesh_comp_data_get_page_2(buf, offset); } return -EINVAL; } +size_t comp_page_0_size(void) +{ + const struct bt_mesh_comp *comp; + const struct bt_mesh_elem *elem; + size_t size = 10; /* Non-variable length params of comp page 0. */ + + comp = bt_mesh_comp_get(); + + for (int i = 0; i < comp->elem_count; i++) { + elem = &comp->elem[i]; + size += bt_mesh_comp_elem_size(elem); + } + + return size; +} + +size_t comp_page_1_size(void) +{ + const struct bt_mesh_comp *comp; + size_t size = 0; + + comp = bt_mesh_comp_get(); + + for (int i = 0; i < comp->elem_count; i++) { + + size += page1_elem_size(&comp->elem[i]); + } + + return size; +} + +size_t comp_page_2_size(void) +{ + size_t size = 0; + + if (!dev_comp2) { + LOG_ERR("Composition data P2 not registered"); + return size; + } + + for (int i = 0; i < dev_comp2->record_cnt; i++) { + size += 8 + dev_comp2->record[i].elem_offset_cnt + dev_comp2->record[i].data_len; + } + return size; +} + +size_t bt_mesh_comp_page_size(uint8_t page) +{ + if (page == 0 || page == 128) { + return comp_page_0_size(); + } else if (IS_ENABLED(CONFIG_BT_MESH_COMP_PAGE_1) && (page == 1 || page == 129)) { + return comp_page_1_size(); + } else if (IS_ENABLED(CONFIG_BT_MESH_COMP_PAGE_2) && (page == 2 || page == 130)) { + return comp_page_2_size(); + } + + return 0; +} + int bt_mesh_comp_store(void) { - NET_BUF_SIMPLE_DEFINE(buf, BT_MESH_TX_SDU_MAX); +#if IS_ENABLED(CONFIG_BT_MESH_V1d1) + NET_BUF_SIMPLE_DEFINE(buf, CONFIG_BT_MESH_COMP_PST_BUF_SIZE); int err; for (int i = 0; i < ARRAY_SIZE(comp_data_pages); i++) { + size_t page_size = bt_mesh_comp_page_size(i); + + if (page_size > CONFIG_BT_MESH_COMP_PST_BUF_SIZE) { + LOG_WRN("CDP%d is larger than the CDP persistence buffer. " + "Please increase the CDP persistence buffer size " + "to the required size (%d bytes)", + i, page_size); + } + net_buf_simple_reset(&buf); err = bt_mesh_comp_data_get_page(&buf, comp_data_pages[i].page, 0); @@ -2242,7 +2302,7 @@ int bt_mesh_comp_store(void) LOG_DBG("Stored CDP%d", comp_data_pages[i].page); } - +#endif return 0; } diff --git a/subsys/bluetooth/mesh/access.h b/subsys/bluetooth/mesh/access.h index 4740963dd21..6027768ea94 100644 --- a/subsys/bluetooth/mesh/access.h +++ b/subsys/bluetooth/mesh/access.h @@ -23,7 +23,7 @@ enum { void bt_mesh_elem_register(struct bt_mesh_elem *elem, uint8_t count); uint8_t bt_mesh_elem_count(void); -size_t bt_mesh_comp_page_0_size(void); +size_t bt_mesh_comp_page_size(uint8_t page); int bt_mesh_comp_data_get_page_0(struct net_buf_simple *buf, size_t offset); size_t bt_mesh_metadata_page_0_size(void); int bt_mesh_metadata_get_page_0(struct net_buf_simple *buf, size_t offset); diff --git a/subsys/bluetooth/mesh/large_comp_data_srv.c b/subsys/bluetooth/mesh/large_comp_data_srv.c index 9f097f4355a..12497d053a2 100644 --- a/subsys/bluetooth/mesh/large_comp_data_srv.c +++ b/subsys/bluetooth/mesh/large_comp_data_srv.c @@ -59,24 +59,59 @@ static int handle_large_comp_data_get(struct bt_mesh_model *model, struct bt_mes LOG_DBG("page %u offset %u", page, offset); bt_mesh_model_msg_init(&rsp, OP_LARGE_COMP_DATA_STATUS); - - if (page != 0U) { + if (page >= 130U && IS_ENABLED(CONFIG_BT_MESH_COMP_PAGE_2) && + (atomic_test_bit(bt_mesh.flags, BT_MESH_COMP_DIRTY) || + IS_ENABLED(CONFIG_BT_MESH_RPR_SRV))) { + page = 130U; + } else if (page >= 129U && IS_ENABLED(CONFIG_BT_MESH_COMP_PAGE_1) && + (atomic_test_bit(bt_mesh.flags, BT_MESH_COMP_DIRTY) || + IS_ENABLED(CONFIG_BT_MESH_RPR_SRV))) { + page = 129U; + } else if (page >= 128U && (atomic_test_bit(bt_mesh.flags, BT_MESH_COMP_DIRTY) || + IS_ENABLED(CONFIG_BT_MESH_RPR_SRV))) { + page = 128U; + } else if (page >= 2U && IS_ENABLED(CONFIG_BT_MESH_COMP_PAGE_2)) { + page = 2U; + } else if (page >= 1U && IS_ENABLED(CONFIG_BT_MESH_COMP_PAGE_1)) { + page = 1U; + } else if (page != 0U) { LOG_DBG("Composition page %u not available", page); page = 0U; } net_buf_simple_add_u8(&rsp, page); - - total_size = bt_mesh_comp_page_0_size(); net_buf_simple_add_le16(&rsp, offset); - net_buf_simple_add_le16(&rsp, total_size); - if (offset < total_size) { - err = bt_mesh_comp_data_get_page_0(&rsp, offset); - if (err && err != -E2BIG) { - LOG_ERR("comp_get_page_0 returned error"); + if (atomic_test_bit(bt_mesh.flags, BT_MESH_COMP_DIRTY) && page < 128) { + size_t msg_space; + + NET_BUF_SIMPLE_DEFINE(temp_buf, CONFIG_BT_MESH_COMP_PST_BUF_SIZE); + err = bt_mesh_comp_read(&temp_buf, page); + if (err) { + LOG_ERR("Could not read comp data p%d, err: %d", page, err); return err; } + + net_buf_simple_add_le16(&rsp, temp_buf.len); + if (offset > temp_buf.len) { + return 0; + } + + msg_space = net_buf_simple_tailroom(&rsp) - BT_MESH_MIC_SHORT; + net_buf_simple_add_mem( + &rsp, temp_buf.data + offset, + (msg_space < (temp_buf.len - offset)) ? msg_space : temp_buf.len - offset); + } else { + total_size = bt_mesh_comp_page_size(page); + net_buf_simple_add_le16(&rsp, total_size); + + if (offset < total_size) { + err = bt_mesh_comp_data_get_page(&rsp, page, offset); + if (err && err != -E2BIG) { + LOG_ERR("Could not read comp data p%d, err: %d", page, err); + return err; + } + } } if (bt_mesh_model_send(model, ctx, &rsp, NULL, NULL)) { From 688605c9b2174c0086e86c235b0377d54ff0b09a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anders=20Storr=C3=B8?= Date: Fri, 6 Oct 2023 08:56:49 +0200 Subject: [PATCH 205/421] [nrf fromtree] Bluetooth: Mesh: Common comp page parse func MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Create common composition page parser function. Signed-off-by: Anders Storrø (cherry picked from commit 65f029e1850090887317efa37fc37758c2bffa93) Signed-off-by: Alperen Şener (cherry picked from commit 646cce25f0247f9a925e4145e57b83c71755f5d0) --- subsys/bluetooth/mesh/access.c | 27 +++++++++++++++++++++ subsys/bluetooth/mesh/access.h | 1 + subsys/bluetooth/mesh/cfg_srv.c | 22 +---------------- subsys/bluetooth/mesh/large_comp_data_srv.c | 22 +---------------- 4 files changed, 30 insertions(+), 42 deletions(-) diff --git a/subsys/bluetooth/mesh/access.c b/subsys/bluetooth/mesh/access.c index 24259165e05..2ea7ece90df 100644 --- a/subsys/bluetooth/mesh/access.c +++ b/subsys/bluetooth/mesh/access.c @@ -2562,3 +2562,30 @@ void bt_mesh_model_data_store_schedule(struct bt_mesh_model *mod) mod->flags |= BT_MESH_MOD_DATA_PENDING; bt_mesh_settings_store_schedule(BT_MESH_SETTINGS_MOD_PENDING); } + +uint8_t bt_mesh_comp_parse_page(struct net_buf_simple *buf) +{ + uint8_t page = net_buf_simple_pull_u8(buf); + + if (page >= 130U && IS_ENABLED(CONFIG_BT_MESH_COMP_PAGE_2) && + (atomic_test_bit(bt_mesh.flags, BT_MESH_COMP_DIRTY) || + IS_ENABLED(CONFIG_BT_MESH_RPR_SRV))) { + page = 130U; + } else if (page >= 129U && IS_ENABLED(CONFIG_BT_MESH_COMP_PAGE_1) && + (atomic_test_bit(bt_mesh.flags, BT_MESH_COMP_DIRTY) || + IS_ENABLED(CONFIG_BT_MESH_RPR_SRV))) { + page = 129U; + } else if (page >= 128U && (atomic_test_bit(bt_mesh.flags, BT_MESH_COMP_DIRTY) || + IS_ENABLED(CONFIG_BT_MESH_RPR_SRV))) { + page = 128U; + } else if (page >= 2U && IS_ENABLED(CONFIG_BT_MESH_COMP_PAGE_2)) { + page = 2U; + } else if (page >= 1U && IS_ENABLED(CONFIG_BT_MESH_COMP_PAGE_1)) { + page = 1U; + } else if (page != 0U) { + LOG_DBG("Composition page %u not available", page); + page = 0U; + } + + return page; +} diff --git a/subsys/bluetooth/mesh/access.h b/subsys/bluetooth/mesh/access.h index 6027768ea94..f58c6f1d449 100644 --- a/subsys/bluetooth/mesh/access.h +++ b/subsys/bluetooth/mesh/access.h @@ -64,6 +64,7 @@ int bt_mesh_model_recv(struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf); int bt_mesh_comp_register(const struct bt_mesh_comp *comp); int bt_mesh_comp_store(void); int bt_mesh_comp_read(struct net_buf_simple *buf, uint8_t page); +uint8_t bt_mesh_comp_parse_page(struct net_buf_simple *buf); int bt_mesh_models_metadata_store(void); int bt_mesh_models_metadata_read(struct net_buf_simple *buf, size_t offset); diff --git a/subsys/bluetooth/mesh/cfg_srv.c b/subsys/bluetooth/mesh/cfg_srv.c index eb732a34910..f65d2cba3c7 100644 --- a/subsys/bluetooth/mesh/cfg_srv.c +++ b/subsys/bluetooth/mesh/cfg_srv.c @@ -59,27 +59,7 @@ static int dev_comp_data_get(struct bt_mesh_model *model, LOG_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s", ctx->net_idx, ctx->app_idx, ctx->addr, buf->len, bt_hex(buf->data, buf->len)); - page = net_buf_simple_pull_u8(buf); - - if (page >= 130U && IS_ENABLED(CONFIG_BT_MESH_COMP_PAGE_2) && - (atomic_test_bit(bt_mesh.flags, BT_MESH_COMP_DIRTY) || - IS_ENABLED(CONFIG_BT_MESH_RPR_SRV))) { - page = 130U; - } else if (page >= 129U && IS_ENABLED(CONFIG_BT_MESH_COMP_PAGE_1) && - (atomic_test_bit(bt_mesh.flags, BT_MESH_COMP_DIRTY) || - IS_ENABLED(CONFIG_BT_MESH_RPR_SRV))) { - page = 129U; - } else if (page >= 128U && (atomic_test_bit(bt_mesh.flags, BT_MESH_COMP_DIRTY) || - IS_ENABLED(CONFIG_BT_MESH_RPR_SRV))) { - page = 128U; - } else if (page >= 2U && IS_ENABLED(CONFIG_BT_MESH_COMP_PAGE_2)) { - page = 2U; - } else if (page >= 1U && IS_ENABLED(CONFIG_BT_MESH_COMP_PAGE_1)) { - page = 1U; - } else if (page != 0U) { - LOG_DBG("Composition page %u not available", page); - page = 0U; - } + page = bt_mesh_comp_parse_page(buf); LOG_DBG("Preparing Composition data page %d", page); bt_mesh_model_msg_init(&sdu, OP_DEV_COMP_DATA_STATUS); diff --git a/subsys/bluetooth/mesh/large_comp_data_srv.c b/subsys/bluetooth/mesh/large_comp_data_srv.c index 12497d053a2..4ee591d9efd 100644 --- a/subsys/bluetooth/mesh/large_comp_data_srv.c +++ b/subsys/bluetooth/mesh/large_comp_data_srv.c @@ -53,32 +53,12 @@ static int handle_large_comp_data_get(struct bt_mesh_model *model, struct bt_mes ctx->net_idx, ctx->app_idx, ctx->addr, buf->len, bt_hex(buf->data, buf->len)); - page = net_buf_simple_pull_u8(buf); + page = bt_mesh_comp_parse_page(buf); offset = net_buf_simple_pull_le16(buf); LOG_DBG("page %u offset %u", page, offset); bt_mesh_model_msg_init(&rsp, OP_LARGE_COMP_DATA_STATUS); - if (page >= 130U && IS_ENABLED(CONFIG_BT_MESH_COMP_PAGE_2) && - (atomic_test_bit(bt_mesh.flags, BT_MESH_COMP_DIRTY) || - IS_ENABLED(CONFIG_BT_MESH_RPR_SRV))) { - page = 130U; - } else if (page >= 129U && IS_ENABLED(CONFIG_BT_MESH_COMP_PAGE_1) && - (atomic_test_bit(bt_mesh.flags, BT_MESH_COMP_DIRTY) || - IS_ENABLED(CONFIG_BT_MESH_RPR_SRV))) { - page = 129U; - } else if (page >= 128U && (atomic_test_bit(bt_mesh.flags, BT_MESH_COMP_DIRTY) || - IS_ENABLED(CONFIG_BT_MESH_RPR_SRV))) { - page = 128U; - } else if (page >= 2U && IS_ENABLED(CONFIG_BT_MESH_COMP_PAGE_2)) { - page = 2U; - } else if (page >= 1U && IS_ENABLED(CONFIG_BT_MESH_COMP_PAGE_1)) { - page = 1U; - } else if (page != 0U) { - LOG_DBG("Composition page %u not available", page); - page = 0U; - } - net_buf_simple_add_u8(&rsp, page); net_buf_simple_add_le16(&rsp, offset); From 598c6d18cfb77ca4aa47e8699e830a1dce1cea05 Mon Sep 17 00:00:00 2001 From: Pavel Vasilyev Date: Wed, 4 Oct 2023 14:47:39 +0200 Subject: [PATCH 206/421] [nrf fromtree] Bluetooth: Mesh: Don't reset mod pointer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Don't reset values set in init callback as it is called only once by bt_mesh_init call. The reset callback is called on every node reset. Signed-off-by: Pavel Vasilyev (cherry picked from commit f4a592f3bb9223fa09a34de3ef150076f1ce237b) Signed-off-by: Alperen Şener (cherry picked from commit d77003f09f5d73739fa01cffa32c8b8daa09dd44) --- subsys/bluetooth/mesh/rpr_srv.c | 1 - 1 file changed, 1 deletion(-) diff --git a/subsys/bluetooth/mesh/rpr_srv.c b/subsys/bluetooth/mesh/rpr_srv.c index c8639d8b514..8fb28e56472 100644 --- a/subsys/bluetooth/mesh/rpr_srv.c +++ b/subsys/bluetooth/mesh/rpr_srv.c @@ -1337,7 +1337,6 @@ static void rpr_srv_reset(struct bt_mesh_model *mod) atomic_clear(srv.flags); srv.link.dev = NULL; srv.scan.dev = NULL; - srv.mod = NULL; } const struct bt_mesh_model_cb _bt_mesh_rpr_srv_cb = { From 2da2829689578d541ec3cd43e4e35a6644d385b5 Mon Sep 17 00:00:00 2001 From: Pavel Vasilyev Date: Fri, 6 Oct 2023 20:15:08 +0200 Subject: [PATCH 207/421] [nrf fromtree] tests: bluetooth: tester: Fix prov ctx init in PTS tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This fixes regression introduced in https://github.com/zephyrproject-rtos/zephyr/pull/63556 In the PR above `bt_mesh_init()` call was moved to `BTP_MESH_INIT` command to allow to select alternative composition data when starting the stack. AutoPTS sends `BTP_MESH_CONFIG_PROVISIONING` command before `BTP_MESH_INIT` to prepare the provisioning context. But because `bt_mesh_init()` is now called after `BTP_MESH_CONFIG_PROVISIONING` command is sent, this configuration is reset to the default which makes PTS tests to fail. To solve this, this commit calls introduces a new command, `BTP_MESH_START`, which will replace the original `BTP_MESH_INIT` command. `bt_mesh_init()` will stay in `BTP_MESH_INIT` while the stack will be started in `BTP_MESH_START` command. Signed-off-by: Pavel Vasilyev (cherry picked from commit 94bd09b1f8a7152bef9a4b4f628da5c5288bbefe) Signed-off-by: Alperen Şener (cherry picked from commit 83ea0749300b962a17e004961749d9b6f445edfe) --- tests/bluetooth/tester/src/btp/btp_mesh.h | 2 ++ tests/bluetooth/tester/src/btp_mesh.c | 13 +++++++++++++ 2 files changed, 15 insertions(+) diff --git a/tests/bluetooth/tester/src/btp/btp_mesh.h b/tests/bluetooth/tester/src/btp/btp_mesh.h index c2636d1445d..b5ab169b263 100644 --- a/tests/bluetooth/tester/src/btp/btp_mesh.h +++ b/tests/bluetooth/tester/src/btp/btp_mesh.h @@ -1038,6 +1038,8 @@ struct btp_proxy_solicit_cmd { uint16_t net_idx; } __packed; +#define BTP_MESH_START 0x78 + /* events */ #define BTP_MESH_EV_OUT_NUMBER_ACTION 0x80 struct btp_mesh_out_number_action_ev { diff --git a/tests/bluetooth/tester/src/btp_mesh.c b/tests/bluetooth/tester/src/btp_mesh.c index c191ed54568..662dca238c1 100644 --- a/tests/bluetooth/tester/src/btp_mesh.c +++ b/tests/bluetooth/tester/src/btp_mesh.c @@ -1305,6 +1305,14 @@ static uint8_t init(const void *cmd, uint16_t cmd_len, return BTP_STATUS_FAILED; } + return BTP_STATUS_SUCCESS; +} + +static uint8_t start(const void *cmd, uint16_t cmd_len, + void *rsp, uint16_t *rsp_len) +{ + int err; + LOG_DBG(""); if (IS_ENABLED(CONFIG_BT_SETTINGS)) { @@ -4961,6 +4969,11 @@ static const struct btp_handler handlers[] = { .func = proxy_solicit }, #endif + { + .opcode = BTP_MESH_START, + .expect_len = 0, + .func = start + }, }; From 3aa391df864261dbb6c527265634dfdb02682ccd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A5vard=20Reierstad?= Date: Mon, 9 Oct 2023 08:28:26 +0200 Subject: [PATCH 208/421] [nrf fromtree] Bluetooth: mesh: Change cfg_cli buffer length check MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Changed buffer length check in bt_mesh_comp_p1_elem_pull. The previous threshold would result in the method not detecting the final element when it consisted of just one model. Signed-off-by: Håvard Reierstad (cherry picked from commit ea753eb52a475fc1f518d00f8f2caac07223aebc) Signed-off-by: Alperen Şener (cherry picked from commit 3f4f2ca1d20caaabccdae23df31db28be05b4a6b) --- subsys/bluetooth/mesh/cfg_cli.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subsys/bluetooth/mesh/cfg_cli.c b/subsys/bluetooth/mesh/cfg_cli.c index 68af4fae59d..c9f4f98f39d 100644 --- a/subsys/bluetooth/mesh/cfg_cli.c +++ b/subsys/bluetooth/mesh/cfg_cli.c @@ -2320,7 +2320,7 @@ struct bt_mesh_mod_id_vnd bt_mesh_comp_p0_elem_mod_vnd(struct bt_mesh_comp_p0_el struct bt_mesh_comp_p1_elem *bt_mesh_comp_p1_elem_pull(struct net_buf_simple *buf, struct bt_mesh_comp_p1_elem *elem) { - if (buf->len < 6) { + if (buf->len < 4) { LOG_DBG("No more elements to pull or missing data"); return NULL; } From 0a1f19bfdc8b030f67b8b2ac0c499dc06d2d64d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A5vard=20Reierstad?= Date: Mon, 9 Oct 2023 08:28:26 +0200 Subject: [PATCH 209/421] [nrf fromtree] Bluetooth: mesh: access: Fix model relation register MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Added offset to the model relation register for vendor models to find correct model index for Composition Data Page 1. The previous implementation used the 'mod_idx' from the 'bt_mesh_model' struct, which led to issues in the model relation register due to SIG and vender models having the same model index. Modified existing functions related to the model relation register to take in the offset. Modified macros for determining if a model is a base- or extending model. Added check in 'add_items_to_page' to check whether the model relation is an extension. Signed-off-by: Håvard Reierstad (cherry picked from commit 3d40d91f8682d023e939af4ef2cfe6509d17a3f6) Signed-off-by: Alperen Şener (cherry picked from commit 8db15583254176f6b7096744631441e8c8389827) --- subsys/bluetooth/mesh/access.c | 92 +++++++++++++++++++++------------- 1 file changed, 56 insertions(+), 36 deletions(-) diff --git a/subsys/bluetooth/mesh/access.c b/subsys/bluetooth/mesh/access.c index 2ea7ece90df..63c4f76c392 100644 --- a/subsys/bluetooth/mesh/access.c +++ b/subsys/bluetooth/mesh/access.c @@ -91,17 +91,13 @@ static struct mod_relation mod_rel_list[MOD_REL_LIST_SIZE]; mod_rel_list[(idx)].idx_ext == 0); \ (idx)++) -#define IS_MOD_BASE(mod, idx) \ +#define IS_MOD_BASE(mod, idx, offset) \ (mod_rel_list[(idx)].elem_base == (mod)->elem_idx && \ - mod_rel_list[(idx)].idx_base == (mod)->mod_idx && \ - !(mod_rel_list[(idx)].elem_ext != (mod)->elem_idx && \ - mod_rel_list[(idx)].idx_ext != (mod)->mod_idx)) + mod_rel_list[(idx)].idx_base == (mod)->mod_idx + (offset)) -#define IS_MOD_EXTENSION(mod, idx) \ +#define IS_MOD_EXTENSION(mod, idx, offset) \ (mod_rel_list[(idx)].elem_ext == (mod)->elem_idx && \ - mod_rel_list[(idx)].idx_ext == (mod)->mod_idx && \ - !(mod_rel_list[(idx)].elem_base != (mod)->elem_idx && \ - mod_rel_list[(idx)].idx_base != (mod)->mod_idx)) + mod_rel_list[(idx)].idx_ext == (mod)->mod_idx + (offset)) #define RELATION_TYPE_EXT 0xFF @@ -456,14 +452,14 @@ int bt_mesh_comp_data_get_page_0(struct net_buf_simple *buf, size_t offset) return 0; } -static uint8_t count_mod_ext(struct bt_mesh_model *mod, uint8_t *max_offset) +static uint8_t count_mod_ext(struct bt_mesh_model *mod, uint8_t *max_offset, uint8_t sig_offset) { int i; uint8_t extensions = 0; int8_t offset, offset_record = 0; MOD_REL_LIST_FOR_EACH(i) { - if (IS_MOD_EXTENSION(mod, i) && + if (IS_MOD_EXTENSION(mod, i, sig_offset) && mod_rel_list[i].type == RELATION_TYPE_EXT) { extensions++; offset = mod_rel_list[i].elem_ext - @@ -480,17 +476,18 @@ static uint8_t count_mod_ext(struct bt_mesh_model *mod, uint8_t *max_offset) return extensions; } -static bool is_cor_present(struct bt_mesh_model *mod, uint8_t *cor_id) +static bool is_cor_present(struct bt_mesh_model *mod, uint8_t *cor_id, uint8_t sig_offset) { int i; - MOD_REL_LIST_FOR_EACH(i) { - if ((IS_MOD_BASE(mod, i) || IS_MOD_EXTENSION(mod, i)) && + MOD_REL_LIST_FOR_EACH(i) + { + if ((IS_MOD_BASE(mod, i, sig_offset) || + IS_MOD_EXTENSION(mod, i, sig_offset)) && mod_rel_list[i].type < RELATION_TYPE_EXT) { if (cor_id) { memcpy(cor_id, &mod_rel_list[i].type, sizeof(uint8_t)); } - return true; } } @@ -498,15 +495,15 @@ static bool is_cor_present(struct bt_mesh_model *mod, uint8_t *cor_id) } static void prep_model_item_header(struct bt_mesh_model *mod, uint8_t *cor_id, uint8_t *mod_cnt, - struct net_buf_simple *buf, size_t *offset) + struct net_buf_simple *buf, size_t *offset, uint8_t sig_offset) { uint8_t ext_mod_cnt; bool cor_present; uint8_t mod_elem_info = 0; int8_t max_offset; - ext_mod_cnt = count_mod_ext(mod, &max_offset); - cor_present = is_cor_present(mod, cor_id); + ext_mod_cnt = count_mod_ext(mod, &max_offset, sig_offset); + cor_present = is_cor_present(mod, cor_id, sig_offset); mod_elem_info = ext_mod_cnt << 2; if (ext_mod_cnt > 31 || @@ -526,13 +523,14 @@ static void prep_model_item_header(struct bt_mesh_model *mod, uint8_t *cor_id, u } static void add_items_to_page(struct net_buf_simple *buf, struct bt_mesh_model *mod, - uint8_t ext_mod_cnt, size_t *offset) + uint8_t ext_mod_cnt, size_t *offset, uint8_t sig_offset) { int i, elem_offset; uint8_t mod_idx; MOD_REL_LIST_FOR_EACH(i) { - if (IS_MOD_EXTENSION(mod, i)) { + if (IS_MOD_EXTENSION(mod, i, sig_offset) && + mod_rel_list[i].type == RELATION_TYPE_EXT) { elem_offset = mod->elem_idx - mod_rel_list[i].elem_base; mod_idx = mod_rel_list[i].idx_base; if (ext_mod_cnt < 32 && @@ -557,18 +555,18 @@ static void add_items_to_page(struct net_buf_simple *buf, struct bt_mesh_model * } } -static size_t mod_items_size(struct bt_mesh_model *mod) +static size_t mod_items_size(struct bt_mesh_model *mod, uint8_t sig_offset) { int i, offset; size_t temp_size = 0; - int ext_mod_cnt = count_mod_ext(mod, NULL); + int ext_mod_cnt = count_mod_ext(mod, NULL, sig_offset); if (!ext_mod_cnt) { return 0; } MOD_REL_LIST_FOR_EACH(i) { - if (IS_MOD_EXTENSION(mod, i)) { + if (IS_MOD_EXTENSION(mod, i, sig_offset)) { offset = mod->elem_idx - mod_rel_list[i].elem_base; temp_size += (ext_mod_cnt < 32 && offset < 4 && offset > -5) ? 1 : 2; } @@ -582,13 +580,13 @@ static size_t page1_elem_size(struct bt_mesh_elem *elem) size_t temp_size = 2; for (int i = 0; i < elem->model_count; i++) { - temp_size += is_cor_present(&elem->models[i], NULL) ? 2 : 1; - temp_size += mod_items_size(&elem->models[i]); + temp_size += is_cor_present(&elem->models[i], NULL, 0) ? 2 : 1; + temp_size += mod_items_size(&elem->models[i], 0); } for (int i = 0; i < elem->vnd_model_count; i++) { - temp_size += is_cor_present(&elem->vnd_models[i], NULL) ? 2 : 1; - temp_size += mod_items_size(&elem->vnd_models[i]); + temp_size += is_cor_present(&elem->vnd_models[i], NULL, elem->model_count) ? 2 : 1; + temp_size += mod_items_size(&elem->vnd_models[i], elem->model_count); } return temp_size; @@ -630,19 +628,22 @@ static int bt_mesh_comp_data_get_page_1(struct net_buf_simple *buf, size_t offse data_buf_add_u8_offset(buf, comp->elem[i].vnd_model_count, &offset); for (j = 0; j < comp->elem[i].model_count; j++) { prep_model_item_header(&comp->elem[i].models[j], &cor_id, &ext_mod_cnt, buf, - &offset); + &offset, 0); if (ext_mod_cnt != 0) { add_items_to_page(buf, &comp->elem[i].models[j], ext_mod_cnt, - &offset); + &offset, + 0); } } for (j = 0; j < comp->elem[i].vnd_model_count; j++) { prep_model_item_header(&comp->elem[i].vnd_models[j], &cor_id, &ext_mod_cnt, - buf, &offset); + buf, &offset, + comp->elem[i].model_count); if (ext_mod_cnt != 0) { add_items_to_page(buf, &comp->elem[i].vnd_models[j], ext_mod_cnt, - &offset); + &offset, + comp->elem[i].model_count); } } } @@ -1616,6 +1617,22 @@ void bt_mesh_model_extensions_walk(struct bt_mesh_model *model, } #ifdef CONFIG_BT_MESH_MODEL_EXTENSIONS +/* For vendor models, determine the offset within the model relation list + * by counting the number of standard SIG models in the associated element. + */ +static uint8_t get_sig_offset(struct bt_mesh_model *mod) +{ + const struct bt_mesh_elem *elem = bt_mesh_model_elem(mod); + uint8_t i; + + for (i = 0U; i < elem->vnd_model_count; i++) { + if (&elem->vnd_models[i] == mod) { + return elem->model_count; + } + } + return 0; +} + static int mod_rel_register(struct bt_mesh_model *base, struct bt_mesh_model *ext, uint8_t type) @@ -1623,9 +1640,9 @@ static int mod_rel_register(struct bt_mesh_model *base, LOG_DBG(""); struct mod_relation extension = { base->elem_idx, - base->mod_idx, + base->mod_idx + get_sig_offset(base), ext->elem_idx, - ext->mod_idx, + ext->mod_idx + get_sig_offset(ext), type, }; int i; @@ -1696,16 +1713,19 @@ int bt_mesh_model_correspond(struct bt_mesh_model *corresponding_mod, return -ENOTSUP; } + uint8_t base_offset = get_sig_offset(base_mod); + uint8_t corresponding_offset = get_sig_offset(corresponding_mod); + MOD_REL_LIST_FOR_EACH(i) { if (mod_rel_list[i].type < RELATION_TYPE_EXT && mod_rel_list[i].type > cor_id) { cor_id = mod_rel_list[i].type; } - if ((IS_MOD_BASE(base_mod, i) || - IS_MOD_EXTENSION(base_mod, i) || - IS_MOD_BASE(corresponding_mod, i) || - IS_MOD_EXTENSION(corresponding_mod, i)) && + if ((IS_MOD_BASE(base_mod, i, base_offset) || + IS_MOD_EXTENSION(base_mod, i, base_offset) || + IS_MOD_BASE(corresponding_mod, i, corresponding_offset) || + IS_MOD_EXTENSION(corresponding_mod, i, corresponding_offset)) && mod_rel_list[i].type < RELATION_TYPE_EXT) { return mod_rel_register(base_mod, corresponding_mod, mod_rel_list[i].type); } From 7baae6c87ada53b681730c226d58a37a8ed6c382 Mon Sep 17 00:00:00 2001 From: Pavel Vasilyev Date: Mon, 9 Oct 2023 09:47:17 +0200 Subject: [PATCH 210/421] [nrf fromtree] Bluetooth: Mesh: Reset targets state before starting DFU on DFD srv MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The list of receives in the Firmware Distribution Server model and and the Firmware Update Client model are 2 different lists. In the Firmware Update Client model it is called the Update Receives state and the Active Update Receivers state which is a subset of receivers from the Update Receivers State. In the Firmware Distribution Server model it is called the Distribution Receivers List state. When Distribute Firmware procedure starts, in the Initiate step, the Receivers List input (which is the input for the Update Receivers state), is composed of the Distribution Receives List state. During DFU, the Update Receivers state becomes the Active Update Receivers state which keeps only active nodes. Timed out or failed nodes dropped out from this list. The Distribution Receivers List state stays unchanged and thus don't need to be populated again after every successfull and failed DFU. Signed-off-by: Pavel Vasilyev (cherry picked from commit 68365d5b67057c8e960a5168c2cf99f4b8c457c1) Signed-off-by: Alperen Şener (cherry picked from commit d6191e479e6e63a7768c0e4ac003fe834d5eacda) --- subsys/bluetooth/mesh/dfd_srv.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/subsys/bluetooth/mesh/dfd_srv.c b/subsys/bluetooth/mesh/dfd_srv.c index 59fe5b830d1..5d3ada4b4aa 100644 --- a/subsys/bluetooth/mesh/dfd_srv.c +++ b/subsys/bluetooth/mesh/dfd_srv.c @@ -1015,6 +1015,13 @@ enum bt_mesh_dfd_status bt_mesh_dfd_srv_start(struct bt_mesh_dfd_srv *srv, sys_slist_init(&srv->inputs.targets); for (i = 0; i < srv->target_cnt; i++) { + uint16_t addr = srv->targets[i].blob.addr; + + memset(&srv->targets[i].blob, 0, sizeof(struct bt_mesh_blob_target)); + memset(&srv->pull_ctxs[i], 0, sizeof(struct bt_mesh_blob_target_pull)); + srv->targets[i].blob.addr = addr; + srv->targets[i].blob.pull = &srv->pull_ctxs[i]; + sys_slist_append(&srv->inputs.targets, &srv->targets[i].blob.n); } From 78ec3b1294a711606b8302f3f95eef0a7095cb51 Mon Sep 17 00:00:00 2001 From: Morten Priess Date: Thu, 29 Jun 2023 09:16:26 +0200 Subject: [PATCH 211/421] [nrf fromtree] Bluetooth: controller: Introduce config for avoiding SDU fragmentation The CIS Central uses the algorithm described in BT Core 5.4 Vol 6, Part G, Section 2.2 to calculate the Max_PDU value for framed mode. However, HAP needs the Max_PDU to be calculated according to "Core enhancement for ISOAL CR" coming with the "Atlanta" update. With this update, the fragmentation is controlled via a parameter at CIG creation. Enabling CONFIG_BT_CTLR_CONN_ISO_AVOID_SEGMENTATION will set the ISO_Interval to 7.5 ms for a 10 ms framed CIG, and calculate Max_PDU to 45/65 for 16/24 kHz. Signed-off-by: Morten Priess (cherry picked from commit 79ab982f468096f6c06776a93fe154ca35d33f8f) Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit 8687b84bd8ba5779b5f3145af994fdefa870a3be) --- subsys/bluetooth/controller/Kconfig | 11 ++++ .../controller/ll_sw/ull_central_iso.c | 59 ++++++++++++++----- 2 files changed, 56 insertions(+), 14 deletions(-) diff --git a/subsys/bluetooth/controller/Kconfig b/subsys/bluetooth/controller/Kconfig index 59ec86d5efe..51890bf51ed 100644 --- a/subsys/bluetooth/controller/Kconfig +++ b/subsys/bluetooth/controller/Kconfig @@ -903,6 +903,17 @@ config BT_CTLR_CONN_ISO_STREAMS_MAX_FT help Maximum number of CIS flush timeout events. +config BT_CTLR_CONN_ISO_AVOID_SEGMENTATION + bool "Avoid SDU fragmentation for framed mode" + depends on BT_CTLR_CENTRAL_ISO + help + When creating a CIG, the Max_PDU size is calculated according to BT + Core 5.4 Vol 6, Part G, Section 2.2. However, HAP specifies a need for + avoiding segmentation by forcing the Max_PDU to the appropriate value. + Since there is no way to control the Max_PDU using the non-test + interface, the config provides a way to force the Max_PDU to Max_SDU + + 5 (header + offset). + config BT_CTLR_ISO bool default BT_CTLR_BROADCAST_ISO || BT_CTLR_CONN_ISO diff --git a/subsys/bluetooth/controller/ll_sw/ull_central_iso.c b/subsys/bluetooth/controller/ll_sw/ull_central_iso.c index 0c7a8e5ef35..49ab4909e3e 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_central_iso.c +++ b/subsys/bluetooth/controller/ll_sw/ull_central_iso.c @@ -234,6 +234,15 @@ uint8_t ll_cig_parameters_commit(uint8_t cig_id, uint16_t *handles) cig->iso_interval = BT_HCI_ISO_INTERVAL_MIN; } +#if defined(CONFIG_BT_CTLR_CONN_ISO_AVOID_SEGMENTATION) + /* Check if this is a HAP usecase which requires higher link bandwidth to ensure + * segmentation is not invoked in ISO-AL. + */ + if (cig->central.framing && cig->c_sdu_interval == 10000U) { + cig->iso_interval = 6; /* 7500 us */ + } +#endif + if (!cig->central.framing && (cig->c_sdu_interval % ISO_INT_UNIT_US)) { /* Framing not requested but requirement for unframed is not met. Force * CIG into framed mode. @@ -1131,29 +1140,51 @@ static void set_bn_max_pdu(bool framed, uint32_t iso_interval, uint8_t *max_pdu) { if (framed) { - uint32_t ceil_f_x_max_sdu; - uint16_t max_pdu_bn1; - uint32_t max_drift; + uint32_t max_drift_us; uint32_t ceil_f; - /* Framed (From ES-18002): + /* BT Core 5.4 Vol 6, Part G, Section 2.2: * Max_PDU >= ((ceil(F) x 5 + ceil(F x Max_SDU)) / BN) + 2 * F = (1 + MaxDrift) x ISO_Interval / SDU_Interval * SegmentationHeader + TimeOffset = 5 bytes * Continuation header = 2 bytes * MaxDrift (Max. allowed SDU delivery timing drift) = 100 ppm */ - max_drift = DIV_ROUND_UP(SDU_MAX_DRIFT_PPM * sdu_interval, 1000000U); - ceil_f = DIV_ROUND_UP(iso_interval + max_drift, sdu_interval); - ceil_f_x_max_sdu = DIV_ROUND_UP(max_sdu * (iso_interval + max_drift), - sdu_interval); - - /* Strategy: Keep lowest possible BN. - * TODO: Implement other strategies, possibly as policies. + max_drift_us = DIV_ROUND_UP(SDU_MAX_DRIFT_PPM * sdu_interval, USEC_PER_SEC); + ceil_f = DIV_ROUND_UP((USEC_PER_SEC + max_drift_us) * (uint64_t)iso_interval, + USEC_PER_SEC * (uint64_t)sdu_interval); + if (false) { +#if defined(CONFIG_BT_CTLR_CONN_ISO_AVOID_SEGMENTATION) + /* To avoid segmentation according to HAP, if the ISO_Interval is less than + * the SDU_Interval, we assume BN=1 and calculate the Max_PDU as: + * Max_PDU = celi(F / BN) x (5 / Max_SDU) + * + * This is in accordance with the "Core enhancement for ISOAL CR". + * + * This ensures that the drift can be contained in the difference between + * SDU_Interval and link bandwidth. For BN=1, ceil(F) == ceil(F/BN). */ - max_pdu_bn1 = ceil_f * 5 + ceil_f_x_max_sdu; - *bn = DIV_ROUND_UP(max_pdu_bn1, LL_CIS_OCTETS_TX_MAX); - *max_pdu = DIV_ROUND_UP(max_pdu_bn1, *bn) + 2; + } else if (iso_interval < sdu_interval) { + *bn = 1; + *max_pdu = ceil_f * (PDU_ISO_SEG_HDR_SIZE + PDU_ISO_SEG_TIMEOFFSET_SIZE + + max_sdu); +#endif + } else { + uint32_t ceil_f_x_max_sdu; + uint16_t max_pdu_bn1; + + ceil_f_x_max_sdu = DIV_ROUND_UP(max_sdu * ((USEC_PER_SEC + max_drift_us) * + (uint64_t)iso_interval), + USEC_PER_SEC * (uint64_t)sdu_interval); + + /* Strategy: Keep lowest possible BN. + * TODO: Implement other strategies, possibly as policies. + */ + max_pdu_bn1 = ceil_f * (PDU_ISO_SEG_HDR_SIZE + + PDU_ISO_SEG_TIMEOFFSET_SIZE) + ceil_f_x_max_sdu; + *bn = DIV_ROUND_UP(max_pdu_bn1, LL_CIS_OCTETS_TX_MAX); + *max_pdu = DIV_ROUND_UP(max_pdu_bn1, *bn) + PDU_ISO_SEG_HDR_SIZE; + } } else { /* For unframed, ISO_Interval must be N x SDU_Interval */ LL_ASSERT(iso_interval % sdu_interval == 0); From c5545cd918742435c48186f39e70fe806a037c0d Mon Sep 17 00:00:00 2001 From: Alberto Escolar Piedras Date: Thu, 7 Sep 2023 11:01:46 +0200 Subject: [PATCH 212/421] [nrf fromtree] Bluetooth: Controller: Nordic LLL: Use HAL to clear RTC event Use the HAL event clear function to clear the RTC EVENT instead of accessing the register directly. This allows using an updated version of the RTC HW models which generate level interrupts (as the real HW) and in which if the EVEN register is not properly cleared, the interrupts are kept high, resulting in the interrupt handler reentering immediately after exiting. Signed-off-by: Alberto Escolar Piedras (cherry picked from commit 7082222ac6606c537c18639ede88286b4a3e575a) Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit cbd608b0bf35569de217332e6bcb562d3d3e42ae) --- subsys/bluetooth/controller/ll_sw/nordic/lll/lll.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll.c b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll.c index bc71bbcd5a6..1f8031a7c07 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll.c @@ -8,6 +8,8 @@ #include #include +#include + #include #include @@ -106,7 +108,7 @@ static void rtc0_nrf5_isr(const void *arg) /* On compare0 run ticker worker instance0 */ if (NRF_RTC0->EVENTS_COMPARE[0]) { - NRF_RTC0->EVENTS_COMPARE[0] = 0; + nrf_rtc_event_clear(NRF_RTC0, NRF_RTC_EVENT_COMPARE_0); ticker_trigger(0); } From e0313b730459f788f15f9e8745f90404ccad1f28 Mon Sep 17 00:00:00 2001 From: Alberto Escolar Piedras Date: Thu, 7 Sep 2023 11:04:33 +0200 Subject: [PATCH 213/421] [nrf fromtree] Bluetooth: Controller: Nordic LLL: Use HAL to clear EVENTs Use the HAL event clear functions to clear EVENTS instead of accessing the registers directly. Signed-off-by: Alberto Escolar Piedras (cherry picked from commit bb811a1e1d7c7662bbfb9278c8994b32dc61b55b) Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit 99ed0b6d46ca7b8eeffa7f6aef65e979f373546d) --- .../ll_sw/nordic/hal/nrf5/radio/radio.c | 46 +++++++++---------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio.c b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio.c index 7b72b1a4b93..1875dca7896 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio.c @@ -568,18 +568,18 @@ void radio_status_reset(void) * register value, PPI task will be triggered. Hence, other * EVENT_* registers are not reset to save code and CPU time. */ - NRF_RADIO->EVENTS_READY = 0; - NRF_RADIO->EVENTS_END = 0; + nrf_radio_event_clear(NRF_RADIO, NRF_RADIO_EVENT_READY); + nrf_radio_event_clear(NRF_RADIO, NRF_RADIO_EVENT_END); #if defined(CONFIG_BT_CTLR_DF_SUPPORT) && !defined(CONFIG_ZTEST) /* Clear it only for SoCs supporting DF extension */ - NRF_RADIO->EVENTS_PHYEND = 0; - NRF_RADIO->EVENTS_CTEPRESENT = 0; - NRF_RADIO->EVENTS_BCMATCH = 0; + nrf_radio_event_clear(NRF_RADIO, NRF_RADIO_EVENT_PHYEND); + nrf_radio_event_clear(NRF_RADIO, NRF_RADIO_EVENT_CTEPRESENT); + nrf_radio_event_clear(NRF_RADIO, NRF_RADIO_EVENT_BCMATCH); #endif /* CONFIG_BT_CTLR_DF_SUPPORT && !CONFIG_ZTEST */ - NRF_RADIO->EVENTS_DISABLED = 0; + nrf_radio_event_clear(NRF_RADIO, NRF_RADIO_EVENT_DISABLED); #if defined(CONFIG_BT_CTLR_PHY_CODED) #if defined(CONFIG_HAS_HW_NRF_RADIO_BLE_CODED) - NRF_RADIO->EVENTS_RATEBOOST = 0; + nrf_radio_event_clear(NRF_RADIO, NRF_RADIO_EVENT_RATEBOOST); #endif /* CONFIG_HAS_HW_NRF_RADIO_BLE_CODED */ #endif /* CONFIG_BT_CTLR_PHY_CODED */ } @@ -1019,7 +1019,7 @@ uint32_t radio_rssi_get(void) void radio_rssi_status_reset(void) { - NRF_RADIO->EVENTS_RSSIEND = 0; + nrf_radio_event_clear(NRF_RADIO, NRF_RADIO_EVENT_RSSIEND); } uint32_t radio_rssi_is_ready(void) @@ -1051,7 +1051,7 @@ void radio_filter_disable(void) void radio_filter_status_reset(void) { - NRF_RADIO->EVENTS_DEVMATCH = 0; + nrf_radio_event_clear(NRF_RADIO, NRF_RADIO_EVENT_DEVMATCH); } uint32_t radio_filter_has_match(void) @@ -1072,7 +1072,7 @@ void radio_bc_configure(uint32_t n) void radio_bc_status_reset(void) { - NRF_RADIO->EVENTS_BCMATCH = 0; + nrf_radio_event_clear(NRF_RADIO, NRF_RADIO_EVENT_BCMATCH); } uint32_t radio_bc_has_match(void) @@ -1356,7 +1356,7 @@ uint32_t radio_tmr_start_us(uint8_t trx, uint32_t start_us) start_us = (now_us << 1) - start_us; /* Setup compare event with min. 1 us offset */ - EVENT_TIMER->EVENTS_COMPARE[0] = 0U; + nrf_timer_event_clear(EVENT_TIMER, NRF_TIMER_EVENT_COMPARE0); nrf_timer_cc_set(EVENT_TIMER, 0, start_us + 1U); /* Capture the current time */ @@ -1749,9 +1749,9 @@ static void *radio_ccm_ext_rx_pkt_set(struct ccm *cnf, uint8_t phy, uint8_t pdu_ NRF_CCM->OUTPTR = (uint32_t)pkt; NRF_CCM->SCRATCHPTR = (uint32_t)_ccm_scratch; NRF_CCM->SHORTS = 0; - NRF_CCM->EVENTS_ENDKSGEN = 0; - NRF_CCM->EVENTS_ENDCRYPT = 0; - NRF_CCM->EVENTS_ERROR = 0; + nrf_ccm_event_clear(NRF_CCM, NRF_CCM_EVENT_ENDKSGEN); + nrf_ccm_event_clear(NRF_CCM, NRF_CCM_EVENT_ENDCRYPT); + nrf_ccm_event_clear(NRF_CCM, NRF_CCM_EVENT_ERROR); nrf_ccm_task_trigger(NRF_CCM, NRF_CCM_TASK_KSGEN); @@ -1820,9 +1820,9 @@ static void *radio_ccm_ext_tx_pkt_set(struct ccm *cnf, uint8_t pdu_type, void *p NRF_CCM->OUTPTR = (uint32_t)_pkt_scratch; NRF_CCM->SCRATCHPTR = (uint32_t)_ccm_scratch; NRF_CCM->SHORTS = CCM_SHORTS_ENDKSGEN_CRYPT_Msk; - NRF_CCM->EVENTS_ENDKSGEN = 0; - NRF_CCM->EVENTS_ENDCRYPT = 0; - NRF_CCM->EVENTS_ERROR = 0; + nrf_ccm_event_clear(NRF_CCM, NRF_CCM_EVENT_ENDKSGEN); + nrf_ccm_event_clear(NRF_CCM, NRF_CCM_EVENT_ENDCRYPT); + nrf_ccm_event_clear(NRF_CCM, NRF_CCM_EVENT_ERROR); nrf_ccm_task_trigger(NRF_CCM, NRF_CCM_TASK_KSGEN); @@ -1899,9 +1899,9 @@ void radio_ar_configure(uint32_t nirk, void *irk, uint8_t flags) NRF_AAR->ADDRPTR = addrptr; NRF_AAR->SCRATCHPTR = (uint32_t)&_aar_scratch[0]; - NRF_AAR->EVENTS_END = 0; - NRF_AAR->EVENTS_RESOLVED = 0; - NRF_AAR->EVENTS_NOTRESOLVED = 0; + nrf_aar_event_clear(NRF_AAR, NRF_AAR_EVENT_END); + nrf_aar_event_clear(NRF_AAR, NRF_AAR_EVENT_RESOLVED); + nrf_aar_event_clear(NRF_AAR, NRF_AAR_EVENT_NOTRESOLVED); radio_bc_configure(bcc); radio_bc_status_reset(); @@ -1957,9 +1957,9 @@ uint8_t radio_ar_resolve(const uint8_t *addr) NRF_AAR->ADDRPTR = (uint32_t)addr - 3; - NRF_AAR->EVENTS_END = 0; - NRF_AAR->EVENTS_RESOLVED = 0; - NRF_AAR->EVENTS_NOTRESOLVED = 0; + nrf_aar_event_clear(NRF_AAR, NRF_AAR_EVENT_END); + nrf_aar_event_clear(NRF_AAR, NRF_AAR_EVENT_RESOLVED); + nrf_aar_event_clear(NRF_AAR, NRF_AAR_EVENT_NOTRESOLVED); NVIC_ClearPendingIRQ(nrfx_get_irq_number(NRF_AAR)); From f98dcccd9c67ed0c9c8e8d03e6b5fa795489ebce Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Wed, 13 Sep 2023 12:37:29 +0530 Subject: [PATCH 214/421] [nrf fromtree] Bluetooth: Controller: Fix some compiler instruction re-ordering Fix some compiler instruction re-ordering. Mayfly code with cpu_dmb() help avoid stalled memq_ull_rx processing when rx_demux is to be executed using mayfly. Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit f2069530ee9d73d2c5c3a65bd3b146b0631593fb) Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit eed5fba328b838861c9947d8608ef3ff02b1a25c) --- subsys/bluetooth/controller/ticker/ticker.c | 1 + subsys/bluetooth/controller/util/mayfly.c | 7 +++++++ 2 files changed, 8 insertions(+) diff --git a/subsys/bluetooth/controller/ticker/ticker.c b/subsys/bluetooth/controller/ticker/ticker.c index 679467d148c..ead148e85ba 100644 --- a/subsys/bluetooth/controller/ticker/ticker.c +++ b/subsys/bluetooth/controller/ticker/ticker.c @@ -3149,6 +3149,7 @@ void ticker_job(void *param) instance->job_guard = 0U; /* trigger worker if deferred */ + cpu_dmb(); if (instance->worker_trigger || compare_trigger) { instance->sched_cb(TICKER_CALL_ID_JOB, TICKER_CALL_ID_WORKER, 1, instance); diff --git a/subsys/bluetooth/controller/util/mayfly.c b/subsys/bluetooth/controller/util/mayfly.c index e8de3acfd80..d45569c6a35 100644 --- a/subsys/bluetooth/controller/util/mayfly.c +++ b/subsys/bluetooth/controller/util/mayfly.c @@ -6,8 +6,13 @@ */ #include + +#include #include #include + +#include "hal/cpu.h" + #include "memq.h" #include "mayfly.h" @@ -154,10 +159,12 @@ static void dequeue(uint8_t callee_id, uint8_t caller_id, memq_link_t *link, m->_link = link; /* reset mayfly state to idle */ + cpu_dmb(); ack = m->_ack; m->_ack = req; /* re-insert, if re-pended by interrupt */ + cpu_dmb(); if (((m->_req - ack) & 0x03) == 1U) { #if defined(MAYFLY_UT) printk("%s: RACE\n", __func__); From f3560c3ff5a62f3c8a90ad03cb623c2dea3c9d04 Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Fri, 16 Jun 2023 18:36:10 +0530 Subject: [PATCH 215/421] [nrf fromtree] Bluetooth: Controller: Minor clean up of redundant initialization Minor clean up of redundant initialization. Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit afd48e03d064568a536e89038d1a31a50cd76349) Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit a11b48a35028caeda7a62f6c0713604e979ca7a5) --- subsys/bluetooth/controller/ll_sw/ull_central_iso.c | 10 +--------- subsys/bluetooth/controller/ll_sw/ull_peripheral_iso.c | 4 ---- 2 files changed, 1 insertion(+), 13 deletions(-) diff --git a/subsys/bluetooth/controller/ll_sw/ull_central_iso.c b/subsys/bluetooth/controller/ll_sw/ull_central_iso.c index 49ab4909e3e..71b8d742a76 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_central_iso.c +++ b/subsys/bluetooth/controller/ll_sw/ull_central_iso.c @@ -690,15 +690,6 @@ void ll_cis_create(uint16_t cis_handle, uint16_t acl_handle) /* Initialize stream states */ cis->established = 0; cis->teardown = 0; - cis->lll.event_count = LLL_CONN_ISO_EVENT_COUNT_MAX; - cis->lll.sn = 0; - cis->lll.nesn = 0; - cis->lll.cie = 0; - cis->lll.flush = LLL_CIS_FLUSH_NONE; - cis->lll.active = 0; - cis->lll.datapath_ready_rx = 0; - cis->lll.tx.bn_curr = 1U; - cis->lll.rx.bn_curr = 1U; (void)memset(&cis->hdr, 0U, sizeof(cis->hdr)); @@ -875,6 +866,7 @@ uint8_t ull_central_iso_setup(uint16_t cis_handle, #endif /* !CONFIG_BT_CTLR_JIT_SCHEDULING */ cis->central.instant = instant; + cis->lll.event_count = LLL_CONN_ISO_EVENT_COUNT_MAX; cis->lll.next_subevent = 0U; cis->lll.sn = 0U; cis->lll.nesn = 0U; diff --git a/subsys/bluetooth/controller/ll_sw/ull_peripheral_iso.c b/subsys/bluetooth/controller/ll_sw/ull_peripheral_iso.c index 5bbac2528d0..d45d89aa009 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_peripheral_iso.c +++ b/subsys/bluetooth/controller/ll_sw/ull_peripheral_iso.c @@ -259,15 +259,11 @@ uint8_t ull_peripheral_iso_acquire(struct ll_conn *acl, cis->lll.rx.bn = req->c_bn; cis->lll.rx.ft = req->c_ft; cis->lll.rx.max_pdu = sys_le16_to_cpu(req->c_max_pdu); - cis->lll.rx.payload_count = 0; - cis->lll.rx.bn_curr = 1U; cis->lll.tx.phy = req->p_phy; cis->lll.tx.bn = req->p_bn; cis->lll.tx.ft = req->p_ft; cis->lll.tx.max_pdu = sys_le16_to_cpu(req->p_max_pdu); - cis->lll.tx.payload_count = 0; - cis->lll.tx.bn_curr = 1U; if (!cis->lll.link_tx_free) { cis->lll.link_tx_free = &cis->lll.link_tx; From f6496260fc1dc3e873cb55cce34ab1814df1a004 Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Thu, 14 Sep 2023 15:33:26 +0530 Subject: [PATCH 216/421] [nrf fromtree] Bluetooth: Controller: Fix initialization of lazy_active Fix initialization of CIS lazy_active event count used when first CIS event is active. Now initialization for first and any subsequent CISes made active. Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit 1291e4b6868d81518167a99dd48108ed48e1abd4) Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit 4dd81a515bbe870224092d5abd7875a01165fb5b) --- subsys/bluetooth/controller/ll_sw/ull_conn_iso.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/subsys/bluetooth/controller/ll_sw/ull_conn_iso.c b/subsys/bluetooth/controller/ll_sw/ull_conn_iso.c index 8b79100d942..cc76c5219cb 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_conn_iso.c +++ b/subsys/bluetooth/controller/ll_sw/ull_conn_iso.c @@ -851,6 +851,10 @@ void ull_conn_iso_start(struct ll_conn *conn, uint16_t cis_handle, */ if (cig->state == CIG_STATE_ACTIVE) { #if !defined(CONFIG_BT_CTLR_JIT_SCHEDULING) + /* Initialize CIS event lazy at CIS create */ + cis->lll.lazy_active = 0U; + + /* Deferred fill CIS event lazy value at CIS create */ cis_lazy_fill(cis); #else /* CONFIG_BT_CTLR_JIT_SCHEDULING */ /* Set CIS active in already active CIG */ @@ -996,6 +1000,9 @@ void ull_conn_iso_start(struct ll_conn *conn, uint16_t cis_handle, } ticks_slot = cig->ull.ticks_slot + ticks_slot_overhead; + + /* Initialize CIS event lazy at CIS create */ + cis->lll.lazy_active = 0U; #endif /* !CONFIG_BT_CTLR_JIT_SCHEDULING */ /* Start CIS peripheral CIG ticker */ @@ -1014,11 +1021,6 @@ void ull_conn_iso_start(struct ll_conn *conn, uint16_t cis_handle, /* Set CIG and the first CIS state as active */ cig->state = CIG_STATE_ACTIVE; cis->lll.active = 1U; - -#if !defined(CONFIG_BT_CTLR_JIT_SCHEDULING) - /* CIS event lazy at CIS create */ - cis->lll.lazy_active = 0U; -#endif /* !CONFIG_BT_CTLR_JIT_SCHEDULING */ } #if !defined(CONFIG_BT_CTLR_JIT_SCHEDULING) From 1cd5c0c6039be61db9eb5e5f0c95586854fdec52 Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Thu, 14 Sep 2023 15:35:53 +0530 Subject: [PATCH 217/421] [nrf fromtree] Bluetooth: Controller: Fix missing lazy calculation for Central ISO Fix missing lazy calculation when using ticker interface required for Central CIS create. Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit d42d14e392e70a846abe5baaceb849ef21a50584) Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit a5bd81633ca8f20ea30729463920f1b5c8cfa896) --- subsys/bluetooth/controller/Kconfig.ll_sw_split | 2 +- subsys/bluetooth/controller/ll_sw/ull_conn_iso.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/subsys/bluetooth/controller/Kconfig.ll_sw_split b/subsys/bluetooth/controller/Kconfig.ll_sw_split index 84db5fddb10..910c3819f0c 100644 --- a/subsys/bluetooth/controller/Kconfig.ll_sw_split +++ b/subsys/bluetooth/controller/Kconfig.ll_sw_split @@ -53,7 +53,7 @@ config BT_LLL_VENDOR_NORDIC (BT_OBSERVER && BT_CTLR_ADV_EXT) select BT_TICKER_REMAINDER if BT_CTLR_CENTRAL_ISO select BT_TICKER_REMAINDER_GET if BT_BROADCASTER && BT_CTLR_ADV_EXT - select BT_TICKER_LAZY_GET if BT_CTLR_ADV_PERIODIC + select BT_TICKER_LAZY_GET if BT_CTLR_ADV_PERIODIC || BT_CTLR_CENTRAL_ISO default y help diff --git a/subsys/bluetooth/controller/ll_sw/ull_conn_iso.c b/subsys/bluetooth/controller/ll_sw/ull_conn_iso.c index cc76c5219cb..2ee5905b23b 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_conn_iso.c +++ b/subsys/bluetooth/controller/ll_sw/ull_conn_iso.c @@ -1042,8 +1042,8 @@ static void mfy_cis_lazy_fill(void *param) uint32_t ticks_to_expire; uint32_t ticks_current; uint32_t remainder; + uint16_t lazy = 0U; uint8_t ticker_id; - uint16_t lazy; uint8_t retry; uint8_t id; From 4259135d4de0b463e3b9e10ab03982d92321e8ca Mon Sep 17 00:00:00 2001 From: Gerard Marull-Paretas Date: Wed, 13 Sep 2023 16:11:40 +0200 Subject: [PATCH 218/421] [nrf fromtree] bluetooth: controller: coex: convert to DT device Convert the driver to a dt-based device. Also update Kconfig so that it depends on the right compatible being enabled, initialize in POST_KERNEL (APPLICATION should not be used for devices) and remove one redundant include. Signed-off-by: Gerard Marull-Paretas (cherry picked from commit 4f80e50b55d325999f6749354a6c8519b1d54096) Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit a226209c81b1a579a5490fe2710a9e27230b5db0) --- samples/bluetooth/beacon/prj-coex.conf | 1 - subsys/bluetooth/controller/coex/Kconfig | 4 ++-- subsys/bluetooth/controller/coex/coex_ticker.c | 18 ++++++------------ 3 files changed, 8 insertions(+), 15 deletions(-) diff --git a/samples/bluetooth/beacon/prj-coex.conf b/samples/bluetooth/beacon/prj-coex.conf index b16487f3999..eb9cd4bb16e 100644 --- a/samples/bluetooth/beacon/prj-coex.conf +++ b/samples/bluetooth/beacon/prj-coex.conf @@ -3,5 +3,4 @@ CONFIG_LOG=y CONFIG_BT_DEVICE_NAME="Test beacon" CONFIG_BT_LL_SW_SPLIT=y -CONFIG_BT_CTLR_COEX_DRIVERS=y CONFIG_BT_CTLR_COEX_TICKER=y diff --git a/subsys/bluetooth/controller/coex/Kconfig b/subsys/bluetooth/controller/coex/Kconfig index 31754fbf52c..b7bc7d30681 100644 --- a/subsys/bluetooth/controller/coex/Kconfig +++ b/subsys/bluetooth/controller/coex/Kconfig @@ -5,8 +5,8 @@ menuconfig BT_CTLR_COEX_DRIVERS bool "Bluetooth Co-existence Drivers" - default n - depends on BT_CTLR + default y + depends on BT_CTLR && DT_HAS_GPIO_RADIO_COEX_ENABLED if BT_CTLR_COEX_DRIVERS diff --git a/subsys/bluetooth/controller/coex/coex_ticker.c b/subsys/bluetooth/controller/coex/coex_ticker.c index 229e2f9e125..be349622ecd 100644 --- a/subsys/bluetooth/controller/coex/coex_ticker.c +++ b/subsys/bluetooth/controller/coex/coex_ticker.c @@ -4,12 +4,13 @@ * SPDX-License-Identifier: Apache-2.0 */ +#define DT_DRV_COMPAT gpio_radio_coex + #include #include #include #include -#include #include #include #include @@ -195,18 +196,11 @@ static int coex_ticker_init(const struct device *dev) return 0; } -#define RADIO_NODE DT_NODELABEL(radio) -#define COEX_NODE DT_PROP(RADIO_NODE, coex) - -#if DT_NODE_EXISTS(COEX_NODE) static struct coex_ticker_config config = { - .grant_spec = GPIO_DT_SPEC_GET(COEX_NODE, grant_gpios), - .grant_delay_us = DT_PROP(COEX_NODE, grant_delay_us) + .grant_spec = GPIO_DT_SPEC_INST_GET(0, grant_gpios), + .grant_delay_us = DT_INST_PROP(0, grant_delay_us) }; static struct coex_ticker_data data; -DEVICE_DEFINE(coex_ticker, "COEX_TICKER", &coex_ticker_init, NULL, - &data, &config, - APPLICATION, 90, - NULL); -#endif +DEVICE_DT_INST_DEFINE(0, &coex_ticker_init, NULL, &data, &config, + POST_KERNEL, 90, NULL); From 1845278ad53c15a557ca81895e9e5c89721d573b Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Fri, 30 Jun 2023 07:07:38 +0530 Subject: [PATCH 219/421] [nrf fromtree] Bluetooth: Controller: Revert EVENT_OVERHEAD_END_US to original value Revert back the EVENT_OVERHEAD_END_US value to original value in initial commit 5c3709c13fd8 ("bluetooth: controller: Add def's re. update to slot reservation calc"). 40 us is a sufficient margin considering ~30 us being the worst case Rx chain delay for S8 Coded PHY on nRF5x SoCs. Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit c986104485914a0adbcfb5cf96dcb152e82fa87d) Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit 6e412944b0ef8b6925efa31ea4a36edc8d1dd620) --- subsys/bluetooth/controller/ll_sw/nordic/lll/lll_vendor.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_vendor.h b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_vendor.h index 5ee063e4d53..7df39f65c8a 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_vendor.h +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_vendor.h @@ -42,7 +42,7 @@ /* Worst-case time margin needed after event end-time in the air * (done/preempt race margin + power-down/chain delay) */ -#define EVENT_OVERHEAD_END_US 100 +#define EVENT_OVERHEAD_END_US 40 /* Sleep Clock Accuracy */ #define EVENT_JITTER_US 16 From 1734da8febc892c0ad4231495b3425acd192668f Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Fri, 30 Jun 2023 08:18:53 +0530 Subject: [PATCH 220/421] [nrf fromtree] Bluetooth: Controller: Make openisa and test hal ticker.h consistent Make openisa and unit test hal ticker.h consistent with nrf hal ticker.h. Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit 01314b2e434e5759327bcf78c38089e6750c54c4) Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit ce4fd380c13264ae16bc3c3805a50ffe19196d0c) --- .../controller/ll_sw/nordic/hal/nrf5/ticker.h | 3 +- .../ll_sw/openisa/hal/RV32M1/ticker.h | 36 ++++++++++---- .../mock_ctrl/include/hal/ticker_vendor_hal.h | 49 +++++++++++++------ 3 files changed, 62 insertions(+), 26 deletions(-) diff --git a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/ticker.h b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/ticker.h index 5845d15145a..315601ce203 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/ticker.h +++ b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/ticker.h @@ -26,7 +26,8 @@ #define HAL_TICKER_US_TO_TICKS(x) \ ( \ ((uint32_t)(((uint64_t) (x) * 1000000000UL) / \ - HAL_TICKER_CNTR_CLK_UNIT_FS)) & HAL_TICKER_CNTR_MASK \ + HAL_TICKER_CNTR_CLK_UNIT_FS)) & \ + HAL_TICKER_CNTR_MASK \ ) /* Macro to translate tick units to microseconds. */ diff --git a/subsys/bluetooth/controller/ll_sw/openisa/hal/RV32M1/ticker.h b/subsys/bluetooth/controller/ll_sw/openisa/hal/RV32M1/ticker.h index 642ca1e608f..e4d162eb9d2 100644 --- a/subsys/bluetooth/controller/ll_sw/openisa/hal/RV32M1/ticker.h +++ b/subsys/bluetooth/controller/ll_sw/openisa/hal/RV32M1/ticker.h @@ -6,37 +6,53 @@ */ #define HAL_TICKER_CNTR_CLK_FREQ_HZ 32768U +#define HAL_TICKER_CNTR_CLK_UNIT_FS 30517578125UL +/* Macro defining the minimum counter compare offset */ #define HAL_TICKER_CNTR_CMP_OFFSET_MIN 2 +/* Macro defining the max. counter update latency in ticks */ #define HAL_TICKER_CNTR_SET_LATENCY 1 + +/* Macro defines the h/w supported most significant bit */ +#define HAL_TICKER_CNTR_MSBIT 31 + +/* Macro defining the HW supported counter bits */ +#define HAL_TICKER_CNTR_MASK 0xFFFFFFFF + /* * When the LPTMR is enabled, the first increment will take an additional * one or two prescaler clock cycles due to synchronization logic. */ +/* Macro to translate microseconds to tick units. + * NOTE: This returns the floor value. + */ #define HAL_TICKER_US_TO_TICKS(x) \ ( \ - ((uint32_t)(((uint64_t) (x) * 1000000000UL) / 30517578125UL)) \ - & HAL_TICKER_CNTR_MASK \ + ((uint32_t)(((uint64_t) (x) * 1000000000UL) / \ + HAL_TICKER_CNTR_CLK_UNIT_FS)) & \ + HAL_TICKER_CNTR_MASK \ + ) + +/* Macro to translate tick units to microseconds. */ +#define HAL_TICKER_TICKS_TO_US(x) \ + ( \ + ((uint32_t)(((uint64_t)(x) * HAL_TICKER_CNTR_CLK_UNIT_FS) / \ + 1000000000UL)) \ ) +/* Macro returning remainder in picoseconds (to fit in 32-bits) */ #define HAL_TICKER_REMAINDER(x) \ ( \ ( \ ((uint64_t) (x) * 1000000000UL) \ - - ((uint64_t)HAL_TICKER_US_TO_TICKS(x) * 30517578125UL) \ + - ((uint64_t)HAL_TICKER_US_TO_TICKS(x) * \ + HAL_TICKER_CNTR_CLK_UNIT_FS) \ ) \ / 1000UL \ ) -#define HAL_TICKER_TICKS_TO_US(x) \ - ((uint32_t)(((uint64_t)(x) * 30517578125UL) / 1000000000UL)) - -#define HAL_TICKER_CNTR_MSBIT 31 - -#define HAL_TICKER_CNTR_MASK 0xFFFFFFFF - /* Macro defining the remainder resolution/range * ~ 1000000 * HAL_TICKER_TICKS_TO_US(1) */ diff --git a/tests/bluetooth/controller/mock_ctrl/include/hal/ticker_vendor_hal.h b/tests/bluetooth/controller/mock_ctrl/include/hal/ticker_vendor_hal.h index bbd4b3e462c..7c3792d848c 100644 --- a/tests/bluetooth/controller/mock_ctrl/include/hal/ticker_vendor_hal.h +++ b/tests/bluetooth/controller/mock_ctrl/include/hal/ticker_vendor_hal.h @@ -3,7 +3,9 @@ * * SPDX-License-Identifier: Apache-2.0 */ + #define HAL_TICKER_CNTR_CLK_FREQ_HZ 32768U +#define HAL_TICKER_CNTR_CLK_UNIT_FS 30517578125UL /* Macro defining the minimum counter compare offset */ #define HAL_TICKER_CNTR_CMP_OFFSET_MIN 3 @@ -11,30 +13,47 @@ /* Macro defining the max. counter update latency in ticks */ #define HAL_TICKER_CNTR_SET_LATENCY 0 +/* Macro defines the h/w supported most significant bit */ +#define HAL_TICKER_CNTR_MSBIT 23 + +/* Macro defining the HW supported counter bits */ +#define HAL_TICKER_CNTR_MASK 0x00FFFFFF + /* Macro to translate microseconds to tick units. * NOTE: This returns the floor value. */ -#define HAL_TICKER_US_TO_TICKS(x) \ - (((uint32_t)(((uint64_t)(x) * 1000000000UL) / 30517578125UL)) & HAL_TICKER_CNTR_MASK) +#define HAL_TICKER_US_TO_TICKS(x) \ + ( \ + ((uint32_t)(((uint64_t) (x) * 1000000000UL) / \ + HAL_TICKER_CNTR_CLK_UNIT_FS)) & \ + HAL_TICKER_CNTR_MASK \ + ) -/* Macro returning remainder in nanoseconds */ -#define HAL_TICKER_REMAINDER(x) \ - ((((uint64_t)(x) * 1000000000UL) - ((uint64_t)HAL_TICKER_US_TO_TICKS(x) * 30517578125UL)) /\ - 1000UL) /* Macro to translate tick units to microseconds. */ -#define HAL_TICKER_TICKS_TO_US(x) ((uint32_t)(((uint64_t)(x) * 30517578125UL) / 1000000000UL)) - -/* Macro defines the h/w supported most significant bit */ -#define HAL_TICKER_CNTR_MSBIT 23 - -/* Macro defining the HW supported counter bits */ -#define HAL_TICKER_CNTR_MASK 0x00FFFFFF +#define HAL_TICKER_TICKS_TO_US(x) \ + ( \ + ((uint32_t)(((uint64_t)(x) * HAL_TICKER_CNTR_CLK_UNIT_FS) / \ + 1000000000UL)) \ + ) + +/* Macro returning remainder in picoseconds (to fit in 32-bits) */ +#define HAL_TICKER_REMAINDER(x) \ + ( \ + ( \ + ((uint64_t) (x) * 1000000000UL) \ + - ((uint64_t)HAL_TICKER_US_TO_TICKS(x) * \ + HAL_TICKER_CNTR_CLK_UNIT_FS) \ + ) \ + / 1000UL \ + ) /* Macro defining the remainder resolution/range * ~ 1000000 * HAL_TICKER_TICKS_TO_US(1) */ -#define HAL_TICKER_REMAINDER_RANGE HAL_TICKER_TICKS_TO_US(1000000) +#define HAL_TICKER_REMAINDER_RANGE \ + HAL_TICKER_TICKS_TO_US(1000000) /* Macro defining the margin for positioning re-scheduled nodes */ -#define HAL_TICKER_RESCHEDULE_MARGIN HAL_TICKER_US_TO_TICKS(150) +#define HAL_TICKER_RESCHEDULE_MARGIN \ + HAL_TICKER_US_TO_TICKS(150) From 4604cde52079bb44a3d2fcfd08c7362969cf3a40 Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Tue, 13 Jun 2023 09:07:19 +0530 Subject: [PATCH 221/421] [nrf fromtree] Bluetooth: Controller: Use HAL_TICKER_US_TO_TICKS_CEIL for ticks_slot Use HAL_TICKER_US_TO_TICKS_CEIL for ticks_slot calculations. Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit 333ff94e6bd19f7b2bc7c9c3ddb1f84fb84bff80) Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit 8412da5360660f100a0d5ae894b222b736756270) --- .../controller/ll_sw/nordic/hal/nrf5/ticker.h | 11 +++++++++++ .../controller/ll_sw/openisa/hal/RV32M1/ticker.h | 11 +++++++++++ subsys/bluetooth/controller/ll_sw/ull_adv.c | 4 ++-- subsys/bluetooth/controller/ll_sw/ull_adv_aux.c | 6 +++--- subsys/bluetooth/controller/ll_sw/ull_adv_iso.c | 2 +- subsys/bluetooth/controller/ll_sw/ull_adv_sync.c | 2 +- subsys/bluetooth/controller/ll_sw/ull_central.c | 11 ++++------- subsys/bluetooth/controller/ll_sw/ull_central_iso.c | 2 +- subsys/bluetooth/controller/ll_sw/ull_conn.c | 10 ++++------ subsys/bluetooth/controller/ll_sw/ull_conn_iso.c | 2 +- subsys/bluetooth/controller/ll_sw/ull_peripheral.c | 11 ++++------- subsys/bluetooth/controller/ll_sw/ull_scan_aux.c | 10 ++++------ subsys/bluetooth/controller/ll_sw/ull_sched.c | 10 ++++++---- subsys/bluetooth/controller/ll_sw/ull_sync.c | 10 ++++------ subsys/bluetooth/controller/ll_sw/ull_sync_iso.c | 10 +++++----- .../mock_ctrl/include/hal/ticker_vendor_hal.h | 10 ++++++++++ 16 files changed, 72 insertions(+), 50 deletions(-) diff --git a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/ticker.h b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/ticker.h index 315601ce203..f179dbd0035 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/ticker.h +++ b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/ticker.h @@ -30,6 +30,17 @@ HAL_TICKER_CNTR_MASK \ ) +/* Macro to translate microseconds to tick units. + * NOTE: This returns the ceil value. + */ +#define HAL_TICKER_US_TO_TICKS_CEIL(x) \ + ( \ + ((uint32_t)(((((uint64_t) (x) * 1000000000UL) + \ + HAL_TICKER_CNTR_CLK_UNIT_FS - 1U)) / \ + HAL_TICKER_CNTR_CLK_UNIT_FS)) & \ + HAL_TICKER_CNTR_MASK \ + ) + /* Macro to translate tick units to microseconds. */ #define HAL_TICKER_TICKS_TO_US(x) \ ( \ diff --git a/subsys/bluetooth/controller/ll_sw/openisa/hal/RV32M1/ticker.h b/subsys/bluetooth/controller/ll_sw/openisa/hal/RV32M1/ticker.h index e4d162eb9d2..1f491739185 100644 --- a/subsys/bluetooth/controller/ll_sw/openisa/hal/RV32M1/ticker.h +++ b/subsys/bluetooth/controller/ll_sw/openisa/hal/RV32M1/ticker.h @@ -35,6 +35,17 @@ HAL_TICKER_CNTR_MASK \ ) +/* Macro to translate microseconds to tick units. + * NOTE: This returns the ceil value. + */ +#define HAL_TICKER_US_TO_TICKS_CEIL(x) \ + ( \ + ((uint32_t)(((((uint64_t) (x) * 1000000000UL) + \ + HAL_TICKER_CNTR_CLK_UNIT_FS - 1U)) / \ + HAL_TICKER_CNTR_CLK_UNIT_FS)) & \ + HAL_TICKER_CNTR_MASK \ + ) + /* Macro to translate tick units to microseconds. */ #define HAL_TICKER_TICKS_TO_US(x) \ ( \ diff --git a/subsys/bluetooth/controller/ll_sw/ull_adv.c b/subsys/bluetooth/controller/ll_sw/ull_adv.c index 3797acdc541..d7d5b23f63e 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_adv.c +++ b/subsys/bluetooth/controller/ll_sw/ull_adv.c @@ -1251,7 +1251,7 @@ uint8_t ll_adv_enable(uint8_t enable) HAL_TICKER_US_TO_TICKS(EVENT_OVERHEAD_XTAL_US); adv->ull.ticks_preempt_to_start = HAL_TICKER_US_TO_TICKS(EVENT_OVERHEAD_PREEMPT_MIN_US); - adv->ull.ticks_slot = HAL_TICKER_US_TO_TICKS(time_us); + adv->ull.ticks_slot = HAL_TICKER_US_TO_TICKS_CEIL(time_us); ticks_slot_offset = MAX(adv->ull.ticks_active_to_start, adv->ull.ticks_prepare_to_start); @@ -2145,7 +2145,7 @@ uint8_t ull_adv_time_update(struct ll_adv_set *adv, struct pdu_adv *pdu, chan_map = lll->chan_map; chan_cnt = util_ones_count_get(&chan_map, sizeof(chan_map)); time_us = adv_time_get(pdu, pdu_scan, chan_cnt, phy, phy_flags); - time_ticks = HAL_TICKER_US_TO_TICKS(time_us); + time_ticks = HAL_TICKER_US_TO_TICKS_CEIL(time_us); #if !defined(CONFIG_BT_CTLR_JIT_SCHEDULING) uint32_t volatile ret_cb; diff --git a/subsys/bluetooth/controller/ll_sw/ull_adv_aux.c b/subsys/bluetooth/controller/ll_sw/ull_adv_aux.c index 907a69b05c7..5349b21dd9f 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_adv_aux.c +++ b/subsys/bluetooth/controller/ll_sw/ull_adv_aux.c @@ -2454,7 +2454,7 @@ uint32_t ull_adv_aux_evt_init(struct ll_adv_aux_set *aux, HAL_TICKER_US_TO_TICKS(EVENT_OVERHEAD_XTAL_US); aux->ull.ticks_preempt_to_start = HAL_TICKER_US_TO_TICKS(EVENT_OVERHEAD_PREEMPT_MIN_US); - aux->ull.ticks_slot = HAL_TICKER_US_TO_TICKS(time_us); + aux->ull.ticks_slot = HAL_TICKER_US_TO_TICKS_CEIL(time_us); if (IS_ENABLED(CONFIG_BT_CTLR_LOW_LAT)) { ticks_slot_overhead = MAX(aux->ull.ticks_active_to_start, @@ -2471,7 +2471,7 @@ uint32_t ull_adv_aux_evt_init(struct ll_adv_aux_set *aux, #if defined(CONFIG_BT_CTLR_ADV_RESERVE_MAX) time_us = ull_adv_aux_time_get(aux, PDU_AC_PAYLOAD_SIZE_MAX, PDU_AC_PAYLOAD_SIZE_MAX); - ticks_slot = HAL_TICKER_US_TO_TICKS(time_us); + ticks_slot = HAL_TICKER_US_TO_TICKS_CEIL(time_us); #else ticks_slot = aux->ull.ticks_slot; #endif @@ -2997,7 +2997,7 @@ static uint8_t aux_time_update(struct ll_adv_aux_set *aux, struct pdu_adv *pdu, uint32_t time_us; time_us = aux_time_min_get(aux); - time_ticks = HAL_TICKER_US_TO_TICKS(time_us); + time_ticks = HAL_TICKER_US_TO_TICKS_CEIL(time_us); #if !defined(CONFIG_BT_CTLR_JIT_SCHEDULING) uint32_t volatile ret_cb; diff --git a/subsys/bluetooth/controller/ll_sw/ull_adv_iso.c b/subsys/bluetooth/controller/ll_sw/ull_adv_iso.c index 765e911b208..89e66ff99e5 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_adv_iso.c +++ b/subsys/bluetooth/controller/ll_sw/ull_adv_iso.c @@ -977,7 +977,7 @@ static uint32_t adv_iso_start(struct ll_adv_iso_set *adv_iso, HAL_TICKER_US_TO_TICKS(EVENT_OVERHEAD_XTAL_US); adv_iso->ull.ticks_preempt_to_start = HAL_TICKER_US_TO_TICKS(EVENT_OVERHEAD_PREEMPT_MIN_US); - adv_iso->ull.ticks_slot = HAL_TICKER_US_TO_TICKS(slot_us); + adv_iso->ull.ticks_slot = HAL_TICKER_US_TO_TICKS_CEIL(slot_us); ticks_slot_offset = MAX(adv_iso->ull.ticks_active_to_start, adv_iso->ull.ticks_prepare_to_start); diff --git a/subsys/bluetooth/controller/ll_sw/ull_adv_sync.c b/subsys/bluetooth/controller/ll_sw/ull_adv_sync.c index 178116a54ec..bbb1b351848 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_adv_sync.c +++ b/subsys/bluetooth/controller/ll_sw/ull_adv_sync.c @@ -1136,7 +1136,7 @@ uint32_t ull_adv_sync_evt_init(struct ll_adv_set *adv, HAL_TICKER_US_TO_TICKS(EVENT_OVERHEAD_XTAL_US); sync->ull.ticks_preempt_to_start = HAL_TICKER_US_TO_TICKS(EVENT_OVERHEAD_PREEMPT_MIN_US); - sync->ull.ticks_slot = HAL_TICKER_US_TO_TICKS(time_us); + sync->ull.ticks_slot = HAL_TICKER_US_TO_TICKS_CEIL(time_us); ticks_slot_offset = MAX(sync->ull.ticks_active_to_start, sync->ull.ticks_prepare_to_start); diff --git a/subsys/bluetooth/controller/ll_sw/ull_central.c b/subsys/bluetooth/controller/ll_sw/ull_central.c index 5effe2ae676..de14395f840 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_central.c +++ b/subsys/bluetooth/controller/ll_sw/ull_central.c @@ -360,13 +360,10 @@ uint8_t ll_create_connection(uint16_t scan_interval, uint16_t scan_window, #endif /* CONFIG_BT_CTLR_ADV_EXT */ #endif /* CONFIG_BT_CTLR_DATA_LENGTH */ - conn->ull.ticks_slot = - HAL_TICKER_US_TO_TICKS(EVENT_OVERHEAD_START_US + - EVENT_OVERHEAD_END_US + - ready_delay_us + - max_tx_time + - EVENT_IFS_US + - max_rx_time); + conn->ull.ticks_slot = HAL_TICKER_US_TO_TICKS_CEIL( + EVENT_OVERHEAD_START_US + EVENT_OVERHEAD_END_US + + ready_delay_us + max_tx_time + EVENT_IFS_US + max_rx_time + + (EVENT_CLOCK_JITTER_US << 1)); #if defined(CONFIG_BT_CTLR_PRIVACY) ull_filter_scan_update(filter_policy); diff --git a/subsys/bluetooth/controller/ll_sw/ull_central_iso.c b/subsys/bluetooth/controller/ll_sw/ull_central_iso.c index 71b8d742a76..2a19e03bde5 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_central_iso.c +++ b/subsys/bluetooth/controller/ll_sw/ull_central_iso.c @@ -559,7 +559,7 @@ uint8_t ll_cig_parameters_commit(uint8_t cig_id, uint16_t *handles) HAL_TICKER_US_TO_TICKS(EVENT_OVERHEAD_XTAL_US); cig->ull.ticks_preempt_to_start = HAL_TICKER_US_TO_TICKS(EVENT_OVERHEAD_PREEMPT_MIN_US); - cig->ull.ticks_slot = HAL_TICKER_US_TO_TICKS(slot_us); + cig->ull.ticks_slot = HAL_TICKER_US_TO_TICKS_CEIL(slot_us); #endif /* !CONFIG_BT_CTLR_JIT_SCHEDULING */ /* Reset params cache */ diff --git a/subsys/bluetooth/controller/ll_sw/ull_conn.c b/subsys/bluetooth/controller/ll_sw/ull_conn.c index 0b54a5dee79..a8d3178e020 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_conn.c +++ b/subsys/bluetooth/controller/ll_sw/ull_conn.c @@ -1257,12 +1257,10 @@ void ull_conn_done(struct node_rx_event_done *done) tx_time = PDU_DC_MAX_US(lll->dle.eff.max_tx_octets, 0); rx_time = PDU_DC_MAX_US(lll->dle.eff.max_rx_octets, 0); #endif /* CONFIG_BT_CTLR_PHY */ - ticks_slot = HAL_TICKER_US_TO_TICKS(EVENT_OVERHEAD_START_US + - ready_delay + - EVENT_IFS_US + - rx_time + - tx_time + - 4); + ticks_slot = HAL_TICKER_US_TO_TICKS_CEIL( + EVENT_OVERHEAD_START_US + EVENT_OVERHEAD_END_US + + ready_delay + EVENT_IFS_US + rx_time + tx_time + + (EVENT_CLOCK_JITTER_US << 1)); if (ticks_slot > conn->ull.ticks_slot) { ticks_slot_plus = ticks_slot - conn->ull.ticks_slot; } else { diff --git a/subsys/bluetooth/controller/ll_sw/ull_conn_iso.c b/subsys/bluetooth/controller/ll_sw/ull_conn_iso.c index 2ee5905b23b..46c00c305fe 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_conn_iso.c +++ b/subsys/bluetooth/controller/ll_sw/ull_conn_iso.c @@ -987,7 +987,7 @@ void ull_conn_iso_start(struct ll_conn *conn, uint16_t cis_handle, HAL_TICKER_US_TO_TICKS(EVENT_OVERHEAD_XTAL_US); cig->ull.ticks_preempt_to_start = HAL_TICKER_US_TO_TICKS(EVENT_OVERHEAD_PREEMPT_MIN_US); - cig->ull.ticks_slot = HAL_TICKER_US_TO_TICKS(slot_us); + cig->ull.ticks_slot = HAL_TICKER_US_TO_TICKS_CEIL(slot_us); } ticks_slot_offset = MAX(cig->ull.ticks_active_to_start, diff --git a/subsys/bluetooth/controller/ll_sw/ull_peripheral.c b/subsys/bluetooth/controller/ll_sw/ull_peripheral.c index f1716c06573..8b813fda9fd 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_peripheral.c +++ b/subsys/bluetooth/controller/ll_sw/ull_peripheral.c @@ -371,13 +371,10 @@ void ull_periph_setup(struct node_rx_hdr *rx, struct node_rx_ftr *ftr, HAL_TICKER_US_TO_TICKS(EVENT_OVERHEAD_XTAL_US); conn->ull.ticks_preempt_to_start = HAL_TICKER_US_TO_TICKS(EVENT_OVERHEAD_PREEMPT_MIN_US); - conn->ull.ticks_slot = - HAL_TICKER_US_TO_TICKS(EVENT_OVERHEAD_START_US + - EVENT_OVERHEAD_END_US + - ready_delay_us + - max_rx_time + - EVENT_IFS_US + - max_tx_time); + conn->ull.ticks_slot = HAL_TICKER_US_TO_TICKS_CEIL( + EVENT_OVERHEAD_START_US + EVENT_OVERHEAD_END_US + + ready_delay_us + max_rx_time + EVENT_IFS_US + max_tx_time + + (EVENT_CLOCK_JITTER_US << 1)); ticks_slot_offset = MAX(conn->ull.ticks_active_to_start, conn->ull.ticks_prepare_to_start); diff --git a/subsys/bluetooth/controller/ll_sw/ull_scan_aux.c b/subsys/bluetooth/controller/ll_sw/ull_scan_aux.c index 26fc6d4806b..316cec7fec7 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_scan_aux.c +++ b/subsys/bluetooth/controller/ll_sw/ull_scan_aux.c @@ -666,12 +666,10 @@ void ull_scan_aux_setup(memq_link_t *link, struct node_rx_hdr *rx) HAL_TICKER_US_TO_TICKS(EVENT_OVERHEAD_XTAL_US); aux->ull.ticks_preempt_to_start = HAL_TICKER_US_TO_TICKS(EVENT_OVERHEAD_PREEMPT_MIN_US); - aux->ull.ticks_slot = - HAL_TICKER_US_TO_TICKS(EVENT_OVERHEAD_START_US + - ready_delay_us + - PDU_AC_MAX_US(PDU_AC_EXT_PAYLOAD_RX_SIZE, - lll_aux->phy) + - EVENT_OVERHEAD_END_US); + aux->ull.ticks_slot = HAL_TICKER_US_TO_TICKS_CEIL( + EVENT_OVERHEAD_START_US + ready_delay_us + + PDU_AC_MAX_US(PDU_AC_EXT_PAYLOAD_RX_SIZE, lll_aux->phy) + + EVENT_OVERHEAD_END_US); ticks_slot_offset = MAX(aux->ull.ticks_active_to_start, aux->ull.ticks_prepare_to_start); diff --git a/subsys/bluetooth/controller/ll_sw/ull_sched.c b/subsys/bluetooth/controller/ll_sw/ull_sched.c index a445d986248..e7ca8a0358b 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_sched.c +++ b/subsys/bluetooth/controller/ll_sw/ull_sched.c @@ -656,7 +656,7 @@ static struct ull_hdr *ull_hdr_get_cb(uint8_t ticker_id, uint32_t *ticks_slot) time_us = ull_adv_aux_time_get(aux, PDU_AC_PAYLOAD_SIZE_MAX, PDU_AC_PAYLOAD_SIZE_MAX); - *ticks_slot = HAL_TICKER_US_TO_TICKS(time_us); + *ticks_slot = HAL_TICKER_US_TO_TICKS_CEIL(time_us); } else { *ticks_slot = aux->ull.ticks_slot; @@ -686,7 +686,7 @@ static struct ull_hdr *ull_hdr_get_cb(uint8_t ticker_id, uint32_t *ticks_slot) uint32_t time_us; time_us = ull_adv_sync_time_get(sync, PDU_AC_PAYLOAD_SIZE_MAX); - *ticks_slot = HAL_TICKER_US_TO_TICKS(time_us); + *ticks_slot = HAL_TICKER_US_TO_TICKS_CEIL(time_us); } else { *ticks_slot = sync->ull.ticks_slot; } @@ -745,9 +745,11 @@ static struct ull_hdr *ull_hdr_get_cb(uint8_t ticker_id, uint32_t *ticks_slot) #endif /* !CONFIG_BT_CTLR_PHY_CODED */ time_us = EVENT_OVERHEAD_START_US + + EVENT_OVERHEAD_END_US + ready_delay_us + max_rx_time + - EVENT_IFS_US + max_tx_time; - *ticks_slot = HAL_TICKER_US_TO_TICKS(time_us); + EVENT_IFS_US + max_tx_time + + (EVENT_CLOCK_JITTER_US << 1); + *ticks_slot = HAL_TICKER_US_TO_TICKS_CEIL(time_us); } else { *ticks_slot = conn->ull.ticks_slot; } diff --git a/subsys/bluetooth/controller/ll_sw/ull_sync.c b/subsys/bluetooth/controller/ll_sw/ull_sync.c index 6c674885810..265475196fd 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_sync.c +++ b/subsys/bluetooth/controller/ll_sw/ull_sync.c @@ -826,12 +826,10 @@ void ull_sync_setup(struct ll_scan_set *scan, struct ll_scan_aux_set *aux, HAL_TICKER_US_TO_TICKS(EVENT_OVERHEAD_XTAL_US); sync->ull.ticks_preempt_to_start = HAL_TICKER_US_TO_TICKS(EVENT_OVERHEAD_PREEMPT_MIN_US); - sync->ull.ticks_slot = - HAL_TICKER_US_TO_TICKS(EVENT_OVERHEAD_START_US + - ready_delay_us + - PDU_AC_MAX_US(PDU_AC_EXT_PAYLOAD_RX_SIZE, - lll->phy) + - EVENT_OVERHEAD_END_US); + sync->ull.ticks_slot = HAL_TICKER_US_TO_TICKS_CEIL( + EVENT_OVERHEAD_START_US + ready_delay_us + + PDU_AC_MAX_US(PDU_AC_EXT_PAYLOAD_RX_SIZE, lll->phy) + + EVENT_OVERHEAD_END_US); ticks_slot_offset = MAX(sync->ull.ticks_active_to_start, sync->ull.ticks_prepare_to_start); diff --git a/subsys/bluetooth/controller/ll_sw/ull_sync_iso.c b/subsys/bluetooth/controller/ll_sw/ull_sync_iso.c index fbacb56f8b4..ff3327ce393 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_sync_iso.c +++ b/subsys/bluetooth/controller/ll_sw/ull_sync_iso.c @@ -509,11 +509,11 @@ void ull_sync_iso_setup(struct ll_sync_iso_set *sync_iso, HAL_TICKER_US_TO_TICKS(EVENT_OVERHEAD_XTAL_US); sync_iso->ull.ticks_preempt_to_start = HAL_TICKER_US_TO_TICKS(EVENT_OVERHEAD_PREEMPT_MIN_US); - sync_iso->ull.ticks_slot = HAL_TICKER_US_TO_TICKS( - EVENT_OVERHEAD_START_US + ready_delay_us + - PDU_BIS_MAX_US(PDU_AC_EXT_PAYLOAD_SIZE_MAX, lll->enc, - lll->phy) + - EVENT_OVERHEAD_END_US); + sync_iso->ull.ticks_slot = HAL_TICKER_US_TO_TICKS_CEIL( + EVENT_OVERHEAD_START_US + ready_delay_us + + PDU_BIS_MAX_US(PDU_AC_EXT_PAYLOAD_SIZE_MAX, lll->enc, + lll->phy) + + EVENT_OVERHEAD_END_US); ticks_slot_offset = MAX(sync_iso->ull.ticks_active_to_start, sync_iso->ull.ticks_prepare_to_start); diff --git a/tests/bluetooth/controller/mock_ctrl/include/hal/ticker_vendor_hal.h b/tests/bluetooth/controller/mock_ctrl/include/hal/ticker_vendor_hal.h index 7c3792d848c..67a46515033 100644 --- a/tests/bluetooth/controller/mock_ctrl/include/hal/ticker_vendor_hal.h +++ b/tests/bluetooth/controller/mock_ctrl/include/hal/ticker_vendor_hal.h @@ -29,6 +29,16 @@ HAL_TICKER_CNTR_MASK \ ) +/* Macro to translate microseconds to tick units. + * NOTE: This returns the ceil value. + */ +#define HAL_TICKER_US_TO_TICKS_CEIL(x) \ + ( \ + ((uint32_t)(((((uint64_t) (x) * 1000000000UL) + \ + HAL_TICKER_CNTR_CLK_UNIT_FS - 1U)) / \ + HAL_TICKER_CNTR_CLK_UNIT_FS)) & \ + HAL_TICKER_CNTR_MASK \ + ) /* Macro to translate tick units to microseconds. */ #define HAL_TICKER_TICKS_TO_US(x) \ From fb5d216e14172be3d897607f7e0928459c3b0dd9 Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Thu, 14 Sep 2023 18:47:25 +0530 Subject: [PATCH 222/421] [nrf fromtree] Bluetooth: Controller: Use defines for femto and pico seconds Use defines for femto and pico seconds in HAL ticker calculations. Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit 34100cb7ea9d398a10281eb76fc97218569f94f1) Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit f1517bc6cf2eec146405fccbd896205cb71f9d6a) --- .../controller/ll_sw/nordic/hal/nrf5/ticker.h | 41 ++++++++++--------- .../ll_sw/openisa/hal/RV32M1/ticker.h | 29 +++++++------ .../mock_ctrl/include/hal/ticker_vendor_hal.h | 29 +++++++------ 3 files changed, 54 insertions(+), 45 deletions(-) diff --git a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/ticker.h b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/ticker.h index f179dbd0035..cbb8ae6a8ce 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/ticker.h +++ b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/ticker.h @@ -5,8 +5,11 @@ * SPDX-License-Identifier: Apache-2.0 */ -#define HAL_TICKER_CNTR_CLK_FREQ_HZ 32768U -#define HAL_TICKER_CNTR_CLK_UNIT_FS 30517578125UL +#define HAL_TICKER_CNTR_CLK_FREQ_HZ 32768U +#define HAL_TICKER_CNTR_CLK_UNIT_FSEC 30517578125UL +#define HAL_TICKER_FSEC_PER_USEC 1000000000UL +#define HAL_TICKER_PSEC_PER_USEC 1000000UL +#define HAL_TICKER_FSEC_PER_PSEC 1000UL /* Macro defining the minimum counter compare offset */ #define HAL_TICKER_CNTR_CMP_OFFSET_MIN 3 @@ -25,8 +28,8 @@ */ #define HAL_TICKER_US_TO_TICKS(x) \ ( \ - ((uint32_t)(((uint64_t) (x) * 1000000000UL) / \ - HAL_TICKER_CNTR_CLK_UNIT_FS)) & \ + ((uint32_t)(((uint64_t) (x) * HAL_TICKER_FSEC_PER_USEC) / \ + HAL_TICKER_CNTR_CLK_UNIT_FSEC)) & \ HAL_TICKER_CNTR_MASK \ ) @@ -35,35 +38,35 @@ */ #define HAL_TICKER_US_TO_TICKS_CEIL(x) \ ( \ - ((uint32_t)(((((uint64_t) (x) * 1000000000UL) + \ - HAL_TICKER_CNTR_CLK_UNIT_FS - 1U)) / \ - HAL_TICKER_CNTR_CLK_UNIT_FS)) & \ + ((uint32_t)(((((uint64_t) (x) * HAL_TICKER_FSEC_PER_USEC) + \ + HAL_TICKER_CNTR_CLK_UNIT_FSEC - 1U)) / \ + HAL_TICKER_CNTR_CLK_UNIT_FSEC)) & \ HAL_TICKER_CNTR_MASK \ ) /* Macro to translate tick units to microseconds. */ #define HAL_TICKER_TICKS_TO_US(x) \ ( \ - ((uint32_t)(((uint64_t)(x) * HAL_TICKER_CNTR_CLK_UNIT_FS) / \ - 1000000000UL)) \ + ((uint32_t)(((uint64_t)(x) * HAL_TICKER_CNTR_CLK_UNIT_FSEC) / \ + HAL_TICKER_FSEC_PER_USEC)) \ ) /* Macro returning remainder in picoseconds (to fit in 32-bits) */ #define HAL_TICKER_REMAINDER(x) \ ( \ ( \ - ((uint64_t) (x) * 1000000000UL) \ + ((uint64_t) (x) * HAL_TICKER_FSEC_PER_USEC) \ - ((uint64_t)HAL_TICKER_US_TO_TICKS(x) * \ - HAL_TICKER_CNTR_CLK_UNIT_FS) \ + HAL_TICKER_CNTR_CLK_UNIT_FSEC) \ ) \ - / 1000UL \ + / HAL_TICKER_FSEC_PER_PSEC \ ) /* Macro defining the remainder resolution/range * ~ 1000000 * HAL_TICKER_TICKS_TO_US(1) */ #define HAL_TICKER_REMAINDER_RANGE \ - HAL_TICKER_TICKS_TO_US(1000000) + HAL_TICKER_TICKS_TO_US(HAL_TICKER_PSEC_PER_USEC) /* Macro defining the margin for positioning re-scheduled nodes */ #define HAL_TICKER_RESCHEDULE_MARGIN \ @@ -74,24 +77,24 @@ static inline void hal_ticker_remove_jitter(uint32_t *ticks, uint32_t *remainder) { /* Is remainder less than 1 us */ - if ((*remainder & BIT(31)) || !(*remainder / 1000000UL)) { + if ((*remainder & BIT(31)) || !(*remainder / HAL_TICKER_PSEC_PER_USEC)) { *ticks -= 1U; - *remainder += HAL_TICKER_CNTR_CLK_UNIT_FS / 1000UL; + *remainder += HAL_TICKER_CNTR_CLK_UNIT_FSEC / HAL_TICKER_FSEC_PER_PSEC; } /* pico seconds to micro seconds unit */ - *remainder /= 1000000UL; + *remainder /= HAL_TICKER_PSEC_PER_USEC; } /* Add ticks and return positive remainder value in microseconds */ static inline void hal_ticker_add_jitter(uint32_t *ticks, uint32_t *remainder) { /* Is remainder less than 1 us */ - if ((*remainder & BIT(31)) || !(*remainder / 1000000UL)) { + if ((*remainder & BIT(31)) || !(*remainder / HAL_TICKER_PSEC_PER_USEC)) { *ticks += 1U; - *remainder += HAL_TICKER_CNTR_CLK_UNIT_FS / 1000UL; + *remainder += HAL_TICKER_CNTR_CLK_UNIT_FSEC / HAL_TICKER_FSEC_PER_PSEC; } /* pico seconds to micro seconds unit */ - *remainder /= 1000000UL; + *remainder /= HAL_TICKER_PSEC_PER_USEC; } diff --git a/subsys/bluetooth/controller/ll_sw/openisa/hal/RV32M1/ticker.h b/subsys/bluetooth/controller/ll_sw/openisa/hal/RV32M1/ticker.h index 1f491739185..78aa6362595 100644 --- a/subsys/bluetooth/controller/ll_sw/openisa/hal/RV32M1/ticker.h +++ b/subsys/bluetooth/controller/ll_sw/openisa/hal/RV32M1/ticker.h @@ -5,8 +5,11 @@ * SPDX-License-Identifier: Apache-2.0 */ -#define HAL_TICKER_CNTR_CLK_FREQ_HZ 32768U -#define HAL_TICKER_CNTR_CLK_UNIT_FS 30517578125UL +#define HAL_TICKER_CNTR_CLK_FREQ_HZ 32768U +#define HAL_TICKER_CNTR_CLK_UNIT_FSEC 30517578125UL +#define HAL_TICKER_FSEC_PER_USEC 1000000000UL +#define HAL_TICKER_PSEC_PER_USEC 1000000UL +#define HAL_TICKER_FSEC_PER_PSEC 1000UL /* Macro defining the minimum counter compare offset */ #define HAL_TICKER_CNTR_CMP_OFFSET_MIN 2 @@ -30,8 +33,8 @@ */ #define HAL_TICKER_US_TO_TICKS(x) \ ( \ - ((uint32_t)(((uint64_t) (x) * 1000000000UL) / \ - HAL_TICKER_CNTR_CLK_UNIT_FS)) & \ + ((uint32_t)(((uint64_t) (x) * HAL_TICKER_FSEC_PER_USEC) / \ + HAL_TICKER_CNTR_CLK_UNIT_FSEC)) & \ HAL_TICKER_CNTR_MASK \ ) @@ -40,35 +43,35 @@ */ #define HAL_TICKER_US_TO_TICKS_CEIL(x) \ ( \ - ((uint32_t)(((((uint64_t) (x) * 1000000000UL) + \ - HAL_TICKER_CNTR_CLK_UNIT_FS - 1U)) / \ - HAL_TICKER_CNTR_CLK_UNIT_FS)) & \ + ((uint32_t)(((((uint64_t) (x) * HAL_TICKER_FSEC_PER_USEC) + \ + HAL_TICKER_CNTR_CLK_UNIT_FSEC - 1U)) / \ + HAL_TICKER_CNTR_CLK_UNIT_FSEC)) & \ HAL_TICKER_CNTR_MASK \ ) /* Macro to translate tick units to microseconds. */ #define HAL_TICKER_TICKS_TO_US(x) \ ( \ - ((uint32_t)(((uint64_t)(x) * HAL_TICKER_CNTR_CLK_UNIT_FS) / \ - 1000000000UL)) \ + ((uint32_t)(((uint64_t)(x) * HAL_TICKER_CNTR_CLK_UNIT_FSEC) / \ + HAL_TICKER_FSEC_PER_USEC)) \ ) /* Macro returning remainder in picoseconds (to fit in 32-bits) */ #define HAL_TICKER_REMAINDER(x) \ ( \ ( \ - ((uint64_t) (x) * 1000000000UL) \ + ((uint64_t) (x) * HAL_TICKER_FSEC_PER_USEC) \ - ((uint64_t)HAL_TICKER_US_TO_TICKS(x) * \ - HAL_TICKER_CNTR_CLK_UNIT_FS) \ + HAL_TICKER_CNTR_CLK_UNIT_FSEC) \ ) \ - / 1000UL \ + / HAL_TICKER_FSEC_PER_PSEC \ ) /* Macro defining the remainder resolution/range * ~ 1000000 * HAL_TICKER_TICKS_TO_US(1) */ #define HAL_TICKER_REMAINDER_RANGE \ - HAL_TICKER_TICKS_TO_US(1000000) + HAL_TICKER_TICKS_TO_US(HAL_TICKER_PSEC_PER_USEC) /* Macro defining the margin for positioning re-scheduled nodes */ #define HAL_TICKER_RESCHEDULE_MARGIN \ diff --git a/tests/bluetooth/controller/mock_ctrl/include/hal/ticker_vendor_hal.h b/tests/bluetooth/controller/mock_ctrl/include/hal/ticker_vendor_hal.h index 67a46515033..c2b20050caa 100644 --- a/tests/bluetooth/controller/mock_ctrl/include/hal/ticker_vendor_hal.h +++ b/tests/bluetooth/controller/mock_ctrl/include/hal/ticker_vendor_hal.h @@ -4,8 +4,11 @@ * SPDX-License-Identifier: Apache-2.0 */ -#define HAL_TICKER_CNTR_CLK_FREQ_HZ 32768U -#define HAL_TICKER_CNTR_CLK_UNIT_FS 30517578125UL +#define HAL_TICKER_CNTR_CLK_FREQ_HZ 32768U +#define HAL_TICKER_CNTR_CLK_UNIT_FSEC 30517578125UL +#define HAL_TICKER_FSEC_PER_USEC 1000000000UL +#define HAL_TICKER_PSEC_PER_USEC 1000000UL +#define HAL_TICKER_FSEC_PER_PSEC 1000UL /* Macro defining the minimum counter compare offset */ #define HAL_TICKER_CNTR_CMP_OFFSET_MIN 3 @@ -24,8 +27,8 @@ */ #define HAL_TICKER_US_TO_TICKS(x) \ ( \ - ((uint32_t)(((uint64_t) (x) * 1000000000UL) / \ - HAL_TICKER_CNTR_CLK_UNIT_FS)) & \ + ((uint32_t)(((uint64_t) (x) * HAL_TICKER_FSEC_PER_USEC) / \ + HAL_TICKER_CNTR_CLK_UNIT_FSEC)) & \ HAL_TICKER_CNTR_MASK \ ) @@ -34,35 +37,35 @@ */ #define HAL_TICKER_US_TO_TICKS_CEIL(x) \ ( \ - ((uint32_t)(((((uint64_t) (x) * 1000000000UL) + \ - HAL_TICKER_CNTR_CLK_UNIT_FS - 1U)) / \ - HAL_TICKER_CNTR_CLK_UNIT_FS)) & \ + ((uint32_t)(((((uint64_t) (x) * HAL_TICKER_FSEC_PER_USEC) + \ + HAL_TICKER_CNTR_CLK_UNIT_FSEC - 1U)) / \ + HAL_TICKER_CNTR_CLK_UNIT_FSEC)) & \ HAL_TICKER_CNTR_MASK \ ) /* Macro to translate tick units to microseconds. */ #define HAL_TICKER_TICKS_TO_US(x) \ ( \ - ((uint32_t)(((uint64_t)(x) * HAL_TICKER_CNTR_CLK_UNIT_FS) / \ - 1000000000UL)) \ + ((uint32_t)(((uint64_t)(x) * HAL_TICKER_CNTR_CLK_UNIT_FSEC) / \ + HAL_TICKER_FSEC_PER_USEC)) \ ) /* Macro returning remainder in picoseconds (to fit in 32-bits) */ #define HAL_TICKER_REMAINDER(x) \ ( \ ( \ - ((uint64_t) (x) * 1000000000UL) \ + ((uint64_t) (x) * HAL_TICKER_FSEC_PER_USEC) \ - ((uint64_t)HAL_TICKER_US_TO_TICKS(x) * \ - HAL_TICKER_CNTR_CLK_UNIT_FS) \ + HAL_TICKER_CNTR_CLK_UNIT_FSEC) \ ) \ - / 1000UL \ + / HAL_TICKER_FSEC_PER_PSEC \ ) /* Macro defining the remainder resolution/range * ~ 1000000 * HAL_TICKER_TICKS_TO_US(1) */ #define HAL_TICKER_REMAINDER_RANGE \ - HAL_TICKER_TICKS_TO_US(1000000) + HAL_TICKER_TICKS_TO_US(HAL_TICKER_PSEC_PER_USEC) /* Macro defining the margin for positioning re-scheduled nodes */ #define HAL_TICKER_RESCHEDULE_MARGIN \ From f5d51232a709225b77d6a2e9bfe25213e74637d5 Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Thu, 14 Sep 2023 19:04:22 +0530 Subject: [PATCH 223/421] [nrf fromtree] Bluetooth: Controller: Use DIV_ROUND_UP macro in HAL ticker Use DIV_ROUND_UP macro in HAL ticker. Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit 5daa864b5e7b21d840b3fdb51c238a009a24c8f1) Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit 96ebab1b3ce374543a83ae745a00418968c534fc) --- subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/ticker.h | 5 ++--- .../bluetooth/controller/ll_sw/openisa/hal/RV32M1/ticker.h | 5 ++--- .../controller/mock_ctrl/include/hal/ticker_vendor_hal.h | 5 ++--- 3 files changed, 6 insertions(+), 9 deletions(-) diff --git a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/ticker.h b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/ticker.h index cbb8ae6a8ce..10d780a559c 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/ticker.h +++ b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/ticker.h @@ -38,9 +38,8 @@ */ #define HAL_TICKER_US_TO_TICKS_CEIL(x) \ ( \ - ((uint32_t)(((((uint64_t) (x) * HAL_TICKER_FSEC_PER_USEC) + \ - HAL_TICKER_CNTR_CLK_UNIT_FSEC - 1U)) / \ - HAL_TICKER_CNTR_CLK_UNIT_FSEC)) & \ + DIV_ROUND_UP(((uint64_t) (x) * HAL_TICKER_FSEC_PER_USEC), \ + HAL_TICKER_CNTR_CLK_UNIT_FSEC) & \ HAL_TICKER_CNTR_MASK \ ) diff --git a/subsys/bluetooth/controller/ll_sw/openisa/hal/RV32M1/ticker.h b/subsys/bluetooth/controller/ll_sw/openisa/hal/RV32M1/ticker.h index 78aa6362595..ab9b14207c1 100644 --- a/subsys/bluetooth/controller/ll_sw/openisa/hal/RV32M1/ticker.h +++ b/subsys/bluetooth/controller/ll_sw/openisa/hal/RV32M1/ticker.h @@ -43,9 +43,8 @@ */ #define HAL_TICKER_US_TO_TICKS_CEIL(x) \ ( \ - ((uint32_t)(((((uint64_t) (x) * HAL_TICKER_FSEC_PER_USEC) + \ - HAL_TICKER_CNTR_CLK_UNIT_FSEC - 1U)) / \ - HAL_TICKER_CNTR_CLK_UNIT_FSEC)) & \ + DIV_ROUND_UP(((uint64_t) (x) * HAL_TICKER_FSEC_PER_USEC), \ + HAL_TICKER_CNTR_CLK_UNIT_FSEC) & \ HAL_TICKER_CNTR_MASK \ ) diff --git a/tests/bluetooth/controller/mock_ctrl/include/hal/ticker_vendor_hal.h b/tests/bluetooth/controller/mock_ctrl/include/hal/ticker_vendor_hal.h index c2b20050caa..8cb4e791a30 100644 --- a/tests/bluetooth/controller/mock_ctrl/include/hal/ticker_vendor_hal.h +++ b/tests/bluetooth/controller/mock_ctrl/include/hal/ticker_vendor_hal.h @@ -37,9 +37,8 @@ */ #define HAL_TICKER_US_TO_TICKS_CEIL(x) \ ( \ - ((uint32_t)(((((uint64_t) (x) * HAL_TICKER_FSEC_PER_USEC) + \ - HAL_TICKER_CNTR_CLK_UNIT_FSEC - 1U)) / \ - HAL_TICKER_CNTR_CLK_UNIT_FSEC)) & \ + DIV_ROUND_UP(((uint64_t) (x) * HAL_TICKER_FSEC_PER_USEC), \ + HAL_TICKER_CNTR_CLK_UNIT_FSEC) & \ HAL_TICKER_CNTR_MASK \ ) From 788c7ff8e63a7ddcd0e7c8850628c29f208e8937 Mon Sep 17 00:00:00 2001 From: Nirosharn Amarasinghe Date: Fri, 30 Jun 2023 09:17:36 +0200 Subject: [PATCH 224/421] [nrf fromtree] Bluetooth: controller: Use consecutive event for framed TX and RX bugfix Changes: -- Disregards target event after segmenting the first TX SDU and instead decide event based on the next payload and feasibility to fragment for that event (time-offset > 0) -- Corrected error SDU release logic when an error occurs while expecting the start of a new SDU, to avoid releasing an SDU which could be received in the next payload or event -- Included additional debug logging Signed-off-by: Nirosharn Amarasinghe (cherry picked from commit e318a3032b0d09ef9439b2a9b1c792a3cae203d6) Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit 40fdecb4fc18d92b4425101a0f6de873ff001a36) --- subsys/bluetooth/controller/ll_sw/isoal.c | 408 +++++++++++++++------- subsys/bluetooth/controller/ll_sw/isoal.h | 4 +- 2 files changed, 292 insertions(+), 120 deletions(-) diff --git a/subsys/bluetooth/controller/ll_sw/isoal.c b/subsys/bluetooth/controller/ll_sw/isoal.c index 0a500cfd05e..110a7aa901e 100644 --- a/subsys/bluetooth/controller/ll_sw/isoal.c +++ b/subsys/bluetooth/controller/ll_sw/isoal.c @@ -50,6 +50,11 @@ LOG_MODULE_REGISTER(bt_ctlr_isoal, LOG_LEVEL_INF); (s == ISOAL_CONTINUE ? "CONTINUE" : \ (s == ISOAL_ERR_SPOOL ? "ERR SPOOL" : "???"))) +#define STATE_TO_STR(s) (s == BT_ISO_SINGLE ? "SINGLE" : \ + (s == BT_ISO_START ? "START" : \ + (s == BT_ISO_CONT ? "CONT" : \ + (s == BT_ISO_END ? "END" : "???")))) + #if defined(CONFIG_BT_CTLR_ADV_ISO) || defined(CONFIG_BT_CTLR_CONN_ISO) /* Given the minimum payload, this defines the minimum number of bytes that * should be remaining in a TX PDU such that it would make inserting a new @@ -186,7 +191,7 @@ static bool isoal_get_time_diff(uint32_t time_before, uint32_t time_after, uint3 #define SET_RX_SDU_TIMESTAMP(_sink, _timestamp, _value) \ _timestamp = _value; \ - ISOAL_LOG_DBGV("[%p] %s updated (%ld)", _sink, #_timestamp, _value); + ISOAL_LOG_DBGV("[%p] %s updated (%lu)", _sink, #_timestamp, _value); static void isoal_rx_framed_update_sdu_release(struct isoal_sink *sink); @@ -415,7 +420,7 @@ static isoal_status_t isoal_rx_allocate_sdu(struct isoal_sink *sink, ); if (err == ISOAL_STATUS_OK) { - sp->sdu_allocated = true; + sp->sdu_allocated = 1U; } /* Nothing has been written into buffer yet */ @@ -599,7 +604,7 @@ static isoal_status_t isoal_rx_try_emit_sdu(struct isoal_sink *sink, bool end_of sdu->status = sp->sdu_status; err = isoal_rx_buffered_emit_sdu(sink, end_of_sdu); - sp->sdu_allocated = false; + sp->sdu_allocated = 0U; if (end_of_sdu) { isoal_rx_framed_update_sdu_release(sink); @@ -729,9 +734,9 @@ static isoal_status_t isoal_rx_unframed_consume(struct isoal_sink *sink, next_state = ISOAL_START; /* If status is not ISOAL_PDU_STATUS_VALID, length and LLID cannot be trusted */ - llid = pdu_meta->pdu->ll_id; + llid = pdu->ll_id; pdu_err = (pdu_meta->meta->status != ISOAL_PDU_STATUS_VALID); - length = pdu_meta->pdu->len; + length = pdu->len; /* A zero length PDU with LLID 0b01 (PDU_BIS_LLID_START_CONTINUE) would be a padding PDU. * However if there are errors in the PDU, it could be an incorrectly receive non-padding * PDU. Therefore only consider a PDU with errors as padding if received after the end @@ -937,7 +942,7 @@ static isoal_status_t isoal_rx_unframed_consume(struct isoal_sink *sink, sp->prev_pdu_is_end = !pdu_err && llid == PDU_BIS_LLID_COMPLETE_END; sp->prev_pdu_is_padding = !pdu_err && pdu_padding; - sp->initialized = true; + sp->initialized = 1U; return err; } @@ -1293,6 +1298,8 @@ static isoal_status_t isoal_rx_framed_consume(struct isoal_sink *sink, } if (pdu_err || seq_err || seg_err) { + bool error_sdu_pending = false; + /* When one or more ISO Data PDUs are not received, the receiving device may * discard all SDUs affected by the missing PDUs. Any partially received SDU * may also be discarded. @@ -1321,14 +1328,28 @@ static isoal_status_t isoal_rx_framed_consume(struct isoal_sink *sink, switch (sp->fsm) { case ISOAL_START: - /* First release lost SDUs and then release a new SDU - * with errors. Since we have an SDU to release - * following any lost SDUs, lost SDUs handling should be - * similar to when a valid timestamp exists. + /* If errors occur while waiting for the start of an SDU + * then an SDU should should only be released if there + * is confirmation that a reception occurred + * unsuccessfully. In the case of STATUS_LOST_DATA which + * could result from a flush, an SDU should not be + * released as the flush does not necessarily mean that + * part of an SDU has been lost. In this case Lost SDU + * release defaults to the lost SDU detection based on + * the SDU interval. If we have a SDU to release + * following any lost SDUs, lost SDU handling should be + * similar to when a valid timestamp for the next SDU + * exists. */ - err |= isoal_rx_framed_release_lost_sdus(sink, pdu_meta, true, timestamp); - sp->sdu_status = next_sdu_status; - err |= isoal_rx_append_to_sdu(sink, pdu_meta, 0, 0, true, false); + error_sdu_pending = seg_err || + (pdu_err && meta->status == ISOAL_SDU_STATUS_ERRORS); + err |= isoal_rx_framed_release_lost_sdus(sink, pdu_meta, + error_sdu_pending, timestamp); + + if (error_sdu_pending) { + sp->sdu_status = next_sdu_status; + err |= isoal_rx_append_to_sdu(sink, pdu_meta, 0, 0, true, false); + } break; case ISOAL_CONTINUE: @@ -1339,11 +1360,13 @@ static isoal_status_t isoal_rx_framed_consume(struct isoal_sink *sink, */ sp->sdu_status = next_sdu_status; err |= isoal_rx_append_to_sdu(sink, pdu_meta, 0, 0, true, false); - err |= isoal_rx_framed_release_lost_sdus(sink, pdu_meta, false, timestamp); + err |= isoal_rx_framed_release_lost_sdus(sink, pdu_meta, + error_sdu_pending, timestamp); break; case ISOAL_ERR_SPOOL: - err |= isoal_rx_framed_release_lost_sdus(sink, pdu_meta, false, timestamp); + err |= isoal_rx_framed_release_lost_sdus(sink, pdu_meta, + error_sdu_pending, timestamp); break; } @@ -1353,7 +1376,7 @@ static isoal_status_t isoal_rx_framed_consume(struct isoal_sink *sink, } sp->prev_pdu_id = meta->payload_number; - sp->initialized = true; + sp->initialized = 1U; return err; } @@ -1610,6 +1633,10 @@ static isoal_status_t isoal_tx_pdu_emit(const struct isoal_source *source_ctx, /* Attempt to enqueue the node towards the LL */ status = source_ctx->session.pdu_emit(node_tx, handle); + ISOAL_LOG_DBG("[%p] PDU %llu err=%X len=%u frags=%u released", + source_ctx, node_tx->payload_count, status, + produced_pdu->contents.pdu->len, sdu_fragments); + if (status != ISOAL_STATUS_OK) { /* If it fails, the node will be released and no further attempt * will be possible @@ -1666,6 +1693,7 @@ static isoal_status_t isoal_tx_allocate_pdu(struct isoal_source *source, /* Nothing has been written into buffer yet */ pp->pdu_written = 0; pp->pdu_available = available_len; + pp->pdu_allocated = 1U; LL_ASSERT(available_len > 0); pp->pdu_cnt++; @@ -1708,6 +1736,7 @@ static isoal_status_t isoal_tx_try_emit_pdu(struct isoal_source *source, pp->pdu_written); pp->payload_number++; pp->sdu_fragments = 0; + pp->pdu_allocated = 0U; } return err; @@ -1751,7 +1780,7 @@ uint16_t isoal_tx_unframed_get_next_payload_number(isoal_source_handle_t source_ time_diff = 0; /* Adjust payload number */ - if (IS_ENABLED(CONFIG_BT_CTLR_ISOAL_SN_STRICT) && session->sn) { + if (IS_ENABLED(CONFIG_BT_CTLR_ISOAL_SN_STRICT) && pp->initialized) { /* Not the first SDU in this session, so reference * information should be valid. At this point, the * current payload number should be at the first PDU of @@ -1806,15 +1835,26 @@ uint16_t isoal_tx_unframed_get_next_payload_number(isoal_source_handle_t source_ return sdus_skipped; } -/* NOTE: Use of target_event and grp_ref_point as input from upper layer. +/** + * @brief Fragment received SDU and produce unframed PDUs + * @details Destination source may have an already partially built PDU * - * For unframed: + * @param source_hdl[in] Destination source handle + * @param tx_sdu[in] SDU with packet boundary information + * + * @return Status + * + * @note + * PSN in SDUs for unframed TX: + * + * @par * Before the modification to use the PSN to decide the position of an SDU in a * stream of SDU, the target event was what was used in deciding the event for * each SDU. This meant that there would possibly have been skews on the - * receiver for each SDU and we had trouble with LL/CIS/PER/BV-39-C which + * receiver for each SDU and there were problems with LL/CIS/PER/BV-39-C which * expects clustering within an event. * + * @par * After the change, the PSN is used to decide the position of an SDU in the * stream anchored at the first PSN received. However for the first SDU * (assume that PSN=0), it will be the target event that decides which event @@ -1823,6 +1863,7 @@ uint16_t isoal_tx_unframed_get_next_payload_number(isoal_source_handle_t source_ * impacts the event chosen for the first SDU and all subsequent SDUs will be * decided relative to the first. * + * @par * The target event and related group reference point is still used to provide * the ISO-AL with a notion of time, for example when storing information * required for the TX Sync command. For example if for PSN 4, target event is @@ -1832,26 +1873,17 @@ uint16_t isoal_tx_unframed_get_next_payload_number(isoal_source_handle_t source_ * for event 7. It is also expected that this value is the latest reference and * is drift compensated. * - * The PSN alone is not sufficient for this because as far as I am aware, host - * and controller have no common reference time for when CIG/BIG event 0 starts. - * Therefore I would expect it is possible to receive PSN 0 in event 2 for - * example. If the target event provided is event 3, then PSN 0 will be - * fragmented into payloads for event 3 and that will serve as the anchor for - * the stream and subsequent SDUs. If for example target event provided was - * event 2 instead, then it could very well be that PSN 0 might not be - * transmitted as is was received midway through event 2 and the payloads - * expired. If this happens then subsequent SDUs might also all be late for - * their transmission slots as they are positioned relative to PSN 0. - */ - -/** - * @brief Fragment received SDU and produce unframed PDUs - * @details Destination source may have an already partially built PDU - * - * @param source_hdl[in] Destination source handle - * @param tx_sdu[in] SDU with packet boundary information - * - * @return Status + * @par + * The PSN alone is not sufficient for this because host and controller have no + * common reference time for when CIG / BIG event 0 starts. Therefore it is + * expected that it is possible to receive PSN 0 in event 2 for example. If the + * target event provided is event 3, then PSN 0 will be fragmented into payloads + * for event 3 and that will serve as the anchor for the stream and subsequent + * SDUs. If for example target event provided was event 2 instead, then it could + * very well be that PSN 0 might not be transmitted as is was received midway + * through event 2 and the payloads expired. If this happens then subsequent + * SDUs might also all be late for their transmission slots as they are + * positioned relative to PSN 0. */ static isoal_status_t isoal_tx_unframed_produce(isoal_source_handle_t source_hdl, const struct isoal_sdu_tx *tx_sdu) @@ -1881,7 +1913,6 @@ static isoal_status_t isoal_tx_unframed_produce(isoal_source_handle_t source_hdl if (tx_sdu->sdu_state == BT_ISO_START || tx_sdu->sdu_state == BT_ISO_SINGLE) { - /* Initialize to info provided in SDU */ uint32_t actual_grp_ref_point; uint64_t next_payload_number; uint16_t sdus_skipped; @@ -2062,6 +2093,8 @@ static isoal_status_t isoal_tx_unframed_produce(isoal_source_handle_t source_hdl zero_length_sdu = false; } + pp->initialized = 1U; + return err; } @@ -2126,6 +2159,9 @@ static isoal_status_t isoal_insert_seg_header_timeoffset(struct isoal_source *so pp->pdu_written += write_size; pp->pdu_available -= write_size; + ISOAL_LOG_DBGV("[%p] Seg header write size=%u sc=%u cmplt=%u TO=%u len=%u", + source, write_size, sc, cmplt, time_offset, seg_hdr.len); + return err; } @@ -2163,6 +2199,155 @@ static isoal_status_t isoal_update_seg_header_cmplt_length(struct isoal_source * pp->last_seg_hdr_loc, (uint8_t *) &seg_hdr, PDU_ISO_SEG_HDR_SIZE); + + ISOAL_LOG_DBGV("[%p] Seg header write size=%u sc=%u cmplt=%u len=%u", + source, PDU_ISO_SEG_HDR_SIZE, seg_hdr.sc, cmplt, seg_hdr.len); +} + +/** + * Find the earliest feasible event for transmission capacity is not wasted and + * return information based on that event. + * @param[in] source_hdl Destination source handle + * @param[in] tx_sdu SDU with meta data information + * @param[out] payload_number Updated payload number for the selected event + * @param[out] grp_ref_point Group reference point for the selected event + * @param[out] time_offset Segmentation Time offset to selected event + * @return The number SDUs skipped from the last + */ +static uint16_t isoal_tx_framed_find_correct_tx_event(isoal_source_handle_t source_hdl, + const struct isoal_sdu_tx *tx_sdu, + uint64_t *payload_number, + uint32_t *grp_ref_point, + uint32_t *time_offset) +{ + struct isoal_source_session *session; + struct isoal_pdu_production *pp; + uint32_t actual_grp_ref_point; + uint64_t next_payload_number; + struct isoal_source *source; + uint16_t sdus_skipped; + uint64_t actual_event; + bool time_diff_valid; + uint32_t time_diff; + + source = &isoal_global.source_state[source_hdl]; + session = &source->session; + pp = &source->pdu_production; + + sdus_skipped = 0; + + /* Continue with the current payload unless there is need to change */ + next_payload_number = pp->payload_number; + actual_event = pp->payload_number / session->burst_number; + + ISOAL_LOG_DBGV("[%p] Start PL=%llu Evt=%lu.", source, next_payload_number, actual_event); + + /* Get the drift updated group reference point for this event based on + * the actual event being set. This might introduce some errors as the + * group refernce point for future events could drift. However as the + * time offset calculation requires an absolute value, this seems to be + * the best candidate. + */ + if (actual_event != tx_sdu->target_event) { + actual_grp_ref_point = isoal_get_wrapped_time_us(tx_sdu->grp_ref_point, + ((actual_event - tx_sdu->target_event) * session->iso_interval * + ISO_INT_UNIT_US)); + } else { + actual_grp_ref_point = tx_sdu->grp_ref_point; + } + + ISOAL_LOG_DBGV("[%p] Current PL=%llu Evt=%llu Ref=%lu", + source, next_payload_number, actual_event, actual_grp_ref_point); + + if (tx_sdu->sdu_state == BT_ISO_START || + tx_sdu->sdu_state == BT_ISO_SINGLE) { + /* Start of a new SDU */ + + /* Adjust payload number */ + if (pp->initialized) { + /* Not the first SDU in this session, so reference + * information should be valid. . + */ + time_diff_valid = isoal_get_time_diff(session->last_input_time_stamp, + tx_sdu->time_stamp, + &time_diff); + + /* Priority is given to the sequence number */ + if (tx_sdu->packet_sn > session->last_input_sn + 1) { + ISOAL_LOG_DBGV("[%p] Using packet_sn for skipped SDUs", source); + sdus_skipped = (tx_sdu->packet_sn - session->last_input_sn) - 1; + + } else if (tx_sdu->packet_sn == session->last_input_sn && + time_diff_valid && time_diff > session->sdu_interval) { + ISOAL_LOG_DBGV("[%p] Using time_stamp for skipped SDUs", source); + /* Round at mid-point */ + sdus_skipped = ((time_diff + (session->sdu_interval / 2)) / + session->sdu_interval) - 1; + } else { + /* SDU is next in sequence */ + } + + } else { + /* First SDU, align with target event */ + actual_event = tx_sdu->target_event; + actual_grp_ref_point = tx_sdu->grp_ref_point; + + ISOAL_LOG_DBGV("[%p] Use target_event", source); + } + + /* Selecting the event for transmission is done solely based on + * the time stamp and the ability to calculate a valid time + * offset. + */ + + /* Check if time stamp on packet is later than the group + * reference point and find next feasible event for transmission. + * + * BT Core V5.3 : Vol 6 Low Energy Controller : Part G IS0-AL: + * 3.1 Time_Offset in framed PDUs : + * The Time_Offset shall be a positive value. + */ + while (!isoal_get_time_diff(tx_sdu->time_stamp, actual_grp_ref_point, &time_diff) || + time_diff == 0) { + /* Advance target to next event */ + actual_event++; + actual_grp_ref_point = isoal_get_wrapped_time_us(actual_grp_ref_point, + session->iso_interval * ISO_INT_UNIT_US); + } + + ISOAL_LOG_DBGV("[%p] Chosen PL=%llu Evt=%llu Ref=%lu", + source, (actual_event * session->burst_number), actual_event, + actual_grp_ref_point); + + /* If the event selected is the last event segmented for, then + * it is possible that that some payloads have already been + * released for this event. Segmentation should continue from + * that payload. + */ + next_payload_number = MAX(pp->payload_number, + (actual_event * session->burst_number)); + } + + ISOAL_LOG_DBGV("[%p] Final Evt=%llu (PL=%llu) Ref.=%lu Next PL=%llu", + source, actual_event, (actual_event * session->burst_number), + actual_grp_ref_point, next_payload_number); + + /* Calculate the time offset */ + time_diff_valid = isoal_get_time_diff(tx_sdu->time_stamp, + actual_grp_ref_point, &time_diff); + + LL_ASSERT(time_diff_valid); + LL_ASSERT(time_diff > 0); + /* Time difference must be less than the maximum possible + * time-offset of 24-bits. + */ + LL_ASSERT(time_diff <= 0x00FFFFFF); + + *payload_number = next_payload_number; + *grp_ref_point = actual_grp_ref_point; + *time_offset = time_diff; + + return sdus_skipped; } /** @@ -2186,7 +2371,6 @@ static isoal_status_t isoal_tx_framed_produce(isoal_source_handle_t source_hdl, bool zero_length_sdu; isoal_status_t err; bool padding_pdu; - uint8_t ll_id; source = &isoal_global.source_state[source_hdl]; session = &source->session; @@ -2202,15 +2386,53 @@ static isoal_status_t isoal_tx_framed_produce(isoal_source_handle_t source_hdl, zero_length_sdu = (packet_available == 0 && tx_sdu->sdu_state == BT_ISO_SINGLE); + ISOAL_LOG_DBGV("[%p] SDU %u len=%u TS=%lu Ref=%lu Evt=%llu Frag=%u", + source, tx_sdu->packet_sn, tx_sdu->iso_sdu_length, tx_sdu->time_stamp, + tx_sdu->grp_ref_point, tx_sdu->target_event, tx_sdu->sdu_state); + if (tx_sdu->sdu_state == BT_ISO_START || tx_sdu->sdu_state == BT_ISO_SINGLE) { + uint32_t actual_grp_ref_point; + uint64_t next_payload_number; + uint16_t sdus_skipped; + /* Start of a new SDU */ - /* Initialize to info provided in SDU */ - uint32_t actual_grp_ref_point = tx_sdu->grp_ref_point; - uint64_t actual_event = tx_sdu->target_event; - bool time_diff_valid = false; - uint32_t time_diff = 0; + /* Find the best transmission event */ + sdus_skipped = isoal_tx_framed_find_correct_tx_event(source_hdl, tx_sdu, + &next_payload_number, + &actual_grp_ref_point, + &time_offset); + + ISOAL_LOG_DBGV("[%p] %u SDUs skipped.", source, sdus_skipped); + ISOAL_LOG_DBGV("[%p] Starting SDU %u PL=(%llu->%llu) Grp Ref=%lu TO=%lu", + source, tx_sdu->packet_sn, pp->payload_number, next_payload_number, + actual_grp_ref_point, time_offset); + + + if (next_payload_number > pp->payload_number) { + /* Moving to a new payload */ + if (pp->pdu_allocated) { + /* Current PDU in production should be released before + * moving to new event. + */ + ISOAL_LOG_DBGV("[%p] Pending PDU released.\n"); + err |= isoal_tx_try_emit_pdu(source, true, PDU_BIS_LLID_FRAMED); + } + + while (err == ISOAL_STATUS_OK && next_payload_number > pp->payload_number && + (pp->payload_number % session->burst_number)) { + /* Release padding PDUs for this event */ + err |= isoal_tx_allocate_pdu(source, tx_sdu); + err |= isoal_tx_try_emit_pdu(source, true, PDU_BIS_LLID_FRAMED); + } + } + + /* Reset PDU production state */ + pp->pdu_state = BT_ISO_START; + + /* Update to new payload number */ + pp->payload_number = next_payload_number; /* Update sequence number for received SDU * @@ -2224,67 +2446,8 @@ static isoal_status_t isoal_tx_framed_produce(isoal_source_handle_t source_hdl, * with the sequence number in the ISOAL once the Datapath is * configured and the link is established. */ - session->sn++; - - /* Reset PDU production state */ - pp->pdu_state = BT_ISO_START; - - /* Update payload counter in case time has passed since the last - * SDU. This should mean that event count * burst number should - * be greater than the current payload number. In the event of - * an SDU interval smaller than the ISO interval, multiple SDUs - * will be sent in the same event. As such the current payload - * number should be retained. Payload numbers are indexed at 0 - * and valid until the PDU is emitted. - */ - pp->payload_number = MAX(pp->payload_number, - (tx_sdu->target_event * session->burst_number)); - - /* Get actual event for this payload number */ - actual_event = pp->payload_number / session->burst_number; - - /* Get group reference point for this PDU based on the actual - * event being set. This might introduce some errors as the - * group refernce point for future events could drift. However - * as the time offset calculation requires an absolute value, - * this seems to be the best candidate. - */ - if (actual_event > tx_sdu->target_event) { - actual_grp_ref_point = isoal_get_wrapped_time_us(tx_sdu->grp_ref_point, - ((actual_event - tx_sdu->target_event) * session->iso_interval * - ISO_INT_UNIT_US)); - } - - /* Check if time stamp on packet is later than the group - * reference point and adjust targets. This could happen if the - * SDU has been time-stampped at the controller when received - * via HCI. - * - * BT Core V5.3 : Vol 6 Low Energy Controller : Part G IS0-AL: - * 3.1 Time_Offset in framed PDUs : - * The Time_Offset shall be a positive value. - */ - if (!isoal_get_time_diff(tx_sdu->time_stamp, actual_grp_ref_point, &time_diff) || - time_diff == 0) { - /* Advance target to next event */ - actual_event++; - actual_grp_ref_point = isoal_get_wrapped_time_us(actual_grp_ref_point, - session->iso_interval * ISO_INT_UNIT_US); - - /* Set payload number */ - pp->payload_number = actual_event * session->burst_number; - } - /* Calculate the time offset */ - time_diff_valid = isoal_get_time_diff(tx_sdu->time_stamp, - actual_grp_ref_point, &time_diff); - LL_ASSERT(time_diff_valid); - LL_ASSERT(time_diff > 0); - /* Time difference must be less than the maximum possible - * time-offset of 24-bits. - */ - LL_ASSERT(time_diff <= 0x00FFFFFF); - time_offset = time_diff; + session->sn += sdus_skipped + 1; /* Store timing info for TX Sync command */ session->tx_time_stamp = actual_grp_ref_point; @@ -2292,6 +2455,10 @@ static isoal_status_t isoal_tx_framed_produce(isoal_source_handle_t source_hdl, /* Reset PDU fragmentation count for this SDU */ pp->pdu_cnt = 0; + + /* Update input packet number and time stamp */ + session->last_input_sn = tx_sdu->packet_sn; + session->last_input_time_stamp = tx_sdu->time_stamp; } /* PDUs should be created until the SDU fragment has been fragmented or if @@ -2305,6 +2472,7 @@ static isoal_status_t isoal_tx_framed_produce(isoal_source_handle_t source_hdl, err |= err_alloc; + ISOAL_LOG_DBGV("[%p] State %s", source, STATE_TO_STR(pp->pdu_state)); if (pp->pdu_state == BT_ISO_START) { /* Start of a new SDU. Segmentation header and time-offset * should be inserted. @@ -2366,15 +2534,13 @@ static isoal_status_t isoal_tx_framed_produce(isoal_source_handle_t source_hdl, /* Update complete flag in last segmentation header */ err |= isoal_update_seg_header_cmplt_length(source, end_of_sdu, consume_len); - /* LLID is fixed for framed PDUs */ - ll_id = PDU_BIS_LLID_FRAMED; - /* If there isn't sufficient usable space then release the * PDU when the end of the SDU is reached, instead of waiting * for the next SDU. */ bool release_pdu = end_of_sdu && (pp->pdu_available <= ISOAL_TX_SEGMENT_MIN_SIZE); - const isoal_status_t err_emit = isoal_tx_try_emit_pdu(source, release_pdu, ll_id); + const isoal_status_t err_emit = isoal_tx_try_emit_pdu(source, release_pdu, + PDU_BIS_LLID_FRAMED); err |= err_emit; @@ -2392,6 +2558,8 @@ static isoal_status_t isoal_tx_framed_produce(isoal_source_handle_t source_hdl, zero_length_sdu = false; } + pp->initialized = 1U; + return err; } @@ -2424,9 +2592,9 @@ static isoal_status_t isoal_tx_framed_event_prepare_handle(isoal_source_handle_t first_event_payload = (session->burst_number * event_count); last_event_payload = (session->burst_number * (event_count + 1ULL)) - 1ULL; - if (pp->pdu_available > 0 && - pp->payload_number <= last_event_payload) { + if (pp->pdu_allocated && pp->payload_number <= last_event_payload) { /* Pending PDU that should be released for framed TX */ + ISOAL_LOG_DBGV("[%p] Prepare PDU released.", source); err = isoal_tx_try_emit_pdu(source, true, PDU_BIS_LLID_FRAMED); } @@ -2462,6 +2630,7 @@ static isoal_status_t isoal_tx_framed_event_prepare_handle(isoal_source_handle_t if (release_padding) { while (!err && !err_alloc && (pp->payload_number < last_event_payload + 1ULL)) { + ISOAL_LOG_DBGV("[%p] Prepare padding PDU release.", source); err_alloc = isoal_tx_allocate_pdu(source, NULL); err = isoal_tx_try_emit_pdu(source, true, PDU_BIS_LLID_FRAMED); @@ -2473,6 +2642,7 @@ static isoal_status_t isoal_tx_framed_event_prepare_handle(isoal_source_handle_t if (pp->payload_number < last_event_payload + 1ULL) { pp->payload_number = last_event_payload + 1ULL; + ISOAL_LOG_DBGV("[%p] Prepare PL updated to %lu.", source, pp->payload_number); } return err; @@ -2500,7 +2670,7 @@ isoal_status_t isoal_tx_sdu_fragment(isoal_source_handle_t source_hdl, /* Set source context active to mutually exclude ISO Event prepare * kick. */ - source->context_active = true; + source->context_active = 1U; if (source->pdu_production.mode != ISOAL_PRODUCTION_MODE_DISABLED) { /* BT Core V5.3 : Vol 6 Low Energy Controller : Part G IS0-AL: @@ -2520,11 +2690,12 @@ isoal_status_t isoal_tx_sdu_fragment(isoal_source_handle_t source_hdl, } } - source->context_active = false; + source->context_active = 0U; if (source->timeout_trigger) { - source->timeout_trigger = false; + source->timeout_trigger = 0U; if (session->framed) { + ISOAL_LOG_DBGV("[%p] Prepare cb flag trigger", source); isoal_tx_framed_event_prepare_handle(source_hdl, source->timeout_event_count); } @@ -2599,13 +2770,14 @@ void isoal_tx_event_prepare(isoal_source_handle_t source_hdl, * is active. */ source->timeout_event_count = event_count; - source->timeout_trigger = true; + source->timeout_trigger = 1U; if (source->context_active) { return; } - source->timeout_trigger = false; + source->timeout_trigger = 0U; if (session->framed) { + ISOAL_LOG_DBGV("[%p] Prepare call back", source); isoal_tx_framed_event_prepare_handle(source_hdl, event_count); } } diff --git a/subsys/bluetooth/controller/ll_sw/isoal.h b/subsys/bluetooth/controller/ll_sw/isoal.h index 44f3504f1a6..cc69e4a5d53 100644 --- a/subsys/bluetooth/controller/ll_sw/isoal.h +++ b/subsys/bluetooth/controller/ll_sw/isoal.h @@ -376,8 +376,6 @@ struct isoal_source_session { uint8_t burst_number; uint8_t pdus_per_sdu; uint8_t max_pdu_size; - int32_t latency_unframed; - int32_t latency_framed; }; struct isoal_pdu_production { @@ -392,6 +390,8 @@ struct isoal_pdu_production { uint64_t seg_hdr_sc:1; uint64_t seg_hdr_length:8; uint64_t sdu_fragments:8; + uint64_t initialized:1; + uint64_t pdu_allocated:1; isoal_pdu_len_t pdu_written; isoal_pdu_len_t pdu_available; /* Location (byte index) of last segmentation header */ From 1fd74b1654859ac2f7c936a6b855667ef34184b2 Mon Sep 17 00:00:00 2001 From: Nirosharn Amarasinghe Date: Fri, 14 Jul 2023 16:57:37 +0200 Subject: [PATCH 225/421] [nrf fromtree] Bluetooth: controller: corrected time-offset for endianness Changes: -- Corrected reading and writing time offset in framed segment header to account for endianness -- Corrected bit positioning of time offset bit field in the segment header structure definition -- Fixed upstream Zephyr BSIM test build failure due to debug logging 39-bit variable Signed-off-by: Nirosharn Amarasinghe (cherry picked from commit 31df0ef80b50cad0cd28cac82888b49eaf80ee2b) Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit e0122d75a70d7e584f0063d6554fde096e102e77) --- subsys/bluetooth/controller/ll_sw/isoal.c | 12 +++++++----- subsys/bluetooth/controller/ll_sw/pdu.h | 2 +- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/subsys/bluetooth/controller/ll_sw/isoal.c b/subsys/bluetooth/controller/ll_sw/isoal.c index 110a7aa901e..00bc40504f7 100644 --- a/subsys/bluetooth/controller/ll_sw/isoal.c +++ b/subsys/bluetooth/controller/ll_sw/isoal.c @@ -16,6 +16,8 @@ #include #include +#include + #include "util/memq.h" #include "hal/ccm.h" @@ -1158,7 +1160,7 @@ static isoal_status_t isoal_rx_framed_consume(struct isoal_sink *sink, case ISOAL_START: if (!sc) { /* Start segment, included time-offset */ - timeoffset = seg_hdr->timeoffset; + timeoffset = sys_le24_to_cpu(seg_hdr->timeoffset); anchorpoint = meta->timestamp; latency = session->sdu_sync_const; timestamp = isoal_get_wrapped_time_us(anchorpoint, @@ -1215,7 +1217,7 @@ static isoal_status_t isoal_rx_framed_consume(struct isoal_sink *sink, if (!sc) { /* Start segment, included time-offset */ - timeoffset = seg_hdr->timeoffset; + timeoffset = sys_le24_to_cpu(seg_hdr->timeoffset); anchorpoint = meta->timestamp; latency = session->sdu_sync_const; timestamp = isoal_get_wrapped_time_us(anchorpoint, @@ -1634,7 +1636,7 @@ static isoal_status_t isoal_tx_pdu_emit(const struct isoal_source *source_ctx, status = source_ctx->session.pdu_emit(node_tx, handle); ISOAL_LOG_DBG("[%p] PDU %llu err=%X len=%u frags=%u released", - source_ctx, node_tx->payload_count, status, + source_ctx, payload_number, status, produced_pdu->contents.pdu->len, sdu_fragments); if (status != ISOAL_STATUS_OK) { @@ -2479,7 +2481,7 @@ static isoal_status_t isoal_tx_framed_produce(isoal_source_handle_t source_hdl, */ err |= isoal_insert_seg_header_timeoffset(source, false, false, - time_offset); + sys_cpu_to_le24(time_offset)); pp->pdu_state = BT_ISO_CONT; } else if (!padding_pdu && pp->pdu_state == BT_ISO_CONT && pp->pdu_written == 0) { /* Continuing an SDU in a new PDU. Segmentation header @@ -2487,7 +2489,7 @@ static isoal_status_t isoal_tx_framed_produce(isoal_source_handle_t source_hdl, */ err |= isoal_insert_seg_header_timeoffset(source, true, false, - 0); + sys_cpu_to_le24(0)); } /* diff --git a/subsys/bluetooth/controller/ll_sw/pdu.h b/subsys/bluetooth/controller/ll_sw/pdu.h index ceeb9ca12e7..93e50e1ebcc 100644 --- a/subsys/bluetooth/controller/ll_sw/pdu.h +++ b/subsys/bluetooth/controller/ll_sw/pdu.h @@ -1018,8 +1018,8 @@ struct pdu_iso_sdu_sh { uint8_t len; /* Note, timeoffset only available in first segment of sdu */ - uint32_t payload:8; uint32_t timeoffset:24; + uint32_t payload:8; #endif /* CONFIG_LITTLE_ENDIAN */ } __packed; From 4ef38a538433f2ca8df60c605d4047f43f1a529b Mon Sep 17 00:00:00 2001 From: Nirosharn Amarasinghe Date: Tue, 18 Jul 2023 16:32:29 +0200 Subject: [PATCH 226/421] [nrf fromtree] Bluetooth: Controller: ISO-AL validation and selection of TX time stamps Intent is to pass Ellisys ISOAL quality tests for framed TX scenarios where the TX SDU includes a time stamp that is not based on the controller's clock. Changes: -- Include controller's reception time as a separate field in the TX SDU information -- Include decision on whether SDU time stamp is valid and based on the controller's clock -- Arbitrate and select / compute time stamp for the SDU Signed-off-by: Nirosharn Amarasinghe (cherry picked from commit d414cab87a87c63a70266a83256a77ae6abaa052) Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit 9c58cfc07250e5803e4920ac8e30bbba46fe445a) --- subsys/bluetooth/controller/hci/hci.c | 14 +- subsys/bluetooth/controller/ll_sw/isoal.c | 212 +++++++++++++++----- subsys/bluetooth/controller/ll_sw/isoal.h | 2 + subsys/bluetooth/controller/ll_sw/ull_iso.c | 3 +- 4 files changed, 176 insertions(+), 55 deletions(-) diff --git a/subsys/bluetooth/controller/hci/hci.c b/subsys/bluetooth/controller/hci/hci.c index 9ca905c44e0..30fb363fc9c 100644 --- a/subsys/bluetooth/controller/hci/hci.c +++ b/subsys/bluetooth/controller/hci/hci.c @@ -5700,17 +5700,21 @@ int hci_iso_handle(struct net_buf *buf, struct net_buf **evt) * -- A captured time stamp of the SDU * -- A time stamp provided by the higher layer * -- A computed time stamp based on a sequence counter provided by the - * higher layer (Not implemented) - * -- Any other method of determining Time_Offset (Not implemented) + * higher layer + * -- Any other method of determining Time_Offset + * (Uses a timestamp computed from the difference in provided + * timestamps, if the timestamp is deemed not based on the + * controller's clock) */ + sdu_frag_tx.cntr_time_stamp = HAL_TICKER_TICKS_TO_US(ticker_ticks_now_get()); if (ts_flag) { - /* Overwrite time stamp with HCI provided time stamp */ + /* Use HCI provided time stamp */ time_stamp = net_buf_pull_mem(buf, sizeof(*time_stamp)); len -= sizeof(*time_stamp); sdu_frag_tx.time_stamp = sys_le32_to_cpu(*time_stamp); } else { - sdu_frag_tx.time_stamp = - HAL_TICKER_TICKS_TO_US(ticker_ticks_now_get()); + /* Use controller's capture time */ + sdu_frag_tx.time_stamp = sdu_frag_tx.cntr_time_stamp; } /* Extract ISO data header if included (PB_Flag 0b00 or 0b10) */ diff --git a/subsys/bluetooth/controller/ll_sw/isoal.c b/subsys/bluetooth/controller/ll_sw/isoal.c index 00bc40504f7..d4cc61cea6c 100644 --- a/subsys/bluetooth/controller/ll_sw/isoal.c +++ b/subsys/bluetooth/controller/ll_sw/isoal.c @@ -1282,7 +1282,7 @@ static isoal_status_t isoal_rx_framed_consume(struct isoal_sink *sink, } /* Update next state */ - ISOAL_LOG_DBGV("[%p] Decoding: Next State %s", sink, FSM_TO_STR(next_state)); + ISOAL_LOG_DBGV("[%p] FSM Next State %s", sink, FSM_TO_STR(next_state)); sp->fsm = next_state; /* Find next segment header, set to null if past end of PDU */ @@ -1350,7 +1350,7 @@ static isoal_status_t isoal_rx_framed_consume(struct isoal_sink *sink, if (error_sdu_pending) { sp->sdu_status = next_sdu_status; - err |= isoal_rx_append_to_sdu(sink, pdu_meta, 0, 0, true, false); + err |= isoal_rx_append_to_sdu(sink, pdu_meta, 0U, 0U, true, false); } break; @@ -1373,8 +1373,8 @@ static isoal_status_t isoal_rx_framed_consume(struct isoal_sink *sink, } /* Update next state */ - ISOAL_LOG_DBGV("[%p] Error: Next State %s", sink, FSM_TO_STR(next_state)); - sink->sdu_production.fsm = next_state; + ISOAL_LOG_DBGV("[%p] FSM Error Next State %s", sink, FSM_TO_STR(next_state)); + sp->fsm = next_state; } sp->prev_pdu_id = meta->payload_number; @@ -1591,6 +1591,46 @@ void isoal_source_destroy(isoal_source_handle_t hdl) isoal_source_deallocate(hdl); } +static bool isoal_is_time_stamp_valid(const struct isoal_source *source_ctx, + const uint32_t cntr_time, + const uint32_t time_stamp) +{ + const struct isoal_source_session *session; + uint32_t time_diff; + + session = &source_ctx->session; + + /* This is an arbitrarily defined range. The purpose is to + * decide if the time stamp provided by the host is sensible + * within the controller's clock domain. An SDU interval plus ISO + * interval is expected to provide a good balance between situations + * where either could be significantly larger than the other. + * + * BT Core V5.4 : Vol 6 Low Energy Controller : Part G IS0-AL: + * 3.3 Time Stamp for SDU : + * When an HCI ISO Data packet sent by the Host does not contain + * a Time Stamp or the Time_Stamp value is not based on the + * Controller's clock, the Controller should determine the CIS + * or BIS event to be used to transmit the SDU contained in that + * packet based on the time of arrival of that packet. + */ + const uint32_t sdu_interval_us = session->sdu_interval; + const uint32_t iso_interval_us = session->iso_interval * ISO_INT_UNIT_US; + /* ISO Interval 0x0000_0004 ~ 0x0000_0C80 x 1250 + + * SDU Interval 0x0000_00FF ~ 0x000F_FFFF <= 004D_08FF + */ + const int32_t time_stamp_valid_half_range = sdu_interval_us + iso_interval_us; + const uint32_t time_stamp_valid_min = isoal_get_wrapped_time_us(cntr_time, + (-time_stamp_valid_half_range)); + const uint32_t time_stamp_valid_range = 2 * time_stamp_valid_half_range; + const bool time_stamp_is_valid = isoal_get_time_diff(time_stamp_valid_min, + time_stamp, + &time_diff) && + time_diff <= time_stamp_valid_range; + + return time_stamp_is_valid; +} + /** * Queue the PDU in production in the relevant LL transmit queue. If the * attmept to release the PDU fails, the buffer linked to the PDU will be released @@ -1636,8 +1676,8 @@ static isoal_status_t isoal_tx_pdu_emit(const struct isoal_source *source_ctx, status = source_ctx->session.pdu_emit(node_tx, handle); ISOAL_LOG_DBG("[%p] PDU %llu err=%X len=%u frags=%u released", - source_ctx, payload_number, status, - produced_pdu->contents.pdu->len, sdu_fragments); + source_ctx, payload_number, status, + produced_pdu->contents.pdu->len, sdu_fragments); if (status != ISOAL_STATUS_OK) { /* If it fails, the node will be released and no further attempt @@ -1841,8 +1881,8 @@ uint16_t isoal_tx_unframed_get_next_payload_number(isoal_source_handle_t source_ * @brief Fragment received SDU and produce unframed PDUs * @details Destination source may have an already partially built PDU * - * @param source_hdl[in] Destination source handle - * @param tx_sdu[in] SDU with packet boundary information + * @param[in] source_hdl Destination source handle + * @param[in] tx_sdu SDU with packet boundary information * * @return Status * @@ -2162,7 +2202,7 @@ static isoal_status_t isoal_insert_seg_header_timeoffset(struct isoal_source *so pp->pdu_available -= write_size; ISOAL_LOG_DBGV("[%p] Seg header write size=%u sc=%u cmplt=%u TO=%u len=%u", - source, write_size, sc, cmplt, time_offset, seg_hdr.len); + source, write_size, sc, cmplt, time_offset, seg_hdr.len); return err; } @@ -2203,46 +2243,48 @@ static isoal_status_t isoal_update_seg_header_cmplt_length(struct isoal_source * PDU_ISO_SEG_HDR_SIZE); ISOAL_LOG_DBGV("[%p] Seg header write size=%u sc=%u cmplt=%u len=%u", - source, PDU_ISO_SEG_HDR_SIZE, seg_hdr.sc, cmplt, seg_hdr.len); + source, PDU_ISO_SEG_HDR_SIZE, seg_hdr.sc, cmplt, seg_hdr.len); } /** * Find the earliest feasible event for transmission capacity is not wasted and * return information based on that event. - * @param[in] source_hdl Destination source handle + * + * @param[in] *source_ctx Destination source context * @param[in] tx_sdu SDU with meta data information * @param[out] payload_number Updated payload number for the selected event * @param[out] grp_ref_point Group reference point for the selected event * @param[out] time_offset Segmentation Time offset to selected event * @return The number SDUs skipped from the last */ -static uint16_t isoal_tx_framed_find_correct_tx_event(isoal_source_handle_t source_hdl, +static uint16_t isoal_tx_framed_find_correct_tx_event(const struct isoal_source *source_ctx, const struct isoal_sdu_tx *tx_sdu, uint64_t *payload_number, uint32_t *grp_ref_point, uint32_t *time_offset) { - struct isoal_source_session *session; - struct isoal_pdu_production *pp; + const struct isoal_source_session *session; + const struct isoal_pdu_production *pp; uint32_t actual_grp_ref_point; uint64_t next_payload_number; - struct isoal_source *source; uint16_t sdus_skipped; uint64_t actual_event; bool time_diff_valid; uint32_t time_diff; + uint32_t time_stamp_selected; - source = &isoal_global.source_state[source_hdl]; - session = &source->session; - pp = &source->pdu_production; + session = &source_ctx->session; + pp = &source_ctx->pdu_production; - sdus_skipped = 0; + sdus_skipped = 0U; + time_diff = 0U; /* Continue with the current payload unless there is need to change */ next_payload_number = pp->payload_number; actual_event = pp->payload_number / session->burst_number; - ISOAL_LOG_DBGV("[%p] Start PL=%llu Evt=%lu.", source, next_payload_number, actual_event); + ISOAL_LOG_DBGV("[%p] Start PL=%llu Evt=%lu.", source_ctx, next_payload_number, + actual_event); /* Get the drift updated group reference point for this event based on * the actual event being set. This might introduce some errors as the @@ -2259,29 +2301,35 @@ static uint16_t isoal_tx_framed_find_correct_tx_event(isoal_source_handle_t sour } ISOAL_LOG_DBGV("[%p] Current PL=%llu Evt=%llu Ref=%lu", - source, next_payload_number, actual_event, actual_grp_ref_point); + source_ctx, next_payload_number, actual_event, actual_grp_ref_point); if (tx_sdu->sdu_state == BT_ISO_START || tx_sdu->sdu_state == BT_ISO_SINGLE) { /* Start of a new SDU */ + const bool time_stamp_is_valid = isoal_is_time_stamp_valid(source_ctx, + tx_sdu->cntr_time_stamp, + tx_sdu->time_stamp); + /* Adjust payload number */ if (pp->initialized) { /* Not the first SDU in this session, so reference * information should be valid. . */ + time_diff_valid = isoal_get_time_diff(session->last_input_time_stamp, tx_sdu->time_stamp, &time_diff); /* Priority is given to the sequence number */ if (tx_sdu->packet_sn > session->last_input_sn + 1) { - ISOAL_LOG_DBGV("[%p] Using packet_sn for skipped SDUs", source); + ISOAL_LOG_DBGV("[%p] Using packet_sn for skipped SDUs", source_ctx); sdus_skipped = (tx_sdu->packet_sn - session->last_input_sn) - 1; } else if (tx_sdu->packet_sn == session->last_input_sn && - time_diff_valid && time_diff > session->sdu_interval) { - ISOAL_LOG_DBGV("[%p] Using time_stamp for skipped SDUs", source); + time_diff_valid && time_diff > session->sdu_interval) { + ISOAL_LOG_DBGV("[%p] Using time_stamp for skipped SDUs", + source_ctx); /* Round at mid-point */ sdus_skipped = ((time_diff + (session->sdu_interval / 2)) / session->sdu_interval) - 1; @@ -2289,12 +2337,58 @@ static uint16_t isoal_tx_framed_find_correct_tx_event(isoal_source_handle_t sour /* SDU is next in sequence */ } + if (time_stamp_is_valid) { + /* Use provided time stamp for time offset + * calcutation + */ + time_stamp_selected = tx_sdu->time_stamp; + ISOAL_LOG_DBGV("[%p] Selecting Time Stamp (%lu) from SDU", + source_ctx, time_stamp_selected); + } else if (time_diff_valid) { + /* Project a time stamp based on the last time + * stamp and the difference in input time stamps + */ + time_stamp_selected = isoal_get_wrapped_time_us( + session->tx_time_stamp, + time_diff - session->tx_time_offset); + ISOAL_LOG_DBGV("[%p] Projecting Time Stamp (%lu) from SDU delta", + source_ctx, time_stamp_selected); + } else { + /* Project a time stamp based on the last time + * stamp and the number of skipped SDUs + */ + time_stamp_selected = isoal_get_wrapped_time_us( + session->tx_time_stamp, + ((sdus_skipped + 1) * session->sdu_interval) + - session->tx_time_offset); + ISOAL_LOG_DBGV("[%p] Projecting Time Stamp (%lu) from skipped SDUs", + source_ctx, time_stamp_selected); + } + } else { /* First SDU, align with target event */ - actual_event = tx_sdu->target_event; - actual_grp_ref_point = tx_sdu->grp_ref_point; + if (actual_event < tx_sdu->target_event) { + actual_event = tx_sdu->target_event; + actual_grp_ref_point = tx_sdu->grp_ref_point; + } - ISOAL_LOG_DBGV("[%p] Use target_event", source); + ISOAL_LOG_DBGV("[%p] Use target_event", source_ctx); + + if (time_stamp_is_valid) { + /* Time stamp is within valid range - + * use provided time stamp + */ + time_stamp_selected = tx_sdu->time_stamp; + ISOAL_LOG_DBGV("[%p] Selecting Time Stamp (%lu) from SDU", + source_ctx, time_stamp_selected); + } else { + /* Time stamp is out of range - + * use controller's capture time + */ + time_stamp_selected = tx_sdu->cntr_time_stamp; + ISOAL_LOG_DBGV("[%p] Selecting Time Stamp (%lu) from controller", + source_ctx, time_stamp_selected); + } } /* Selecting the event for transmission is done solely based on @@ -2309,8 +2403,8 @@ static uint16_t isoal_tx_framed_find_correct_tx_event(isoal_source_handle_t sour * 3.1 Time_Offset in framed PDUs : * The Time_Offset shall be a positive value. */ - while (!isoal_get_time_diff(tx_sdu->time_stamp, actual_grp_ref_point, &time_diff) || - time_diff == 0) { + while (!isoal_get_time_diff(time_stamp_selected, actual_grp_ref_point, &time_diff) + || time_diff == 0) { /* Advance target to next event */ actual_event++; actual_grp_ref_point = isoal_get_wrapped_time_us(actual_grp_ref_point, @@ -2318,8 +2412,8 @@ static uint16_t isoal_tx_framed_find_correct_tx_event(isoal_source_handle_t sour } ISOAL_LOG_DBGV("[%p] Chosen PL=%llu Evt=%llu Ref=%lu", - source, (actual_event * session->burst_number), actual_event, - actual_grp_ref_point); + source_ctx, (actual_event * session->burst_number), actual_event, + actual_grp_ref_point); /* If the event selected is the last event segmented for, then * it is possible that that some payloads have already been @@ -2327,23 +2421,23 @@ static uint16_t isoal_tx_framed_find_correct_tx_event(isoal_source_handle_t sour * that payload. */ next_payload_number = MAX(pp->payload_number, - (actual_event * session->burst_number)); - } + (actual_event * session->burst_number)); - ISOAL_LOG_DBGV("[%p] Final Evt=%llu (PL=%llu) Ref.=%lu Next PL=%llu", - source, actual_event, (actual_event * session->burst_number), - actual_grp_ref_point, next_payload_number); + ISOAL_LOG_DBGV("[%p] Final Evt=%llu (PL=%llu) Ref.=%lu Next PL=%llu", + source, actual_event, (actual_event * session->burst_number), + actual_grp_ref_point, next_payload_number); - /* Calculate the time offset */ - time_diff_valid = isoal_get_time_diff(tx_sdu->time_stamp, - actual_grp_ref_point, &time_diff); + /* Calculate the time offset */ + time_diff_valid = isoal_get_time_diff(time_stamp_selected, + actual_grp_ref_point, &time_diff); - LL_ASSERT(time_diff_valid); - LL_ASSERT(time_diff > 0); - /* Time difference must be less than the maximum possible - * time-offset of 24-bits. - */ - LL_ASSERT(time_diff <= 0x00FFFFFF); + LL_ASSERT(time_diff_valid); + LL_ASSERT(time_diff > 0); + /* Time difference must be less than the maximum possible + * time-offset of 24-bits. + */ + LL_ASSERT(time_diff <= 0x00FFFFFF); + } *payload_number = next_payload_number; *grp_ref_point = actual_grp_ref_point; @@ -2389,19 +2483,24 @@ static isoal_status_t isoal_tx_framed_produce(isoal_source_handle_t source_hdl, tx_sdu->sdu_state == BT_ISO_SINGLE); ISOAL_LOG_DBGV("[%p] SDU %u len=%u TS=%lu Ref=%lu Evt=%llu Frag=%u", - source, tx_sdu->packet_sn, tx_sdu->iso_sdu_length, tx_sdu->time_stamp, - tx_sdu->grp_ref_point, tx_sdu->target_event, tx_sdu->sdu_state); + source, tx_sdu->packet_sn, tx_sdu->iso_sdu_length, tx_sdu->time_stamp, + tx_sdu->grp_ref_point, tx_sdu->target_event, tx_sdu->sdu_state); if (tx_sdu->sdu_state == BT_ISO_START || tx_sdu->sdu_state == BT_ISO_SINGLE) { uint32_t actual_grp_ref_point; uint64_t next_payload_number; uint16_t sdus_skipped; + bool time_diff_valid; + uint32_t time_diff; /* Start of a new SDU */ + time_diff_valid = isoal_get_time_diff(session->last_input_time_stamp, + tx_sdu->time_stamp, + &time_diff); /* Find the best transmission event */ - sdus_skipped = isoal_tx_framed_find_correct_tx_event(source_hdl, tx_sdu, + sdus_skipped = isoal_tx_framed_find_correct_tx_event(source, tx_sdu, &next_payload_number, &actual_grp_ref_point, &time_offset); @@ -2460,7 +2559,22 @@ static isoal_status_t isoal_tx_framed_produce(isoal_source_handle_t source_hdl, /* Update input packet number and time stamp */ session->last_input_sn = tx_sdu->packet_sn; - session->last_input_time_stamp = tx_sdu->time_stamp; + + if (pp->initialized && tx_sdu->time_stamp == tx_sdu->cntr_time_stamp && + (!time_diff_valid || time_diff < session->sdu_interval)) { + /* If the time-stamp is invalid or the difference is + * less than an SDU interval, then set the reference + * time stamp to what should have been received. This is + * done to avoid incorrectly detecting a gap in time + * stamp inputs should there be a burst of SDUs + * clustered together. + */ + session->last_input_time_stamp = isoal_get_wrapped_time_us( + session->last_input_time_stamp, + session->sdu_interval); + } else { + session->last_input_time_stamp = tx_sdu->time_stamp; + } } /* PDUs should be created until the SDU fragment has been fragmented or if diff --git a/subsys/bluetooth/controller/ll_sw/isoal.h b/subsys/bluetooth/controller/ll_sw/isoal.h index cc69e4a5d53..61d3773c43d 100644 --- a/subsys/bluetooth/controller/ll_sw/isoal.h +++ b/subsys/bluetooth/controller/ll_sw/isoal.h @@ -189,6 +189,8 @@ struct isoal_sdu_tx { uint16_t iso_sdu_length; /** Time stamp from HCI or vendor specific path (us) */ uint32_t time_stamp; + /** Capture time stamp from controller (us) */ + uint32_t cntr_time_stamp; /** CIG Reference of target event (us, compensated for drift) */ uint32_t grp_ref_point; /** Target Event of SDU */ diff --git a/subsys/bluetooth/controller/ll_sw/ull_iso.c b/subsys/bluetooth/controller/ll_sw/ull_iso.c index 1520bd76963..70d018e7e0c 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_iso.c +++ b/subsys/bluetooth/controller/ll_sw/ull_iso.c @@ -1058,7 +1058,8 @@ void ll_iso_transmit_test_send_sdu(uint16_t handle, uint32_t ticks_at_expire) /* Send all SDU fragments */ do { - sdu.time_stamp = HAL_TICKER_TICKS_TO_US(ticks_at_expire); + sdu.cntr_time_stamp = HAL_TICKER_TICKS_TO_US(ticks_at_expire); + sdu.time_stamp = sdu.cntr_time_stamp; sdu.size = MIN(remaining_tx, ISO_TEST_TX_BUFFER_SIZE); memset(tx_buffer, 0, sdu.size); From 85f3925dbeea3ffb867ae802773eca323c096322 Mon Sep 17 00:00:00 2001 From: Erik Brockhoff Date: Thu, 10 Aug 2023 14:44:59 +0200 Subject: [PATCH 227/421] [nrf fromtree] Bluetooth: controller: disregard length field on pdu error In case of unframed iso rx, length field cannot be trusted in case of PDU error. Signed-off-by: Erik Brockhoff (cherry picked from commit 365a56ce87fa91eb3a059f0353a450c4408d0bf4) Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit aff4981928a83b16a7c1b29f995d06e88b90d813) --- subsys/bluetooth/controller/ll_sw/isoal.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subsys/bluetooth/controller/ll_sw/isoal.c b/subsys/bluetooth/controller/ll_sw/isoal.c index d4cc61cea6c..6c1dedd7b9d 100644 --- a/subsys/bluetooth/controller/ll_sw/isoal.c +++ b/subsys/bluetooth/controller/ll_sw/isoal.c @@ -738,7 +738,7 @@ static isoal_status_t isoal_rx_unframed_consume(struct isoal_sink *sink, /* If status is not ISOAL_PDU_STATUS_VALID, length and LLID cannot be trusted */ llid = pdu->ll_id; pdu_err = (pdu_meta->meta->status != ISOAL_PDU_STATUS_VALID); - length = pdu->len; + length = pdu_err ? 0U : pdu->len; /* A zero length PDU with LLID 0b01 (PDU_BIS_LLID_START_CONTINUE) would be a padding PDU. * However if there are errors in the PDU, it could be an incorrectly receive non-padding * PDU. Therefore only consider a PDU with errors as padding if received after the end From c88e67bb9ad3655d3a5bab013518bf11950eda92 Mon Sep 17 00:00:00 2001 From: Nirosharn Amarasinghe Date: Fri, 8 Sep 2023 16:37:40 +0200 Subject: [PATCH 228/421] [nrf fromtree] Bluetooth: controller: Included kconfigs for ISO-AL logging Included kconfigs to set the ISO-AL logging level and control debug logging verbosity. Signed-off-by: Nirosharn Amarasinghe (cherry picked from commit b96436296fc593329325a03689896d73193a1589) Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit 5951daa0dff93f4b59f8478e46f26a830f41d21e) --- subsys/bluetooth/Kconfig.logging | 17 +++++++++++++++++ subsys/bluetooth/controller/Kconfig | 7 +++++++ subsys/bluetooth/controller/ll_sw/isoal.c | 6 +++--- 3 files changed, 27 insertions(+), 3 deletions(-) diff --git a/subsys/bluetooth/Kconfig.logging b/subsys/bluetooth/Kconfig.logging index 67a18afa919..addf8eb65fe 100644 --- a/subsys/bluetooth/Kconfig.logging +++ b/subsys/bluetooth/Kconfig.logging @@ -398,6 +398,16 @@ config BT_DEBUG_SERVICE This option enables debug support for the Bluetooth Services. +# CONTROLLER (subsys/bluetooth/controller/Kconfig) + +config BT_CTLR_DEBUG_ISOAL + bool "[DEPRECATED] Bluetooth ISO-AL debug" + select DEPRECATED + depends on BT_CTLR_ISO + help + This option enables debug support for the Bluetooth ISO-AL. + + endmenu # [DEPRECATED] Others menu "[DEPRECATED] BR/EDR" @@ -900,6 +910,13 @@ legacy-debug-sym = BT_DEBUG_SERVICE module-str = "Bluetooth Services" source "subsys/bluetooth/common/Kconfig.template.log_config_bt" +# CONTROLLER (subsys/bluetooth/controller/Kconfig) + +module = BT_CTLR_ISOAL +legacy-debug-sym = BT_CTLR_DEBUG_ISOAL +module-str = "Bluetooth Controller ISO-AL" +source "subsys/bluetooth/common/Kconfig.template.log_config_bt" + endmenu # Others menu "BR/EDR" diff --git a/subsys/bluetooth/controller/Kconfig b/subsys/bluetooth/controller/Kconfig index 51890bf51ed..467683705f3 100644 --- a/subsys/bluetooth/controller/Kconfig +++ b/subsys/bluetooth/controller/Kconfig @@ -207,6 +207,13 @@ config BT_CTLR_ISO_TX_BUFFER_SIZE Size of the Isochronous Tx buffers and the value returned in HCI LE Read Buffer Size V2 command response. +config BT_CTLR_ISOAL_LOG_DBG_VERBOSE + bool "ISO-AL verbose debug logging" + depends on BT_CTLR_ISOAL_LOG_LEVEL = 4 + default n + help + Use this option to enable ISO-AL verbose debug logging. + config BT_CTLR_ISOAL_SOURCES int "Number of Isochronous Adaptation Layer sources" depends on BT_CTLR_ADV_ISO || BT_CTLR_CONN_ISO diff --git a/subsys/bluetooth/controller/ll_sw/isoal.c b/subsys/bluetooth/controller/ll_sw/isoal.c index 6c1dedd7b9d..d43233f0289 100644 --- a/subsys/bluetooth/controller/ll_sw/isoal.c +++ b/subsys/bluetooth/controller/ll_sw/isoal.c @@ -36,15 +36,15 @@ #include -LOG_MODULE_REGISTER(bt_ctlr_isoal, LOG_LEVEL_INF); +LOG_MODULE_REGISTER(bt_ctlr_isoal, CONFIG_BT_CTLR_ISOAL_LOG_LEVEL); #define ISOAL_LOG_DBG(...) LOG_DBG(__VA_ARGS__) -#if defined(ISOAL_DEBUG_VERBOSE) +#if defined(CONFIG_BT_CTLR_ISOAL_LOG_DBG_VERBOSE) #define ISOAL_LOG_DBGV(...) LOG_DBG(__VA_ARGS__) #else #define ISOAL_LOG_DBGV(...) (void) 0 -#endif /* ISOAL_DEBUG_VERBOSE */ +#endif /* CONFIG_BT_CTLR_ISOAL_LOG_DBG_VERBOSE */ #include "hal/debug.h" From 3d9d12428797dd3d53f0d772c611be6e54cb934f Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Sun, 17 Sep 2023 21:35:58 +0200 Subject: [PATCH 229/421] [nrf fromtree] Bluetooth: Controller: Fix ticker to prefer ticker node started Fix ticker implementation to prefer to keep ticker node started in case of race condition to start and stop. Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit f4e05e3e5426b492b34073dd2acde0b164736f97) Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit 31efdfbf33f9cd2705f4ee7eee3c2f06523eade7) --- .../bluetooth/controller/Kconfig.ll_sw_split | 17 +++++ subsys/bluetooth/controller/ticker/ticker.c | 12 +++- tests/bluetooth/init/prj_ctlr_ticker.conf | 65 +++++++++++++++++++ tests/bluetooth/init/testcase.yaml | 9 +++ 4 files changed, 102 insertions(+), 1 deletion(-) create mode 100644 tests/bluetooth/init/prj_ctlr_ticker.conf diff --git a/subsys/bluetooth/controller/Kconfig.ll_sw_split b/subsys/bluetooth/controller/Kconfig.ll_sw_split index 910c3819f0c..5fb2c54d085 100644 --- a/subsys/bluetooth/controller/Kconfig.ll_sw_split +++ b/subsys/bluetooth/controller/Kconfig.ll_sw_split @@ -55,6 +55,8 @@ config BT_LLL_VENDOR_NORDIC select BT_TICKER_REMAINDER_GET if BT_BROADCASTER && BT_CTLR_ADV_EXT select BT_TICKER_LAZY_GET if BT_CTLR_ADV_PERIODIC || BT_CTLR_CENTRAL_ISO + select BT_TICKER_PREFER_START_BEFORE_STOP if BT_TICKER_SLOT_AGNOSTIC + default y help Use Nordic Lower Link Layer implementation. @@ -1036,6 +1038,21 @@ config BT_TICKER_SLOT_AGNOSTIC reservations and collision handling, and operates as a simple multi-instance programmable timer. +config BT_TICKER_PREFER_START_BEFORE_STOP + bool "Ticker prefer start before stop request" + help + Under race conditions wherein for a given ticker node if a number of + start and stop operations are enqueued towards ticker_job by a said + user execution context, then start operations is preferred to be + processed before stop operations. + + Without this option, the default behavior is to defer all start + requests after all stop requests enqueued by all user context having + been processed. The rationale for default behavior being that under + race conditions, start followed by stop requests, or start before stop + requests, the said ticker node is always scheduled and at timeout the + execution context can take decision based on its execution state. + config BT_CTLR_JIT_SCHEDULING bool "Just-in-Time Scheduling" select BT_TICKER_SLOT_AGNOSTIC diff --git a/subsys/bluetooth/controller/ticker/ticker.c b/subsys/bluetooth/controller/ticker/ticker.c index ead148e85ba..e5c89dca905 100644 --- a/subsys/bluetooth/controller/ticker/ticker.c +++ b/subsys/bluetooth/controller/ticker/ticker.c @@ -55,9 +55,11 @@ struct ticker_node { uint8_t force:1; /* If non-zero, node timeout should * be forced at next expiration */ +#if defined(CONFIG_BT_TICKER_PREFER_START_BEFORE_STOP) uint8_t start_pending:1; /* If non-zero, start is pending for * bottom half of ticker_job. */ +#endif /* CONFIG_BT_TICKER_PREFER_START_BEFORE_STOP */ uint32_t ticks_periodic; /* If non-zero, interval * between expirations */ @@ -1907,12 +1909,15 @@ static inline uint8_t ticker_job_list_manage(struct ticker_instance *instance, /* if op is start, then skip update and stop ops */ if (user_op->op < TICKER_USER_OP_TYPE_UPDATE) { +#if defined(CONFIG_BT_TICKER_PREFER_START_BEFORE_STOP) if (user_op->op == TICKER_USER_OP_TYPE_START) { /* Set start pending to validate a * successive, inline stop operation. */ ticker->start_pending = 1U; } +#endif /* CONFIG_BT_TICKER_PREFER_START_BEFORE_STOP */ + continue; } @@ -1923,7 +1928,10 @@ static inline uint8_t ticker_job_list_manage(struct ticker_instance *instance, * set status and continue. */ if ((user_op->op > TICKER_USER_OP_TYPE_STOP_ABS) || - (((state == 0U) && !ticker->start_pending) && + ((state == 0U) && +#if defined(CONFIG_BT_TICKER_PREFER_START_BEFORE_STOP) + !ticker->start_pending && +#endif /* CONFIG_BT_TICKER_PREFER_START_BEFORE_STOP */ (user_op->op != TICKER_USER_OP_TYPE_YIELD_ABS)) || ((user_op->op == TICKER_USER_OP_TYPE_UPDATE) && (user_op->params.update.ticks_drift_plus == 0U) && @@ -2731,7 +2739,9 @@ static inline void ticker_job_list_insert(struct ticker_instance *instance, continue; } +#if defined(CONFIG_BT_TICKER_PREFER_START_BEFORE_STOP) ticker->start_pending = 0U; +#endif /* CONFIG_BT_TICKER_PREFER_START_BEFORE_STOP */ if (((ticker->req - ticker->ack) & 0xff) != 0U) { diff --git a/tests/bluetooth/init/prj_ctlr_ticker.conf b/tests/bluetooth/init/prj_ctlr_ticker.conf new file mode 100644 index 00000000000..d77f519406b --- /dev/null +++ b/tests/bluetooth/init/prj_ctlr_ticker.conf @@ -0,0 +1,65 @@ +CONFIG_BT=y +CONFIG_BT_CTLR=y +CONFIG_BT_LL_SW_SPLIT=y +CONFIG_BT_CTLR_DUP_FILTER_LEN=16 +CONFIG_BT_CTLR_CONN_PARAM_REQ=y +CONFIG_BT_CTLR_LE_PING=y +CONFIG_BT_CTLR_PRIVACY=n +CONFIG_BT_CTLR_EXT_SCAN_FP=n +CONFIG_BT_DATA_LEN_UPDATE=n +CONFIG_BT_PHY_UPDATE=y +CONFIG_BT_CTLR_CHAN_SEL_2=y +CONFIG_BT_CTLR_MIN_USED_CHAN=y +CONFIG_BT_CTLR_ADV_EXT=y +CONFIG_BT_CTLR_DTM_HCI=y +CONFIG_BT_CTLR_ADVANCED_FEATURES=y +CONFIG_BT_CTLR_PHY_2M=y +CONFIG_BT_CTLR_PHY_2M_NRF=y +CONFIG_BT_CTLR_PHY_CODED=y +CONFIG_BT_CTLR_ADV_AUX_PDU_BACK2BACK=y +CONFIG_BT_CTLR_LLL_PRIO=0 +CONFIG_BT_CTLR_ULL_HIGH_PRIO=1 +CONFIG_BT_CTLR_XTAL_ADVANCED=n +CONFIG_BT_CTLR_SCHED_ADVANCED=n +CONFIG_BT_CTLR_RADIO_ENABLE_FAST=y +CONFIG_BT_CTLR_TIFS_HW=n +CONFIG_BT_CTLR_FAST_ENC=y +CONFIG_BT_CTLR_TX_RETRY_DISABLE=y +CONFIG_BT_CTLR_CONN_RSSI=y +CONFIG_BT_CTLR_ADV_INDICATION=y +CONFIG_BT_CTLR_SCAN_REQ_NOTIFY=y +CONFIG_BT_CTLR_SCAN_REQ_RSSI=y +CONFIG_BT_CTLR_SCAN_INDICATION=y +CONFIG_BT_CTLR_PROFILE_ISR=y +CONFIG_BT_CTLR_DEBUG_PINS=y +CONFIG_BT_CTLR_TEST=y +CONFIG_BT_TICKER_EXT=n +CONFIG_BT_TICKER_SLOT_AGNOSTIC=y +CONFIG_BT_TICKER_PREFER_START_BEFORE_STOP=y +CONFIG_BT_HCI_VS_EXT=y +CONFIG_BT_HCI_MESH_EXT=n +CONFIG_BT_PERIPHERAL=y +CONFIG_BT_CENTRAL=y +CONFIG_BT_SMP=y +CONFIG_BT_SIGNING=y +CONFIG_BT_SMP_SC_ONLY=y +CONFIG_BT_TINYCRYPT_ECC=y +CONFIG_BT_USE_DEBUG_KEYS=y +CONFIG_BT_L2CAP_DYNAMIC_CHANNEL=y +CONFIG_BT_GATT_CLIENT=y +CONFIG_BT_DEBUG_MONITOR_UART=y +CONFIG_BT_HCI_CORE_LOG_LEVEL_DBG=y +CONFIG_BT_CONN_LOG_LEVEL_DBG=y +CONFIG_BT_KEYS_LOG_LEVEL_DBG=y +CONFIG_BT_L2CAP_LOG_LEVEL_DBG=y +CONFIG_BT_SMP_LOG_LEVEL_DBG=y +CONFIG_BT_HCI_DRIVER_LOG_LEVEL_DBG=y +CONFIG_BT_SMP_SELFTEST=y +CONFIG_BT_ATT_LOG_LEVEL_DBG=y +CONFIG_BT_GATT_LOG_LEVEL_DBG=y +CONFIG_BT_BREDR=n +CONFIG_DEBUG=y +CONFIG_FLASH=y +CONFIG_SOC_FLASH_NRF_RADIO_SYNC_TICKER=n +CONFIG_ZTEST=y +CONFIG_ZTEST_NEW_API=y diff --git a/tests/bluetooth/init/testcase.yaml b/tests/bluetooth/init/testcase.yaml index 4c252115178..fa30920dc1e 100644 --- a/tests/bluetooth/init/testcase.yaml +++ b/tests/bluetooth/init/testcase.yaml @@ -122,6 +122,15 @@ tests: integration_platforms: - nrf52840dk_nrf52840 - nrf52dk_nrf52832 + bluetooth.init.test_ctlr_ticker: + extra_args: + - CONF_FILE=prj_ctlr_ticker.conf + platform_allow: + - nrf52840dk_nrf52840 + - nrf52dk_nrf52832 + integration_platforms: + - nrf52840dk_nrf52840 + - nrf52dk_nrf52832 bluetooth.init.test_ctlr_broadcaster: extra_args: CONF_FILE=prj_ctlr_broadcaster.conf platform_allow: From 8246e66a8ecaa438b87a025d7d02312ad239a0ce Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Mon, 18 Sep 2023 09:00:14 +0200 Subject: [PATCH 230/421] [nrf fromtree] Bluetooth: Controller: Fix order of preempt timeout requested flag Fix the order of setting the flag that indicates that preempt timeout has been successfully requested versus the request is waiting to be scheduled. Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit 4cefcb6fc7917a44c51cb4c16e06daefcd8d9ca2) Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit 439362352fdc840063b04b90da531970da11d445) --- .../controller/ll_sw/nordic/lll/lll.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll.c b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll.c index 1f8031a7c07..fe0a031d402 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll.c @@ -835,11 +835,17 @@ static void ticker_start_op_cb(uint32_t status, void *param) ARG_UNUSED(param); LL_ASSERT(status == TICKER_STATUS_SUCCESS); - LL_ASSERT(preempt_start_req != preempt_start_ack); - preempt_start_ack++; - + /* Increase preempt requested count before acknowledging that the + * ticker start operation for the preempt timeout has been handled. + */ LL_ASSERT(preempt_req == preempt_ack); preempt_req++; + + /* Increase preempt start ack count, to acknowledge that the ticker + * start operation has been handled. + */ + LL_ASSERT(preempt_start_req != preempt_start_ack); + preempt_start_ack++; } static uint32_t preempt_ticker_start(struct lll_event *first, @@ -854,7 +860,11 @@ static uint32_t preempt_ticker_start(struct lll_event *first, uint32_t preempt_to; uint32_t ret; - /* Do not request to start preempt timeout if already requested */ + /* Do not request to start preempt timeout if already requested. + * + * Check if there is pending preempt timeout start requested or if + * preempt timeout ticker has already been scheduled. + */ if ((preempt_start_req != preempt_start_ack) || (preempt_req != preempt_ack)) { uint32_t diff; From 4af51708076cf561df2c53eb8154f39426100718 Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Tue, 19 Sep 2023 14:16:41 +0200 Subject: [PATCH 231/421] [nrf fromtree] Bluetooth: Controller: Fix LE Set Ext Adv Param Cmd invalid status Fix HCI LE Set Extended Advertising Parameter Command invalid status reason. Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit 879c611f58c2af8ed26af4cbb54a96ca42f52ad9) Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit ae5d8e2eec5ee1b744f1b2d74a6220e4fcbd5ca8) --- subsys/bluetooth/controller/ll_sw/ull_adv.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/subsys/bluetooth/controller/ll_sw/ull_adv.c b/subsys/bluetooth/controller/ll_sw/ull_adv.c index d7d5b23f63e..b5595e5e9c2 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_adv.c +++ b/subsys/bluetooth/controller/ll_sw/ull_adv.c @@ -690,7 +690,7 @@ uint8_t ll_adv_params_set(uint16_t interval, uint8_t adv_type, lll_adv_data_reset(&adv->lll.scan_rsp); err = lll_adv_aux_data_init(&adv->lll.scan_rsp); if (err) { - return err; + return BT_HCI_ERR_MEM_CAPACITY_EXCEEDED; } pdu = lll_adv_scan_rsp_peek(&adv->lll); @@ -710,7 +710,7 @@ uint8_t ll_adv_params_set(uint16_t interval, uint8_t adv_type, lll_adv_data_reset(&adv->lll.scan_rsp); err = lll_adv_data_init(&adv->lll.scan_rsp); if (err) { - return err; + return BT_HCI_ERR_MEM_CAPACITY_EXCEEDED; } pdu = lll_adv_scan_rsp_peek(&adv->lll); @@ -926,7 +926,7 @@ uint8_t ll_adv_enable(uint8_t enable) err = lll_adv_data_init(&adv->lll.scan_rsp); if (err) { - return err; + return BT_HCI_ERR_MEM_CAPACITY_EXCEEDED; } pdu_scan = lll_adv_scan_rsp_peek(lll); @@ -1873,7 +1873,7 @@ uint8_t ull_scan_rsp_set(struct ll_adv_set *adv, uint8_t len, err = lll_adv_data_init(&adv->lll.scan_rsp); if (err) { - return err; + return BT_HCI_ERR_MEM_CAPACITY_EXCEEDED; } prev = lll_adv_scan_rsp_peek(&adv->lll); From 1d6f3410fd50fe1b4920a95c3928f2e77e77c37d Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Fri, 1 Sep 2023 05:11:50 +0200 Subject: [PATCH 232/421] [nrf fromtree] Revert "Bluetooth: Controller: Fix ull_prepare_dequeue for skipped events" These change are reverted as part of fixing regression failure in LL/DDI/SCN/BV-21-C and LL/DDI/SCN/BV-25-C. This reverts commit 0d54ca876168b7d5d28219af3f3f1a247da49209. Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit 91781306e95c28ca9b96fff242e342acb86edf11) Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit 69d2075b285425dedd0b399bcce008494e03c4ba) --- .../controller/ll_sw/nordic/lll/lll.c | 6 +-- subsys/bluetooth/controller/ll_sw/ull.c | 48 +++++++------------ 2 files changed, 21 insertions(+), 33 deletions(-) diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll.c b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll.c index fe0a031d402..cde3eaaa6ee 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll.c @@ -930,8 +930,8 @@ static uint32_t preempt_ticker_start(struct lll_event *first, TICKER_NULL_REMAINDER, TICKER_NULL_LAZY, TICKER_NULL_SLOT, - preempt_ticker_cb, first->prepare_param.param, - ticker_start_op_cb, NULL); + preempt_ticker_cb, first, + ticker_start_op_cb, first); return ret; } @@ -1007,7 +1007,7 @@ static void preempt(void *param) } /* Preemptor not in pipeline */ - if (next->prepare_param.param != param) { + if (next != param) { uint32_t ret; /* Start the preempt timeout */ diff --git a/subsys/bluetooth/controller/ll_sw/ull.c b/subsys/bluetooth/controller/ll_sw/ull.c index 6be8bc4759e..29cf43cd6d9 100644 --- a/subsys/bluetooth/controller/ll_sw/ull.c +++ b/subsys/bluetooth/controller/ll_sw/ull.c @@ -2063,8 +2063,6 @@ void *ull_prepare_dequeue_iter(uint8_t *idx) void ull_prepare_dequeue(uint8_t caller_id) { - void *param_normal_head = NULL; - void *param_normal_next = NULL; void *param_resume_head = NULL; void *param_resume_next = NULL; struct lll_event *next; @@ -2105,41 +2103,31 @@ void ull_prepare_dequeue(uint8_t caller_id) /* The prepare element was not a resume event, it would * use the radio or was enqueued back into prepare * pipeline with a preempt timeout being set. - * - * Remember the first encountered and the next element - * in the prepare pipeline so that we do not infinitely - * loop through the resume events in prepare pipeline. */ if (!is_resume) { - if (!param_normal_head) { - param_normal_head = param; - } else if (!param_normal_next) { - param_normal_next = param; - } - } else { - if (!param_resume_head) { - param_resume_head = param; - } else if (!param_resume_next) { - param_resume_next = param; - } + break; + } + + /* Remember the first encountered resume and the next + * resume element in the prepare pipeline so that we do + * not infinitely loop through the resume events in + * prepare pipeline. + */ + if (!param_resume_head) { + param_resume_head = param; + } else if (!param_resume_next) { + param_resume_next = param; } /* Stop traversing the prepare pipeline when we reach - * back to the first or next event where we + * back to the first or next resume event where we * initially started processing the prepare pipeline. */ - if (!next->is_aborted && - ((!next->is_resume && - ((next->prepare_param.param == - param_normal_head) || - (next->prepare_param.param == - param_normal_next))) || - (next->is_resume && - !param_normal_next && - ((next->prepare_param.param == - param_resume_head) || - (next->prepare_param.param == - param_resume_next))))) { + if (next->is_resume && + ((next->prepare_param.param == + param_resume_head) || + (next->prepare_param.param == + param_resume_next))) { break; } } From cb9acc327517604cbdf672db7e60e09623c0b053 Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Fri, 1 Sep 2023 05:18:47 +0200 Subject: [PATCH 233/421] [nrf fromtree] Bluetooth: Controller: Use the state/role param in prepare pipeline Use the state/role context parameter in prepare pipeline to identify the preempt timeout that was setup. Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit dacadf2f1a987339cb4ec08e29fd88b77f8e5ae6) Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit 3494cea88c375065424b4c1873e184fefd48eea9) --- subsys/bluetooth/controller/ll_sw/nordic/lll/lll.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll.c b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll.c index cde3eaaa6ee..fe0a031d402 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll.c @@ -930,8 +930,8 @@ static uint32_t preempt_ticker_start(struct lll_event *first, TICKER_NULL_REMAINDER, TICKER_NULL_LAZY, TICKER_NULL_SLOT, - preempt_ticker_cb, first, - ticker_start_op_cb, first); + preempt_ticker_cb, first->prepare_param.param, + ticker_start_op_cb, NULL); return ret; } @@ -1007,7 +1007,7 @@ static void preempt(void *param) } /* Preemptor not in pipeline */ - if (next != param) { + if (next->prepare_param.param != param) { uint32_t ret; /* Start the preempt timeout */ From 146b77c3f11030a321efb7cf7eec51f76a13e0a8 Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Sat, 2 Sep 2023 09:18:23 +0530 Subject: [PATCH 234/421] [nrf fromtree] Bluetooth: Controller: Use ticker_ticks_diff_get to check short prepare Use ticker_ticks_diff_get consistently when calculating difference between ticker ticks when determining short prepare requests. Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit 67a2fc429320f4422faa35adbfc2fff14ee198de) Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit 0d3ec7701bc79d2131943c3de1cd57aa5130914d) --- subsys/bluetooth/controller/ll_sw/nordic/lll/lll.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll.c b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll.c index fe0a031d402..b127e60a9f4 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll.c @@ -869,6 +869,13 @@ static uint32_t preempt_ticker_start(struct lll_event *first, (preempt_req != preempt_ack)) { uint32_t diff; + /* preempt timeout already started but no role/state in the head + * of prepare pipeline. + */ + if (!prev || prev->is_aborted) { + return TICKER_STATUS_SUCCESS; + } + /* Calc the preempt timeout */ p = &next->prepare_param; ull = HDR_LLL2ULL(p->param); @@ -881,9 +888,9 @@ static uint32_t preempt_ticker_start(struct lll_event *first, ticks_at_preempt_new &= HAL_TICKER_CNTR_MASK; /* Check for short preempt timeouts */ - diff = ticks_at_preempt_new - ticks_at_preempt; - if (!prev || prev->is_aborted || - ((diff & BIT(HAL_TICKER_CNTR_MSBIT)) == 0U)) { + diff = ticker_ticks_diff_get(ticks_at_preempt_new, + ticks_at_preempt); + if ((diff & BIT(HAL_TICKER_CNTR_MSBIT)) == 0U) { return TICKER_STATUS_SUCCESS; } From 368963a73f394687b0fd9b648942d7674213d201 Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Fri, 1 Sep 2023 05:35:19 +0200 Subject: [PATCH 235/421] [nrf fromtree] Bluetooth: Controller: Fix ticks_slot_window use in Observer Fix ticks_slot_window use in Observer, do not use for unreserved continuous scanning, and do not use when scanning on both 1M and Coded PHY simultaneously. Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit 377e2a1f48720a53e8b727eba32d40442c1ad46b) Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit 13b422479ccd0cce310059ec3b9c2b88fc1c798f) --- subsys/bluetooth/controller/ll_sw/ull_scan.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/subsys/bluetooth/controller/ll_sw/ull_scan.c b/subsys/bluetooth/controller/ll_sw/ull_scan.c index 1ee99565a13..21d6cc9c401 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_scan.c +++ b/subsys/bluetooth/controller/ll_sw/ull_scan.c @@ -500,6 +500,10 @@ uint8_t ull_scan_enable(struct ll_scan_set *scan) * enabled. */ } + +#if defined(CONFIG_BT_TICKER_EXT) + ll_scan_ticker_ext[handle].ticks_slot_window = 0U; +#endif /* CONFIG_BT_TICKER_EXT */ } /* 1M scan window starts without any offset */ @@ -559,6 +563,10 @@ uint8_t ull_scan_enable(struct ll_scan_set *scan) } else { ticks_offset = 0U; } + +#if defined(CONFIG_BT_TICKER_EXT) + ll_scan_ticker_ext[handle].ticks_slot_window = 0U; +#endif /* CONFIG_BT_TICKER_EXT */ } else { ticks_offset = 0U; } From 3cefcc0b7485c4bdf5c494b9dda99921d5a36ae7 Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Tue, 18 Jan 2022 17:52:06 +0530 Subject: [PATCH 236/421] [nrf fromtree] Bluetooth: Controller: Fix short prepare when many enqueued in pipeline Fix short prepare handling when more than one event is enqueued in the pipeline and the short prepare is placed at the end of the prepare pipeline. Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit 7f388bb70a3dadb5b3d4a2b4d2a63d1837108492) Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit f200aa6c187e72e344ca531c95717c6ba0d139eb) --- .../controller/ll_sw/nordic/lll/lll.c | 69 ++++++++++++------- 1 file changed, 46 insertions(+), 23 deletions(-) diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll.c b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll.c index b127e60a9f4..9ccc36e49e5 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll.c @@ -899,15 +899,6 @@ static uint32_t preempt_ticker_start(struct lll_event *first, LL_ASSERT((ret == TICKER_STATUS_SUCCESS) || (ret == TICKER_STATUS_BUSY)); - /* Set early as we get called again through the call to - * abort_cb(). - */ - ticks_at_preempt = ticks_at_preempt_new; - - /* Abort previous prepare that set the preempt timeout */ - prev->is_aborted = 1U; - prev->abort_cb(&prev->prepare_param, prev->prepare_param.param); - /* Schedule short preempt timeout */ first = next; } else { @@ -996,17 +987,11 @@ static void preempt(void *param) return; } - /* Check if any prepare in pipeline */ - idx = UINT8_MAX; - next = ull_prepare_dequeue_iter(&idx); - if (!next) { - return; - } - /* Find a prepare that is ready and not a resume */ - while (next && (next->is_aborted || next->is_resume)) { + idx = UINT8_MAX; + do { next = ull_prepare_dequeue_iter(&idx); - } + } while (next && (next->is_aborted || next->is_resume)); /* No ready prepare */ if (!next) { @@ -1015,14 +1000,52 @@ static void preempt(void *param) /* Preemptor not in pipeline */ if (next->prepare_param.param != param) { + struct lll_event *next_next = NULL; + struct lll_event *e; uint32_t ret; - /* Start the preempt timeout */ - ret = preempt_ticker_start(next, NULL, next); - LL_ASSERT((ret == TICKER_STATUS_SUCCESS) || - (ret == TICKER_STATUS_BUSY)); + /* Find if a short prepare request in the pipeline */ + do { + e = ull_prepare_dequeue_iter(&idx); + if (!next_next && e && !e->is_aborted && + !e->is_resume) { + next_next = e; + } + } while (e && (e->is_aborted || e->is_resume || + (e->prepare_param.param != param))); - return; + /* No short prepare request in pipeline */ + if (!e) { + /* Start the preempt timeout for next event */ + ret = preempt_ticker_start(next, NULL, next); + LL_ASSERT((ret == TICKER_STATUS_SUCCESS) || + (ret == TICKER_STATUS_BUSY)); + + return; + } + + /* FIXME: Abort all events in pipeline before the short + * prepare event. For now, lets assert when many + * enqueued prepares need aborting. + */ + LL_ASSERT(next_next == e); + + /* Abort the prepare that is present before the short prepare */ + next->is_aborted = 1; + next->abort_cb(&next->prepare_param, next->prepare_param.param); + + /* As the prepare queue has been refreshed due to the call of + * abort_cb which invokes the lll_done, find the latest prepare + */ + idx = UINT8_MAX; + do { + next = ull_prepare_dequeue_iter(&idx); + } while (next && (next->is_aborted || next->is_resume)); + + /* No ready prepare */ + if (!next) { + return; + } } /* Check if current event want to continue */ From 290662fbfd0c9aecf7067a2440db51b9d6260027 Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Wed, 20 Sep 2023 09:54:23 +0200 Subject: [PATCH 237/421] [nrf fromtree] Bluetooth: Controller: Refactor prepare dequeue iteration code Refactor/rename prepare dequeue iteration code and reuse it. Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit c1042dff408cb37947e069e963c4424a249db525) Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit 0a00dd78411e6b42f4dd9ada16196a1b44d900c1) --- .../controller/ll_sw/nordic/lll/lll.c | 165 +++++++++--------- 1 file changed, 82 insertions(+), 83 deletions(-) diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll.c b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll.c index 9ccc36e49e5..db8f25a374c 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll.c @@ -65,7 +65,9 @@ static int init_reset(void); #if defined(CONFIG_BT_CTLR_LOW_LAT_ULL_DONE) static inline void done_inc(void); #endif /* CONFIG_BT_CTLR_LOW_LAT_ULL_DONE */ -static struct lll_event *resume_enqueue(lll_prepare_cb_t resume_cb); +static inline bool is_done_sync(void); +static inline struct lll_event *prepare_dequeue_iter_ready_get(uint8_t *idx); +static inline struct lll_event *resume_enqueue(lll_prepare_cb_t resume_cb); static void isr_race(void *param); #if !defined(CONFIG_BT_CTLR_LOW_LAT) @@ -643,52 +645,27 @@ void lll_isr_early_abort(void *param) lll_done(NULL); } -static int init_reset(void) -{ - return 0; -} - -#if defined(CONFIG_BT_CTLR_LOW_LAT_ULL_DONE) -static inline void done_inc(void) -{ - event.done.lll_count++; - LL_ASSERT(event.done.lll_count != event.done.ull_count); -} -#endif /* CONFIG_BT_CTLR_LOW_LAT_ULL_DONE */ - -static inline bool is_done_sync(void) -{ -#if defined(CONFIG_BT_CTLR_LOW_LAT_ULL_DONE) - return event.done.lll_count == event.done.ull_count; -#else /* !CONFIG_BT_CTLR_LOW_LAT_ULL_DONE */ - return true; -#endif /* !CONFIG_BT_CTLR_LOW_LAT_ULL_DONE */ -} - int lll_prepare_resolve(lll_is_abort_cb_t is_abort_cb, lll_abort_cb_t abort_cb, lll_prepare_cb_t prepare_cb, struct lll_prepare_param *prepare_param, uint8_t is_resume, uint8_t is_dequeue) { - struct lll_event *p; + struct lll_event *ready; + struct lll_event *next; uint8_t idx; int err; /* Find the ready prepare in the pipeline */ idx = UINT8_MAX; - p = ull_prepare_dequeue_iter(&idx); - while (p && (p->is_aborted || p->is_resume)) { - p = ull_prepare_dequeue_iter(&idx); - } + ready = prepare_dequeue_iter_ready_get(&idx); /* Current event active or another prepare is ready in the pipeline */ if ((!is_dequeue && !is_done_sync()) || event.curr.abort_cb || - (p && is_resume)) { + (ready && is_resume)) { #if defined(CONFIG_BT_CTLR_LOW_LAT) lll_prepare_cb_t resume_cb; #endif /* CONFIG_BT_CTLR_LOW_LAT */ - struct lll_event *next; if (IS_ENABLED(CONFIG_BT_CTLR_LOW_LAT) && event.curr.param) { /* early abort */ @@ -706,29 +683,28 @@ int lll_prepare_resolve(lll_is_abort_cb_t is_abort_cb, lll_abort_cb_t abort_cb, } /* Always start preempt timeout for first prepare in pipeline */ - struct lll_event *first = p ? p : next; + struct lll_event *first = ready ? ready : next; uint32_t ret; /* Start the preempt timeout */ - ret = preempt_ticker_start(first, p, next); + ret = preempt_ticker_start(first, ready, next); LL_ASSERT((ret == TICKER_STATUS_SUCCESS) || (ret == TICKER_STATUS_BUSY)); #else /* CONFIG_BT_CTLR_LOW_LAT */ next = NULL; - while (p) { - if (!p->is_aborted) { - if (event.curr.param == - p->prepare_param.param) { - p->is_aborted = 1; - p->abort_cb(&p->prepare_param, - p->prepare_param.param); + while (ready) { + if (!ready->is_aborted) { + if (event.curr.param == ready->prepare_param.param) { + ready->is_aborted = 1; + ready->abort_cb(&ready->prepare_param, + ready->prepare_param.param); } else { - next = p; + next = ready; } } - p = ull_prepare_dequeue_iter(&idx); + ready = ull_prepare_dequeue_iter(&idx); } if (next) { @@ -749,7 +725,7 @@ int lll_prepare_resolve(lll_is_abort_cb_t is_abort_cb, lll_abort_cb_t abort_cb, return -EINPROGRESS; } - LL_ASSERT(!p || &p->prepare_param == prepare_param); + LL_ASSERT(!ready || &ready->prepare_param == prepare_param); event.curr.param = prepare_param->param; event.curr.is_abort_cb = is_abort_cb; @@ -774,15 +750,13 @@ int lll_prepare_resolve(lll_is_abort_cb_t is_abort_cb, lll_abort_cb_t abort_cb, */ /* Find next prepare needing preempt timeout to be setup */ - do { - p = ull_prepare_dequeue_iter(&idx); - if (!p) { - return err; - } - } while (p->is_aborted || p->is_resume); + next = prepare_dequeue_iter_ready_get(&idx); + if (!next) { + return err; + } /* Start the preempt timeout */ - ret = preempt_ticker_start(p, NULL, p); + ret = preempt_ticker_start(next, NULL, next); LL_ASSERT((ret == TICKER_STATUS_SUCCESS) || (ret == TICKER_STATUS_BUSY)); #endif /* !CONFIG_BT_CTLR_LOW_LAT */ @@ -790,7 +764,40 @@ int lll_prepare_resolve(lll_is_abort_cb_t is_abort_cb, lll_abort_cb_t abort_cb, return err; } -static struct lll_event *resume_enqueue(lll_prepare_cb_t resume_cb) +static int init_reset(void) +{ + return 0; +} + +#if defined(CONFIG_BT_CTLR_LOW_LAT_ULL_DONE) +static inline void done_inc(void) +{ + event.done.lll_count++; + LL_ASSERT(event.done.lll_count != event.done.ull_count); +} +#endif /* CONFIG_BT_CTLR_LOW_LAT_ULL_DONE */ + +static inline bool is_done_sync(void) +{ +#if defined(CONFIG_BT_CTLR_LOW_LAT_ULL_DONE) + return event.done.lll_count == event.done.ull_count; +#else /* !CONFIG_BT_CTLR_LOW_LAT_ULL_DONE */ + return true; +#endif /* !CONFIG_BT_CTLR_LOW_LAT_ULL_DONE */ +} + +static inline struct lll_event *prepare_dequeue_iter_ready_get(uint8_t *idx) +{ + struct lll_event *ready; + + do { + ready = ull_prepare_dequeue_iter(idx); + } while (ready && (ready->is_aborted || ready->is_resume)); + + return ready; +} + +static inline struct lll_event *resume_enqueue(lll_prepare_cb_t resume_cb) { struct lll_prepare_param prepare_param = {0}; @@ -978,7 +985,7 @@ static void preempt_ticker_cb(uint32_t ticks_at_expire, uint32_t ticks_drift, static void preempt(void *param) { lll_prepare_cb_t resume_cb; - struct lll_event *next; + struct lll_event *ready; uint8_t idx; int err; @@ -989,35 +996,32 @@ static void preempt(void *param) /* Find a prepare that is ready and not a resume */ idx = UINT8_MAX; - do { - next = ull_prepare_dequeue_iter(&idx); - } while (next && (next->is_aborted || next->is_resume)); - - /* No ready prepare */ - if (!next) { + ready = prepare_dequeue_iter_ready_get(&idx); + if (!ready) { + /* No ready prepare */ return; } /* Preemptor not in pipeline */ - if (next->prepare_param.param != param) { - struct lll_event *next_next = NULL; - struct lll_event *e; + if (ready->prepare_param.param != param) { + struct lll_event *ready_next = NULL; + struct lll_event *preemptor; uint32_t ret; /* Find if a short prepare request in the pipeline */ do { - e = ull_prepare_dequeue_iter(&idx); - if (!next_next && e && !e->is_aborted && - !e->is_resume) { - next_next = e; + preemptor = ull_prepare_dequeue_iter(&idx); + if (!ready_next && preemptor && !preemptor->is_aborted && + !preemptor->is_resume) { + ready_next = preemptor; } - } while (e && (e->is_aborted || e->is_resume || - (e->prepare_param.param != param))); + } while (preemptor && (preemptor->is_aborted || preemptor->is_resume || + (preemptor->prepare_param.param != param))); /* No short prepare request in pipeline */ - if (!e) { - /* Start the preempt timeout for next event */ - ret = preempt_ticker_start(next, NULL, next); + if (!preemptor) { + /* Start the preempt timeout for ready event */ + ret = preempt_ticker_start(ready, NULL, ready); LL_ASSERT((ret == TICKER_STATUS_SUCCESS) || (ret == TICKER_STATUS_BUSY)); @@ -1028,34 +1032,29 @@ static void preempt(void *param) * prepare event. For now, lets assert when many * enqueued prepares need aborting. */ - LL_ASSERT(next_next == e); + LL_ASSERT(preemptor == ready_next); /* Abort the prepare that is present before the short prepare */ - next->is_aborted = 1; - next->abort_cb(&next->prepare_param, next->prepare_param.param); + ready->is_aborted = 1; + ready->abort_cb(&ready->prepare_param, ready->prepare_param.param); /* As the prepare queue has been refreshed due to the call of * abort_cb which invokes the lll_done, find the latest prepare */ idx = UINT8_MAX; - do { - next = ull_prepare_dequeue_iter(&idx); - } while (next && (next->is_aborted || next->is_resume)); - - /* No ready prepare */ - if (!next) { + ready = prepare_dequeue_iter_ready_get(&idx); + if (!ready) { + /* No ready prepare */ return; } } /* Check if current event want to continue */ - err = event.curr.is_abort_cb(next->prepare_param.param, - event.curr.param, - &resume_cb); + err = event.curr.is_abort_cb(ready->prepare_param.param, event.curr.param, &resume_cb); if (!err) { /* Let preemptor LLL know about the cancelled prepare */ - next->is_aborted = 1; - next->abort_cb(&next->prepare_param, next->prepare_param.param); + ready->is_aborted = 1; + ready->abort_cb(&ready->prepare_param, ready->prepare_param.param); return; } From c86add5e2012481673862ff86407a15979280e0b Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Sun, 26 Mar 2023 21:38:42 +0530 Subject: [PATCH 238/421] [nrf fromtree] Bluetooth: Controller: Reduce successive ticker_job() on Extended Scan Reduce number of successive calls to ticker_job() by disabling mayflies in the ULL_HIGH priority, enqueue ticker_yield_abs() and ticker_start() before re-enabling so that single ticker_job() handles both yield and start. Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit 02b1c768206291a8f4d105a34ab357b973240195) Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit 1902baed85baf58cf7f5436e06ce28efe0e05e58) --- subsys/bluetooth/controller/ll_sw/ull_scan_aux.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/subsys/bluetooth/controller/ll_sw/ull_scan_aux.c b/subsys/bluetooth/controller/ll_sw/ull_scan_aux.c index 316cec7fec7..ecdfdd60d07 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_scan_aux.c +++ b/subsys/bluetooth/controller/ll_sw/ull_scan_aux.c @@ -682,6 +682,13 @@ void ull_scan_aux_setup(memq_link_t *link, struct node_rx_hdr *rx) ticks_aux_offset = HAL_TICKER_US_TO_TICKS(aux_offset_us); +#if (CONFIG_BT_CTLR_ULL_HIGH_PRIO == CONFIG_BT_CTLR_ULL_LOW_PRIO) + /* disable ticker job, in order to chain yield and start to reduce + * CPU use by reducing successive calls to ticker_job(). + */ + mayfly_enable(TICKER_USER_ID_ULL_HIGH, TICKER_USER_ID_ULL_LOW, 0); +#endif + /* Yield the primary scan window or auxiliary or periodic sync event * in ticker. */ @@ -714,6 +721,13 @@ void ull_scan_aux_setup(memq_link_t *link, struct node_rx_hdr *rx) ((ticker_status == TICKER_STATUS_FAILURE) && IS_ENABLED(CONFIG_BT_TICKER_LOW_LAT))); +#if (CONFIG_BT_CTLR_ULL_HIGH_PRIO == CONFIG_BT_CTLR_ULL_LOW_PRIO) + /* enable ticker job, queued ticker operation will be handled + * thereafter. + */ + mayfly_enable(TICKER_USER_ID_ULL_HIGH, TICKER_USER_ID_ULL_LOW, 1); +#endif + return; ull_scan_aux_rx_flush: From 064912923c684da6a02b32ebec9a895b4f2ae319 Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Mon, 4 Sep 2023 15:26:18 +0530 Subject: [PATCH 239/421] [nrf fromtree] Bluetooth: Controller: Revert EVENT_OVERHEAD_START_US for Coded PHY Revert EVENT_OVERHEAD_START_US value for Coded PHY support, needed to pass LL/DDI/SCN/BV-21-C and LL/DDI/SCN/BV-25-C. Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit d8f0006de5182d233ab1a438fe8594c2faa4372e) Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit 8418b5780f68c264214172a636f0bb87ddbfef21) --- subsys/bluetooth/controller/ll_sw/nordic/lll/lll_vendor.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_vendor.h b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_vendor.h index 7df39f65c8a..db5f8e3f1d8 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_vendor.h +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_vendor.h @@ -21,22 +21,22 @@ /* Active connection in peripheral role with extended scanning on 1M and Coded * PHY, scheduling and receiving auxiliary PDUs. */ -#define EVENT_OVERHEAD_START_US 458 +#define EVENT_OVERHEAD_START_US 733 /* 24 RTC ticks */ #else /* !CONFIG_BT_CTLR_PHY_CODED */ /* Active connection in peripheral role with extended scanning on 1M only, * scheduling and receiving auxiliary PDUs. */ -#define EVENT_OVERHEAD_START_US 428 +#define EVENT_OVERHEAD_START_US 428 /* 14 RTC ticks */ #endif /* !CONFIG_BT_CTLR_PHY_CODED */ #else /* !CONFIG_BT_OBSERVER */ /* Active connection in peripheral role with legacy scanning on 1M. */ -#define EVENT_OVERHEAD_START_US 275 +#define EVENT_OVERHEAD_START_US 275 /* 9 RTC ticks */ #endif /* !CONFIG_BT_OBSERVER */ #else /* !CONFIG_BT_CTLR_ADV_EXT */ /* Active connection in peripheral role with additional advertising state. */ -#define EVENT_OVERHEAD_START_US 275 +#define EVENT_OVERHEAD_START_US 275 /* 9 RTC ticks */ #endif /* !CONFIG_BT_CTLR_ADV_EXT */ /* Worst-case time margin needed after event end-time in the air From 46a5b07bbc1d5dd0ed2c5bb7a12d4996d6703795 Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Thu, 6 Jul 2023 06:05:42 +0530 Subject: [PATCH 240/421] [nrf fromtree] Bluetooth: Controller: Minor rename ull_adv_sync_iso_created() Minor rename to ull_adv_sync_iso_created(). Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit 5b4eb9bc76b68c50d1babdef988efcce2491ce4a) Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit 65ab80d42f80c8d7d8ee7c6a0e8e794b4cdaeafd) --- subsys/bluetooth/controller/ll_sw/ull_adv_internal.h | 2 +- subsys/bluetooth/controller/ll_sw/ull_adv_iso.c | 2 +- subsys/bluetooth/controller/ll_sw/ull_adv_sync.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/subsys/bluetooth/controller/ll_sw/ull_adv_internal.h b/subsys/bluetooth/controller/ll_sw/ull_adv_internal.h index 00bf3c126df..f4d059e0cd3 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_adv_internal.h +++ b/subsys/bluetooth/controller/ll_sw/ull_adv_internal.h @@ -205,7 +205,7 @@ ull_adv_aux_hdr_len_fill(struct pdu_adv_com_ext_adv *com_hdr, uint8_t len) void ull_adv_sync_started_stopped(struct ll_adv_aux_set *aux); /* notify adv_sync_set that an iso instance has been created for it */ -void ull_adv_iso_created(struct ll_adv_sync_set *sync); +void ull_adv_sync_iso_created(struct ll_adv_sync_set *sync); #endif /* CONFIG_BT_CTLR_ADV_EXT */ diff --git a/subsys/bluetooth/controller/ll_sw/ull_adv_iso.c b/subsys/bluetooth/controller/ll_sw/ull_adv_iso.c index 89e66ff99e5..cb53f913b01 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_adv_iso.c +++ b/subsys/bluetooth/controller/ll_sw/ull_adv_iso.c @@ -487,7 +487,7 @@ uint8_t ll_big_create(uint8_t big_handle, uint8_t adv_handle, uint8_t num_bis, #if defined(CONFIG_BT_TICKER_EXT_EXPIRE_INFO) /* Notify the sync instance */ - ull_adv_iso_created(HDR_LLL2ULL(lll_adv_sync)); + ull_adv_sync_iso_created(HDR_LLL2ULL(lll_adv_sync)); #endif /* CONFIG_BT_TICKER_EXT_EXPIRE_INFO */ /* Commit the BIGInfo in the ACAD field of Periodic Advertising */ diff --git a/subsys/bluetooth/controller/ll_sw/ull_adv_sync.c b/subsys/bluetooth/controller/ll_sw/ull_adv_sync.c index bbb1b351848..f1f521ca235 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_adv_sync.c +++ b/subsys/bluetooth/controller/ll_sw/ull_adv_sync.c @@ -222,7 +222,7 @@ uint8_t ll_adv_sync_param_set(uint8_t handle, uint16_t interval, uint16_t flags) } #if defined(CONFIG_BT_CTLR_ADV_ISO) && defined(CONFIG_BT_TICKER_EXT_EXPIRE_INFO) -void ull_adv_iso_created(struct ll_adv_sync_set *sync) +void ull_adv_sync_iso_created(struct ll_adv_sync_set *sync) { if (sync->lll.iso && sync->is_started) { uint8_t iso_handle = sync->lll.iso->handle; From 5066d19a144b3096e6ee5c6ceb755b7589938a5e Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Wed, 5 Jul 2023 05:29:24 +0530 Subject: [PATCH 241/421] [nrf fromtree] Bluetooth: Controller: Calculate Broadcast ISO event overheads Calculate Broadcast ISO event overheads due to extended and periodic advertising events. Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit 87138e7ee34a54e609f45f3fb1acb5475e745cea) Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit cbc4b5ed65c4df3a7875bfa4b355dc3416a284cd) --- .../bluetooth/controller/ll_sw/ull_adv_iso.c | 52 ++++++++++++++++--- 1 file changed, 46 insertions(+), 6 deletions(-) diff --git a/subsys/bluetooth/controller/ll_sw/ull_adv_iso.c b/subsys/bluetooth/controller/ll_sw/ull_adv_iso.c index cb53f913b01..4551fac228d 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_adv_iso.c +++ b/subsys/bluetooth/controller/ll_sw/ull_adv_iso.c @@ -97,13 +97,19 @@ uint8_t ll_big_create(uint8_t big_handle, uint8_t adv_handle, uint8_t num_bis, struct ll_adv_iso_set *adv_iso; struct pdu_adv *pdu_prev, *pdu; struct pdu_big_info *big_info; + uint32_t ticks_slot_overhead; + struct ll_adv_sync_set *sync; + struct ll_adv_aux_set *aux; uint32_t event_spacing_max; uint8_t pdu_big_info_size; uint32_t iso_interval_us; uint32_t latency_packing; + uint32_t ticks_slot_sync; + uint32_t ticks_slot_aux; memq_link_t *link_cmplt; memq_link_t *link_term; struct ll_adv_set *adv; + uint32_t slot_overhead; uint32_t event_spacing; uint16_t ctrl_spacing; uint8_t sdu_per_event; @@ -275,14 +281,48 @@ uint8_t ll_big_create(uint8_t big_handle, uint8_t adv_handle, uint8_t num_bis, lll_adv_iso->num_bis; event_spacing = latency_packing + ctrl_spacing + EVENT_OVERHEAD_START_US + EVENT_OVERHEAD_END_US; - /* FIXME: calculate overheads due to extended and periodic advertising. + + /* Calculate overheads due to extended advertising. */ + aux = HDR_LLL2ULL(adv->lll.aux); + ticks_slot_aux = aux->ull.ticks_slot; + if (IS_ENABLED(CONFIG_BT_CTLR_LOW_LAT)) { + ticks_slot_overhead = MAX(aux->ull.ticks_active_to_start, + aux->ull.ticks_prepare_to_start); + } else { + ticks_slot_overhead = 0U; + } + ticks_slot_aux += ticks_slot_overhead; + + /* Calculate overheads due to periodic advertising. */ + sync = HDR_LLL2ULL(lll_adv_sync); + ticks_slot_sync = sync->ull.ticks_slot; + if (IS_ENABLED(CONFIG_BT_CTLR_LOW_LAT)) { + ticks_slot_overhead = MAX(sync->ull.ticks_active_to_start, + sync->ull.ticks_prepare_to_start); + } else { + ticks_slot_overhead = 0U; + } + ticks_slot_sync += ticks_slot_overhead; + + /* Calculate total overheads due to extended and periodic advertising */ + if (CONFIG_BT_CTLR_ADV_AUX_SYNC_OFFSET > 0U) { + ticks_slot_overhead = MAX(ticks_slot_aux, ticks_slot_sync); + } else { + ticks_slot_overhead = ticks_slot_aux + ticks_slot_sync; + } + + /* Calculate max available ISO event spacing */ + slot_overhead = HAL_TICKER_TICKS_TO_US(ticks_slot_overhead); + if (slot_overhead < iso_interval_us) { + event_spacing_max = iso_interval_us - slot_overhead; + } else { + event_spacing_max = 0U; + } + + /* Check if ISO interval too small to fit the calculated BIG event + * timing required for the supplied BIG create parameters. */ - event_spacing_max = iso_interval_us - 2000U; if (event_spacing > event_spacing_max) { - /* ISO interval too small to fit the calculated BIG event - * timing required for the supplied BIG create parameters. - */ - /* Release allocated link buffers */ ll_rx_link_release(link_cmplt); ll_rx_link_release(link_term); From 15f89d667165914c90f6b5931e3d15b97f624f4a Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Tue, 31 Jan 2023 12:30:49 +0530 Subject: [PATCH 242/421] [nrf fromtree] Bluetooth: Controller: Maximize BIG event length and preempt PTO & CTRL Maximize BIG event length to extend upto ISO interval, and allow PTO and Control subevents to be pre-emptible. Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit 0f2980db15f3448533c8a978e71daffbde2cdbf2) Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit 10adc66508cc691039a69c0a7ae1b384dfee05f8) --- .../bluetooth/controller/Kconfig.ll_sw_split | 12 +++++ .../bluetooth/controller/ll_sw/ull_adv_iso.c | 51 +++++++++++++------ 2 files changed, 48 insertions(+), 15 deletions(-) diff --git a/subsys/bluetooth/controller/Kconfig.ll_sw_split b/subsys/bluetooth/controller/Kconfig.ll_sw_split index 5fb2c54d085..1fa9031d47f 100644 --- a/subsys/bluetooth/controller/Kconfig.ll_sw_split +++ b/subsys/bluetooth/controller/Kconfig.ll_sw_split @@ -386,6 +386,18 @@ config BT_CTLR_ADV_RESERVE_MAX corresponding to the Advertising Data present at the time of the start/enable of Advertising is used. +config BT_CTLR_ADV_ISO_RESERVE_MAX + bool "Use maximum Broadcast ISO event time reservation" + depends on BT_CTLR_ADV_ISO + default y + help + Use maximum Broadcast ISO event time reservation. If disabled, then + time reservation does not include the pre-transmissions of the last + BIS and any Control subevents. This will allow extended or periodic + advertising events to preempt the BIG events but allow higher radio + utilizations by allowing larger BIG events when not overlapping with + extended or periodic advertising. + config BT_CTLR_ADV_AUX_SYNC_OFFSET int "Pre-defined offset between AUX_ADV_IND and AUX_SYNC_IND" depends on BT_CTLR_ADV_PERIODIC diff --git a/subsys/bluetooth/controller/ll_sw/ull_adv_iso.c b/subsys/bluetooth/controller/ll_sw/ull_adv_iso.c index 4551fac228d..de78352baa2 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_adv_iso.c +++ b/subsys/bluetooth/controller/ll_sw/ull_adv_iso.c @@ -282,27 +282,41 @@ uint8_t ll_big_create(uint8_t big_handle, uint8_t adv_handle, uint8_t num_bis, event_spacing = latency_packing + ctrl_spacing + EVENT_OVERHEAD_START_US + EVENT_OVERHEAD_END_US; + /* Check if aux context allocated before we are creating ISO */ + if (adv->lll.aux) { + aux = HDR_LLL2ULL(adv->lll.aux); + } else { + aux = NULL; + } + /* Calculate overheads due to extended advertising. */ - aux = HDR_LLL2ULL(adv->lll.aux); - ticks_slot_aux = aux->ull.ticks_slot; - if (IS_ENABLED(CONFIG_BT_CTLR_LOW_LAT)) { - ticks_slot_overhead = MAX(aux->ull.ticks_active_to_start, - aux->ull.ticks_prepare_to_start); + if (aux && aux->is_started) { + ticks_slot_aux = aux->ull.ticks_slot; + if (IS_ENABLED(CONFIG_BT_CTLR_LOW_LAT)) { + ticks_slot_overhead = MAX(aux->ull.ticks_active_to_start, + aux->ull.ticks_prepare_to_start); + } else { + ticks_slot_overhead = 0U; + } + ticks_slot_aux += ticks_slot_overhead; } else { - ticks_slot_overhead = 0U; + ticks_slot_aux = 0U; } - ticks_slot_aux += ticks_slot_overhead; /* Calculate overheads due to periodic advertising. */ sync = HDR_LLL2ULL(lll_adv_sync); - ticks_slot_sync = sync->ull.ticks_slot; - if (IS_ENABLED(CONFIG_BT_CTLR_LOW_LAT)) { - ticks_slot_overhead = MAX(sync->ull.ticks_active_to_start, - sync->ull.ticks_prepare_to_start); + if (sync->is_started) { + ticks_slot_sync = sync->ull.ticks_slot; + if (IS_ENABLED(CONFIG_BT_CTLR_LOW_LAT)) { + ticks_slot_overhead = MAX(sync->ull.ticks_active_to_start, + sync->ull.ticks_prepare_to_start); + } else { + ticks_slot_overhead = 0U; + } + ticks_slot_sync += ticks_slot_overhead; } else { - ticks_slot_overhead = 0U; + ticks_slot_sync = 0U; } - ticks_slot_sync += ticks_slot_overhead; /* Calculate total overheads due to extended and periodic advertising */ if (CONFIG_BT_CTLR_ADV_AUX_SYNC_OFFSET > 0U) { @@ -1008,8 +1022,15 @@ static uint32_t adv_iso_start(struct ll_adv_iso_set *adv_iso, EVENT_MSS_US; ctrl_spacing = PDU_BIS_US(sizeof(struct pdu_big_ctrl), lll_iso->enc, lll_iso->phy, lll_iso->phy_flags); - slot_us = (pdu_spacing * lll_iso->nse * lll_iso->num_bis) + - ctrl_spacing; + + if (IS_ENABLED(CONFIG_BT_CTLR_ADV_ISO_RESERVE_MAX)) { + slot_us = (pdu_spacing * lll_iso->nse * lll_iso->num_bis) + + ctrl_spacing; + } else { + slot_us = pdu_spacing * ((lll_iso->nse * lll_iso->num_bis) - + lll_iso->ptc); + } + slot_us += EVENT_OVERHEAD_START_US + EVENT_OVERHEAD_END_US; adv_iso->ull.ticks_active_to_start = 0U; From 5f4e7b0cc6f13cd4c8d659fc8833787d8997fa9e Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Thu, 6 Jul 2023 06:03:43 +0530 Subject: [PATCH 243/421] [nrf fromtree] Bluetooth: Controller: Use max time when scheduling Broadcast ISO Use maximum event time length when scheduling Broadcast ISO events. Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit 3fba1a18e70dbf6d2993ce9fb9d5424601ddce16) Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit 71e9b9f93028ba1420391a314748d364df13dc12) --- .../controller/ll_sw/ull_adv_internal.h | 3 + .../bluetooth/controller/ll_sw/ull_adv_iso.c | 63 +++++++++++++------ subsys/bluetooth/controller/ll_sw/ull_sched.c | 5 +- 3 files changed, 52 insertions(+), 19 deletions(-) diff --git a/subsys/bluetooth/controller/ll_sw/ull_adv_internal.h b/subsys/bluetooth/controller/ll_sw/ull_adv_internal.h index f4d059e0cd3..a2a0db7391f 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_adv_internal.h +++ b/subsys/bluetooth/controller/ll_sw/ull_adv_internal.h @@ -322,6 +322,9 @@ struct lll_adv_iso_stream *ull_adv_iso_stream_get(uint16_t handle); /* helper function to release stream instances */ void ull_adv_iso_stream_release(struct ll_adv_iso_set *adv_iso); +/* helper function to return time reservation for Broadcast ISO event */ +uint32_t ull_adv_iso_max_time_get(const struct ll_adv_iso_set *adv_iso); + #if defined(CONFIG_BT_CTLR_DF_ADV_CTE_TX) /* helper function to release unused DF configuration memory */ void ull_df_adv_cfg_release(struct lll_df_adv_cfg *df_adv_cfg); diff --git a/subsys/bluetooth/controller/ll_sw/ull_adv_iso.c b/subsys/bluetooth/controller/ll_sw/ull_adv_iso.c index de78352baa2..6191f811311 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_adv_iso.c +++ b/subsys/bluetooth/controller/ll_sw/ull_adv_iso.c @@ -57,6 +57,7 @@ static struct stream *adv_iso_stream_acquire(void); static uint16_t adv_iso_stream_handle_get(struct lll_adv_iso_stream *stream); static uint8_t ptc_calc(const struct lll_adv_iso *lll, uint32_t event_spacing, uint32_t event_spacing_max); +static uint32_t adv_iso_time_get(const struct ll_adv_iso_set *adv_iso, bool max); static uint32_t adv_iso_start(struct ll_adv_iso_set *adv_iso, uint32_t iso_interval_us); static uint8_t adv_iso_chm_update(uint8_t big_handle); @@ -945,6 +946,11 @@ void ull_adv_iso_stream_release(struct ll_adv_iso_set *adv_iso) lll->adv = NULL; } +uint32_t ull_adv_iso_max_time_get(const struct ll_adv_iso_set *adv_iso) +{ + return adv_iso_time_get(adv_iso, true); +} + static int init_reset(void) { /* Add initializations common to power up initialization and HCI reset @@ -998,22 +1004,12 @@ static uint8_t ptc_calc(const struct lll_adv_iso *lll, uint32_t event_spacing, return 0U; } -static uint32_t adv_iso_start(struct ll_adv_iso_set *adv_iso, - uint32_t iso_interval_us) +static uint32_t adv_iso_time_get(const struct ll_adv_iso_set *adv_iso, bool max) { - uint32_t ticks_slot_overhead; - struct lll_adv_iso *lll_iso; - uint32_t ticks_slot_offset; - uint32_t volatile ret_cb; - uint32_t ticks_anchor; + const struct lll_adv_iso *lll_iso; uint32_t ctrl_spacing; uint32_t pdu_spacing; - uint32_t ticks_slot; - uint32_t slot_us; - uint32_t ret; - int err; - - ull_hdr_init(&adv_iso->ull); + uint32_t time_us; lll_iso = &adv_iso->lll; @@ -1023,15 +1019,46 @@ static uint32_t adv_iso_start(struct ll_adv_iso_set *adv_iso, ctrl_spacing = PDU_BIS_US(sizeof(struct pdu_big_ctrl), lll_iso->enc, lll_iso->phy, lll_iso->phy_flags); - if (IS_ENABLED(CONFIG_BT_CTLR_ADV_ISO_RESERVE_MAX)) { - slot_us = (pdu_spacing * lll_iso->nse * lll_iso->num_bis) + + /* 1. Maximum PDU transmission time in 1M/2M/S8 PHY is 17040 us, or + * represented in 15-bits. + * 2. NSE in the range 1 to 31 is represented in 5-bits + * 3. num_bis in the range 1 to 31 is represented in 5-bits + * + * Hence, worst case event time can be represented in 25-bits plus + * one each bit for added ctrl_spacing and radio event overheads. I.e. + * 27-bits required and sufficiently covered by using 32-bit data type + * for time_us. + */ + + if (IS_ENABLED(CONFIG_BT_CTLR_ADV_ISO_RESERVE_MAX) || max) { + time_us = (pdu_spacing * lll_iso->nse * lll_iso->num_bis) + ctrl_spacing; } else { - slot_us = pdu_spacing * ((lll_iso->nse * lll_iso->num_bis) - + time_us = pdu_spacing * ((lll_iso->nse * lll_iso->num_bis) - lll_iso->ptc); } - slot_us += EVENT_OVERHEAD_START_US + EVENT_OVERHEAD_END_US; + /* Add implementation defined radio event overheads */ + time_us += EVENT_OVERHEAD_START_US + EVENT_OVERHEAD_END_US; + + return time_us; +} + +static uint32_t adv_iso_start(struct ll_adv_iso_set *adv_iso, + uint32_t iso_interval_us) +{ + uint32_t ticks_slot_overhead; + uint32_t ticks_slot_offset; + volatile uint32_t ret_cb; + uint32_t ticks_anchor; + uint32_t ticks_slot; + uint32_t slot_us; + uint32_t ret; + int err; + + ull_hdr_init(&adv_iso->ull); + + slot_us = adv_iso_time_get(adv_iso, false); adv_iso->ull.ticks_active_to_start = 0U; adv_iso->ull.ticks_prepare_to_start = @@ -1066,7 +1093,7 @@ static uint32_t adv_iso_start(struct ll_adv_iso_set *adv_iso, ret_cb = TICKER_STATUS_BUSY; ret = ticker_start(TICKER_INSTANCE_ID_CTLR, TICKER_USER_ID_THREAD, - (TICKER_ID_ADV_ISO_BASE + lll_iso->handle), + (TICKER_ID_ADV_ISO_BASE + adv_iso->lll.handle), ticks_anchor, 0U, HAL_TICKER_US_TO_TICKS(iso_interval_us), HAL_TICKER_REMAINDER(iso_interval_us), diff --git a/subsys/bluetooth/controller/ll_sw/ull_sched.c b/subsys/bluetooth/controller/ll_sw/ull_sched.c index e7ca8a0358b..38589a2e644 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_sched.c +++ b/subsys/bluetooth/controller/ll_sw/ull_sched.c @@ -701,7 +701,10 @@ static struct ull_hdr *ull_hdr_get_cb(uint8_t ticker_id, uint32_t *ticks_slot) adv_iso = ull_adv_iso_get(ticker_id - TICKER_ID_ADV_ISO_BASE); if (adv_iso) { - *ticks_slot = adv_iso->ull.ticks_slot; + uint32_t time_us; + + time_us = ull_adv_iso_max_time_get(adv_iso); + *ticks_slot = HAL_TICKER_US_TO_TICKS_CEIL(time_us); return &adv_iso->ull; } From 18f4f8597ba8339cb26fde13ac9917d027fca9ec Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Thu, 17 Aug 2023 01:55:58 +0530 Subject: [PATCH 244/421] [nrf fromtree] Bluetooth: Controller: Fix PHY value in HCI LE CIS Established Event Fix PHY_C_TO_P and PHY_P_TO_C value in HCI LE CIS Established Event. Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit e4cc5838fd8f32ffa73b808a9a6505bb1b0ae6a9) Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit 834626a2bf61c8c641bf8cc31d0172079067d59a) --- subsys/bluetooth/controller/hci/hci.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/subsys/bluetooth/controller/hci/hci.c b/subsys/bluetooth/controller/hci/hci.c index 30fb363fc9c..0adbf5ff70c 100644 --- a/subsys/bluetooth/controller/hci/hci.c +++ b/subsys/bluetooth/controller/hci/hci.c @@ -4245,8 +4245,8 @@ static void le_cis_established(struct pdu_data *pdu_data, sys_put_le24(cis->sync_delay, sep->cis_sync_delay); sys_put_le24(cig->c_latency, sep->c_latency); sys_put_le24(cig->p_latency, sep->p_latency); - sep->c_phy = lll_cis_c->phy; - sep->p_phy = lll_cis_p->phy; + sep->c_phy = find_lsb_set(lll_cis_c->phy); + sep->p_phy = find_lsb_set(lll_cis_p->phy); sep->nse = lll_cis->nse; sep->c_bn = lll_cis_c->bn; sep->p_bn = lll_cis_p->bn; From ca85f44bdbc22337acd4b3ff64b7fab086443271 Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Sat, 19 Aug 2023 21:29:56 +0530 Subject: [PATCH 245/421] [nrf fromtree] Bluetooth: Controller: Fix assertion due to late PER CIS active set Fix assertion due to late Peripheral CIS active flag being initialized. CIS active flag shall be initialized when it is acquired. Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit cb28104cb08b5f9f86d043bbc8bf9bac1347c693) Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit 796be5a12f47be2ee33a36cf15da79241e2bb32d) --- subsys/bluetooth/controller/ll_sw/ull_peripheral_iso.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/subsys/bluetooth/controller/ll_sw/ull_peripheral_iso.c b/subsys/bluetooth/controller/ll_sw/ull_peripheral_iso.c index d45d89aa009..f68ca66656f 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_peripheral_iso.c +++ b/subsys/bluetooth/controller/ll_sw/ull_peripheral_iso.c @@ -250,7 +250,8 @@ uint8_t ull_peripheral_iso_acquire(struct ll_conn *acl, cis->p_max_sdu = (uint16_t)(req->p_max_sdu[1] & 0x0F) << 8 | req->p_max_sdu[0]; - cis->lll.handle = 0xFFFF; + cis->lll.active = 0U; + cis->lll.handle = LLL_HANDLE_INVALID; cis->lll.acl_handle = acl->lll.handle; cis->lll.sub_interval = sys_get_le24(req->sub_interval); cis->lll.nse = req->nse; @@ -325,7 +326,6 @@ uint8_t ull_peripheral_iso_setup(struct pdu_data_llctrl_cis_ind *ind, cis->lll.cie = 0U; cis->lll.npi = 0U; cis->lll.flush = LLL_CIS_FLUSH_NONE; - cis->lll.active = 0U; cis->lll.datapath_ready_rx = 0U; cis->lll.tx.payload_count = 0U; cis->lll.rx.payload_count = 0U; From 0cbe44c1bf783f13cf6da1ede4e199771e97f3fd Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Sun, 20 Aug 2023 10:48:43 +0530 Subject: [PATCH 246/421] [nrf fromtree] Bluetooth: Controller: Fix missing host feature reset Fix missing host feature reset on HCI reset command. Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit 94bd4837bbdc2036b60325772830fbe8c08f6870) Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit b0a6f693ec8acb3cbbaf6c864f4e2139b9c28771) --- subsys/bluetooth/controller/ll_sw/ll_feat.c | 5 +++++ subsys/bluetooth/controller/ll_sw/ll_feat_internal.h | 7 +++++++ subsys/bluetooth/controller/ll_sw/ull.c | 7 ++++++- 3 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 subsys/bluetooth/controller/ll_sw/ll_feat_internal.h diff --git a/subsys/bluetooth/controller/ll_sw/ll_feat.c b/subsys/bluetooth/controller/ll_sw/ll_feat.c index a1aaa99ba6d..d2ba2fefba0 100644 --- a/subsys/bluetooth/controller/ll_sw/ll_feat.c +++ b/subsys/bluetooth/controller/ll_sw/ll_feat.c @@ -70,6 +70,11 @@ uint8_t ll_set_host_feature(uint8_t bit_number, uint8_t bit_value) return BT_HCI_ERR_SUCCESS; } +void ll_feat_reset(void) +{ + host_features = 0U; +} + uint64_t ll_feat_get(void) { return LL_FEAT | (host_features & LL_FEAT_HOST_BIT_MASK); diff --git a/subsys/bluetooth/controller/ll_sw/ll_feat_internal.h b/subsys/bluetooth/controller/ll_sw/ll_feat_internal.h new file mode 100644 index 00000000000..7c23cb1a4e5 --- /dev/null +++ b/subsys/bluetooth/controller/ll_sw/ll_feat_internal.h @@ -0,0 +1,7 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +void ll_feat_reset(void); diff --git a/subsys/bluetooth/controller/ll_sw/ull.c b/subsys/bluetooth/controller/ll_sw/ull.c index 29cf43cd6d9..e6a736f939d 100644 --- a/subsys/bluetooth/controller/ll_sw/ull.c +++ b/subsys/bluetooth/controller/ll_sw/ull.c @@ -44,6 +44,7 @@ #include "lll_sync_iso.h" #include "lll_iso_tx.h" #include "lll_conn.h" +#include "lll_conn_iso.h" #include "lll_df.h" #include "ull_adv_types.h" @@ -60,6 +61,7 @@ #endif /* CONFIG_BT_CTLR_USER_EXT */ #include "isoal.h" +#include "ll_feat_internal.h" #include "ull_internal.h" #include "ull_iso_internal.h" #include "ull_adv_internal.h" @@ -69,7 +71,6 @@ #include "ull_central_internal.h" #include "ull_iso_types.h" #include "ull_conn_internal.h" -#include "lll_conn_iso.h" #include "ull_conn_iso_types.h" #include "ull_central_iso_internal.h" #include "ull_llcp.h" @@ -899,6 +900,10 @@ void ll_reset(void) LL_ASSERT(!err); #endif +#if defined(CONFIG_BT_CTLR_SET_HOST_FEATURE) + ll_feat_reset(); +#endif /* CONFIG_BT_CTLR_SET_HOST_FEATURE */ + /* clear static random address */ (void)ll_addr_set(1U, NULL); } From cd06b1c9d643c1b3591a925d03bcc48cd9cbc36e Mon Sep 17 00:00:00 2001 From: Alberto Escolar Piedras Date: Thu, 21 Sep 2023 08:57:08 +0200 Subject: [PATCH 247/421] [nrf fromtree] Bluetooth controller: nrf: Switch to use SOC_COMPATIBLE Switch use of kconfig: * SOC_SERIES_NRF53X -> SOC_COPATIBLE_NRF53X * SOC_NRF5340_CPUNET -> SOC_COMPATIBLE_NRF5340_CPUNET to also select those options/code when building for the nrf53 simulated targets. Also switch three kconfig range dependencies from SOC_SERIES_NRF52X to SOC_COPATIBLE_NRF52X (IRQ priority related) for consistency. These sound not really have an impact. Signed-off-by: Alberto Escolar Piedras (cherry picked from commit bab4ed16238e74f089932819de2edf3cbc1fc6c9) Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit 169087459e88e2f19a0792177ac295e635072a5a) --- .../bluetooth/controller/Kconfig.ll_sw_split | 10 +-- .../controller/hci/nordic/hci_vendor.h | 2 +- .../ll_sw/nordic/hal/nrf5/radio/radio.c | 72 +++++++++---------- .../nrf5/radio/radio_nrf5_dppi_resources.h | 4 +- .../controller/ll_sw/nordic/hal/nrf5/swi.h | 8 +-- 5 files changed, 48 insertions(+), 48 deletions(-) diff --git a/subsys/bluetooth/controller/Kconfig.ll_sw_split b/subsys/bluetooth/controller/Kconfig.ll_sw_split index 1fa9031d47f..4cd8e200b63 100644 --- a/subsys/bluetooth/controller/Kconfig.ll_sw_split +++ b/subsys/bluetooth/controller/Kconfig.ll_sw_split @@ -643,7 +643,7 @@ config BT_CTLR_SLOT_RESERVATION_UPDATE config BT_CTLR_LLL_PRIO int "Lower Link Layer (Radio) IRQ priority" if (BT_CTLR_ULL_LLL_PRIO_SUPPORT && !BT_CTLR_ZLI) range 0 3 if SOC_SERIES_NRF51X - range 0 6 if (SOC_SERIES_NRF52X || SOC_SERIES_NRF53X) + range 0 6 if (SOC_COMPATIBLE_NRF52X || SOC_COMPATIBLE_NRF53X) default 0 help The interrupt priority for event preparation and radio IRQ. @@ -651,7 +651,7 @@ config BT_CTLR_LLL_PRIO config BT_CTLR_ULL_HIGH_PRIO int "Upper Link Layer High IRQ priority" if BT_CTLR_ULL_LLL_PRIO_SUPPORT range BT_CTLR_LLL_PRIO 3 if SOC_SERIES_NRF51X - range BT_CTLR_LLL_PRIO 6 if (SOC_SERIES_NRF52X || SOC_SERIES_NRF53X) + range BT_CTLR_LLL_PRIO 6 if (SOC_COMPATIBLE_NRF52X || SOC_COMPATIBLE_NRF53X) default BT_CTLR_LLL_PRIO if (!BT_CTLR_ULL_LLL_PRIO_SUPPORT || BT_CTLR_ZLI || BT_CTLR_LOW_LAT) default 1 help @@ -661,7 +661,7 @@ config BT_CTLR_ULL_HIGH_PRIO config BT_CTLR_ULL_LOW_PRIO int "Upper Link Layer Low IRQ priority" if BT_CTLR_ULL_LLL_PRIO_SUPPORT range BT_CTLR_ULL_HIGH_PRIO 3 if SOC_SERIES_NRF51X - range BT_CTLR_ULL_HIGH_PRIO 6 if (SOC_SERIES_NRF52X || SOC_SERIES_NRF53X) + range BT_CTLR_ULL_HIGH_PRIO 6 if (SOC_COMPATIBLE_NRF52X || SOC_COMPATIBLE_NRF53X) default BT_CTLR_ULL_HIGH_PRIO help The interrupt priority for Ticker's Job IRQ and Upper Link Layer @@ -705,7 +705,7 @@ config BT_CTLR_RX_PDU_META config BT_CTLR_RADIO_ENABLE_FAST bool "Use tTXEN/RXEN,FAST ramp-up" - depends on SOC_COMPATIBLE_NRF52X || SOC_SERIES_NRF53X + depends on SOC_COMPATIBLE_NRF52X || SOC_COMPATIBLE_NRF53X default y help Enable use of fast radio ramp-up mode. @@ -719,7 +719,7 @@ config BT_CTLR_TIFS_HW config BT_CTLR_SW_SWITCH_SINGLE_TIMER bool "Single TIMER tIFS Trx SW switching" - depends on (!BT_CTLR_TIFS_HW) && (SOC_COMPATIBLE_NRF52X || SOC_SERIES_NRF53X) + depends on (!BT_CTLR_TIFS_HW) && (SOC_COMPATIBLE_NRF52X || SOC_COMPATIBLE_NRF53X) help Implement the tIFS Trx SW switch with the same TIMER instance, as the one used for BLE event timing. Requires diff --git a/subsys/bluetooth/controller/hci/nordic/hci_vendor.h b/subsys/bluetooth/controller/hci/nordic/hci_vendor.h index 4d3245728ed..bea7004f9c9 100644 --- a/subsys/bluetooth/controller/hci/nordic/hci_vendor.h +++ b/subsys/bluetooth/controller/hci/nordic/hci_vendor.h @@ -10,7 +10,7 @@ #define BT_HCI_VS_HW_VAR BT_HCI_VS_HW_VAR_NORDIC_NRF51X #elif defined(CONFIG_SOC_COMPATIBLE_NRF52X) #define BT_HCI_VS_HW_VAR BT_HCI_VS_HW_VAR_NORDIC_NRF52X -#elif defined(CONFIG_SOC_SERIES_NRF53X) +#elif defined(CONFIG_SOC_COMPATIBLE_NRF53X) #define BT_HCI_VS_HW_VAR BT_HCI_VS_HW_VAR_NORDIC_NRF53X #endif #else diff --git a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio.c b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio.c index 1875dca7896..3fc76a27bdf 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio.c @@ -311,7 +311,7 @@ void radio_phy_set(uint8_t phy, uint8_t flags) void radio_tx_power_set(int8_t power) { -#if defined(CONFIG_SOC_SERIES_NRF53X) +#if defined(CONFIG_SOC_COMPATIBLE_NRF53X) uint32_t value; /* NOTE: TXPOWER register only accepts upto 0dBm, hence use the HAL @@ -322,12 +322,12 @@ void radio_tx_power_set(int8_t power) NRF_RADIO->TXPOWER = value; hal_radio_tx_power_high_voltage_set(power); -#else /* !CONFIG_SOC_SERIES_NRF53X */ +#else /* !CONFIG_SOC_COMPATIBLE_NRF53X */ /* NOTE: valid value range is passed by Kconfig define. */ NRF_RADIO->TXPOWER = (uint32_t)power; -#endif /* !CONFIG_SOC_SERIES_NRF53X */ +#endif /* !CONFIG_SOC_COMPATIBLE_NRF53X */ } void radio_tx_power_max_set(void) @@ -345,25 +345,25 @@ int8_t radio_tx_power_min_get(void) int8_t radio_tx_power_max_get(void) { -#if defined(CONFIG_SOC_SERIES_NRF53X) +#if defined(CONFIG_SOC_COMPATIBLE_NRF53X) return RADIO_TXPOWER_TXPOWER_Pos3dBm; -#else /* !CONFIG_SOC_SERIES_NRF53X */ +#else /* !CONFIG_SOC_COMPATIBLE_NRF53X */ return (int8_t)hal_radio_tx_power_max_get(); -#endif /* !CONFIG_SOC_SERIES_NRF53X */ +#endif /* !CONFIG_SOC_COMPATIBLE_NRF53X */ } int8_t radio_tx_power_floor(int8_t power) { -#if defined(CONFIG_SOC_SERIES_NRF53X) +#if defined(CONFIG_SOC_COMPATIBLE_NRF53X) /* NOTE: TXPOWER register only accepts upto 0dBm, +3dBm permitted by * use of high voltage being set for radio when TXPOWER register is set. */ if (power >= (int8_t)RADIO_TXPOWER_TXPOWER_Pos3dBm) { return RADIO_TXPOWER_TXPOWER_Pos3dBm; } -#endif /* CONFIG_SOC_SERIES_NRF53X */ +#endif /* CONFIG_SOC_COMPATIBLE_NRF53X */ return (int8_t)hal_radio_tx_power_floor(power); } @@ -413,7 +413,7 @@ void radio_pkt_configure(uint8_t bits_len, uint8_t max_len, uint8_t flags) bits_s1 = RADIO_PKT_CONF_LENGTH_8BIT - bits_len; #elif defined(CONFIG_SOC_COMPATIBLE_NRF52X) || \ - defined(CONFIG_SOC_SERIES_NRF53X) + defined(CONFIG_SOC_COMPATIBLE_NRF53X) extra = 0U; phy = RADIO_PKT_CONF_PHY_GET(flags); @@ -510,7 +510,7 @@ uint32_t radio_rx_chain_delay_get(uint8_t phy, uint8_t flags) void radio_rx_enable(void) { #if !defined(CONFIG_BT_CTLR_TIFS_HW) -#if defined(CONFIG_SOC_SERIES_NRF53X) +#if defined(CONFIG_SOC_COMPATIBLE_NRF53X) /* NOTE: Timer clear DPPI configuration is needed only for nRF53 * because of calls to radio_disable() and * radio_switch_complete_and_disable() inside a radio event call @@ -523,7 +523,7 @@ void radio_rx_enable(void) * radio event but when the radio event is done. */ hal_sw_switch_timer_clear_ppi_config(); -#endif /* CONFIG_SOC_SERIES_NRF53X */ +#endif /* CONFIG_SOC_COMPATIBLE_NRF53X */ #endif /* !CONFIG_BT_CTLR_TIFS_HW */ nrf_radio_task_trigger(NRF_RADIO, NRF_RADIO_TASK_RXEN); @@ -532,7 +532,7 @@ void radio_rx_enable(void) void radio_tx_enable(void) { #if !defined(CONFIG_BT_CTLR_TIFS_HW) -#if defined(CONFIG_SOC_SERIES_NRF53X) +#if defined(CONFIG_SOC_COMPATIBLE_NRF53X) /* NOTE: Timer clear DPPI configuration is needed only for nRF53 * because of calls to radio_disable() and * radio_switch_complete_and_disable() inside a radio event call @@ -545,7 +545,7 @@ void radio_tx_enable(void) * radio event but when the radio event is done. */ hal_sw_switch_timer_clear_ppi_config(); -#endif /* CONFIG_SOC_SERIES_NRF53X */ +#endif /* CONFIG_SOC_COMPATIBLE_NRF53X */ #endif /* !CONFIG_BT_CTLR_TIFS_HW */ nrf_radio_task_trigger(NRF_RADIO, NRF_RADIO_TASK_TXEN); @@ -891,13 +891,13 @@ void sw_switch(uint8_t dir_curr, uint8_t dir_next, uint8_t phy_curr, uint8_t fla * time-stamp. */ hal_radio_end_time_capture_ppi_config(); -#if !defined(CONFIG_SOC_SERIES_NRF53X) +#if !defined(CONFIG_SOC_COMPATIBLE_NRF53X) /* The function is not called for nRF5340 single timer configuration because * HAL_SW_SWITCH_TIMER_CLEAR_PPI is equal to HAL_RADIO_END_TIME_CAPTURE_PPI, * so channel is already enabled. */ hal_radio_nrf_ppi_channels_enable(BIT(HAL_RADIO_END_TIME_CAPTURE_PPI)); -#endif /* !CONFIG_SOC_SERIES_NRF53X */ +#endif /* !CONFIG_SOC_COMPATIBLE_NRF53X */ #endif /* CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER */ sw_tifs_toggle += 1U; @@ -1186,38 +1186,38 @@ void radio_tmr_rx_status_reset(void) void radio_tmr_tx_enable(void) { -#if defined(CONFIG_SOC_SERIES_NRF53X) -#else /* !CONFIG_SOC_SERIES_NRF53X */ +#if defined(CONFIG_SOC_COMPATIBLE_NRF53X) +#else /* !CONFIG_SOC_COMPATIBLE_NRF53X */ #if (HAL_RADIO_ENABLE_TX_ON_TICK_PPI == HAL_RADIO_ENABLE_RX_ON_TICK_PPI) hal_radio_enable_on_tick_ppi_config_and_enable(1U); #endif /* HAL_RADIO_ENABLE_TX_ON_TICK_PPI == HAL_RADIO_ENABLE_RX_ON_TICK_PPI */ -#endif /* !CONFIG_SOC_SERIES_NRF53X */ +#endif /* !CONFIG_SOC_COMPATIBLE_NRF53X */ } void radio_tmr_rx_enable(void) { -#if defined(CONFIG_SOC_SERIES_NRF53X) -#else /* !CONFIG_SOC_SERIES_NRF53X */ +#if defined(CONFIG_SOC_COMPATIBLE_NRF53X) +#else /* !CONFIG_SOC_COMPATIBLE_NRF53X */ #if (HAL_RADIO_ENABLE_TX_ON_TICK_PPI == HAL_RADIO_ENABLE_RX_ON_TICK_PPI) hal_radio_enable_on_tick_ppi_config_and_enable(0U); #endif /* HAL_RADIO_ENABLE_TX_ON_TICK_PPI == HAL_RADIO_ENABLE_RX_ON_TICK_PPI */ -#endif /* !CONFIG_SOC_SERIES_NRF53X */ +#endif /* !CONFIG_SOC_COMPATIBLE_NRF53X */ } void radio_tmr_tx_disable(void) { -#if defined(CONFIG_SOC_SERIES_NRF53X) +#if defined(CONFIG_SOC_COMPATIBLE_NRF53X) nrf_radio_subscribe_clear(NRF_RADIO, NRF_RADIO_TASK_TXEN); -#else /* !CONFIG_SOC_SERIES_NRF53X */ -#endif /* !CONFIG_SOC_SERIES_NRF53X */ +#else /* !CONFIG_SOC_COMPATIBLE_NRF53X */ +#endif /* !CONFIG_SOC_COMPATIBLE_NRF53X */ } void radio_tmr_rx_disable(void) { -#if defined(CONFIG_SOC_SERIES_NRF53X) +#if defined(CONFIG_SOC_COMPATIBLE_NRF53X) nrf_radio_subscribe_clear(NRF_RADIO, NRF_RADIO_TASK_RXEN); -#else /* !CONFIG_SOC_SERIES_NRF53X */ -#endif /* !CONFIG_SOC_SERIES_NRF53X */ +#else /* !CONFIG_SOC_COMPATIBLE_NRF53X */ +#endif /* !CONFIG_SOC_COMPATIBLE_NRF53X */ } void radio_tmr_tifs_set(uint32_t tifs) @@ -1304,7 +1304,7 @@ uint32_t radio_tmr_start_tick(uint8_t trx, uint32_t tick) #if defined(CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER) last_pdu_end_us = 0U; #endif /* CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER */ -#if defined(CONFIG_SOC_SERIES_NRF53X) +#if defined(CONFIG_SOC_COMPATIBLE_NRF53X) /* NOTE: Timer clear DPPI configuration is needed only for nRF53 * because of calls to radio_disable() and * radio_switch_complete_and_disable() inside a radio event call @@ -1317,7 +1317,7 @@ uint32_t radio_tmr_start_tick(uint8_t trx, uint32_t tick) * radio event but when the radio event is done. */ hal_sw_switch_timer_clear_ppi_config(); -#endif /* CONFIG_SOC_SERIES_NRF53X */ +#endif /* CONFIG_SOC_COMPATIBLE_NRF53X */ #endif /* !CONFIG_BT_CTLR_TIFS_HW */ return remainder_us; @@ -1331,7 +1331,7 @@ uint32_t radio_tmr_start_us(uint8_t trx, uint32_t start_us) #if defined(CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER) last_pdu_end_us = 0U; #endif /* CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER */ -#if defined(CONFIG_SOC_SERIES_NRF53X) +#if defined(CONFIG_SOC_COMPATIBLE_NRF53X) /* NOTE: Timer clear DPPI configuration is needed only for nRF53 * because of calls to radio_disable() and * radio_switch_complete_and_disable() inside a radio event call @@ -1344,7 +1344,7 @@ uint32_t radio_tmr_start_us(uint8_t trx, uint32_t start_us) * radio event but when the radio event is done. */ hal_sw_switch_timer_clear_ppi_config(); -#endif /* CONFIG_SOC_SERIES_NRF53X */ +#endif /* CONFIG_SOC_COMPATIBLE_NRF53X */ #endif /* !CONFIG_BT_CTLR_TIFS_HW */ /* start_us could be the current count in the timer */ @@ -1464,12 +1464,12 @@ void radio_tmr_end_capture(void) * hal_sw_switch_timer_clear_ppi_config() and sw_switch(). There is no need to * configure the channel again in this function. */ -#if !defined(CONFIG_SOC_SERIES_NRF53X) || \ - (defined(CONFIG_SOC_SERIES_NRF53X) && !defined(CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER)) +#if !defined(CONFIG_SOC_COMPATIBLE_NRF53X) || \ + (defined(CONFIG_SOC_COMPATIBLE_NRF53X) && !defined(CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER)) hal_radio_end_time_capture_ppi_config(); hal_radio_nrf_ppi_channels_enable(BIT(HAL_RADIO_END_TIME_CAPTURE_PPI)); -#endif /* !CONFIG_SOC_SERIES_NRF53X || - * (CONFIG_SOC_SERIES_NRF53X && !CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER) +#endif /* !CONFIG_SOC_COMPATIBLE_NRF53X || + * (CONFIG_SOC_COMPATIBLE_NRF53X && !CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER) */ } @@ -1776,7 +1776,7 @@ static void *radio_ccm_ext_tx_pkt_set(struct ccm *cnf, uint8_t pdu_type, void *p NRF_CCM->ENABLE = CCM_ENABLE_ENABLE_Enabled; mode = (CCM_MODE_MODE_Encryption << CCM_MODE_MODE_Pos) & CCM_MODE_MODE_Msk; -#if defined(CONFIG_SOC_COMPATIBLE_NRF52X) || defined(CONFIG_SOC_SERIES_NRF53X) +#if defined(CONFIG_SOC_COMPATIBLE_NRF52X) || defined(CONFIG_SOC_COMPATIBLE_NRF53X) /* Enable CCM support for 8-bit length field PDUs. */ mode |= (CCM_MODE_LENGTH_Extended << CCM_MODE_LENGTH_Pos) & CCM_MODE_LENGTH_Msk; diff --git a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5_dppi_resources.h b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5_dppi_resources.h index 74fb56d9b5c..e1b47d03fd7 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5_dppi_resources.h +++ b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5_dppi_resources.h @@ -3,7 +3,7 @@ * * SPDX-License-Identifier: Apache-2.0 */ -#if defined(CONFIG_SOC_NRF5340_CPUNET) || defined(DPPI_PRESENT) +#if defined(CONFIG_SOC_COMPATIBLE_NRF5340_CPUNET) || defined(DPPI_PRESENT) /******************************************************************************* * Enable Radio on Event Timer tick: @@ -157,4 +157,4 @@ #define SW_SWITCH_TIMER_TASK_GROUP_BASE 0 #endif /* !CONFIG_BT_CTLR_TIFS_HW */ -#endif /* CONFIG_SOC_NRF5340_CPUNET || DPPI_PRESENT */ +#endif /* CONFIG_SOC_COMPATIBLE_NRF5340_CPUNET || DPPI_PRESENT */ diff --git a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/swi.h b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/swi.h index eb9da5652ff..6b364fd349a 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/swi.h +++ b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/swi.h @@ -18,10 +18,10 @@ #endif /* nRF53 Series IRQ mapping */ -#elif defined(CONFIG_SOC_SERIES_NRF53X) +#elif defined(CONFIG_SOC_COMPATIBLE_NRF53X) /* nRF53 Series Engineering D and Revision 1 IRQ mapping */ -#if defined(CONFIG_SOC_NRF5340_CPUNET) +#if defined(CONFIG_SOC_COMPATIBLE_NRF5340_CPUNET) #define HAL_SWI_RADIO_IRQ SWI2_IRQn #define HAL_SWI_WORKER_IRQ RTC0_IRQn @@ -33,9 +33,9 @@ #define HAL_SWI_JOB_IRQ SWI3_IRQn #endif -#endif /* CONFIG_SOC_NRF5340_CPUNET */ +#endif /* CONFIG_SOC_COMPATIBLE_NRF5340_CPUNET */ -#endif /* CONFIG_SOC_SERIES_NRF53X */ +#endif /* CONFIG_SOC_COMPATIBLE_NRF53X */ static inline void hal_swi_init(void) { From 6a7a93c5ff3a44b58457be8b140fec29fb13ebe1 Mon Sep 17 00:00:00 2001 From: Alberto Escolar Piedras Date: Thu, 21 Sep 2023 09:21:27 +0200 Subject: [PATCH 248/421] [nrf fromtree] Bluetooth controller nrf: ifdef some coded phy only code To avoid a build error when coded phy is not enabled for a nrf53: These three functions are only used for coded phy, and depend on macros which are only defined if coded phy is enabled. Signed-off-by: Alberto Escolar Piedras (cherry picked from commit f1557804a93d61b0effe9f513985c0159144da79) Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit 5c5a3446b04fcfeb79b3389a7da50868ef5fda38) --- .../controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5_dppi.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5_dppi.h b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5_dppi.h index 71e5ffa0e6f..9ed66dc3442 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5_dppi.h +++ b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5_dppi.h @@ -551,6 +551,7 @@ static inline void hal_radio_sw_switch_cleanup(void) nrf_dppi_group_disable(NRF_DPPIC, SW_SWITCH_TIMER_TASK_GROUP(1)); } +#if defined(CONFIG_BT_CTLR_PHY_CODED) static inline void hal_radio_sw_switch_coded_tx_config_set(uint8_t ppi_en, uint8_t ppi_dis, uint8_t cc_s2, uint8_t group_index) { @@ -612,6 +613,7 @@ static inline void hal_radio_sw_switch_disable_group_clear(uint8_t ppi_dis, uint HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI_TASK( ppi_dis); } +#endif /* defined(CONFIG_BT_CTLR_PHY_CODED) */ static inline void hal_radio_sw_switch_ppi_group_setup(void) { From 5d1edf1e72deadd5680ed527feed12faeb2ee329 Mon Sep 17 00:00:00 2001 From: Alberto Escolar Piedras Date: Thu, 21 Sep 2023 09:50:56 +0200 Subject: [PATCH 249/421] [nrf fromtree] Bluetooth controller nrf: Rename bsim radio hal header Rename the bsim header in preparation for having more simulated targets. Signed-off-by: Alberto Escolar Piedras (cherry picked from commit bae0dace163eddd6c60963d4cf3267125186fd99) Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit 6dfef35b08327580d01559bb38c07702aade8176) --- .../controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5.h | 4 ++-- .../hal/nrf5/radio/{radio_sim_nrfxx.h => radio_sim_nrf52.h} | 0 2 files changed, 2 insertions(+), 2 deletions(-) rename subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/{radio_sim_nrfxx.h => radio_sim_nrf52.h} (100%) diff --git a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5.h b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5.h index a03e55f519d..9e29ab5f70b 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5.h +++ b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5.h @@ -15,8 +15,8 @@ #define HAL_RADIO_NS2US_ROUND(ns) ((ns + 500)/1000) /* SoC specific defines */ -#if defined(CONFIG_SOC_SERIES_BSIM_NRFXX) -#include "radio_sim_nrfxx.h" +#if defined(CONFIG_BOARD_NRF52_BSIM) +#include "radio_sim_nrf52.h" #elif defined(CONFIG_SOC_SERIES_NRF51X) #include "radio_nrf51.h" #elif defined(CONFIG_SOC_NRF52805) diff --git a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_sim_nrfxx.h b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_sim_nrf52.h similarity index 100% rename from subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_sim_nrfxx.h rename to subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_sim_nrf52.h From c3bc6faf52e3b301e91b62efc1a1763d28f29a46 Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Fri, 22 Sep 2023 12:42:57 +0200 Subject: [PATCH 250/421] [nrf fromtree] Bluetooth: Controller: nRF53: Fix sw switch single timer id regression Fix regression in sw switch single timer id use for nRF53x series SoC. Regression introduced in commit cfcbe5d68ed3 ("Bluetooth: Controller: Remove redudant header file includes"). Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit 8c9ac505dbe04585ebb6c3532c93c24884db70bb) Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit 0aa27c019b2d7407e61bf8cd533f5ffe646ed401) --- .../ll_sw/nordic/hal/nrf5/radio/radio_nrf5340.h | 14 ++++++++++++++ tests/bluetooth/init/testcase.yaml | 13 +++++++++++++ 2 files changed, 27 insertions(+) diff --git a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5340.h b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5340.h index e0f43014508..68267490129 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5340.h +++ b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5340.h @@ -5,6 +5,20 @@ * SPDX-License-Identifier: Apache-2.0 */ +/* Override EVENT_TIMER_ID from 4 to 0, as nRF5340 does not have 4 timer + * instances. + */ +#if defined(CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER) +#undef EVENT_TIMER_ID +#define EVENT_TIMER_ID 0 + +#undef EVENT_TIMER +#define EVENT_TIMER _CONCAT(NRF_TIMER, EVENT_TIMER_ID) + +#undef SW_SWITCH_TIMER +#define SW_SWITCH_TIMER EVENT_TIMER +#endif /* CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER */ + /* NRF Radio HW timing constants * - provided in US and NS (for higher granularity) * - based on empirical measurements and sniffer logs diff --git a/tests/bluetooth/init/testcase.yaml b/tests/bluetooth/init/testcase.yaml index fa30920dc1e..c38f5bed69e 100644 --- a/tests/bluetooth/init/testcase.yaml +++ b/tests/bluetooth/init/testcase.yaml @@ -122,6 +122,19 @@ tests: integration_platforms: - nrf52840dk_nrf52840 - nrf52dk_nrf52832 + bluetooth.init.test_ctlr_sw_switch_single_timer: + extra_args: + - CONF_FILE=prj_ctlr.conf + - CONFIG_BT_CTLR_ADVANCED_FEATURES=y + - CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER=y + platform_allow: + - nrf5340dk_nrf5340_cpunet + - nrf52840dk_nrf52840 + - nrf52dk_nrf52832 + integration_platforms: + - nrf5340dk_nrf5340_cpunet + - nrf52840dk_nrf52840 + - nrf52dk_nrf52832 bluetooth.init.test_ctlr_ticker: extra_args: - CONF_FILE=prj_ctlr_ticker.conf From 694b89fdbd9a78aedfd9e8521028622b9c54fd52 Mon Sep 17 00:00:00 2001 From: Alberto Escolar Piedras Date: Thu, 21 Sep 2023 15:37:45 +0200 Subject: [PATCH 251/421] [nrf fromtree] Bluetooth: Controller: nrf: Use HAL for DPPI configuration The following changes have been done: 1. HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI_REGISTER_TASK(index) = HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI_TASK(channel) has been convered into HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI_REGISTER_TASK(index, channel) 2. HAL_SW_SWITCH_GROUP_TASK_ENABLE_PPI_REGISTER_TASK(index) = HAL_SW_SWITCH_GROUP_TASK_ENABLE_PPI_TASK Which was only used in one place, has been replaced with the equivalent HAL call 3. HAL_SW_SWITCH_GROUP_TASK_ENABLE_PPI_REGISTER_TASK(index) = 0 was replaced with the HAL subscribe clear function nrf_dppi_subscribe_clear(NRF_DPPIC, HAL_SW_DPPI_TASK_EN_FROM_IDX(SW_SWITCH_TIMER_TASK_GROUP(index))); 4. NRF_DPPIC->SUBSCRIBE_CHG[group].EN/DIS = 0; have been replaced with the equivalent HAL clear call 5. NRF_DPPIC->TASKS_CHG[group].DIS = 1; have been replaced with the equivalent hal task_trigger() call 6. Manually setting the CHG registers, has been replaced with a clear + add (because the hal does not have a set function yet) So, NRF_DPPIC->CHG[group] = value has been replaced with nrf_dppi_group_clear(NRF_DPPIC, group); nrf_dppi_channels_include_in_group(NRF_DPPIC, value, group); (A set function has been requested from the HAL team) Note: There is other direct registes writes to the dppi subscribe and CHG registers in the coded phy parts which have not been changed yet. Signed-off-by: Alberto Escolar Piedras (cherry picked from commit c5191ba5b78127d9b530d586c45fea58c2958155) Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit 8c16b538a6074bd030e9d14f092aebc3c19010fe) --- .../nordic/hal/nrf5/radio/radio_nrf5_dppi.h | 102 ++++++++++-------- 1 file changed, 58 insertions(+), 44 deletions(-) diff --git a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5_dppi.h b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5_dppi.h index 9ed66dc3442..69069288141 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5_dppi.h +++ b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5_dppi.h @@ -317,6 +317,20 @@ static inline void hal_sw_switch_timer_clear_ppi_config(void) #define SW_SWITCH_TIMER_S2_EVTS_COMP(index) \ (SW_SWITCH_TIMER_EVTS_COMP_S2_BASE + (index)) +/* + * Convert a dppi channel group number into the *enable* task enumerate value + * the nrfx hal accepts + */ +#define HAL_SW_DPPI_TASK_EN_FROM_IDX(index) \ + (NRF_DPPI_TASK_CHG0_EN + ((index) * (NRF_DPPI_TASK_CHG1_EN - NRF_DPPI_TASK_CHG0_EN))) + +/* + * Convert a dppi channel group number into the *disable* task enumerate value + * the nrfx hal accepts + */ +#define HAL_SW_DPPI_TASK_DIS_FROM_IDX(index) \ + (NRF_DPPI_TASK_CHG0_DIS + ((index) * (NRF_DPPI_TASK_CHG1_EN - NRF_DPPI_TASK_CHG0_EN))) + /* Wire a SW SWITCH TIMER EVENTS_COMPARE[] event * to a PPI GROUP TASK DISABLE task (PPI group with index ). * 2 adjacent PPIs (8 & 9) and 2 adjacent PPI groups are used for this wiring; @@ -332,14 +346,10 @@ static inline void hal_sw_switch_timer_clear_ppi_config(void) & TIMER_PUBLISH_COMPARE_CHIDX_Msk) | \ ((TIMER_PUBLISH_COMPARE_EN_Enabled << TIMER_PUBLISH_COMPARE_EN_Pos) \ & TIMER_PUBLISH_COMPARE_EN_Msk)) -#define HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI_REGISTER_TASK(index) \ - NRF_DPPIC->SUBSCRIBE_CHG[SW_SWITCH_TIMER_TASK_GROUP(index)].DIS -#define HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI_TASK(chan) \ - (((chan << DPPIC_SUBSCRIBE_CHG_DIS_CHIDX_Pos) \ - & DPPIC_SUBSCRIBE_CHG_DIS_CHIDX_Msk) | \ - ((DPPIC_SUBSCRIBE_CHG_DIS_EN_Enabled << \ - DPPIC_SUBSCRIBE_CHG_DIS_EN_Pos) \ - & DPPIC_SUBSCRIBE_CHG_DIS_EN_Msk)) +#define HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI_REGISTER_TASK(index, channel) \ + nrf_dppi_subscribe_set(NRF_DPPIC, \ + HAL_SW_DPPI_TASK_DIS_FROM_IDX(SW_SWITCH_TIMER_TASK_GROUP(index)), \ + channel); /* Enable the SW Switch PPI Group on RADIO END Event. * @@ -353,15 +363,6 @@ static inline void hal_sw_switch_timer_clear_ppi_config(void) & RADIO_PUBLISH_END_CHIDX_Msk) | \ ((RADIO_PUBLISH_END_EN_Enabled << RADIO_PUBLISH_END_EN_Pos) \ & RADIO_PUBLISH_END_EN_Msk)) -#define HAL_SW_SWITCH_GROUP_TASK_ENABLE_PPI_REGISTER_TASK(index) \ - (NRF_DPPIC->SUBSCRIBE_CHG[SW_SWITCH_TIMER_TASK_GROUP(index)].EN) -#define HAL_SW_SWITCH_GROUP_TASK_ENABLE_PPI_TASK \ - (((HAL_SW_SWITCH_GROUP_TASK_ENABLE_PPI << \ - DPPIC_SUBSCRIBE_CHG_EN_CHIDX_Pos) \ - & DPPIC_SUBSCRIBE_CHG_EN_CHIDX_Msk) | \ - ((DPPIC_SUBSCRIBE_CHG_EN_EN_Enabled << \ - DPPIC_SUBSCRIBE_CHG_EN_EN_Pos) \ - & DPPIC_SUBSCRIBE_CHG_EN_EN_Msk)) /* Enable Radio on SW Switch timer event. * Wire a SW SWITCH TIMER EVENTS_COMPARE[] event @@ -473,12 +474,15 @@ static inline void hal_radio_sw_switch_setup( */ HAL_SW_SWITCH_GROUP_TASK_ENABLE_PPI_REGISTER_EVT = HAL_SW_SWITCH_GROUP_TASK_ENABLE_PPI_EVT; - HAL_SW_SWITCH_GROUP_TASK_ENABLE_PPI_REGISTER_TASK(ppi_group_index) = - HAL_SW_SWITCH_GROUP_TASK_ENABLE_PPI_TASK; + nrf_dppi_subscribe_set(NRF_DPPIC, + HAL_SW_DPPI_TASK_EN_FROM_IDX(SW_SWITCH_TIMER_TASK_GROUP(ppi_group_index)), + HAL_SW_SWITCH_GROUP_TASK_ENABLE_PPI); /* We need to un-subscribe the other group from the PPI channel. */ - HAL_SW_SWITCH_GROUP_TASK_ENABLE_PPI_REGISTER_TASK( - (ppi_group_index + 1) & 0x01) = 0; + uint8_t other_grp = (ppi_group_index + 1) & 0x01; + + nrf_dppi_subscribe_clear(NRF_DPPIC, + HAL_SW_DPPI_TASK_EN_FROM_IDX(SW_SWITCH_TIMER_TASK_GROUP(other_grp))); /* Wire SW Switch timer event to the * PPI[] for enabling Radio. Do @@ -537,8 +541,10 @@ static inline void hal_radio_sw_switch_disable(void) * So we simply cancel the task subscription. */ nrf_timer_subscribe_clear(SW_SWITCH_TIMER, NRF_TIMER_TASK_CLEAR); - HAL_SW_SWITCH_GROUP_TASK_ENABLE_PPI_REGISTER_TASK(0) = 0; - HAL_SW_SWITCH_GROUP_TASK_ENABLE_PPI_REGISTER_TASK(1) = 0; + nrf_dppi_subscribe_clear(NRF_DPPIC, + HAL_SW_DPPI_TASK_EN_FROM_IDX(SW_SWITCH_TIMER_TASK_GROUP(0))); + nrf_dppi_subscribe_clear(NRF_DPPIC, + HAL_SW_DPPI_TASK_EN_FROM_IDX(SW_SWITCH_TIMER_TASK_GROUP(1))); } static inline void hal_radio_sw_switch_cleanup(void) @@ -567,8 +573,8 @@ static inline void hal_radio_sw_switch_coded_tx_config_set(uint8_t ppi_en, HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI_REGISTER_EVT(cc_s2) = HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI_EVT(ppi_dis); - HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI_REGISTER_TASK(group_index) = - HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI_TASK(ppi_dis); + HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI_REGISTER_TASK(group_index, + ppi_dis); /* Capture CC to cancel the timer that has assumed * S8 reception, if packet will be received in S2. @@ -609,9 +615,7 @@ static inline void hal_radio_sw_switch_disable_group_clear(uint8_t ppi_dis, uint HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI_EVT( ppi_dis); HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI_REGISTER_TASK( - group_index) = - HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI_TASK( - ppi_dis); + group_index, ppi_dis); } #endif /* defined(CONFIG_BT_CTLR_PHY_CODED) */ @@ -624,21 +628,33 @@ static inline void hal_radio_sw_switch_ppi_group_setup(void) * registers are written, therefore, we clear the task registers * here. */ - NRF_DPPIC->SUBSCRIBE_CHG[SW_SWITCH_TIMER_TASK_GROUP(0)].EN = 0; - NRF_DPPIC->SUBSCRIBE_CHG[SW_SWITCH_TIMER_TASK_GROUP(0)].DIS = 0; - NRF_DPPIC->SUBSCRIBE_CHG[SW_SWITCH_TIMER_TASK_GROUP(1)].EN = 0; - NRF_DPPIC->SUBSCRIBE_CHG[SW_SWITCH_TIMER_TASK_GROUP(1)].DIS = 0; - - NRF_DPPIC->TASKS_CHG[SW_SWITCH_TIMER_TASK_GROUP(0)].DIS = 1; - NRF_DPPIC->TASKS_CHG[SW_SWITCH_TIMER_TASK_GROUP(1)].DIS = 1; + nrf_dppi_subscribe_clear(NRF_DPPIC, + HAL_SW_DPPI_TASK_EN_FROM_IDX(SW_SWITCH_TIMER_TASK_GROUP(0))); + nrf_dppi_subscribe_clear(NRF_DPPIC, + HAL_SW_DPPI_TASK_DIS_FROM_IDX(SW_SWITCH_TIMER_TASK_GROUP(0))); + nrf_dppi_subscribe_clear(NRF_DPPIC, + HAL_SW_DPPI_TASK_EN_FROM_IDX(SW_SWITCH_TIMER_TASK_GROUP(1))); + nrf_dppi_subscribe_clear(NRF_DPPIC, + HAL_SW_DPPI_TASK_DIS_FROM_IDX(SW_SWITCH_TIMER_TASK_GROUP(1))); + + nrf_dppi_task_trigger(NRF_DPPIC, + HAL_SW_DPPI_TASK_DIS_FROM_IDX(SW_SWITCH_TIMER_TASK_GROUP(0))); + nrf_dppi_task_trigger(NRF_DPPIC, + HAL_SW_DPPI_TASK_DIS_FROM_IDX(SW_SWITCH_TIMER_TASK_GROUP(1))); /* Include the appropriate PPI channels in the two PPI Groups. */ - NRF_DPPIC->CHG[SW_SWITCH_TIMER_TASK_GROUP(0)] = + nrf_dppi_group_clear(NRF_DPPIC, + SW_SWITCH_TIMER_TASK_GROUP(0)); + nrf_dppi_channels_include_in_group(NRF_DPPIC, BIT(HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI(0)) | - BIT(HAL_SW_SWITCH_RADIO_ENABLE_PPI(0)); - NRF_DPPIC->CHG[SW_SWITCH_TIMER_TASK_GROUP(1)] = + BIT(HAL_SW_SWITCH_RADIO_ENABLE_PPI(0)), + SW_SWITCH_TIMER_TASK_GROUP(0)); + nrf_dppi_group_clear(NRF_DPPIC, + SW_SWITCH_TIMER_TASK_GROUP(1)); + nrf_dppi_channels_include_in_group(NRF_DPPIC, BIT(HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI(1)) | - BIT(HAL_SW_SWITCH_RADIO_ENABLE_PPI(1)); + BIT(HAL_SW_SWITCH_RADIO_ENABLE_PPI(1)), + SW_SWITCH_TIMER_TASK_GROUP(1)); /* Sanity build-time check that RADIO Enable and Group Disable * tasks are going to be subscribed on the same PPIs. @@ -663,8 +679,7 @@ static inline void hal_radio_group_task_disable_ppi_setup(void) SW_SWITCH_TIMER_EVTS_COMP(0)) = HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI_EVT( HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI(0)); - HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI_REGISTER_TASK(0) = - HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI_TASK( + HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI_REGISTER_TASK(0, HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI(0)); /* Wire SW SWITCH TIMER event to @@ -674,9 +689,8 @@ static inline void hal_radio_group_task_disable_ppi_setup(void) SW_SWITCH_TIMER_EVTS_COMP(1)) = HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI_EVT( HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI(1)); - HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI_REGISTER_TASK(1) = - HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI_TASK( - HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI(1)); + HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI_REGISTER_TASK(1, + HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI(1)); } #if defined(CONFIG_BT_CTLR_DF_PHYEND_OFFSET_COMPENSATION_ENABLE) From 65eaabbf2ff41853284222cf9f6f2776ef3a794c Mon Sep 17 00:00:00 2001 From: Alberto Escolar Piedras Date: Fri, 22 Sep 2023 09:50:22 +0200 Subject: [PATCH 252/421] [nrf fromtree] Bluetooth: Controller: nrf: HAL for DPPI configuration cleanup Remove a few macros which are not used anywhere in the tree. For the sake of simplifying the header and easing its understanding. Signed-off-by: Alberto Escolar Piedras (cherry picked from commit 07bb88d28ad366b0b3ba0ea0a9353140b7523efe) Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit 32d3dcd906d7e2c637f8864a42d61c20f6b09f47) --- .../ll_sw/nordic/hal/nrf5/radio/radio_nrf5_dppi.h | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5_dppi.h b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5_dppi.h index 69069288141..c28cc35a617 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5_dppi.h +++ b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5_dppi.h @@ -388,21 +388,6 @@ static inline void hal_sw_switch_timer_clear_ppi_config(void) & TIMER_PUBLISH_COMPARE_CHIDX_Msk) | \ ((TIMER_PUBLISH_COMPARE_EN_Enabled << TIMER_PUBLISH_COMPARE_EN_Pos) \ & TIMER_PUBLISH_COMPARE_EN_Msk)) -#define HAL_SW_SWITCH_RADIO_ENABLE_PPI_REGISTER_TASK_TX \ - NRF_RADIO->SUBSCRIBE_TXEN -#define HAL_SW_SWITCH_RADIO_ENABLE_PPI_REGISTER_TASK_RX \ - NRF_RADIO->SUBSCRIBE_RXEN -#define HAL_SW_SWITCH_RADIO_ENABLE_PPI_TASK_TX_SET(chan) \ - (((chan << RADIO_SUBSCRIBE_TXEN_CHIDX_Pos) \ - & RADIO_SUBSCRIBE_TXEN_CHIDX_Msk) | \ - ((RADIO_SUBSCRIBE_TXEN_EN_Enabled << \ - RADIO_SUBSCRIBE_TXEN_EN_Pos) \ - & RADIO_SUBSCRIBE_TXEN_EN_Msk)) -#define HAL_SW_SWITCH_RADIO_ENABLE_PPI_TASK_RX_SET(chan) \ - (((chan << RADIO_SUBSCRIBE_RXEN_CHIDX_Pos) \ - & RADIO_SUBSCRIBE_RXEN_CHIDX_Msk) | \ - ((RADIO_SUBSCRIBE_RXEN_EN_Enabled << RADIO_SUBSCRIBE_RXEN_EN_Pos) \ - & RADIO_SUBSCRIBE_RXEN_EN_Msk)) /* Cancel the SW switch timer running considering S8 timing: * wire the RADIO EVENTS_RATEBOOST event to SW_SWITCH_TIMER TASKS_CAPTURE task. From 5b8de9becc22ff98ef6eeaa36284417a670942d3 Mon Sep 17 00:00:00 2001 From: Alberto Escolar Piedras Date: Thu, 21 Sep 2023 10:09:47 +0200 Subject: [PATCH 253/421] [nrf fromtree] Bluetooth controller nrf: nrf52 bsim radio hal header minor updates Align the header a bit with the one for the real radio, adding missing Tx power levels and removing TODO which did not need doing. The old one originated as a copy of the nrf52833 one, and did not evolve like the real ones. Signed-off-by: Alberto Escolar Piedras (cherry picked from commit 865f3c161496a66d818e8bb2a59ecfc9ad77eae4) Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit 7dc07d4c24d1a482cfe7aa695685c7ce20f6ecc9) --- .../nordic/hal/nrf5/radio/radio_sim_nrf52.h | 41 +++++++++++-------- 1 file changed, 24 insertions(+), 17 deletions(-) diff --git a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_sim_nrf52.h b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_sim_nrf52.h index a767fe1ab30..3d53462326a 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_sim_nrf52.h +++ b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_sim_nrf52.h @@ -185,14 +185,10 @@ static inline void hal_radio_reset(void) { - /* TODO: Add any required setup for each radio event - */ } static inline void hal_radio_stop(void) { - /* TODO: Add any required cleanup of actions taken in hal_radio_reset() - */ } static inline void hal_radio_ram_prio_setup(void) @@ -226,25 +222,39 @@ static inline uint32_t hal_radio_tx_power_min_get(void) static inline uint32_t hal_radio_tx_power_max_get(void) { -#if defined(RADIO_TXPOWER_TXPOWER_Pos4dBm) - return RADIO_TXPOWER_TXPOWER_Pos4dBm; -#else - return RADIO_TXPOWER_TXPOWER_0dBm; -#endif + return RADIO_TXPOWER_TXPOWER_Pos8dBm; } static inline uint32_t hal_radio_tx_power_floor(int8_t tx_power_lvl) { -#if defined(RADIO_TXPOWER_TXPOWER_Pos4dBm) + if (tx_power_lvl >= (int8_t)RADIO_TXPOWER_TXPOWER_Pos8dBm) { + return RADIO_TXPOWER_TXPOWER_Pos8dBm; + } + + if (tx_power_lvl >= (int8_t)RADIO_TXPOWER_TXPOWER_Pos7dBm) { + return RADIO_TXPOWER_TXPOWER_Pos7dBm; + } + + if (tx_power_lvl >= (int8_t)RADIO_TXPOWER_TXPOWER_Pos6dBm) { + return RADIO_TXPOWER_TXPOWER_Pos6dBm; + } + + if (tx_power_lvl >= (int8_t)RADIO_TXPOWER_TXPOWER_Pos5dBm) { + return RADIO_TXPOWER_TXPOWER_Pos5dBm; + } + if (tx_power_lvl >= (int8_t)RADIO_TXPOWER_TXPOWER_Pos4dBm) { return RADIO_TXPOWER_TXPOWER_Pos4dBm; } -#endif -#if defined(RADIO_TXPOWER_TXPOWER_Pos3dBm) + if (tx_power_lvl >= (int8_t)RADIO_TXPOWER_TXPOWER_Pos3dBm) { return RADIO_TXPOWER_TXPOWER_Pos3dBm; } -#endif + + if (tx_power_lvl >= (int8_t)RADIO_TXPOWER_TXPOWER_Pos2dBm) { + return RADIO_TXPOWER_TXPOWER_Pos2dBm; + } + if (tx_power_lvl >= (int8_t)RADIO_TXPOWER_TXPOWER_0dBm) { return RADIO_TXPOWER_TXPOWER_0dBm; } @@ -269,10 +279,7 @@ static inline uint32_t hal_radio_tx_power_floor(int8_t tx_power_lvl) return RADIO_TXPOWER_TXPOWER_Neg20dBm; } - if (tx_power_lvl >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg30dBm) { - return RADIO_TXPOWER_TXPOWER_Neg30dBm; - } - + /* Note: The -30 dBm power level is deprecated so ignore it! */ return RADIO_TXPOWER_TXPOWER_Neg40dBm; } From 35d5889e89181556ca0b4c16f2cb87ad2bbb51ee Mon Sep 17 00:00:00 2001 From: Alberto Escolar Piedras Date: Fri, 22 Sep 2023 14:00:44 +0200 Subject: [PATCH 254/421] [nrf fromtree] Bluetooth controller nrf: nrf52 bsim radio hal fix hal_radio_tx_chain_delay_ns_get() was incorrectly returning the microsecond value, resulting in a 1us error in the timing => Fix it. Signed-off-by: Alberto Escolar Piedras (cherry picked from commit 292ca93795598e02210bc8c2114ed46db5ea4cc0) Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit adeeb74a23a498d6be0fc680175898e944b3025c) --- .../ll_sw/nordic/hal/nrf5/radio/radio_sim_nrf52.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_sim_nrf52.h b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_sim_nrf52.h index 3d53462326a..1b8c1583547 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_sim_nrf52.h +++ b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_sim_nrf52.h @@ -14,7 +14,10 @@ /* NRF Radio HW timing constants * - provided in US and NS (for higher granularity) - * - based on empirical measurements and sniffer logs + * - based on the timings configured in the HW models, which are based + * on the product specification + * - Note that this timings are approx. the same as in the real HW, + * but tend to be rounded to the nearest microsecond */ /* TXEN->TXIDLE + TXIDLE->TX (with fast Radio ramp-up mode) @@ -361,7 +364,7 @@ static inline uint32_t hal_radio_tx_chain_delay_ns_get(uint8_t phy, uint8_t flag ARG_UNUSED(phy); ARG_UNUSED(flags); - return HAL_RADIO_NRF52833_TX_CHAIN_DELAY_US; + return HAL_RADIO_NRF52833_TX_CHAIN_DELAY_NS; } static inline uint32_t hal_radio_rx_chain_delay_ns_get(uint8_t phy, uint8_t flags) From ac999bd51ac7d24cb11df0171b137ef6444279a4 Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Sun, 17 Sep 2023 06:13:40 +0200 Subject: [PATCH 255/421] [nrf fromtree] Bluetooth: Controller: Use unique goto label in scan aux code Use unique goto label in scan aux connect response ISR. Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit ed5883d9a07383a1651cb178f23b8c1c5bd7ab52) Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit fbf506c371523e3dd404077af9d682aaeebf3a8b) --- subsys/bluetooth/controller/ll_sw/nordic/lll/lll_scan_aux.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_scan_aux.c b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_scan_aux.c index 50bcb0e6662..c8188d87cb6 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_scan_aux.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_scan_aux.c @@ -1510,7 +1510,7 @@ static void isr_rx_connect_rsp(void *param) rx = ftr->extra; rx->hdr.type = NODE_RX_TYPE_RELEASE; - goto isr_rx_do_close; + goto isr_rx_connect_rsp_do_close; } /* Update the max Tx and Rx time; and connection PHY based on the @@ -1548,7 +1548,7 @@ static void isr_rx_connect_rsp(void *param) } #endif /* CONFIG_BT_CTLR_PRIVACY */ -isr_rx_do_close: +isr_rx_connect_rsp_do_close: if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) { lll_prof_cputime_capture(); } From 2528d7a49d30ff0334b4bf9af48618ddbf359373 Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Mon, 25 Sep 2023 20:36:41 +0200 Subject: [PATCH 256/421] [nrf fromtree] Bluetooth: Controller: nRF53: Fix missing NRF_CCM subscribe clear Fix missing NRF_CCM subscribe clear which can lead to spurious trigger of TASK_CRYPT in NRF_CCM. This may lead to corruption of Rx PDU buffers. Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit 9e01c4df53370c5700f2d41a8d017f6e4f6925e8) Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit 1bcc5f707ad3b654495894901a9340ef5444978f) --- .../controller/ll_sw/nordic/hal/nrf5/radio/radio.c | 6 ++++++ .../ll_sw/nordic/hal/nrf5/radio/radio_nrf5_dppi.h | 8 ++++++++ .../ll_sw/nordic/hal/nrf5/radio/radio_nrf5_ppi.h | 10 ++++++++++ 3 files changed, 24 insertions(+) diff --git a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio.c b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio.c index 3fc76a27bdf..0b41a9bbfb6 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio.c @@ -1084,6 +1084,8 @@ void radio_tmr_status_reset(void) { nrf_rtc_event_disable(NRF_RTC0, RTC_EVTENCLR_COMPARE2_Msk); + hal_trigger_crypt_ppi_disable(); + hal_radio_nrf_ppi_channels_disable( BIT(HAL_RADIO_ENABLE_TX_ON_TICK_PPI) | BIT(HAL_RADIO_ENABLE_RX_ON_TICK_PPI) | @@ -1116,6 +1118,8 @@ void radio_tmr_tx_status_reset(void) { nrf_rtc_event_disable(NRF_RTC0, RTC_EVTENCLR_COMPARE2_Msk); + hal_trigger_crypt_ppi_disable(); + hal_radio_nrf_ppi_channels_disable( #if (HAL_RADIO_ENABLE_TX_ON_TICK_PPI != HAL_RADIO_ENABLE_RX_ON_TICK_PPI) && \ !defined(DPPI_PRESENT) @@ -1152,6 +1156,8 @@ void radio_tmr_rx_status_reset(void) { nrf_rtc_event_disable(NRF_RTC0, RTC_EVTENCLR_COMPARE2_Msk); + hal_trigger_crypt_ppi_disable(); + hal_radio_nrf_ppi_channels_disable( #if (HAL_RADIO_ENABLE_TX_ON_TICK_PPI != HAL_RADIO_ENABLE_RX_ON_TICK_PPI) && \ !defined(DPPI_PRESENT) diff --git a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5_dppi.h b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5_dppi.h index c28cc35a617..3792111292a 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5_dppi.h +++ b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5_dppi.h @@ -127,6 +127,14 @@ static inline void hal_trigger_crypt_ppi_config(void) nrf_ccm_subscribe_set(NRF_CCM, NRF_CCM_TASK_CRYPT, HAL_RADIO_RECV_TIMEOUT_CANCEL_PPI); } +/******************************************************************************* + * Disable trigger encryption task + */ +static inline void hal_trigger_crypt_ppi_disable(void) +{ + nrf_ccm_subscribe_clear(NRF_CCM, NRF_CCM_TASK_CRYPT); +} + #if defined(CONFIG_BT_CTLR_DF_CONN_CTE_RX) /******************************************************************************* * Trigger encryption task on Bit counter match: diff --git a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5_ppi.h b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5_ppi.h index 866769c95eb..d964129bfa1 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5_ppi.h +++ b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5_ppi.h @@ -205,6 +205,16 @@ static inline void hal_trigger_crypt_ppi_config(void) /* No need to configure anything for the pre-programmed channel. */ } +/******************************************************************************* + * Disable trigger encryption task + */ +static inline void hal_trigger_crypt_ppi_disable(void) +{ + /* No need to disable anything as ppi channel will be disabled in a + * separate disable ppi call by the caller of this function. + */ +} + #if defined(CONFIG_BT_CTLR_DF_CONN_CTE_RX) /******************************************************************************* * Trigger encryption task on Bit counter match: From bce70f4a637c8efd602bd72c598182909f5697f0 Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Thu, 10 Aug 2023 00:37:01 +0530 Subject: [PATCH 257/421] [nrf fromtree] Bluetooth: Controller: Fix CIS assymmetric PHY usage Fix CIS assymmetric PHY usage by adding implementation to use correct PHY in radio when switching transceiver. Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit 652544e3967161a66cf99a4202b9011343e2ec01) Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit 9e941c2c5eb15527a4bd195fe3a4860b09942345) --- .../controller/ll_sw/nordic/lll/lll_central_iso.c | 12 +++++++++--- .../controller/ll_sw/nordic/lll/lll_peripheral_iso.c | 11 ++++++++++- subsys/bluetooth/controller/ll_sw/ull_central_iso.c | 4 ++++ .../bluetooth/controller/ll_sw/ull_peripheral_iso.c | 2 ++ 4 files changed, 25 insertions(+), 4 deletions(-) diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_central_iso.c b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_central_iso.c index 6135cc9d863..d287bc794a6 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_central_iso.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_central_iso.c @@ -488,14 +488,17 @@ static void isr_tx(void *param) /* Get reference to CIS LLL context */ cis_lll = param; + /* Acquire rx node for reception */ + node_rx = ull_iso_pdu_rx_alloc_peek(1U); + LL_ASSERT(node_rx); + #if defined(CONFIG_BT_CTLR_LE_ENC) /* Get reference to ACL context */ const struct lll_conn *conn_lll = ull_conn_lll_get(cis_lll->acl_handle); #endif /* CONFIG_BT_CTLR_LE_ENC */ - /* Acquire rx node for reception */ - node_rx = ull_iso_pdu_rx_alloc_peek(1U); - LL_ASSERT(node_rx); + /* PHY */ + radio_phy_set(cis_lll->rx.phy, PHY_FLAGS_S8); /* Encryption */ if (false) { @@ -1087,6 +1090,9 @@ static void isr_prepare_subevent(void *param) const struct lll_conn *conn_lll = ull_conn_lll_get(cis_lll->acl_handle); #endif /* CONFIG_BT_CTLR_LE_ENC */ + /* PHY */ + radio_phy_set(cis_lll->tx.phy, cis_lll->tx.phy_flags); + /* Encryption */ if (false) { diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_peripheral_iso.c b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_peripheral_iso.c index 4796696ce73..f089a07bb0b 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_peripheral_iso.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_peripheral_iso.c @@ -244,7 +244,7 @@ static int prepare_cb(struct lll_prepare_param *p) #endif /* !CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL */ phy = cis_lll->rx.phy; - radio_phy_set(phy, cis_lll->rx.phy_flags); + radio_phy_set(phy, PHY_FLAGS_S8); radio_aa_set(cis_lll->access_addr); radio_crc_configure(PDU_CRC_POLYNOMIAL, sys_get_le24(conn_lll->crc_init)); lll_chan_set(data_chan_use); @@ -738,6 +738,9 @@ static void isr_rx(void *param) pdu_tx->rfu0 = 0U; pdu_tx->rfu1 = 0U; + /* PHY */ + radio_phy_set(cis_lll->tx.phy, cis_lll->tx.phy_flags); + /* Encryption */ if (false) { @@ -880,6 +883,9 @@ static void isr_tx(void *param) const struct lll_conn *conn_lll = ull_conn_lll_get(cis_lll->acl_handle); #endif /* CONFIG_BT_CTLR_LE_ENC */ + /* PHY */ + radio_phy_set(cis_lll->rx.phy, PHY_FLAGS_S8); + /* Encryption */ if (false) { @@ -1094,6 +1100,9 @@ static void isr_prepare_subevent_common(void *param) const struct lll_conn *conn_lll = ull_conn_lll_get(cis_lll->acl_handle); #endif /* CONFIG_BT_CTLR_LE_ENC */ + /* PHY */ + radio_phy_set(cis_lll->rx.phy, PHY_FLAGS_S8); + /* Encryption */ if (false) { diff --git a/subsys/bluetooth/controller/ll_sw/ull_central_iso.c b/subsys/bluetooth/controller/ll_sw/ull_central_iso.c index 2a19e03bde5..aac5d2057d2 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_central_iso.c +++ b/subsys/bluetooth/controller/ll_sw/ull_central_iso.c @@ -136,7 +136,9 @@ uint8_t ll_cis_parameters_set(uint8_t cis_id, ll_iso_setup.stream[cis_idx].c_max_sdu = c_sdu; ll_iso_setup.stream[cis_idx].p_max_sdu = p_sdu; ll_iso_setup.stream[cis_idx].lll.tx.phy = c_phy; + ll_iso_setup.stream[cis_idx].lll.tx.phy_flags = PHY_FLAGS_S8; ll_iso_setup.stream[cis_idx].lll.rx.phy = p_phy; + ll_iso_setup.stream[cis_idx].lll.rx.phy_flags = PHY_FLAGS_S8; ll_iso_setup.stream[cis_idx].central.c_rtn = c_rtn; ll_iso_setup.stream[cis_idx].central.p_rtn = p_rtn; ll_iso_setup.cis_idx++; @@ -635,7 +637,9 @@ uint8_t ll_cis_parameters_test_set(uint8_t cis_id, uint8_t nse, ll_iso_setup.stream[cis_idx].lll.tx.max_pdu = c_bn ? c_pdu : 0U; ll_iso_setup.stream[cis_idx].lll.rx.max_pdu = p_bn ? p_pdu : 0U; ll_iso_setup.stream[cis_idx].lll.tx.phy = c_phy; + ll_iso_setup.stream[cis_idx].lll.tx.phy_flags = PHY_FLAGS_S8; ll_iso_setup.stream[cis_idx].lll.rx.phy = p_phy; + ll_iso_setup.stream[cis_idx].lll.rx.phy_flags = PHY_FLAGS_S8; ll_iso_setup.stream[cis_idx].lll.tx.bn = c_bn; ll_iso_setup.stream[cis_idx].lll.rx.bn = p_bn; ll_iso_setup.cis_idx++; diff --git a/subsys/bluetooth/controller/ll_sw/ull_peripheral_iso.c b/subsys/bluetooth/controller/ll_sw/ull_peripheral_iso.c index f68ca66656f..d2627502ac2 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_peripheral_iso.c +++ b/subsys/bluetooth/controller/ll_sw/ull_peripheral_iso.c @@ -257,11 +257,13 @@ uint8_t ull_peripheral_iso_acquire(struct ll_conn *acl, cis->lll.nse = req->nse; cis->lll.rx.phy = req->c_phy; + cis->lll.rx.phy_flags = PHY_FLAGS_S8; cis->lll.rx.bn = req->c_bn; cis->lll.rx.ft = req->c_ft; cis->lll.rx.max_pdu = sys_le16_to_cpu(req->c_max_pdu); cis->lll.tx.phy = req->p_phy; + cis->lll.tx.phy_flags = PHY_FLAGS_S8; cis->lll.tx.bn = req->p_bn; cis->lll.tx.ft = req->p_ft; cis->lll.tx.max_pdu = sys_le16_to_cpu(req->p_max_pdu); From 85b2b7136d56092617648e8bee0e0d860cfbf524 Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Sun, 24 Sep 2023 07:10:31 +0200 Subject: [PATCH 258/421] [nrf fromtree] Bluetooth: Controller: nRF53: Cleanup dppi and dppi resources file Minor cleanup typo, redundant conditional compile and refinition. Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit e39d98302d9f9e7640b74f39335b9d59a9bf08ad) Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit a0dd720eda6a895c2d4fb09b720e69561714d82d) --- .../controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5_dppi.h | 4 ++-- .../ll_sw/nordic/hal/nrf5/radio/radio_nrf5_dppi_resources.h | 2 +- .../ll_sw/nordic/hal/nrf5/radio/radio_nrf5_ppi_resources.h | 5 ----- 3 files changed, 3 insertions(+), 8 deletions(-) diff --git a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5_dppi.h b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5_dppi.h index 3792111292a..787755866ab 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5_dppi.h +++ b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5_dppi.h @@ -341,7 +341,7 @@ static inline void hal_sw_switch_timer_clear_ppi_config(void) /* Wire a SW SWITCH TIMER EVENTS_COMPARE[] event * to a PPI GROUP TASK DISABLE task (PPI group with index ). - * 2 adjacent PPIs (8 & 9) and 2 adjacent PPI groups are used for this wiring; + * 2 adjacent PPIs (14 & 15) and 2 adjacent PPI groups are used for this wiring; * must be 0 or 1. must be a valid TIMER CC register offset. */ #define HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI(index) \ @@ -429,10 +429,10 @@ static inline void hal_sw_switch_timer_clear_ppi_config(void) (SW_SWITCH_TIMER_EVTS_COMP_PHYEND_DELAY_COMPENSATION_BASE + (index)) #define HAL_SW_SWITCH_RADIO_ENABLE_PHYEND_DELAY_COMPENSATION_PPI(index) \ HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI(index) + /* Cancel the SW switch timer running considering PHYEND delay compensation timing: * wire the RADIO EVENTS_CTEPRESENT event to SW_SWITCH_TIMER TASKS_CAPTURE task. */ -#define HAL_SW_SWITCH_TIMER_PHYEND_DELAY_COMPENSATION_DISABLE_PPI 16 #define HAL_SW_SWITCH_TIMER_PHYEND_DELAY_COMPENSATION_DISABLE_PPI_REGISTER_EVT \ NRF_RADIO->PUBLISH_CTEPRESENT diff --git a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5_dppi_resources.h b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5_dppi_resources.h index e1b47d03fd7..a8bbe8e63b4 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5_dppi_resources.h +++ b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5_dppi_resources.h @@ -98,7 +98,7 @@ /* Wire a SW SWITCH TIMER EVENTS_COMPARE[] event * to a PPI GROUP TASK DISABLE task (PPI group with index ). - * 2 adjacent PPIs (8 & 9) and 2 adjacent PPI groups are used for this wiring; + * 2 adjacent PPIs (14 & 15) and 2 adjacent PPI groups are used for this wiring; * must be 0 or 1. must be a valid TIMER CC register offset. */ #define HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI_BASE 14 diff --git a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5_ppi_resources.h b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5_ppi_resources.h index 5c5093f4b52..ab196e17d58 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5_ppi_resources.h +++ b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5_ppi_resources.h @@ -143,9 +143,6 @@ #define HAL_SW_SWITCH_RADIO_ENABLE_PPI_BASE 12 #endif -#if defined(CONFIG_BT_CTLR_PHY_CODED) && \ - defined(CONFIG_HAS_HW_NRF_RADIO_BLE_CODED) - /* Wire the SW SWITCH TIMER EVENTS_COMPARE[] event * to RADIO TASKS_TXEN/RXEN task. */ @@ -156,8 +153,6 @@ */ #define HAL_SW_SWITCH_TIMER_S8_DISABLE_PPI 19 -#endif /* CONFIG_HAS_HW_NRF_RADIO_BLE_CODED */ - #if defined(CONFIG_BT_CTLR_DF_PHYEND_OFFSET_COMPENSATION_ENABLE) /* Wire the SW SWITCH PHYEND delay compensation TIMER EVENTS_COMPARE[] event to software * switch TIMER0->CLEAR taks task. From a91031e38b7c7e412c23636630ae62c0744c6cc9 Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Mon, 25 Sep 2023 10:17:22 +0200 Subject: [PATCH 259/421] [nrf fromtree] Bluetooth: Controller: nrf53: Fix back-to-back Tx Rx implementation Back-to-back Tx Rx implementation was incorrect for nRF53 that uses DPPI. Both current and next DPPI channels where enabled in the implementation which only worked correctly to have the right tIFS when current and next PDU length were same. Fix ensures that the correct current DPPI is subscribed to by the radio subscribe. The implementation has been refactor to be able to use the current sw_tifs_toggle value in the HAL implementation. Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit b61bd2364c1a4267f489910987d7d2c0d14e62c2) Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit fbf08870e25889dd450b614168da8a398e6eeb7f) --- .../ll_sw/nordic/hal/nrf5/radio/radio.c | 30 +++++- .../ll_sw/nordic/hal/nrf5/radio/radio.h | 2 + .../nordic/hal/nrf5/radio/radio_nrf5_dppi.h | 100 ++++++++++++------ .../nordic/hal/nrf5/radio/radio_nrf5_ppi.h | 66 +++++++----- .../controller/ll_sw/nordic/lll/lll_adv_iso.c | 2 +- 5 files changed, 133 insertions(+), 67 deletions(-) diff --git a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio.c b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio.c index 0b41a9bbfb6..a657ab95dfe 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio.c @@ -718,7 +718,7 @@ void sw_switch(uint8_t dir_curr, uint8_t dir_next, uint8_t phy_curr, uint8_t fla #endif /* CONFIG_BT_CTLR_DF_PHYEND_OFFSET_COMPENSATION_ENABLE */ uint32_t delay; - hal_radio_sw_switch_setup(cc, ppi, sw_tifs_toggle); + hal_radio_sw_switch_setup(sw_tifs_toggle); /* NOTE: As constants are passed to dir_curr and dir_next, the * compiler should optimize out the redundant code path @@ -736,7 +736,7 @@ void sw_switch(uint8_t dir_curr, uint8_t dir_next, uint8_t phy_curr, uint8_t fla hal_radio_tx_chain_delay_ns_get(phy_curr, flags_curr)); - hal_radio_b2b_txen_on_sw_switch(ppi); + hal_radio_b2b_txen_on_sw_switch(cc, ppi); } else { /* If RX PHY is LE Coded, calculate for S8 coding. * Assumption being, S8 has higher delay. @@ -746,7 +746,7 @@ void sw_switch(uint8_t dir_curr, uint8_t dir_next, uint8_t phy_curr, uint8_t fla flags_next) + hal_radio_rx_chain_delay_ns_get(phy_curr, 1)); - hal_radio_txen_on_sw_switch(ppi); + hal_radio_txen_on_sw_switch(cc, ppi); } #if defined(CONFIG_BT_CTLR_DF_PHYEND_OFFSET_COMPENSATION_ENABLE) @@ -839,7 +839,7 @@ void sw_switch(uint8_t dir_curr, uint8_t dir_next, uint8_t phy_curr, uint8_t fla flags_curr)) + (EVENT_CLOCK_JITTER_US << 1); - hal_radio_rxen_on_sw_switch(ppi); + hal_radio_rxen_on_sw_switch(cc, ppi); } else { delay = HAL_RADIO_NS2US_CEIL( hal_radio_rx_ready_delay_ns_get(phy_next, @@ -848,7 +848,7 @@ void sw_switch(uint8_t dir_curr, uint8_t dir_next, uint8_t phy_curr, uint8_t fla flags_curr)) + (EVENT_CLOCK_JITTER_US << 1); - hal_radio_b2b_rxen_on_sw_switch(ppi); + hal_radio_b2b_rxen_on_sw_switch(cc, ppi); } @@ -982,6 +982,26 @@ void radio_switch_complete_and_b2b_rx(uint8_t phy_curr, uint8_t flags_curr, #endif /* !CONFIG_BT_CTLR_TIFS_HW */ } +void radio_switch_complete_and_b2b_tx_disable(void) +{ +#if defined(CONFIG_BT_CTLR_TIFS_HW) + NRF_RADIO->SHORTS = (RADIO_SHORTS_READY_START_Msk | RADIO_SHORTS_END_DISABLE_Msk); +#else /* CONFIG_BT_CTLR_TIFS_HW */ + NRF_RADIO->SHORTS = (RADIO_SHORTS_READY_START_Msk | NRF_RADIO_SHORTS_PDU_END_DISABLE); + hal_radio_sw_switch_b2b_tx_disable(sw_tifs_toggle); +#endif /* !CONFIG_BT_CTLR_TIFS_HW */ +} + +void radio_switch_complete_and_b2b_rx_disable(void) +{ +#if defined(CONFIG_BT_CTLR_TIFS_HW) + NRF_RADIO->SHORTS = (RADIO_SHORTS_READY_START_Msk | RADIO_SHORTS_END_DISABLE_Msk); +#else /* CONFIG_BT_CTLR_TIFS_HW */ + NRF_RADIO->SHORTS = (RADIO_SHORTS_READY_START_Msk | NRF_RADIO_SHORTS_PDU_END_DISABLE); + hal_radio_sw_switch_b2b_rx_disable(sw_tifs_toggle); +#endif /* !CONFIG_BT_CTLR_TIFS_HW */ +} + void radio_switch_complete_and_disable(void) { #if defined(CONFIG_BT_CTLR_TIFS_HW) diff --git a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio.h b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio.h index 600d7e95481..4bf833b233a 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio.h +++ b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio.h @@ -106,6 +106,8 @@ void radio_switch_complete_and_b2b_tx(uint8_t phy_curr, uint8_t flags_curr, uint8_t phy_next, uint8_t flags_next); void radio_switch_complete_and_b2b_rx(uint8_t phy_curr, uint8_t flags_curr, uint8_t phy_next, uint8_t flags_next); +void radio_switch_complete_and_b2b_tx_disable(void); +void radio_switch_complete_and_b2b_rx_disable(void); void radio_switch_complete_and_disable(void); uint8_t radio_phy_flags_rx_get(void); diff --git a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5_dppi.h b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5_dppi.h index 787755866ab..1fdf7d90d30 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5_dppi.h +++ b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5_dppi.h @@ -455,10 +455,7 @@ static inline void hal_sw_switch_timer_clear_ppi_config(void) #endif /* CONFIG_BT_CTLR_DF_PHYEND_OFFSET_COMPENSATION_ENABLE */ -static inline void hal_radio_sw_switch_setup( - uint8_t compare_reg, - uint8_t radio_enable_ppi, - uint8_t ppi_group_index) +static inline void hal_radio_sw_switch_setup(uint8_t ppi_group_index) { /* Set up software switch mechanism for next Radio switch. */ @@ -466,7 +463,7 @@ static inline void hal_radio_sw_switch_setup( * over PPI[] */ HAL_SW_SWITCH_GROUP_TASK_ENABLE_PPI_REGISTER_EVT = - HAL_SW_SWITCH_GROUP_TASK_ENABLE_PPI_EVT; + HAL_SW_SWITCH_GROUP_TASK_ENABLE_PPI_EVT; nrf_dppi_subscribe_set(NRF_DPPIC, HAL_SW_DPPI_TASK_EN_FROM_IDX(SW_SWITCH_TIMER_TASK_GROUP(ppi_group_index)), HAL_SW_SWITCH_GROUP_TASK_ENABLE_PPI); @@ -476,55 +473,70 @@ static inline void hal_radio_sw_switch_setup( nrf_dppi_subscribe_clear(NRF_DPPIC, HAL_SW_DPPI_TASK_EN_FROM_IDX(SW_SWITCH_TIMER_TASK_GROUP(other_grp))); +} +static inline void hal_radio_txen_on_sw_switch(uint8_t compare_reg_index, uint8_t radio_enable_ppi) +{ /* Wire SW Switch timer event to the * PPI[] for enabling Radio. Do * not wire the task; it is done by the caller of * the function depending on the desired direction * (TX/RX). */ - HAL_SW_SWITCH_RADIO_ENABLE_PPI_REGISTER_EVT(compare_reg) = + HAL_SW_SWITCH_RADIO_ENABLE_PPI_REGISTER_EVT(compare_reg_index) = HAL_SW_SWITCH_RADIO_ENABLE_PPI_EVT(radio_enable_ppi); -} -static inline void hal_radio_txen_on_sw_switch(uint8_t ppi) -{ - nrf_radio_subscribe_set(NRF_RADIO, NRF_RADIO_TASK_TXEN, ppi); + nrf_radio_subscribe_set(NRF_RADIO, NRF_RADIO_TASK_TXEN, radio_enable_ppi); } -static inline void hal_radio_b2b_txen_on_sw_switch(uint8_t ppi) +static inline void hal_radio_b2b_txen_on_sw_switch(uint8_t compare_reg_index, + uint8_t radio_enable_ppi) { - /* NOTE: Calling radio_tmr_start/radio_tmr_start_us/radio_tmr_start_now - * after the radio_switch_complete_and_b2b_tx() call would have - * changed the PPI channel to HAL_RADIO_ENABLE_ON_TICK_PPI as we - * cannot double buffer the subscribe buffer. Hence, lets have - * both DPPI channel enabled (other one was enabled by the DPPI - * group when the Radio End occurred) so that when both timer - * trigger one of the DPPI is correct in the radio tx - * subscription. + /* Wire SW Switch timer event to the + * PPI[] for enabling Radio. Do + * not wire the task; it is done by the caller of + * the function depending on the desired direction + * (TX/RX). */ - nrf_radio_subscribe_set(NRF_RADIO, NRF_RADIO_TASK_TXEN, ppi); - nrf_dppi_channels_enable(NRF_DPPIC, BIT(ppi)); + HAL_SW_SWITCH_RADIO_ENABLE_PPI_REGISTER_EVT(compare_reg_index) = + HAL_SW_SWITCH_RADIO_ENABLE_PPI_EVT(radio_enable_ppi); + + uint8_t prev_ppi_idx = (compare_reg_index + 0x01) & 0x01; + + radio_enable_ppi = HAL_SW_SWITCH_RADIO_ENABLE_PPI(prev_ppi_idx); + nrf_radio_subscribe_set(NRF_RADIO, NRF_RADIO_TASK_TXEN, radio_enable_ppi); } -static inline void hal_radio_rxen_on_sw_switch(uint8_t ppi) +static inline void hal_radio_rxen_on_sw_switch(uint8_t compare_reg_index, uint8_t radio_enable_ppi) { - nrf_radio_subscribe_set(NRF_RADIO, NRF_RADIO_TASK_RXEN, ppi); + /* Wire SW Switch timer event to the + * PPI[] for enabling Radio. Do + * not wire the task; it is done by the caller of + * the function depending on the desired direction + * (TX/RX). + */ + HAL_SW_SWITCH_RADIO_ENABLE_PPI_REGISTER_EVT(compare_reg_index) = + HAL_SW_SWITCH_RADIO_ENABLE_PPI_EVT(radio_enable_ppi); + + nrf_radio_subscribe_set(NRF_RADIO, NRF_RADIO_TASK_RXEN, radio_enable_ppi); } -static inline void hal_radio_b2b_rxen_on_sw_switch(uint8_t ppi) +static inline void hal_radio_b2b_rxen_on_sw_switch(uint8_t compare_reg_index, + uint8_t radio_enable_ppi) { - /* NOTE: Calling radio_tmr_start/radio_tmr_start_us/radio_tmr_start_now - * after the radio_switch_complete_and_b2b_rx() call would have - * changed the PPI channel to HAL_RADIO_ENABLE_ON_TICK_PPI as we - * cannot double buffer the subscribe buffer. Hence, lets have - * both DPPI channel enabled (other one was enabled by the DPPI - * group when the Radio End occurred) so that when both timer - * trigger one of the DPPI is correct in the radio rx - * subscription. + /* Wire SW Switch timer event to the + * PPI[] for enabling Radio. Do + * not wire the task; it is done by the caller of + * the function depending on the desired direction + * (TX/RX). */ - nrf_radio_subscribe_set(NRF_RADIO, NRF_RADIO_TASK_RXEN, ppi); - nrf_dppi_channels_enable(NRF_DPPIC, BIT(ppi)); + HAL_SW_SWITCH_RADIO_ENABLE_PPI_REGISTER_EVT(compare_reg_index) = + HAL_SW_SWITCH_RADIO_ENABLE_PPI_EVT(radio_enable_ppi); + + uint8_t prev_ppi_idx = (compare_reg_index + 0x01) & 0x01; + + radio_enable_ppi = HAL_SW_SWITCH_RADIO_ENABLE_PPI(prev_ppi_idx); + nrf_radio_subscribe_set(NRF_RADIO, NRF_RADIO_TASK_RXEN, radio_enable_ppi); } static inline void hal_radio_sw_switch_disable(void) @@ -540,6 +552,26 @@ static inline void hal_radio_sw_switch_disable(void) HAL_SW_DPPI_TASK_EN_FROM_IDX(SW_SWITCH_TIMER_TASK_GROUP(1))); } +static inline void hal_radio_sw_switch_b2b_tx_disable(uint8_t compare_reg_index) +{ + hal_radio_sw_switch_disable(); + + uint8_t prev_ppi_idx = (compare_reg_index + 0x01) & 0x01; + uint8_t radio_enable_ppi = HAL_SW_SWITCH_RADIO_ENABLE_PPI(prev_ppi_idx); + + nrf_radio_subscribe_set(NRF_RADIO, NRF_RADIO_TASK_TXEN, radio_enable_ppi); +} + +static inline void hal_radio_sw_switch_b2b_rx_disable(uint8_t compare_reg_index) +{ + hal_radio_sw_switch_disable(); + + uint8_t prev_ppi_idx = (compare_reg_index + 0x01) & 0x01; + uint8_t radio_enable_ppi = HAL_SW_SWITCH_RADIO_ENABLE_PPI(prev_ppi_idx); + + nrf_radio_subscribe_set(NRF_RADIO, NRF_RADIO_TASK_RXEN, radio_enable_ppi); +} + static inline void hal_radio_sw_switch_cleanup(void) { hal_radio_sw_switch_disable(); diff --git a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5_ppi.h b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5_ppi.h index d964129bfa1..44cec4621a3 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5_ppi.h +++ b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5_ppi.h @@ -420,10 +420,7 @@ static inline void hal_sw_switch_timer_clear_ppi_config(void) #define HAL_SW_SWITCH_RADIO_ENABLE_PPI_TASK_RX \ ((uint32_t)&(NRF_RADIO->TASKS_RXEN)) -static inline void hal_radio_sw_switch_setup( - uint8_t compare_reg, - uint8_t radio_enable_ppi, - uint8_t ppi_group_index) +static inline void hal_radio_sw_switch_setup(uint8_t ppi_group_index) { /* Set up software switch mechanism for next Radio switch. */ @@ -435,53 +432,58 @@ static inline void hal_radio_sw_switch_setup( HAL_SW_SWITCH_GROUP_TASK_ENABLE_PPI, HAL_SW_SWITCH_GROUP_TASK_ENABLE_PPI_EVT, HAL_SW_SWITCH_GROUP_TASK_ENABLE_PPI_TASK(ppi_group_index)); +} +static inline void hal_radio_txen_on_sw_switch(uint8_t compare_reg_index, uint8_t radio_enable_ppi) +{ /* Wire SW Switch timer event to the * PPI[] for enabling Radio. Do * not wire the task; it is done by the caller of * the function depending on the desired direction * (TX/RX). */ - nrf_ppi_event_endpoint_setup( - NRF_PPI, - radio_enable_ppi, - HAL_SW_SWITCH_RADIO_ENABLE_PPI_EVT(compare_reg)); -} + nrf_ppi_event_endpoint_setup(NRF_PPI, radio_enable_ppi, + HAL_SW_SWITCH_RADIO_ENABLE_PPI_EVT(compare_reg_index)); -static inline void hal_radio_txen_on_sw_switch(uint8_t ppi) -{ - nrf_ppi_task_endpoint_setup( - NRF_PPI, - ppi, - HAL_SW_SWITCH_RADIO_ENABLE_PPI_TASK_TX); + nrf_ppi_task_endpoint_setup(NRF_PPI, radio_enable_ppi, + HAL_SW_SWITCH_RADIO_ENABLE_PPI_TASK_TX); } -static inline void hal_radio_b2b_txen_on_sw_switch(uint8_t ppi) +static inline void hal_radio_b2b_txen_on_sw_switch(uint8_t compare_reg_index, + uint8_t radio_enable_ppi) { /* NOTE: As independent PPI are used to trigger the Radio Tx task, * double buffers implementation works for sw_switch using PPIs, * simply reuse the hal_radio_txen_on_sw_switch() functon to set * the next PPIs task to be Radio Tx enable. */ - hal_radio_txen_on_sw_switch(ppi); + hal_radio_txen_on_sw_switch(compare_reg_index, radio_enable_ppi); } -static inline void hal_radio_rxen_on_sw_switch(uint8_t ppi) +static inline void hal_radio_rxen_on_sw_switch(uint8_t compare_reg_index, uint8_t radio_enable_ppi) { - nrf_ppi_task_endpoint_setup( - NRF_PPI, - ppi, - HAL_SW_SWITCH_RADIO_ENABLE_PPI_TASK_RX); + /* Wire SW Switch timer event to the + * PPI[] for enabling Radio. Do + * not wire the task; it is done by the caller of + * the function depending on the desired direction + * (TX/RX). + */ + nrf_ppi_event_endpoint_setup(NRF_PPI, radio_enable_ppi, + HAL_SW_SWITCH_RADIO_ENABLE_PPI_EVT(compare_reg_index)); + + nrf_ppi_task_endpoint_setup(NRF_PPI, radio_enable_ppi, + HAL_SW_SWITCH_RADIO_ENABLE_PPI_TASK_RX); } -static inline void hal_radio_b2b_rxen_on_sw_switch(uint8_t ppi) +static inline void hal_radio_b2b_rxen_on_sw_switch(uint8_t compare_reg_index, + uint8_t radio_enable_ppi) { - /* NOTE: As independent PPI are used to trigger the Radio Rx task, + /* NOTE: As independent PPI are used to trigger the Radio Tx task, * double buffers implementation works for sw_switch using PPIs, - * simply reuse the hal_radio_rxen_on_sw_switch() functon to set - * the next PPIs task to be Radio Rx enable. + * simply reuse the hal_radio_txen_on_sw_switch() functon to set + * the next PPIs task to be Radio Tx enable. */ - hal_radio_rxen_on_sw_switch(ppi); + hal_radio_rxen_on_sw_switch(compare_reg_index, radio_enable_ppi); } static inline void hal_radio_sw_switch_disable(void) @@ -496,6 +498,16 @@ static inline void hal_radio_sw_switch_disable(void) BIT(HAL_SW_SWITCH_GROUP_TASK_ENABLE_PPI)); } +static inline void hal_radio_sw_switch_b2b_tx_disable(uint8_t compare_reg_index) +{ + hal_radio_sw_switch_disable(); +} + +static inline void hal_radio_sw_switch_b2b_rx_disable(uint8_t compare_reg_index) +{ + hal_radio_sw_switch_disable(); +} + static inline void hal_radio_sw_switch_cleanup(void) { hal_radio_sw_switch_disable(); diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_adv_iso.c b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_adv_iso.c index 87849d0e1fd..20e3fe528e1 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_adv_iso.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_adv_iso.c @@ -717,7 +717,7 @@ static void isr_tx_common(void *param, pkt_flags); } - radio_switch_complete_and_disable(); + radio_switch_complete_and_b2b_tx_disable(); radio_isr_set(isr_done_term, lll); } else { From fd76eac8e690a1181d84cba6a89cdfc3808ef3e7 Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Thu, 21 Sep 2023 13:18:19 +0200 Subject: [PATCH 260/421] [nrf fromtree] Bluetooth: Controller: Fix compile error when BT_CTLR_CENTRAL_SPACING=n Fix compile error when CONFIG_BT_CTLR_CENTRAL_SPACING is undefined. Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit 1ab007a2ba01bf5888eb13e700c4ecd526602f60) Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit 6f1be380e58da2555c4c1d4ff49ffc68b5b20cff) --- subsys/bluetooth/controller/ll_sw/ull_central_iso.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/subsys/bluetooth/controller/ll_sw/ull_central_iso.c b/subsys/bluetooth/controller/ll_sw/ull_central_iso.c index aac5d2057d2..19dec37c937 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_central_iso.c +++ b/subsys/bluetooth/controller/ll_sw/ull_central_iso.c @@ -857,13 +857,19 @@ uint8_t ull_central_iso_setup(uint16_t cis_handle, cis->offset = cis_offset; #else /* !CONFIG_BT_CTLR_JIT_SCHEDULING */ - if (IS_ENABLED(CONFIG_BT_CTLR_CENTRAL_SPACING) && (CONFIG_BT_CTLR_CENTRAL_SPACING > 0)) { + + if (false) { + +#if defined(CONFIG_BT_CTLR_CENTRAL_SPACING) + } else if (CONFIG_BT_CTLR_CENTRAL_SPACING > 0) { uint32_t cis_offset; cis_offset = MAX((HAL_TICKER_TICKS_TO_US(conn->ull.ticks_slot) + (EVENT_TICKER_RES_MARGIN_US << 1U) + cig->sync_delay - cis->sync_delay), *cis_offset_min); cis->offset = cis_offset; +#endif /* CONFIG_BT_CTLR_CENTRAL_SPACING */ + } else { cis->offset = *cis_offset_min; } From 34f39e4fa35bfc3af1ba376d8bd04b791503e315 Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Fri, 5 May 2023 10:15:02 +0530 Subject: [PATCH 261/421] [nrf fromtree] Bluetooth: Controller: Add BT_CTLR_EVENT_OVERHEAD_RESERVE_MAX Kconfig Add BT_CTLR_EVENT_OVERHEAD_RESERVE_MAX Kconfig to allow the omit of EVENT_OVERHEAD_START_US and EVENT_OVERHEAD_END_US in the time reservation calculations. Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit 3c2b1f952cdf982635cccf2164a42aa3ef08f814) Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit ef922a5dafc0a32ce231ca6aa510d75c1f54418a) --- .../bluetooth/controller/Kconfig.ll_sw_split | 11 +++ .../bluetooth/controller/ll_sw/ull_central.c | 12 ++- .../controller/ll_sw/ull_central_iso.c | 18 +++-- subsys/bluetooth/controller/ll_sw/ull_conn.c | 18 +++-- .../bluetooth/controller/ll_sw/ull_conn_iso.c | 4 +- .../controller/ll_sw/ull_peripheral.c | 23 ++++-- .../controller/ll_sw/ull_peripheral_iso.c | 4 + tests/bluetooth/init/prj_ctlr_5_x_dbg.conf | 76 +++++++++++++++++++ tests/bluetooth/init/testcase.yaml | 10 +++ 9 files changed, 152 insertions(+), 24 deletions(-) create mode 100644 tests/bluetooth/init/prj_ctlr_5_x_dbg.conf diff --git a/subsys/bluetooth/controller/Kconfig.ll_sw_split b/subsys/bluetooth/controller/Kconfig.ll_sw_split index 4cd8e200b63..3f6f3c10382 100644 --- a/subsys/bluetooth/controller/Kconfig.ll_sw_split +++ b/subsys/bluetooth/controller/Kconfig.ll_sw_split @@ -632,6 +632,17 @@ config BT_CTLR_CENTRAL_RESERVE_MAX Note, currently this value is only used to space multiple central connections and not for actual ticker time reservations. +config BT_CTLR_EVENT_OVERHEAD_RESERVE_MAX + bool "Reserve maximum event overhead in time reservations" + default y + help + Use radio event scheduling CPU time overhead in calculations of event + time reservations. + + If this option is disabled, then Peripheral ACL and Peripheral ISO + role will not include CPU time overhead. Other role will continue to + use CPU overheads in their event time reservations. + config BT_CTLR_SLOT_RESERVATION_UPDATE bool "Update event length reservation after PHY or DLE update" depends on (BT_CTLR_DATA_LENGTH || BT_CTLR_PHY) diff --git a/subsys/bluetooth/controller/ll_sw/ull_central.c b/subsys/bluetooth/controller/ll_sw/ull_central.c index de14395f840..b189c65fa21 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_central.c +++ b/subsys/bluetooth/controller/ll_sw/ull_central.c @@ -97,6 +97,7 @@ uint8_t ll_create_connection(uint16_t scan_interval, uint16_t scan_window, uint16_t max_tx_time; uint16_t max_rx_time; memq_link_t *link; + uint32_t slot_us; uint8_t hop; int err; @@ -360,10 +361,13 @@ uint8_t ll_create_connection(uint16_t scan_interval, uint16_t scan_window, #endif /* CONFIG_BT_CTLR_ADV_EXT */ #endif /* CONFIG_BT_CTLR_DATA_LENGTH */ - conn->ull.ticks_slot = HAL_TICKER_US_TO_TICKS_CEIL( - EVENT_OVERHEAD_START_US + EVENT_OVERHEAD_END_US + - ready_delay_us + max_tx_time + EVENT_IFS_US + max_rx_time + - (EVENT_CLOCK_JITTER_US << 1)); + /* Calculate event time reservation */ + slot_us = max_tx_time + max_rx_time; + slot_us += EVENT_IFS_US + (EVENT_CLOCK_JITTER_US << 1); + slot_us += ready_delay_us; + slot_us += EVENT_OVERHEAD_START_US + EVENT_OVERHEAD_END_US; + + conn->ull.ticks_slot = HAL_TICKER_US_TO_TICKS_CEIL(slot_us); #if defined(CONFIG_BT_CTLR_PRIVACY) ull_filter_scan_update(filter_policy); diff --git a/subsys/bluetooth/controller/ll_sw/ull_central_iso.c b/subsys/bluetooth/controller/ll_sw/ull_central_iso.c index 19dec37c937..8c516826e06 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_central_iso.c +++ b/subsys/bluetooth/controller/ll_sw/ull_central_iso.c @@ -864,9 +864,15 @@ uint8_t ull_central_iso_setup(uint16_t cis_handle, } else if (CONFIG_BT_CTLR_CENTRAL_SPACING > 0) { uint32_t cis_offset; - cis_offset = MAX((HAL_TICKER_TICKS_TO_US(conn->ull.ticks_slot) + - (EVENT_TICKER_RES_MARGIN_US << 1U) + cig->sync_delay - - cis->sync_delay), *cis_offset_min); + cis_offset = HAL_TICKER_TICKS_TO_US(conn->ull.ticks_slot) + + (EVENT_TICKER_RES_MARGIN_US << 1U); + + cis_offset += cig->sync_delay - cis->sync_delay; + + if (cis_offset < *cis_offset_min) { + cis_offset = *cis_offset_min; + } + cis->offset = cis_offset; #endif /* CONFIG_BT_CTLR_CENTRAL_SPACING */ @@ -942,8 +948,9 @@ int ull_central_iso_cis_offset_get(uint16_t cis_handle, #endif /* CONFIG_BT_CTLR_CENTRAL_SPACING != 0 */ *cis_offset_min = HAL_TICKER_TICKS_TO_US(conn->ull.ticks_slot) + - (EVENT_TICKER_RES_MARGIN_US << 1U) + - cig->sync_delay - cis->sync_delay; + (EVENT_TICKER_RES_MARGIN_US << 1U); + + *cis_offset_min += cig->sync_delay - cis->sync_delay; return 0; } @@ -984,7 +991,6 @@ static void mfy_cig_offset_get(void *param) offset_min_us += cig->sync_delay - cis->sync_delay; conn = ll_conn_get(cis->lll.acl_handle); - conn_interval_us = (uint32_t)conn->lll.interval * CONN_INT_UNIT_US; while (offset_min_us >= (conn_interval_us + PDU_CIS_OFFSET_MIN_US)) { offset_min_us -= conn_interval_us; diff --git a/subsys/bluetooth/controller/ll_sw/ull_conn.c b/subsys/bluetooth/controller/ll_sw/ull_conn.c index a8d3178e020..9d78af7acc1 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_conn.c +++ b/subsys/bluetooth/controller/ll_sw/ull_conn.c @@ -1233,7 +1233,7 @@ void ull_conn_done(struct node_rx_event_done *done) #if defined(CONFIG_BT_CTLR_SLOT_RESERVATION_UPDATE) #if defined(CONFIG_BT_CTLR_DATA_LENGTH) || defined(CONFIG_BT_CTLR_PHY) if (lll->evt_len_upd) { - uint32_t ready_delay, rx_time, tx_time, ticks_slot; + uint32_t ready_delay, rx_time, tx_time, ticks_slot, slot_us; lll->evt_len_upd = 0; #if defined(CONFIG_BT_CTLR_PHY) @@ -1257,10 +1257,18 @@ void ull_conn_done(struct node_rx_event_done *done) tx_time = PDU_DC_MAX_US(lll->dle.eff.max_tx_octets, 0); rx_time = PDU_DC_MAX_US(lll->dle.eff.max_rx_octets, 0); #endif /* CONFIG_BT_CTLR_PHY */ - ticks_slot = HAL_TICKER_US_TO_TICKS_CEIL( - EVENT_OVERHEAD_START_US + EVENT_OVERHEAD_END_US + - ready_delay + EVENT_IFS_US + rx_time + tx_time + - (EVENT_CLOCK_JITTER_US << 1)); + + /* Calculate event time reservation */ + slot_us = tx_time + rx_time; + slot_us += EVENT_IFS_US + (EVENT_CLOCK_JITTER_US << 1); + slot_us += ready_delay; + + if (IS_ENABLED(CONFIG_BT_CTLR_EVENT_OVERHEAD_RESERVE_MAX) || + !conn->lll.role) { + slot_us += EVENT_OVERHEAD_START_US + EVENT_OVERHEAD_END_US; + } + + ticks_slot = HAL_TICKER_US_TO_TICKS_CEIL(slot_us); if (ticks_slot > conn->ull.ticks_slot) { ticks_slot_plus = ticks_slot - conn->ull.ticks_slot; } else { diff --git a/subsys/bluetooth/controller/ll_sw/ull_conn_iso.c b/subsys/bluetooth/controller/ll_sw/ull_conn_iso.c index 46c00c305fe..2ec6a73b4a4 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_conn_iso.c +++ b/subsys/bluetooth/controller/ll_sw/ull_conn_iso.c @@ -972,7 +972,9 @@ void ull_conn_iso_start(struct ll_conn *conn, uint16_t cis_handle, /* Below is time reservation for sequential packing */ slot_us = cis->lll.sub_interval * cis->lll.nse; - slot_us += EVENT_OVERHEAD_START_US + EVENT_OVERHEAD_END_US; + if (IS_ENABLED(CONFIG_BT_CTLR_EVENT_OVERHEAD_RESERVE_MAX)) { + slot_us += EVENT_OVERHEAD_START_US + EVENT_OVERHEAD_END_US; + } /* FIXME: How to use ready_delay_us in the time reservation? * i.e. when CISes use different PHYs? Is that even diff --git a/subsys/bluetooth/controller/ll_sw/ull_peripheral.c b/subsys/bluetooth/controller/ll_sw/ull_peripheral.c index 8b813fda9fd..5a34f787ec7 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_peripheral.c +++ b/subsys/bluetooth/controller/ll_sw/ull_peripheral.c @@ -89,6 +89,7 @@ void ull_periph_setup(struct node_rx_hdr *rx, struct node_rx_ftr *ftr, uint16_t max_rx_time; uint16_t win_offset; memq_link_t *link; + uint32_t slot_us; uint8_t chan_sel; void *node; @@ -360,10 +361,19 @@ void ull_periph_setup(struct node_rx_hdr *rx, struct node_rx_ftr *ftr, #endif /* !CONFIG_BT_CTLR_DATA_LENGTH */ #if defined(CONFIG_BT_CTLR_PHY) - ready_delay_us = lll_radio_rx_ready_delay_get(lll->phy_rx, 1); -#else - ready_delay_us = lll_radio_rx_ready_delay_get(0, 0); -#endif + ready_delay_us = lll_radio_rx_ready_delay_get(lll->phy_rx, PHY_FLAGS_S8); +#else /* CONFIG_BT_CTLR_PHY */ + ready_delay_us = lll_radio_rx_ready_delay_get(0U, 0U); +#endif /* CONFIG_BT_CTLR_PHY */ + + /* Calculate event time reservation */ + slot_us = max_rx_time + max_tx_time; + slot_us += EVENT_IFS_US + (EVENT_CLOCK_JITTER_US << 1); + slot_us += ready_delay_us; + + if (IS_ENABLED(CONFIG_BT_CTLR_EVENT_OVERHEAD_RESERVE_MAX)) { + slot_us += EVENT_OVERHEAD_START_US + EVENT_OVERHEAD_END_US; + } /* TODO: active_to_start feature port */ conn->ull.ticks_active_to_start = 0U; @@ -371,10 +381,7 @@ void ull_periph_setup(struct node_rx_hdr *rx, struct node_rx_ftr *ftr, HAL_TICKER_US_TO_TICKS(EVENT_OVERHEAD_XTAL_US); conn->ull.ticks_preempt_to_start = HAL_TICKER_US_TO_TICKS(EVENT_OVERHEAD_PREEMPT_MIN_US); - conn->ull.ticks_slot = HAL_TICKER_US_TO_TICKS_CEIL( - EVENT_OVERHEAD_START_US + EVENT_OVERHEAD_END_US + - ready_delay_us + max_rx_time + EVENT_IFS_US + max_tx_time + - (EVENT_CLOCK_JITTER_US << 1)); + conn->ull.ticks_slot = HAL_TICKER_US_TO_TICKS_CEIL(slot_us); ticks_slot_offset = MAX(conn->ull.ticks_active_to_start, conn->ull.ticks_prepare_to_start); diff --git a/subsys/bluetooth/controller/ll_sw/ull_peripheral_iso.c b/subsys/bluetooth/controller/ll_sw/ull_peripheral_iso.c index d2627502ac2..eeef778734b 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_peripheral_iso.c +++ b/subsys/bluetooth/controller/ll_sw/ull_peripheral_iso.c @@ -110,6 +110,10 @@ uint8_t ll_cis_accept(uint16_t handle) } else { cis_offset_min = HAL_TICKER_TICKS_TO_US(conn->ull.ticks_slot) + (EVENT_TICKER_RES_MARGIN_US << 1U); + + if (!IS_ENABLED(CONFIG_BT_CTLR_EVENT_OVERHEAD_RESERVE_MAX)) { + cis_offset_min += EVENT_OVERHEAD_START_US + EVENT_OVERHEAD_END_US; + } } /* Accept request */ diff --git a/tests/bluetooth/init/prj_ctlr_5_x_dbg.conf b/tests/bluetooth/init/prj_ctlr_5_x_dbg.conf new file mode 100644 index 00000000000..df0d006a13e --- /dev/null +++ b/tests/bluetooth/init/prj_ctlr_5_x_dbg.conf @@ -0,0 +1,76 @@ +CONFIG_BT=y +CONFIG_BT_CTLR=y +CONFIG_BT_LL_SW_SPLIT=y +CONFIG_BT_CTLR_DUP_FILTER_LEN=16 +CONFIG_BT_CTLR_CONN_PARAM_REQ=y +CONFIG_BT_CTLR_LE_PING=y +CONFIG_BT_CTLR_PRIVACY=n +CONFIG_BT_CTLR_EXT_SCAN_FP=n +CONFIG_BT_DATA_LEN_UPDATE=n +CONFIG_BT_PHY_UPDATE=y +CONFIG_BT_CTLR_CHAN_SEL_2=y +CONFIG_BT_CTLR_MIN_USED_CHAN=y +CONFIG_BT_CTLR_ADV_EXT=y +CONFIG_BT_CTLR_ADV_PERIODIC=y +CONFIG_BT_CTLR_ADV_ISO=y +CONFIG_BT_CTLR_SYNC_PERIODIC=y +CONFIG_BT_CTLR_SYNC_ISO=y +CONFIG_BT_CTLR_CENTRAL_ISO=y +CONFIG_BT_CTLR_PERIPHERAL_ISO=y +CONFIG_BT_CTLR_DTM_HCI=y +CONFIG_BT_CTLR_ADVANCED_FEATURES=y +CONFIG_BT_CTLR_PHY_2M=y +CONFIG_BT_CTLR_PHY_2M_NRF=y +CONFIG_BT_CTLR_PHY_CODED=y +CONFIG_BT_CTLR_ADV_AUX_PDU_BACK2BACK=y +CONFIG_BT_CTLR_LLL_PRIO=0 +CONFIG_BT_CTLR_ULL_HIGH_PRIO=1 +CONFIG_BT_CTLR_XTAL_ADVANCED=n +CONFIG_BT_CTLR_SCHED_ADVANCED=y +CONFIG_BT_CTLR_RADIO_ENABLE_FAST=y +CONFIG_BT_CTLR_TIFS_HW=n +CONFIG_BT_CTLR_FAST_ENC=y +CONFIG_BT_CTLR_TX_RETRY_DISABLE=y +CONFIG_BT_CTLR_CONN_RSSI=y +CONFIG_BT_CTLR_ADV_INDICATION=y +CONFIG_BT_CTLR_SCAN_REQ_NOTIFY=y +CONFIG_BT_CTLR_SCAN_REQ_RSSI=y +CONFIG_BT_CTLR_SCAN_INDICATION=y +CONFIG_BT_CTLR_EVENT_OVERHEAD_RESERVE_MAX=n +CONFIG_BT_CTLR_PROFILE_ISR=y +CONFIG_BT_CTLR_DEBUG_PINS=y +CONFIG_BT_CTLR_TEST=y +CONFIG_BT_HCI_VS_EXT=y +CONFIG_BT_HCI_MESH_EXT=n +CONFIG_BT_PERIPHERAL=y +CONFIG_BT_CENTRAL=y +CONFIG_BT_EXT_ADV=y +CONFIG_BT_PER_ADV=y +CONFIG_BT_PER_ADV_SYNC=y +CONFIG_BT_ISO_BROADCASTER=y +CONFIG_BT_ISO_SYNC_RECEIVER=y +CONFIG_BT_ISO_CENTRAL=y +CONFIG_BT_ISO_PERIPHERAL=y +CONFIG_BT_SMP=y +CONFIG_BT_SIGNING=y +CONFIG_BT_SMP_SC_ONLY=y +CONFIG_BT_TINYCRYPT_ECC=y +CONFIG_BT_USE_DEBUG_KEYS=y +CONFIG_BT_L2CAP_DYNAMIC_CHANNEL=y +CONFIG_BT_GATT_CLIENT=y +CONFIG_BT_DEBUG_MONITOR_UART=y +CONFIG_BT_HCI_CORE_LOG_LEVEL_DBG=y +CONFIG_BT_CONN_LOG_LEVEL_DBG=y +CONFIG_BT_KEYS_LOG_LEVEL_DBG=y +CONFIG_BT_L2CAP_LOG_LEVEL_DBG=y +CONFIG_BT_SMP_LOG_LEVEL_DBG=y +CONFIG_BT_HCI_DRIVER_LOG_LEVEL_DBG=y +CONFIG_BT_SMP_SELFTEST=y +CONFIG_BT_ATT_LOG_LEVEL_DBG=y +CONFIG_BT_GATT_LOG_LEVEL_DBG=y +CONFIG_BT_BREDR=n +CONFIG_DEBUG=y +CONFIG_FLASH=y +CONFIG_SOC_FLASH_NRF_RADIO_SYNC_TICKER=n +CONFIG_ZTEST=y +CONFIG_ZTEST_NEW_API=y diff --git a/tests/bluetooth/init/testcase.yaml b/tests/bluetooth/init/testcase.yaml index c38f5bed69e..17d57ec9d47 100644 --- a/tests/bluetooth/init/testcase.yaml +++ b/tests/bluetooth/init/testcase.yaml @@ -122,6 +122,16 @@ tests: integration_platforms: - nrf52840dk_nrf52840 - nrf52dk_nrf52832 + bluetooth.init.test_ctlr_5_x_dbg: + extra_args: + - CONF_FILE=prj_ctlr_5_x_dbg.conf + - DTC_OVERLAY_FILE=pa_lna.overlay + platform_allow: + - nrf52840dk_nrf52840 + - nrf52dk_nrf52832 + integration_platforms: + - nrf52840dk_nrf52840 + - nrf52dk_nrf52832 bluetooth.init.test_ctlr_sw_switch_single_timer: extra_args: - CONF_FILE=prj_ctlr.conf From be0d9e0314e8bbf148d1eb054c04f003b4c04576 Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Tue, 26 Sep 2023 22:41:33 +0200 Subject: [PATCH 262/421] [nrf fromtree] Bluetooth: Controller: Fix BIS payload sliding window overrun check Fix BIS implementation for checking overrun of the BIS PDU sliding window buffer overrun. Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit 7af967a2f5dff86f400d7f53be7da79cdc23f2d6) Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit d219043b4107e7f6970025d6735bf3b07efb1ef7) --- .../bluetooth/controller/ll_sw/lll_sync_iso.h | 1 - .../ll_sw/nordic/lll/lll_sync_iso.c | 52 +++++++++++++++---- .../bluetooth/controller/ll_sw/ull_sync_iso.c | 3 +- 3 files changed, 42 insertions(+), 14 deletions(-) diff --git a/subsys/bluetooth/controller/ll_sw/lll_sync_iso.h b/subsys/bluetooth/controller/ll_sw/lll_sync_iso.h index 2426f51105e..c47aa433c63 100644 --- a/subsys/bluetooth/controller/ll_sw/lll_sync_iso.h +++ b/subsys/bluetooth/controller/ll_sw/lll_sync_iso.h @@ -74,7 +74,6 @@ struct lll_sync_iso { struct node_rx_pdu *payload[BT_CTLR_SYNC_ISO_STREAM_MAX] [PDU_BIG_PAYLOAD_COUNT_MAX]; uint8_t payload_count_max; - uint8_t payload_head; uint8_t payload_tail; uint32_t window_widening_periodic_us; diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_sync_iso.c b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_sync_iso.c index 5089c6ccde7..12e9fd342b9 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_sync_iso.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_sync_iso.c @@ -489,7 +489,6 @@ static void isr_rx(void *param) uint8_t access_addr[4]; uint16_t data_chan_id; uint8_t data_chan_use; - uint8_t payload_index; uint8_t crc_init[3]; uint8_t rssi_ready; uint32_t start_us; @@ -556,6 +555,8 @@ static void isr_rx(void *param) if (crc_ok) { struct lll_sync_iso_stream *sync_stream; uint16_t stream_handle; + uint8_t payload_offset; + uint8_t payload_index; struct pdu_bis *pdu; /* Check if Control Subevent being received */ @@ -593,21 +594,28 @@ static void isr_rx(void *param) /* TODO: check same CSSN is used in every subevent */ } - /* calculate the payload index in the sliding window */ - payload_index = lll->payload_tail + (lll->bn_curr - 1U) + - (lll->ptc_curr * lll->pto); + /* Check payload buffer overflow */ + payload_offset = (lll->bn_curr - 1U) + + (lll->ptc_curr * lll->pto); + if (payload_offset > lll->payload_count_max) { + goto isr_rx_done; + } + + /* Calculate the payload index in the sliding window */ + payload_index = lll->payload_tail + payload_offset; if (payload_index >= lll->payload_count_max) { payload_index -= lll->payload_count_max; } + /* Get reference to stream context */ stream_handle = lll->stream_handle[lll->stream_curr]; sync_stream = ull_sync_iso_lll_stream_get(stream_handle); - /* store the received PDU */ + /* Store the received PDU if selected stream and not already + * received (say in previous event as pre-transmitted PDU. + */ if ((lll->bis_curr == sync_stream->bis_index) && pdu->len && - !lll->payload[bis_idx][payload_index] && - ((payload_index >= lll->payload_tail) || - (payload_index < lll->payload_head))) { + !lll->payload[bis_idx][payload_index]) { uint16_t handle; if (lll->enc) { @@ -644,10 +652,23 @@ static void isr_rx(void *param) /* Find the next (bn_curr)th subevent to receive PDU */ while (lll->bn_curr < lll->bn) { + uint8_t payload_offset; + uint8_t payload_index; + + /* Next burst number to check for reception required */ lll->bn_curr++; + /* Check payload buffer overflow */ + payload_offset = (lll->bn_curr - 1U); + if (payload_offset > lll->payload_count_max) { + /* (bn_curr)th Rx PDU skip subevent */ + skipped++; + + continue; + } + /* Find the index of the (bn_curr)th Rx PDU buffer */ - payload_index = lll->payload_tail + (lll->bn_curr - 1U); + payload_index = lll->payload_tail + payload_offset; if (payload_index >= lll->payload_count_max) { payload_index -= lll->payload_count_max; } @@ -667,6 +688,11 @@ static void isr_rx(void *param) /* Find the next repetition (irc_curr)th subevent to receive PDU */ if (lll->irc_curr < lll->irc) { if (!new_burst) { + uint8_t payload_index; + + /* Increment to next repetition count and be at first + * burst count for it. + */ lll->bn_curr = 1U; lll->irc_curr++; @@ -715,6 +741,10 @@ static void isr_rx(void *param) if (lll->ptc_curr < lll->ptc) { lll->ptc_curr++; + /* TODO: optimize to skip pre-transmission subevent in case + * of insufficient buffers in sliding window. + */ + /* Receive the (ptc_curr)th Rx PDU of bis_curr */ bis = lll->bis_curr; @@ -733,6 +763,7 @@ static void isr_rx(void *param) stream_handle = lll->stream_handle[lll->stream_curr]; sync_stream = ull_sync_iso_lll_stream_get(stream_handle); if (sync_stream->bis_index <= lll->num_bis) { + uint8_t payload_index; uint8_t bis_idx_new; lll->bis_curr = sync_stream->bis_index; @@ -1058,8 +1089,7 @@ static void isr_rx_done(void *param) bn = lll->bn; while (bn--) { if (lll->payload[bis_idx][payload_tail]) { - node_rx = - lll->payload[bis_idx][payload_tail]; + node_rx = lll->payload[bis_idx][payload_tail]; lll->payload[bis_idx][payload_tail] = NULL; iso_rx_put(node_rx->hdr.link, node_rx); diff --git a/subsys/bluetooth/controller/ll_sw/ull_sync_iso.c b/subsys/bluetooth/controller/ll_sw/ull_sync_iso.c index ff3327ce393..513ee3cdbed 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_sync_iso.c +++ b/subsys/bluetooth/controller/ll_sw/ull_sync_iso.c @@ -454,10 +454,9 @@ void ull_sync_iso_setup(struct ll_sync_iso_set *sync_iso, /* Initialize payload pointers */ lll->payload_count_max = PDU_BIG_PAYLOAD_COUNT_MAX; - lll->payload_head = 0U; lll->payload_tail = 0U; for (int i = 0; i < CONFIG_BT_CTLR_SYNC_ISO_STREAM_MAX; i++) { - for (int j = 0; j < PDU_BIG_PAYLOAD_COUNT_MAX; j++) { + for (int j = 0; j < lll->payload_count_max; j++) { lll->payload[i][j] = NULL; } } From cd4014a2feb3e7f3ca2aeec959506dd6002ffca0 Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Wed, 27 Sep 2023 20:16:19 +0200 Subject: [PATCH 263/421] [nrf fromtree] Bluetooth: Controller: nRF53: Fix back-to-back PDU chaining Fix back-to-back PDU chaining using DPPI on nRF53x SoC. Relates to commit b61bd2364c1a ("Bluetooth: Controller: nrf53: Fix back-to-back Tx Rx implementation"). Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit 1b0cb324f3827ed5dcd08b63de7b8168fc2a3ffa) Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit 1c6b81d1a2af8c8f5c3cb3306dc02aa6e4a9eacb) --- subsys/bluetooth/controller/ll_sw/nordic/lll/lll_adv_aux.c | 2 +- subsys/bluetooth/controller/ll_sw/nordic/lll/lll_adv_sync.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_adv_aux.c b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_adv_aux.c index ca566a04db4..6fa0204fb56 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_adv_aux.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_adv_aux.c @@ -394,7 +394,7 @@ static void isr_tx_chain(void *param) lll->phy_s, lll->phy_flags); } else { radio_isr_set(isr_done, lll_aux); - radio_switch_complete_and_disable(); + radio_switch_complete_and_b2b_tx_disable(); } radio_pkt_tx_set(pdu); diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_adv_sync.c b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_adv_sync.c index 1e56f70493c..79a8c6b25cd 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_adv_sync.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_adv_sync.c @@ -367,7 +367,7 @@ static void isr_tx(void *param) switch_radio_complete_and_b2b_tx(lll_sync, lll->phy_s); } else { radio_isr_set(isr_done, lll_sync); - radio_switch_complete_and_disable(); + radio_switch_complete_and_b2b_tx_disable(); } radio_pkt_tx_set(pdu); From 6df62154bb91974ca7dfd26683ec98dca62fef2e Mon Sep 17 00:00:00 2001 From: Emil Gydesen Date: Mon, 28 Aug 2023 14:02:22 +0200 Subject: [PATCH 264/421] [nrf fromtree] Bluetooth: Controller: ISO: Fix compile issue with unicast There was a case where TICKER_ID_ADV_AUX_BASE was not available but was attempted to be used. Signed-off-by: Emil Gydesen (cherry picked from commit cbf7312e370eba63586fbd516ab9c54e62b0203f) Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit 33872e13426421588ace17a53c53aca825fe0722) --- subsys/bluetooth/controller/ll_sw/ull_sched.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/subsys/bluetooth/controller/ll_sw/ull_sched.c b/subsys/bluetooth/controller/ll_sw/ull_sched.c index 38589a2e644..4eb7687b97d 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_sched.c +++ b/subsys/bluetooth/controller/ll_sw/ull_sched.c @@ -321,7 +321,7 @@ static int group_free_slot_get(uint8_t user_id, uint32_t ticks_slot_abs, if (false) { -#if defined(CONFIG_BT_BROADCASTER) +#if defined(CONFIG_BT_BROADCASTER) && CONFIG_BT_CTLR_ADV_AUX_SET > 0 } else if (IN_RANGE(ticker_id, TICKER_ID_ADV_AUX_BASE, TICKER_ID_ADV_AUX_LAST)) { const struct ll_adv_aux_set *aux; @@ -391,7 +391,7 @@ static int group_free_slot_get(uint8_t user_id, uint32_t ticks_slot_abs, #endif /* CONFIG_BT_CTLR_ADV_ISO */ #endif /* CONFIG_BT_CTLR_ADV_PERIODIC */ -#endif /* CONFIG_BT_BROADCASTER */ +#endif /* CONFIG_BT_BROADCASTER && CONFIG_BT_CTLR_ADV_AUX_SET > 0 */ #if defined(CONFIG_BT_CONN) } else if (IN_RANGE(ticker_id, TICKER_ID_CONN_BASE, From 6721814fdc868cdc5d4f9fb066c58915741ea9bf Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Wed, 27 Sep 2023 14:27:33 +0200 Subject: [PATCH 265/421] [nrf fromtree] Bluetooth: Controller: Fix ULL_HIGH ticker operations count Fix ULL_HIGH ticker operations count, it is discovered in new BabbleSim test implementations that mesh tests using Extended Advertising and Scanning enqueue upto 4 ticker operations before ULL_LOW ticker_job could process it. Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit 3bfeadfa4a68666a4e7ec5b8752860c6e9efe844) Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit e606f4ed0d9199aa5f257490ef2bf8662c52f74d) --- subsys/bluetooth/controller/ll_sw/ull.c | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/subsys/bluetooth/controller/ll_sw/ull.c b/subsys/bluetooth/controller/ll_sw/ull.c index e6a736f939d..9811076b9ba 100644 --- a/subsys/bluetooth/controller/ll_sw/ull.c +++ b/subsys/bluetooth/controller/ll_sw/ull.c @@ -278,22 +278,21 @@ #define TICKER_USER_ULL_LOW_OPS (1 + TICKER_USER_ULL_LOW_VENDOR_OPS + 1) -/* NOTE: When ULL_LOW priority is configured to lower than ULL_HIGH, then extra - * ULL_HIGH operations queue elements are required to buffer the - * requested ticker operations. +/* NOTE: Extended Advertising needs one extra ticker operation being enqueued + * for scheduling the auxiliary PDU reception while there can already + * be three other operations being enqueued. + * + * This value also covers the case were initiator with 1M and Coded PHY + * scan window is stopping the two scan tickers, stopping one scan stop + * ticker and starting one new ticker for establishing an ACL connection. */ -#if defined(CONFIG_BT_CENTRAL) && defined(CONFIG_BT_CTLR_ADV_EXT) && \ - defined(CONFIG_BT_CTLR_PHY_CODED) +#if defined(CONFIG_BT_CTLR_ADV_EXT) #define TICKER_USER_ULL_HIGH_OPS (4 + TICKER_USER_ULL_HIGH_VENDOR_OPS + \ TICKER_USER_ULL_HIGH_FLASH_OPS + 1) -#else /* !CONFIG_BT_CENTRAL || !CONFIG_BT_CTLR_ADV_EXT || - * !CONFIG_BT_CTLR_PHY_CODED - */ +#else /* !CONFIG_BT_CTLR_ADV_EXT */ #define TICKER_USER_ULL_HIGH_OPS (3 + TICKER_USER_ULL_HIGH_VENDOR_OPS + \ TICKER_USER_ULL_HIGH_FLASH_OPS + 1) -#endif /* !CONFIG_BT_CENTRAL || !CONFIG_BT_CTLR_ADV_EXT || - * !CONFIG_BT_CTLR_PHY_CODED - */ +#endif /* !CONFIG_BT_CTLR_ADV_EXT */ #define TICKER_USER_LLL_OPS (3 + TICKER_USER_LLL_VENDOR_OPS + 1) From 287777875f227f7ba6b1691973f5ae708ff90d16 Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Wed, 27 Sep 2023 22:02:24 +0200 Subject: [PATCH 266/421] [nrf fromtree] Bluetooth: Controller: Fix connected ISO dynamic tx power Fix connected ISO dynamic tx power support compilation error. Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit 28ed48cbac70c8aaa3905b13040a658830b4d5b7) Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit ad506ab73c578540d0e60903dac02e87e0097c5c) --- .../hci_rpmsg/nrf5340_cpunet_iso-bt_ll_sw_split.conf | 3 +++ samples/bluetooth/hci_uart/overlay-all-bt_ll_sw_split.conf | 3 +++ .../bluetooth/controller/ll_sw/nordic/lll/lll_central_iso.c | 4 ++-- .../controller/ll_sw/nordic/lll/lll_peripheral_iso.c | 2 +- 4 files changed, 9 insertions(+), 3 deletions(-) diff --git a/samples/bluetooth/hci_rpmsg/nrf5340_cpunet_iso-bt_ll_sw_split.conf b/samples/bluetooth/hci_rpmsg/nrf5340_cpunet_iso-bt_ll_sw_split.conf index bb95b6ea74e..e9e5ac63483 100644 --- a/samples/bluetooth/hci_rpmsg/nrf5340_cpunet_iso-bt_ll_sw_split.conf +++ b/samples/bluetooth/hci_rpmsg/nrf5340_cpunet_iso-bt_ll_sw_split.conf @@ -112,3 +112,6 @@ CONFIG_BT_CTLR_ISOAL_SOURCES=2 # ISO Receptions CONFIG_BT_CTLR_ISO_RX_BUFFERS=8 CONFIG_BT_CTLR_ISOAL_SINKS=2 + +# Tx Power Dynamic Control +CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL=y diff --git a/samples/bluetooth/hci_uart/overlay-all-bt_ll_sw_split.conf b/samples/bluetooth/hci_uart/overlay-all-bt_ll_sw_split.conf index 1f976f75f22..3774532c424 100644 --- a/samples/bluetooth/hci_uart/overlay-all-bt_ll_sw_split.conf +++ b/samples/bluetooth/hci_uart/overlay-all-bt_ll_sw_split.conf @@ -104,3 +104,6 @@ CONFIG_BT_CTLR_ISOAL_SOURCES=2 # ISO Receptions CONFIG_BT_CTLR_ISO_RX_BUFFERS=8 CONFIG_BT_CTLR_ISOAL_SINKS=2 + +# Tx Power Dynamic Control +CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL=y diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_central_iso.c b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_central_iso.c index d287bc794a6..46360ef88d7 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_central_iso.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_central_iso.c @@ -220,7 +220,7 @@ static int prepare_cb(struct lll_prepare_param *p) radio_reset(); #if defined(CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL) - radio_tx_power_set(cis_lll->tx_pwr_lvl); + radio_tx_power_set(conn_lll->tx_pwr_lvl); #else /* !CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL */ radio_tx_power_set(RADIO_TXP_DEFAULT); #endif /* !CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL */ @@ -986,7 +986,7 @@ static void isr_rx(void *param) next_cis_lll->rx.bn_curr = 1U; #if defined(CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL) - radio_tx_power_set(next_cis_lll->tx_pwr_lvl); + radio_tx_power_set(next_conn_lll->tx_pwr_lvl); #else radio_tx_power_set(RADIO_TXP_DEFAULT); #endif diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_peripheral_iso.c b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_peripheral_iso.c index f089a07bb0b..13238c081cf 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_peripheral_iso.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_peripheral_iso.c @@ -238,7 +238,7 @@ static int prepare_cb(struct lll_prepare_param *p) radio_reset(); #if defined(CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL) - radio_tx_power_set(cis_lll->tx_pwr_lvl); + radio_tx_power_set(conn_lll->tx_pwr_lvl); #else /* !CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL */ radio_tx_power_set(RADIO_TXP_DEFAULT); #endif /* !CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL */ From 48accabe1924f7c77291a9cad93c26e92df14447 Mon Sep 17 00:00:00 2001 From: Erik Brockhoff Date: Wed, 16 Aug 2023 10:22:49 +0200 Subject: [PATCH 267/421] [nrf fromtree] Bluetooth: controller: add missing NTF alloc in central CIS Create If a CIS create is requested prior to having a complete feature exchange the central will initiate a feat exch before enqueing the CIS create. IF then the feature exchange results in peripheral NOT supporting CIS create the central needs to allocate an RX node for the NTF Signed-off-by: Erik Brockhoff (cherry picked from commit 730f7caa21ff178e928263c0f148f198df7be98a) Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit f9fb6c01815f05a0db9eda71b764f1d0affa1d44) --- .../bluetooth/controller/ll_sw/ull_llcp_cc.c | 26 ++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/subsys/bluetooth/controller/ll_sw/ull_llcp_cc.c b/subsys/bluetooth/controller/ll_sw/ull_llcp_cc.c index 387cc884dea..69dc80bda13 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_llcp_cc.c +++ b/subsys/bluetooth/controller/ll_sw/ull_llcp_cc.c @@ -643,6 +643,7 @@ static void lp_cc_execute_fsm(struct ll_conn *conn, struct proc_ctx *ctx, uint8_ /* LLCP Local Procedure FSM states */ enum { LP_CC_STATE_IDLE, + LP_CC_STATE_WAIT_NTF_AVAIL, LP_CC_STATE_WAIT_OFFSET_CALC, LP_CC_STATE_WAIT_OFFSET_CALC_TX_REQ, LP_CC_STATE_WAIT_TX_CIS_REQ, @@ -839,7 +840,7 @@ static void lp_cc_st_idle(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t ev } else { /* Peer doesn't support CIS Peripheral so report unsupported */ ctx->data.cis_create.error = BT_HCI_ERR_UNSUPP_REMOTE_FEATURE; - lp_cc_complete(conn, ctx, evt, param); + ctx->state = LP_CC_STATE_WAIT_NTF_AVAIL; } break; default: @@ -854,6 +855,26 @@ static void lp_cc_st_idle(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t ev } } +static void lp_cc_state_wait_ntf_avail(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t evt, + void *param) +{ + switch (evt) { + case LP_CC_EVT_RUN: + if (llcp_ntf_alloc_is_available()) { + ctx->node_ref.rx = llcp_ntf_alloc(); + /* Mark node as RETAIN to trigger put/sched */ + ctx->node_ref.rx->hdr.type = NODE_RX_TYPE_RETAIN; + + /* Now we're good to complete procedure*/ + lp_cc_complete(conn, ctx, evt, param); + } + break; + default: + /* Ignore other evts */ + break; + } +} + static void cc_prepare_cis_ind(struct ll_conn *conn, struct proc_ctx *ctx) { uint8_t err; @@ -1040,6 +1061,9 @@ static void lp_cc_execute_fsm(struct ll_conn *conn, struct proc_ctx *ctx, uint8_ case LP_CC_STATE_IDLE: lp_cc_st_idle(conn, ctx, evt, param); break; + case LP_CC_STATE_WAIT_NTF_AVAIL: + lp_cc_state_wait_ntf_avail(conn, ctx, evt, param); + break; case LP_CC_STATE_WAIT_OFFSET_CALC_TX_REQ: lp_cc_st_wait_offset_calc_tx_req(conn, ctx, evt, param); break; From 340f46a013f08c35562f1aa1d75464e61246b77e Mon Sep 17 00:00:00 2001 From: Erik Brockhoff Date: Wed, 16 Aug 2023 14:50:04 +0200 Subject: [PATCH 268/421] [nrf fromtree] Bluetooth: controller: adding API for unmasking peer features For asymetrical features there needs to be a separate mechanism to unmask features in peer. This must be used in central for unmasking in case of 'unsupported in peer' condition for CIS Create. Signed-off-by: Erik Brockhoff (cherry picked from commit 1de8a76f58bf3f18a8c604d63e7e82070e324c0e) Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit 26455711ce52d61e86a4c313db7b93e51e7d8fc3) --- subsys/bluetooth/controller/ll_sw/ull_llcp_cc.c | 4 ++-- subsys/bluetooth/controller/ll_sw/ull_llcp_features.h | 5 +++++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/subsys/bluetooth/controller/ll_sw/ull_llcp_cc.c b/subsys/bluetooth/controller/ll_sw/ull_llcp_cc.c index 69dc80bda13..59c23e7a0f6 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_llcp_cc.c +++ b/subsys/bluetooth/controller/ll_sw/ull_llcp_cc.c @@ -921,14 +921,14 @@ static void lp_cc_st_wait_rx_cis_rsp(struct ll_conn *conn, struct proc_ctx *ctx, break; case LP_CC_EVT_UNKNOWN: /* Unsupported in peer, so disable locally for this connection */ - feature_unmask_features(conn, LL_FEAT_BIT_CIS_PERIPHERAL); + feature_unmask_peer_features(conn, LL_FEAT_BIT_CIS_PERIPHERAL); ctx->data.cis_create.error = BT_HCI_ERR_UNSUPP_REMOTE_FEATURE; lp_cc_complete(conn, ctx, evt, param); break; case LP_CC_EVT_REJECT: if (pdu->llctrl.reject_ext_ind.error_code == BT_HCI_ERR_UNSUPP_REMOTE_FEATURE) { /* Unsupported in peer, so disable locally for this connection */ - feature_unmask_features(conn, LL_FEAT_BIT_CIS_PERIPHERAL); + feature_unmask_peer_features(conn, LL_FEAT_BIT_CIS_PERIPHERAL); } ctx->data.cis_create.error = pdu->llctrl.reject_ext_ind.error_code; lp_cc_complete(conn, ctx, evt, param); diff --git a/subsys/bluetooth/controller/ll_sw/ull_llcp_features.h b/subsys/bluetooth/controller/ll_sw/ull_llcp_features.h index ac60206bc70..75d92d5524e 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_llcp_features.h +++ b/subsys/bluetooth/controller/ll_sw/ull_llcp_features.h @@ -9,6 +9,11 @@ static inline void feature_unmask_features(struct ll_conn *conn, uint64_t ll_fea conn->llcp.fex.features_used &= ~ll_feat_mask; } +static inline void feature_unmask_peer_features(struct ll_conn *conn, uint64_t ll_feat_mask) +{ + conn->llcp.fex.features_peer &= ~ll_feat_mask; +} + static inline bool feature_le_encryption(struct ll_conn *conn) { #if defined(CONFIG_BT_CTLR_LE_ENC) From a993ec04f01370731fd9fbdb1eaec298d865beff Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Fri, 29 Sep 2023 13:27:51 +0200 Subject: [PATCH 269/421] [nrf fromtree] Bluetooth: Controller: Fix regression in Adv PDU overflow calculation Fix regression in Adv PDU payload length overflow calculation. Regression in commit de8c19da5ebf ("Bluetooth: controller: Handle fragmented AD without chaining PDUs"). Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit 303ce143c2b8a097a6d0ae489f08ee9b7cea76cc) Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit a2ef051537fb3a5e3a4d18baab99d8a0411a175d) --- subsys/bluetooth/controller/ll_sw/ull_adv_aux.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/subsys/bluetooth/controller/ll_sw/ull_adv_aux.c b/subsys/bluetooth/controller/ll_sw/ull_adv_aux.c index 5349b21dd9f..302dc6da785 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_adv_aux.c +++ b/subsys/bluetooth/controller/ll_sw/ull_adv_aux.c @@ -1804,7 +1804,7 @@ uint8_t ull_adv_aux_hdr_set_clear(struct ll_adv_set *adv, /* TODO: need aux_chain_ind support */ if ((sec_len + ad_len + ad_fragment_len) > PDU_AC_PAYLOAD_SIZE_MAX) { /* return excess length */ - *(uint8_t *)hdr_data = sec_len + ad_len - + *(uint8_t *)hdr_data = sec_len + ad_len + ad_fragment_len - PDU_AC_PAYLOAD_SIZE_MAX; if (pri_pdu == pri_pdu_prev) { @@ -2272,7 +2272,7 @@ uint8_t ull_adv_aux_pdu_set_clear(struct ll_adv_set *adv, /* Check AdvData overflow */ if ((len + ad_len + ad_fragment_len) > PDU_AC_PAYLOAD_SIZE_MAX) { /* return excess length */ - *(uint8_t *)hdr_data = len + ad_len - + *(uint8_t *)hdr_data = len + ad_len + ad_fragment_len - PDU_AC_PAYLOAD_SIZE_MAX; /* Will use packet too long error to determine fragmenting From 4b5aac399c721b01dfd7924ce565d367e526fa59 Mon Sep 17 00:00:00 2001 From: Alberto Escolar Piedras Date: Thu, 28 Sep 2023 14:00:12 +0200 Subject: [PATCH 270/421] [nrf fromtree] Bluetooth: Controller: Fix clang warning on ull Fix a clang warning ull.c:1235: warning: use of bitwise '|' with boolean operands The result of ({1/0} &&(int)) is either true(1) or false(0), not the int and therefore bm is not a bitmask, but just true(1) or false(0) all together. Signed-off-by: Alberto Escolar Piedras (cherry picked from commit 48f70eba2ba97cf9006bb7751eb35808f1bd2bfe) Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit 655f1b77f693adfb85ec5280623c47ca00a2ce43) --- subsys/bluetooth/controller/ll_sw/ull.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/subsys/bluetooth/controller/ll_sw/ull.c b/subsys/bluetooth/controller/ll_sw/ull.c index 9811076b9ba..3130978df4e 100644 --- a/subsys/bluetooth/controller/ll_sw/ull.c +++ b/subsys/bluetooth/controller/ll_sw/ull.c @@ -1232,10 +1232,8 @@ void ll_rx_dequeue(void) /* FIXME: use the correct adv and scan set to get * enabled status bitmask */ - bm = (IS_ENABLED(CONFIG_BT_OBSERVER) && - (ull_scan_is_enabled(0) << 1)) | - (IS_ENABLED(CONFIG_BT_BROADCASTER) && - ull_adv_is_enabled(0)); + bm = (IS_ENABLED(CONFIG_BT_OBSERVER)?(ull_scan_is_enabled(0) << 1):0) | + (IS_ENABLED(CONFIG_BT_BROADCASTER)?ull_adv_is_enabled(0):0); if (!bm) { ull_filter_adv_scan_state_cb(0); From 10552082f75c89d7b69b7ad5b4ee815d84348761 Mon Sep 17 00:00:00 2001 From: Alberto Escolar Piedras Date: Thu, 21 Sep 2023 09:53:02 +0200 Subject: [PATCH 271/421] [nrf fromtree] Bluetooth controller nrf: Provide radio hal header for simulated nrf5340 Provide a radio HAL header for the new nrf53 bsim target Signed-off-by: Alberto Escolar Piedras (cherry picked from commit 2243d7b717e090025c7915db23a7392f26d1b64f) Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit 313eed69c585067c7a9cd74b4d0751b29590f44a) --- .../ll_sw/nordic/hal/nrf5/radio/radio_nrf5.h | 2 + .../nordic/hal/nrf5/radio/radio_sim_nrf5340.h | 431 ++++++++++++++++++ 2 files changed, 433 insertions(+) create mode 100644 subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_sim_nrf5340.h diff --git a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5.h b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5.h index 9e29ab5f70b..842b4189184 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5.h +++ b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5.h @@ -17,6 +17,8 @@ /* SoC specific defines */ #if defined(CONFIG_BOARD_NRF52_BSIM) #include "radio_sim_nrf52.h" +#elif defined(CONFIG_BOARD_NRF5340BSIM_NRF5340_CPUNET) +#include "radio_sim_nrf5340.h" #elif defined(CONFIG_SOC_SERIES_NRF51X) #include "radio_nrf51.h" #elif defined(CONFIG_SOC_NRF52805) diff --git a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_sim_nrf5340.h b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_sim_nrf5340.h new file mode 100644 index 00000000000..c0cd88b30b0 --- /dev/null +++ b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_sim_nrf5340.h @@ -0,0 +1,431 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * Copyright (c) 2019 Ioannis Glaropoulos + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +/* NRF Radio HW timing constants + * - provided in US and NS (for higher granularity) + * - based on the timings configured in the HW models, which are based + * on the product specification + * - Note that this timings are approx. the same as in the real HW, + * but tend to be rounded to the nearest microsecond + */ + +/* Override EVENT_TIMER_ID from 4 to 0, as nRF5340 does not have 4 timer + * instances. + */ +#if defined(CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER) +#undef EVENT_TIMER_ID +#define EVENT_TIMER_ID 0 + +#undef EVENT_TIMER +#define EVENT_TIMER _CONCAT(NRF_TIMER, EVENT_TIMER_ID) + +#undef SW_SWITCH_TIMER +#define SW_SWITCH_TIMER EVENT_TIMER +#endif /* CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER */ + +/* TXEN->TXIDLE + TXIDLE->TX (with fast Radio ramp-up mode) + * in microseconds for LE 1M PHY. + */ +#define HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_1M_FAST_NS 41000 +#define HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_1M_FAST_US \ + HAL_RADIO_NS2US_ROUND(HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_1M_FAST_NS) + +/* TXEN->TXIDLE + TXIDLE->TX (with default Radio ramp-up mode) + * in microseconds for LE 1M PHY. + */ +#define HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_1M_DEFAULT_NS 141000 +#define HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_1M_DEFAULT_US \ + HAL_RADIO_NS2US_ROUND(HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_1M_DEFAULT_NS) + +/* TXEN->TXIDLE + TXIDLE->TX (with default Radio ramp-up mode + * and no HW TIFS auto-switch) in microseconds for LE 1M PHY. + */ + /* 129.5 + 0.8 */ +#define HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_1M_DEFAULT_NO_HW_TIFS_NS 130000 +#define HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_1M_DEFAULT_NO_HW_TIFS_US \ + HAL_RADIO_NS2US_ROUND( \ + HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_1M_DEFAULT_NO_HW_TIFS_NS) + +/* TXEN->TXIDLE + TXIDLE->TX (with fast Radio ramp-up mode) + * in microseconds for LE 2M PHY. + */ +#define HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_2M_FAST_NS 40000 +#define HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_2M_FAST_US \ + HAL_RADIO_NS2US_ROUND(HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_2M_FAST_NS) + +/* TXEN->TXIDLE + TXIDLE->TX (with default Radio ramp-up mode) + * in microseconds for LE 2M PHY. + */ +#define HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_2M_DEFAULT_NS 140000 +#define HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_2M_DEFAULT_US \ + HAL_RADIO_NS2US_ROUND(HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_2M_DEFAULT_NS) + +/* TXEN->TXIDLE + TXIDLE->TX (with default Radio ramp-up mode and + * no HW TIFS auto-switch) in microseconds for LE 2M PHY. + */ +#define HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_2M_DEFAULT_NO_HW_TIFS_NS 129000 +#define HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_2M_DEFAULT_NO_HW_TIFS_US \ + HAL_RADIO_NS2US_ROUND( \ + HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_2M_DEFAULT_NO_HW_TIFS_NS) + +/* RXEN->RXIDLE + RXIDLE->RX (with fast Radio ramp-up mode) + * in microseconds for LE 1M PHY. + */ +#define HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_1M_FAST_NS 40000 +#define HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_1M_FAST_US \ + HAL_RADIO_NS2US_CEIL(HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_1M_FAST_NS) + +/* RXEN->RXIDLE + RXIDLE->RX (with default Radio ramp-up mode) + * in microseconds for LE 1M PHY. + */ +#define HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_1M_DEFAULT_NS 140000 +#define HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_1M_DEFAULT_US \ + HAL_RADIO_NS2US_CEIL(HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_1M_DEFAULT_NS) + +/* RXEN->RXIDLE + RXIDLE->RX (with default Radio ramp-up mode and + * no HW TIFS auto-switch) in microseconds for LE 1M PHY. + */ +/* 129.5 + 0.2 */ +#define HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_1M_DEFAULT_NO_HW_TIFS_NS 129000 +#define HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_1M_DEFAULT_NO_HW_TIFS_US \ + HAL_RADIO_NS2US_CEIL( \ + HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_1M_DEFAULT_NO_HW_TIFS_NS) + +/* RXEN->RXIDLE + RXIDLE->RX (with fast Radio ramp-up mode) + * in microseconds for LE 2M PHY. + */ +#define HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_2M_FAST_NS 40000 +#define HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_2M_FAST_US \ + HAL_RADIO_NS2US_CEIL(HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_2M_FAST_NS) + +/* RXEN->RXIDLE + RXIDLE->RX (with default Radio ramp-up mode) + * in microseconds for LE 2M PHY. + */ +#define HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_2M_DEFAULT_NS 140000 +#define HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_2M_DEFAULT_US \ + HAL_RADIO_NS2US_CEIL(HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_2M_DEFAULT_NS) + +/* RXEN->RXIDLE + RXIDLE->RX (with default Radio ramp-up mode and + * no HW TIFS auto-switch) in microseconds for LE 2M PHY. + */ +/* 129.5 + 0.2 */ +#define HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_2M_DEFAULT_NO_HW_TIFS_NS 129000 +#define HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_2M_DEFAULT_NO_HW_TIFS_US \ + HAL_RADIO_NS2US_CEIL( \ + HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_2M_DEFAULT_NO_HW_TIFS_NS) + +#define HAL_RADIO_NRF5340_TX_CHAIN_DELAY_NS 1000 +#define HAL_RADIO_NRF5340_TX_CHAIN_DELAY_US \ + HAL_RADIO_NS2US_CEIL(HAL_RADIO_NRF5340_TX_CHAIN_DELAY_NS) + +#define HAL_RADIO_NRF5340_RX_CHAIN_DELAY_1M_US 9 +#define HAL_RADIO_NRF5340_RX_CHAIN_DELAY_1M_NS 9000 +#define HAL_RADIO_NRF5340_RX_CHAIN_DELAY_2M_US 5 +#define HAL_RADIO_NRF5340_RX_CHAIN_DELAY_2M_NS 5000 + +#if defined(CONFIG_BT_CTLR_RADIO_ENABLE_FAST) +#define HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_1M_US \ + HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_1M_FAST_US +#define HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_1M_NS \ + HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_1M_FAST_NS + +#define HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_2M_US \ + HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_2M_FAST_US +#define HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_2M_NS \ + HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_2M_FAST_NS + +#define HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_1M_US \ + HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_1M_FAST_US +#define HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_1M_NS \ + HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_1M_FAST_NS + +#define HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_2M_US \ + HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_2M_FAST_US +#define HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_2M_NS \ + HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_2M_FAST_NS + +#else /* !CONFIG_BT_CTLR_RADIO_ENABLE_FAST */ +#if defined(CONFIG_BT_CTLR_TIFS_HW) +#define HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_1M_US \ + HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_1M_DEFAULT_US +#define HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_1M_NS \ + HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_1M_DEFAULT_NS + +#define HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_2M_US \ + HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_2M_DEFAULT_US +#define HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_2M_NS \ + HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_2M_DEFAULT_NS + +#define HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_1M_US \ + HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_1M_DEFAULT_US +#define HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_1M_NS \ + HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_1M_DEFAULT_NS + +#define HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_2M_US \ + HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_2M_DEFAULT_US +#define HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_2M_NS \ + HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_2M_DEFAULT_NS + +#else /* !CONFIG_BT_CTLR_TIFS_HW */ +#define HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_1M_US \ + HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_1M_DEFAULT_NO_HW_TIFS_US +#define HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_1M_NS \ + HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_1M_DEFAULT_NO_HW_TIFS_NS + +#define HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_2M_US \ + HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_2M_DEFAULT_NO_HW_TIFS_US +#define HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_2M_NS \ + HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_2M_DEFAULT_NO_HW_TIFS_NS + +#define HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_1M_US \ + HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_1M_DEFAULT_NO_HW_TIFS_US +#define HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_1M_NS \ + HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_1M_DEFAULT_NO_HW_TIFS_NS + +#define HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_2M_US \ + HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_2M_DEFAULT_NO_HW_TIFS_US +#define HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_2M_NS \ + HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_2M_DEFAULT_NO_HW_TIFS_NS + +#endif /* !CONFIG_BT_CTLR_TIFS_HW */ +#endif /* !CONFIG_BT_CTLR_RADIO_ENABLE_FAST */ + +/* nRF5340 supports +3dBm Tx Power using high voltage request, define +3dBm + * value for Controller use. + */ +#ifndef RADIO_TXPOWER_TXPOWER_Pos3dBm +#define RADIO_TXPOWER_TXPOWER_Pos3dBm (0x03UL) +#endif + +/* SoC specific NRF_RADIO power-on reset value. Refer to Product Specification, + * RADIO Registers section for the documented reset values. + * + * NOTE: Only implementation used values defined here. + * In the future if MDK or nRFx header include these, use them instead. + */ +#define HAL_RADIO_RESET_VALUE_DFEMODE 0x00000000UL +#define HAL_RADIO_RESET_VALUE_CTEINLINECONF 0x00002800UL + +static inline void hal_radio_tx_power_high_voltage_clear(void); + +static inline void hal_radio_reset(void) +{ +} + +static inline void hal_radio_stop(void) +{ + /* If +3dBm Tx power was used, then turn off high voltage when radio not + * used. + */ + hal_radio_tx_power_high_voltage_clear(); +} + +static inline void hal_radio_ram_prio_setup(void) +{ +} + +static inline uint32_t hal_radio_phy_mode_get(uint8_t phy, uint8_t flags) +{ + uint32_t mode; + + switch (phy) { + case BIT(0): + default: + mode = RADIO_MODE_MODE_Ble_1Mbit; + break; + + case BIT(1): + mode = RADIO_MODE_MODE_Ble_2Mbit; + break; + +#if defined(CONFIG_BT_CTLR_PHY_CODED) + case BIT(2): + if (flags & 0x01) { + mode = RADIO_MODE_MODE_Ble_LR125Kbit; + } else { + mode = RADIO_MODE_MODE_Ble_LR500Kbit; + } + break; +#endif /* CONFIG_BT_CTLR_PHY_CODED */ + } + + return mode; +} + +static inline uint32_t hal_radio_tx_power_max_get(void) +{ + return RADIO_TXPOWER_TXPOWER_0dBm; +} + +static inline uint32_t hal_radio_tx_power_min_get(void) +{ + return RADIO_TXPOWER_TXPOWER_Neg40dBm; +} + +static inline uint32_t hal_radio_tx_power_floor(int8_t tx_power_lvl) +{ + if (tx_power_lvl >= (int8_t)RADIO_TXPOWER_TXPOWER_0dBm) { + return RADIO_TXPOWER_TXPOWER_0dBm; + } + + if (tx_power_lvl >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg1dBm) { + return RADIO_TXPOWER_TXPOWER_Neg1dBm; + } + + if (tx_power_lvl >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg2dBm) { + return RADIO_TXPOWER_TXPOWER_Neg2dBm; + } + + if (tx_power_lvl >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg3dBm) { + return RADIO_TXPOWER_TXPOWER_Neg3dBm; + } + + if (tx_power_lvl >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg4dBm) { + return RADIO_TXPOWER_TXPOWER_Neg4dBm; + } + + if (tx_power_lvl >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg5dBm) { + return RADIO_TXPOWER_TXPOWER_Neg5dBm; + } + + if (tx_power_lvl >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg6dBm) { + return RADIO_TXPOWER_TXPOWER_Neg6dBm; + } + + if (tx_power_lvl >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg7dBm) { + return RADIO_TXPOWER_TXPOWER_Neg7dBm; + } + + if (tx_power_lvl >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg8dBm) { + return RADIO_TXPOWER_TXPOWER_Neg8dBm; + } + + if (tx_power_lvl >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg12dBm) { + return RADIO_TXPOWER_TXPOWER_Neg12dBm; + } + + if (tx_power_lvl >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg16dBm) { + return RADIO_TXPOWER_TXPOWER_Neg16dBm; + } + + if (tx_power_lvl >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg20dBm) { + return RADIO_TXPOWER_TXPOWER_Neg20dBm; + } + + /* Note: The -30 dBm power level is deprecated so ignore it! */ + return RADIO_TXPOWER_TXPOWER_Neg40dBm; +} + +static inline void hal_radio_tx_power_high_voltage_set(int8_t tx_power_lvl) +{ + if (tx_power_lvl >= (int8_t)RADIO_TXPOWER_TXPOWER_Pos3dBm) { + nrf_vreqctrl_radio_high_voltage_set(NRF_VREQCTRL, true); + } +} + +static inline void hal_radio_tx_power_high_voltage_clear(void) +{ + nrf_vreqctrl_radio_high_voltage_set(NRF_VREQCTRL, false); +} + +static inline uint32_t hal_radio_tx_ready_delay_us_get(uint8_t phy, uint8_t flags) +{ + ARG_UNUSED(flags); + + switch (phy) { + default: + case BIT(0): + return HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_1M_US; + case BIT(1): + return HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_2M_US; + } +} + +static inline uint32_t hal_radio_rx_ready_delay_us_get(uint8_t phy, uint8_t flags) +{ + ARG_UNUSED(flags); + + switch (phy) { + default: + case BIT(0): + return HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_1M_US; + case BIT(1): + return HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_2M_US; + } +} + +static inline uint32_t hal_radio_tx_chain_delay_us_get(uint8_t phy, uint8_t flags) +{ + ARG_UNUSED(phy); + ARG_UNUSED(flags); + + return HAL_RADIO_NRF5340_TX_CHAIN_DELAY_US; +} + +static inline uint32_t hal_radio_rx_chain_delay_us_get(uint8_t phy, uint8_t flags) +{ + ARG_UNUSED(flags); + + switch (phy) { + default: + case BIT(0): + return HAL_RADIO_NRF5340_RX_CHAIN_DELAY_1M_US; + case BIT(1): + return HAL_RADIO_NRF5340_RX_CHAIN_DELAY_2M_US; + } +} + +static inline uint32_t hal_radio_tx_ready_delay_ns_get(uint8_t phy, uint8_t flags) +{ + ARG_UNUSED(flags); + + switch (phy) { + default: + case BIT(0): + return HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_1M_NS; + case BIT(1): + return HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_2M_NS; + } +} + +static inline uint32_t hal_radio_rx_ready_delay_ns_get(uint8_t phy, uint8_t flags) +{ + ARG_UNUSED(flags); + + switch (phy) { + default: + case BIT(0): + return HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_1M_NS; + case BIT(1): + return HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_2M_NS; + } +} + +static inline uint32_t hal_radio_tx_chain_delay_ns_get(uint8_t phy, uint8_t flags) +{ + ARG_UNUSED(phy); + ARG_UNUSED(flags); + + return HAL_RADIO_NRF5340_TX_CHAIN_DELAY_NS; +} + +static inline uint32_t hal_radio_rx_chain_delay_ns_get(uint8_t phy, uint8_t flags) +{ + ARG_UNUSED(flags); + + switch (phy) { + default: + case BIT(0): + return HAL_RADIO_NRF5340_RX_CHAIN_DELAY_1M_NS; + case BIT(1): + return HAL_RADIO_NRF5340_RX_CHAIN_DELAY_2M_NS; + + } +} From 495dce2550cd4bba79af1b4429d8ab8f377244d4 Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Thu, 22 Jun 2023 22:49:14 +0530 Subject: [PATCH 272/421] [nrf fromtree] Bluetooth: Controller: Remove HCI ISO data with invalid status Remove incorrect implementation of HCI ISO data with invalid status. Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit 7a14830d85587d22bcf812f1ec6931c3c35ce02f) Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit bd1490cd0d7f2239b4a9125cc86f7a903d25b95f) --- .../ll_sw/nordic/lll/lll_central_iso.c | 97 ++----------------- .../ll_sw/nordic/lll/lll_peripheral_iso.c | 43 -------- 2 files changed, 8 insertions(+), 132 deletions(-) diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_central_iso.c b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_central_iso.c index 46360ef88d7..936087369f1 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_central_iso.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_central_iso.c @@ -845,7 +845,6 @@ static void isr_rx(void *param) struct lll_conn_iso_group *cig_lll; struct lll_conn *next_conn_lll; uint8_t phy; - uint8_t bn; /* Fetch next CIS */ /* TODO: Use a new ull_conn_iso_lll_stream_get_active_by_group() @@ -861,18 +860,6 @@ static void isr_rx(void *param) goto isr_rx_done; } - /* Adjust sn when flushing Tx */ - /* FIXME: When Flush Timeout is implemented */ - if (cis_lll->tx.bn_curr <= cis_lll->tx.bn) { - lll_flush_tx(cis_lll); - } - - /* Adjust nesn when flushing Rx */ - /* FIXME: When Flush Timeout is implemented */ - if (cis_lll->rx.bn_curr <= cis_lll->rx.bn) { - lll_flush_rx(cis_lll); - } - /* Get reference to ACL context */ next_conn_lll = ull_conn_lll_get(next_cis_lll->acl_handle); @@ -940,45 +927,17 @@ static void isr_rx(void *param) cis_lll = old_cis_lll; } - /* Generate ISO Data Invalid Status */ - bn = cis_lll->rx.bn_curr; - while (bn <= cis_lll->rx.bn) { - struct node_rx_iso_meta *iso_meta; - struct node_rx_pdu *status_node_rx; - - /* Ensure there is always one free for reception - * of ISO PDU by the radio h/w DMA, hence peek - * for two available ISO PDU when using one for - * generating invalid ISO data. - */ - status_node_rx = ull_iso_pdu_rx_alloc_peek(2U); - if (!status_node_rx) { - break; - } - - status_node_rx->hdr.type = NODE_RX_TYPE_ISO_PDU; - status_node_rx->hdr.handle = cis_lll->handle; - iso_meta = &status_node_rx->hdr.rx_iso_meta; - iso_meta->payload_number = (cis_lll->event_count * - cis_lll->rx.bn) + (bn - 1U); - iso_meta->timestamp = - HAL_TICKER_TICKS_TO_US(radio_tmr_start_get()) + - radio_tmr_ready_restore(); - iso_meta->timestamp %= - HAL_TICKER_TICKS_TO_US(BIT(HAL_TICKER_CNTR_MSBIT + 1U)); - iso_meta->status = 1U; - - ull_iso_pdu_rx_alloc(); - iso_rx_put(status_node_rx->hdr.link, status_node_rx); - - bn++; + /* Adjust sn when flushing Tx */ + /* FIXME: When Flush Timeout is implemented */ + if (cis_lll->tx.bn_curr <= cis_lll->tx.bn) { + lll_flush_tx(cis_lll); } -#if !defined(CONFIG_BT_CTLR_LOW_LAT_ULL) - if (bn != cis_lll->rx.bn_curr) { - iso_rx_sched(); + /* Adjust nesn when flushing Rx */ + /* FIXME: When Flush Timeout is implemented */ + if (cis_lll->rx.bn_curr <= cis_lll->rx.bn) { + lll_flush_rx(cis_lll); } -#endif /* CONFIG_BT_CTLR_LOW_LAT_ULL */ /* Reset indices for the next CIS */ se_curr = 0U; /* isr_prepare_subevent() will increase se_curr */ @@ -1176,7 +1135,6 @@ static void isr_done(void *param) { struct lll_conn_iso_stream *cis_lll; struct event_done_extra *e; - uint8_t bn; lll_isr_status_reset(); @@ -1195,45 +1153,6 @@ static void isr_done(void *param) lll_flush_rx(cis_lll); } - /* Generate ISO Data Invalid Status */ - bn = cis_lll->rx.bn_curr; - while (bn <= cis_lll->rx.bn) { - struct node_rx_iso_meta *iso_meta; - struct node_rx_pdu *node_rx; - - /* Ensure there is always one free for reception of ISO PDU by - * the radio h/w DMA, hence peek for two available ISO PDU when - * using one for generating invalid ISO data. - */ - node_rx = ull_iso_pdu_rx_alloc_peek(2U); - if (!node_rx) { - break; - } - - node_rx->hdr.type = NODE_RX_TYPE_ISO_PDU; - node_rx->hdr.handle = cis_lll->handle; - iso_meta = &node_rx->hdr.rx_iso_meta; - iso_meta->payload_number = (cis_lll->event_count * - cis_lll->rx.bn) + (bn - 1U); - iso_meta->timestamp = - HAL_TICKER_TICKS_TO_US(radio_tmr_start_get()) + - radio_tmr_ready_restore(); - iso_meta->timestamp %= - HAL_TICKER_TICKS_TO_US(BIT(HAL_TICKER_CNTR_MSBIT + 1U)); - iso_meta->status = 1U; - - ull_iso_pdu_rx_alloc(); - iso_rx_put(node_rx->hdr.link, node_rx); - - bn++; - } - -#if !defined(CONFIG_BT_CTLR_LOW_LAT_ULL) - if (bn != cis_lll->rx.bn_curr) { - iso_rx_sched(); - } -#endif /* CONFIG_BT_CTLR_LOW_LAT_ULL */ - e = ull_event_done_extra_get(); LL_ASSERT(e); diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_peripheral_iso.c b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_peripheral_iso.c index 13238c081cf..3bbdb5fbf90 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_peripheral_iso.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_peripheral_iso.c @@ -1229,7 +1229,6 @@ static void isr_done(void *param) { struct lll_conn_iso_stream *cis_lll; struct event_done_extra *e; - uint8_t bn; lll_isr_status_reset(); @@ -1242,48 +1241,6 @@ static void isr_done(void *param) lll_flush_rx(cis_lll); } - /* Generate ISO Data Invalid Status */ - bn = cis_lll->rx.bn_curr; - while (bn <= cis_lll->rx.bn) { - struct node_rx_iso_meta *iso_meta; - struct node_rx_pdu *node_rx; - - node_rx = ull_iso_pdu_rx_alloc_peek(2U); - if (!node_rx) { - break; - } - - node_rx->hdr.type = NODE_RX_TYPE_ISO_PDU; - node_rx->hdr.handle = cis_lll->handle; - iso_meta = &node_rx->hdr.rx_iso_meta; - iso_meta->payload_number = (cis_lll->event_count * - cis_lll->rx.bn) + (bn - 1U); - if (trx_performed_bitmask) { - iso_meta->timestamp = cis_lll->offset + - HAL_TICKER_TICKS_TO_US(radio_tmr_start_get()) + - radio_tmr_aa_restore() - cis_offset_first - - addr_us_get(cis_lll->rx.phy); - } else { - iso_meta->timestamp = cis_lll->offset + - HAL_TICKER_TICKS_TO_US(radio_tmr_start_get()) + - radio_tmr_ready_restore() - cis_offset_first; - } - iso_meta->timestamp %= - HAL_TICKER_TICKS_TO_US(BIT(HAL_TICKER_CNTR_MSBIT + 1U)); - iso_meta->status = 1U; - - ull_iso_pdu_rx_alloc(); - iso_rx_put(node_rx->hdr.link, node_rx); - - bn++; - } - -#if !defined(CONFIG_BT_CTLR_LOW_LAT_ULL) - if (bn != cis_lll->rx.bn_curr) { - iso_rx_sched(); - } -#endif /* CONFIG_BT_CTLR_LOW_LAT_ULL */ - e = ull_event_done_extra_get(); LL_ASSERT(e); From 7c19e78ea41afa3f5b10c001af8bc84042620830 Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Sat, 17 Jun 2023 05:05:42 +0530 Subject: [PATCH 273/421] [nrf fromtree] Bluetooth: Controller: Use of payload_count for Flush Timeout Use of payload_count for supporting flush timeout in Central and Peripheral ISO Lower Link Layer. Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit 7fa77a67fc1c924899982bbcde3d87c80b3e13cb) Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit ba03122ea83048f49921fe2738d472d4a8085327) --- .../bluetooth/controller/ll_sw/lll_conn_iso.h | 3 +- .../ll_sw/nordic/lll/lll_central_iso.c | 379 ++++++++++------ .../ll_sw/nordic/lll/lll_peripheral_iso.c | 405 +++++++++++------- 3 files changed, 503 insertions(+), 284 deletions(-) diff --git a/subsys/bluetooth/controller/ll_sw/lll_conn_iso.h b/subsys/bluetooth/controller/ll_sw/lll_conn_iso.h index 7fdf6bf48d5..9822066f513 100644 --- a/subsys/bluetooth/controller/ll_sw/lll_conn_iso.h +++ b/subsys/bluetooth/controller/ll_sw/lll_conn_iso.h @@ -16,8 +16,7 @@ struct lll_conn_iso_stream_rxtx { uint64_t bn:4; /* Burst number (BN) */ uint64_t phy:3; /* PHY */ uint64_t rfu:1; - uint8_t bn_curr:4; /* Current burst number */ - + uint8_t bn_curr:4; /* Current burst number */ #if defined(CONFIG_BT_CTLR_LE_ENC) struct ccm ccm; diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_central_iso.c b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_central_iso.c index 936087369f1..d4f4c8c3262 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_central_iso.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_central_iso.c @@ -40,14 +40,15 @@ #include "hal/debug.h" static int init_reset(void); -static inline void lll_flush_tx(struct lll_conn_iso_stream *cis_lll); -static inline void lll_flush_rx(struct lll_conn_iso_stream *cis_lll); static int prepare_cb(struct lll_prepare_param *p); static void abort_cb(struct lll_prepare_param *prepare_param, void *param); static void isr_tx(void *param); static void isr_rx(void *param); static void isr_prepare_subevent(void *param); static void isr_done(void *param); +static void payload_count_flush(struct lll_conn_iso_stream *cis_lll); +static void payload_count_flush_or_inc_on_close(struct lll_conn_iso_stream *cis_lll); +static void payload_count_lazy(struct lll_conn_iso_stream *cis_lll, uint16_t lazy); static uint16_t next_cis_chan_remap_idx; static uint16_t next_cis_chan_prn_s; @@ -118,24 +119,6 @@ static int init_reset(void) return 0; } -static inline void lll_flush_tx(struct lll_conn_iso_stream *cis_lll) -{ - /* sn and nesn are 1-bit, only Least Significant bit is needed */ - uint8_t sn_update = cis_lll->tx.bn + 1U - cis_lll->tx.bn_curr; - - /* we'll re-use sn_update when implementing flush timeout */ - cis_lll->sn += sn_update; -} - -static inline void lll_flush_rx(struct lll_conn_iso_stream *cis_lll) -{ - /* sn and nesn are 1-bit, only Least Significant bit is needed */ - uint8_t nesn_update = cis_lll->rx.bn + 1U - cis_lll->rx.bn_curr; - - /* we'll re-use sn_update when implementing flush timeout */ - cis_lll->nesn += nesn_update; -} - static int prepare_cb(struct lll_prepare_param *p) { struct lll_conn_iso_group *cig_lll = p->param; @@ -197,24 +180,10 @@ static int prepare_cb(struct lll_prepare_param *p) /* Reset accumulated latencies */ cig_lll->latency_prepare = 0U; - /* Adjust the SN and NESN for skipped CIG events */ - if (cis_lll->event_count) { - uint16_t cis_lazy; - - if (lazy > cis_lll->event_count) { - cis_lazy = lazy - cis_lll->event_count; - } else { - cis_lazy = lazy; - } - - /* sn and nesn are 1-bit, only Least Significant bit is needed */ - cis_lll->sn += cis_lll->tx.bn * cis_lazy; - cis_lll->nesn += cis_lll->rx.bn * cis_lazy; - } - se_curr = 1U; - cis_lll->tx.bn_curr = 1U; - cis_lll->rx.bn_curr = 1U; + + /* Adjust the SN and NESN for skipped CIG events */ + payload_count_lazy(cis_lll, lazy); /* Start setting up of Radio h/w */ radio_reset(); @@ -248,7 +217,8 @@ static int prepare_cb(struct lll_prepare_param *p) struct node_tx_iso *node_tx; memq_link_t *link; - payload_count = cis_lll->event_count * cis_lll->tx.bn; + payload_count = cis_lll->tx.payload_count + + cis_lll->tx.bn_curr - 1U; do { link = memq_peek(cis_lll->memq_tx.head, @@ -399,33 +369,12 @@ static int prepare_cb(struct lll_prepare_param *p) do { cis_lll = ull_conn_iso_lll_stream_get_by_group(cig_lll, &cis_handle); if (cis_lll && cis_lll->active) { - if (cis_lll->event_count) { - uint16_t cis_lazy; - - if (lazy > cis_lll->event_count) { - cis_lazy = lazy - cis_lll->event_count; - } else { - cis_lazy = lazy; - } + /* Adjust sn and nesn for skipped CIG events */ + payload_count_lazy(cis_lll, lazy); - /* sn and nesn are 1-bit, only Least Significant bit is needed */ - cis_lll->sn += cis_lll->tx.bn * cis_lazy; - cis_lll->nesn += cis_lll->rx.bn * cis_lazy; - - /* Adjust sn and nesn for canceled events */ - if (err) { - /* Adjust sn when flushing Tx */ - /* FIXME: When Flush Timeout is implemented */ - if (cis_lll->tx.bn_curr <= cis_lll->tx.bn) { - lll_flush_tx(cis_lll); - } - - /* Adjust nesn when flushing Rx */ - /* FIXME: When Flush Timeout is implemented */ - if (cis_lll->rx.bn_curr <= cis_lll->rx.bn) { - lll_flush_rx(cis_lll); - } - } + /* Adjust sn and nesn for canceled events */ + if (err) { + payload_count_flush_or_inc_on_close(cis_lll); } } } while (cis_lll); @@ -450,9 +399,21 @@ static void abort_cb(struct lll_prepare_param *prepare_param, void *param) /* NOTE: This is not a prepare being cancelled */ if (!prepare_param) { + struct lll_conn_iso_stream *next_cis_lll; struct lll_conn_iso_stream *cis_lll; + struct lll_conn_iso_group *cig_lll; cis_lll = ull_conn_iso_lll_stream_get(cis_handle_curr); + cig_lll = param; + + /* Adjust the SN, NESN and payload_count on abort for CISes */ + do { + next_cis_lll = ull_conn_iso_lll_stream_get_by_group(cig_lll, + &cis_handle_curr); + if (next_cis_lll && next_cis_lll->active) { + payload_count_flush_or_inc_on_close(next_cis_lll); + } + } while (next_cis_lll); /* Perform event abort here. * After event has been cleanly aborted, clean up resources @@ -508,8 +469,8 @@ static void isr_tx(void *param) uint64_t payload_count; uint8_t pkt_flags; - payload_count = (cis_lll->event_count * cis_lll->rx.bn) + - (cis_lll->rx.bn_curr - 1U); + payload_count = cis_lll->rx.payload_count + + cis_lll->rx.bn_curr - 1U; cis_lll->rx.ccm.counter = payload_count; @@ -652,7 +613,9 @@ static void isr_tx(void *param) cis_lll = next_cis_lll; /* Tx Ack stale ISO Data */ - payload_count = cis_lll->event_count * cis_lll->tx.bn; + payload_count = cis_lll->tx.payload_count + + cis_lll->tx.bn_curr - 1U; + do { link = memq_peek(cis_lll->memq_tx.head, cis_lll->memq_tx.tail, @@ -687,8 +650,6 @@ static void isr_tx(void *param) static void isr_rx(void *param) { struct lll_conn_iso_stream *cis_lll; - struct node_rx_pdu *node_rx; - struct pdu_cis *pdu_rx; uint8_t ack_pending; uint8_t trx_done; uint8_t crc_ok; @@ -714,6 +675,8 @@ static void isr_rx(void *param) /* No Rx */ if (!trx_done) { + payload_count_flush(cis_lll); + goto isr_rx_next_subevent; } @@ -723,23 +686,23 @@ static void isr_rx(void *param) /* Set the bit corresponding to CIS index */ trx_performed_bitmask |= (1U << LL_CIS_IDX_FROM_HANDLE(cis_lll->handle)); - /* Get reference to received PDU */ - node_rx = ull_iso_pdu_rx_alloc_peek(1U); - LL_ASSERT(node_rx); + if (crc_ok) { + struct node_rx_pdu *node_rx; + struct pdu_cis *pdu_rx; - pdu_rx = (void *)node_rx->pdu; + /* Get reference to received PDU */ + node_rx = ull_iso_pdu_rx_alloc_peek(1U); + LL_ASSERT(node_rx); + pdu_rx = (void *)node_rx->pdu; - if (crc_ok) { /* Tx ACK */ - if (pdu_rx->nesn != cis_lll->sn) { - /* Increment sequence number */ + if ((pdu_rx->nesn != cis_lll->sn) && (cis_lll->tx.bn_curr <= cis_lll->tx.bn)) { cis_lll->sn++; - - /* Increment burst number */ - if (cis_lll->tx.bn_curr <= cis_lll->tx.bn) { - - cis_lll->tx.bn_curr++; - + cis_lll->tx.bn_curr++; + if ((cis_lll->tx.bn_curr > cis_lll->tx.bn) && + ((cis_lll->tx.payload_count / cis_lll->tx.bn) < cis_lll->event_count)) { + cis_lll->tx.payload_count += cis_lll->tx.bn; + cis_lll->tx.bn_curr = 1U; } /* TODO: Implement early Tx Ack. Currently Tx Ack @@ -755,7 +718,6 @@ static void isr_rx(void *param) ull_iso_pdu_rx_alloc_peek(2U)) { struct node_rx_iso_meta *iso_meta; - /* Increment next expected sequence number */ cis_lll->nesn++; #if defined(CONFIG_BT_CTLR_LE_ENC) @@ -786,9 +748,8 @@ static void isr_rx(void *param) node_rx->hdr.type = NODE_RX_TYPE_ISO_PDU; node_rx->hdr.handle = cis_lll->handle; iso_meta = &node_rx->hdr.rx_iso_meta; - iso_meta->payload_number = (cis_lll->event_count * - cis_lll->rx.bn) + - (cis_lll->rx.bn_curr - 1U); + iso_meta->payload_number = cis_lll->rx.payload_count + + cis_lll->rx.bn_curr - 1U; iso_meta->timestamp = HAL_TICKER_TICKS_TO_US(radio_tmr_start_get()) + radio_tmr_ready_restore(); @@ -803,36 +764,23 @@ static void isr_rx(void *param) iso_rx_sched(); #endif /* CONFIG_BT_CTLR_LOW_LAT_ULL */ - /* Increment burst number */ cis_lll->rx.bn_curr++; + if ((cis_lll->rx.bn_curr > cis_lll->rx.bn) && + ((cis_lll->rx.payload_count / cis_lll->rx.bn) < cis_lll->event_count)) { + cis_lll->rx.payload_count += cis_lll->rx.bn; + cis_lll->rx.bn_curr = 1U; + } /* Need to be acked */ ack_pending = 1U; - - /* Handle NULL PDU indication received */ - } else if (pdu_rx->npi) { - /* Source could not send ISO data, increment NESN as if - * we received and expect to receive the next PDU in the - * burst. - */ - if (cis_lll->rx.bn_curr <= cis_lll->rx.bn) { - /* Increment next expected serial number */ - cis_lll->nesn++; - - /* Increment burst number */ - cis_lll->rx.bn_curr++; - } - - /* Not NPI, or more than the BN, or no free Rx ISO PDU buffers. - */ - } else { - /* Do nothing, ignore the Rx buffer */ } /* Close Isochronous Event */ cie = cie || pdu_rx->cie; } + payload_count_flush(cis_lll); + /* Close Isochronous Event */ cie = cie || ((cis_lll->rx.bn_curr > cis_lll->rx.bn) && (cis_lll->tx.bn_curr > cis_lll->tx.bn) && @@ -893,7 +841,8 @@ static void isr_rx(void *param) old_cis_lll = cis_lll; cis_lll = next_cis_lll; - payload_count = cis_lll->event_count * cis_lll->tx.bn; + payload_count = cis_lll->tx.payload_count + + cis_lll->tx.bn_curr - 1U; do { link = memq_peek(cis_lll->memq_tx.head, @@ -927,22 +876,10 @@ static void isr_rx(void *param) cis_lll = old_cis_lll; } - /* Adjust sn when flushing Tx */ - /* FIXME: When Flush Timeout is implemented */ - if (cis_lll->tx.bn_curr <= cis_lll->tx.bn) { - lll_flush_tx(cis_lll); - } - - /* Adjust nesn when flushing Rx */ - /* FIXME: When Flush Timeout is implemented */ - if (cis_lll->rx.bn_curr <= cis_lll->rx.bn) { - lll_flush_rx(cis_lll); - } + payload_count_flush_or_inc_on_close(cis_lll); /* Reset indices for the next CIS */ se_curr = 0U; /* isr_prepare_subevent() will increase se_curr */ - next_cis_lll->tx.bn_curr = 1U; - next_cis_lll->rx.bn_curr = 1U; #if defined(CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL) radio_tx_power_set(next_conn_lll->tx_pwr_lvl); @@ -1001,8 +938,7 @@ static void isr_prepare_subevent(void *param) memq_link_t *link; payload_index = cis_lll->tx.bn_curr - 1U; - payload_count = cis_lll->event_count * cis_lll->tx.bn + - payload_index; + payload_count = cis_lll->tx.payload_count + payload_index; link = memq_peek_n(cis_lll->memq_tx.head, cis_lll->memq_tx.tail, payload_index, (void **)&node_tx); @@ -1141,17 +1077,7 @@ static void isr_done(void *param) /* Get reference to CIS LLL context */ cis_lll = param; - /* Adjust sn when flushing Tx */ - /* FIXME: When Flush Timeout is implemented */ - if (cis_lll->tx.bn_curr <= cis_lll->tx.bn) { - lll_flush_tx(cis_lll); - } - - /* Adjust nesn when flushing Rx */ - /* FIXME: When Flush Timeout is implemented */ - if (cis_lll->rx.bn_curr <= cis_lll->rx.bn) { - lll_flush_rx(cis_lll); - } + payload_count_flush_or_inc_on_close(cis_lll); e = ull_event_done_extra_get(); LL_ASSERT(e); @@ -1166,3 +1092,190 @@ static void isr_done(void *param) lll_isr_cleanup(param); } + +static void payload_count_flush(struct lll_conn_iso_stream *cis_lll) +{ + if (cis_lll->tx.bn) { + uint64_t payload_count; + uint8_t u; + + payload_count = cis_lll->tx.payload_count + cis_lll->tx.bn_curr - 1U; + u = cis_lll->nse - ((cis_lll->nse / cis_lll->tx.bn) * + (cis_lll->tx.bn - 1U - + (payload_count % cis_lll->tx.bn))); + if ((((cis_lll->tx.payload_count / cis_lll->tx.bn) + cis_lll->tx.ft) == + (cis_lll->event_count + 1U)) && (u <= se_curr) && + (((cis_lll->tx.bn_curr < cis_lll->tx.bn) && + ((cis_lll->tx.payload_count / cis_lll->tx.bn) <= cis_lll->event_count)) || + ((cis_lll->tx.bn_curr == cis_lll->tx.bn) && + ((cis_lll->tx.payload_count / cis_lll->tx.bn) < cis_lll->event_count)))) { + /* sn and nesn are 1-bit, only Least Significant bit is needed */ + cis_lll->sn++; + cis_lll->tx.bn_curr++; + if (cis_lll->tx.bn_curr > cis_lll->tx.bn) { + cis_lll->tx.payload_count += cis_lll->tx.bn; + cis_lll->tx.bn_curr = 1U; + } + } + } + + if (cis_lll->rx.bn) { + uint64_t payload_count; + uint8_t u; + + payload_count = cis_lll->rx.payload_count + cis_lll->rx.bn_curr - 1U; + u = cis_lll->nse - ((cis_lll->nse / cis_lll->rx.bn) * + (cis_lll->rx.bn - 1U - + (payload_count % cis_lll->rx.bn))); + if ((((cis_lll->rx.payload_count / cis_lll->rx.bn) + cis_lll->rx.ft) == + (cis_lll->event_count + 1U)) && (u <= se_curr) && + (((cis_lll->rx.bn_curr < cis_lll->rx.bn) && + ((cis_lll->rx.payload_count / cis_lll->rx.bn) <= cis_lll->event_count)) || + ((cis_lll->rx.bn_curr == cis_lll->rx.bn) && + ((cis_lll->rx.payload_count / cis_lll->rx.bn) < cis_lll->event_count)))) { + /* sn and nesn are 1-bit, only Least Significant bit is needed */ + cis_lll->nesn++; + cis_lll->rx.bn_curr++; + if (cis_lll->rx.bn_curr > cis_lll->rx.bn) { + cis_lll->rx.payload_count += cis_lll->rx.bn; + cis_lll->rx.bn_curr = 1U; + } + } + } +} + +static void payload_count_flush_or_inc_on_close(struct lll_conn_iso_stream *cis_lll) +{ + if (cis_lll->tx.bn) { + uint64_t payload_count; + uint8_t u; + + if (((cis_lll->tx.payload_count / cis_lll->tx.bn) + cis_lll->tx.bn_curr) > + (cis_lll->event_count + cis_lll->tx.bn)) { + cis_lll->tx.payload_count += cis_lll->tx.bn; + cis_lll->tx.bn_curr = 1U; + + goto payload_count_flush_or_inc_on_close_rx; + } + + payload_count = cis_lll->tx.payload_count + cis_lll->tx.bn_curr - 1U; + u = cis_lll->nse - ((cis_lll->nse / cis_lll->tx.bn) * + (cis_lll->tx.bn - 1U - + (payload_count % cis_lll->tx.bn))); + while ((((cis_lll->tx.payload_count / cis_lll->tx.bn) + cis_lll->tx.ft) < + (cis_lll->event_count + 1U)) || + ((((cis_lll->tx.payload_count / cis_lll->tx.bn) + cis_lll->tx.ft) == + (cis_lll->event_count + 1U)) && (u <= (cis_lll->nse + 1U)))) { + /* sn and nesn are 1-bit, only Least Significant bit is needed */ + cis_lll->sn++; + cis_lll->tx.bn_curr++; + if (cis_lll->tx.bn_curr > cis_lll->tx.bn) { + cis_lll->tx.payload_count += cis_lll->tx.bn; + cis_lll->tx.bn_curr = 1U; + } + + payload_count = cis_lll->tx.payload_count + cis_lll->tx.bn_curr - 1U; + u = cis_lll->nse - ((cis_lll->nse / cis_lll->tx.bn) * + (cis_lll->tx.bn - 1U - + (payload_count % cis_lll->tx.bn))); + } + } + +payload_count_flush_or_inc_on_close_rx: + if (cis_lll->rx.bn) { + uint64_t payload_count; + uint8_t u; + + if (((cis_lll->rx.payload_count / cis_lll->rx.bn) + cis_lll->rx.bn_curr) > + (cis_lll->event_count + cis_lll->rx.bn)) { + cis_lll->rx.payload_count += cis_lll->rx.bn; + cis_lll->rx.bn_curr = 1U; + + return; + } + + payload_count = cis_lll->rx.payload_count + cis_lll->rx.bn_curr - 1U; + u = cis_lll->nse - ((cis_lll->nse / cis_lll->rx.bn) * + (cis_lll->rx.bn - 1U - + (payload_count % cis_lll->rx.bn))); + while ((((cis_lll->rx.payload_count / cis_lll->rx.bn) + cis_lll->rx.ft) < + (cis_lll->event_count + 1U)) || + ((((cis_lll->rx.payload_count / cis_lll->rx.bn) + cis_lll->rx.ft) == + (cis_lll->event_count + 1U)) && (u <= (cis_lll->nse + 1U)))) { + /* sn and nesn are 1-bit, only Least Significant bit is needed */ + cis_lll->nesn++; + cis_lll->rx.bn_curr++; + if (cis_lll->rx.bn_curr > cis_lll->rx.bn) { + cis_lll->rx.payload_count += cis_lll->rx.bn; + cis_lll->rx.bn_curr = 1U; + } + + payload_count = cis_lll->rx.payload_count + cis_lll->rx.bn_curr - 1U; + u = cis_lll->nse - ((cis_lll->nse / cis_lll->rx.bn) * + (cis_lll->rx.bn - 1U - + (payload_count % cis_lll->rx.bn))); + } + } +} + +static void payload_count_lazy(struct lll_conn_iso_stream *cis_lll, uint16_t lazy) +{ + if (cis_lll->tx.bn) { + uint16_t tx_lazy; + + tx_lazy = lazy; + while (tx_lazy--) { + uint64_t payload_count; + uint8_t u; + + payload_count = cis_lll->tx.payload_count + cis_lll->tx.bn_curr - 1U; + u = cis_lll->nse - ((cis_lll->nse / cis_lll->tx.bn) * + (cis_lll->tx.bn - 1U - + (payload_count % cis_lll->tx.bn))); + while (((cis_lll->tx.payload_count / cis_lll->tx.bn) + cis_lll->tx.ft) < + (cis_lll->event_count + 1U)) { + /* sn and nesn are 1-bit, only Least Significant bit is needed */ + cis_lll->sn++; + cis_lll->tx.bn_curr++; + if (cis_lll->tx.bn_curr > cis_lll->tx.bn) { + cis_lll->tx.payload_count += cis_lll->tx.bn; + cis_lll->tx.bn_curr = 1U; + } + + payload_count = cis_lll->tx.payload_count + + cis_lll->tx.bn_curr - 1U; + u = cis_lll->nse - ((cis_lll->nse / cis_lll->tx.bn) * + (cis_lll->tx.bn - 1U - + (payload_count % cis_lll->tx.bn))); + } + } + } + + if (cis_lll->rx.bn) { + while (lazy--) { + uint64_t payload_count; + uint8_t u; + + payload_count = cis_lll->rx.payload_count + cis_lll->rx.bn_curr - 1U; + u = cis_lll->nse - ((cis_lll->nse / cis_lll->rx.bn) * + (cis_lll->rx.bn - 1U - + (payload_count % cis_lll->rx.bn))); + while (((cis_lll->rx.payload_count / cis_lll->rx.bn) + cis_lll->rx.ft) < + (cis_lll->event_count + 1U)) { + /* sn and nesn are 1-bit, only Least Significant bit is needed */ + cis_lll->nesn++; + cis_lll->rx.bn_curr++; + if (cis_lll->rx.bn_curr > cis_lll->rx.bn) { + cis_lll->rx.payload_count += cis_lll->rx.bn; + cis_lll->rx.bn_curr = 1U; + } + + payload_count = cis_lll->rx.payload_count + + cis_lll->rx.bn_curr - 1U; + u = cis_lll->nse - ((cis_lll->nse / cis_lll->rx.bn) * + (cis_lll->rx.bn - 1U - + (payload_count % cis_lll->rx.bn))); + } + } + } +} diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_peripheral_iso.c b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_peripheral_iso.c index 3bbdb5fbf90..75af765f9d0 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_peripheral_iso.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_peripheral_iso.c @@ -49,8 +49,9 @@ static void isr_prepare_subevent(void *param); static void isr_prepare_subevent_next_cis(void *param); static void isr_prepare_subevent_common(void *param); static void isr_done(void *param); -static inline void lll_flush_tx(struct lll_conn_iso_stream *cis_lll); -static inline void lll_flush_rx(struct lll_conn_iso_stream *cis_lll); +static void payload_count_flush(struct lll_conn_iso_stream *cis_lll); +static void payload_count_rx_flush_or_txrx_inc(struct lll_conn_iso_stream *cis_lll); +static void payload_count_lazy(struct lll_conn_iso_stream *cis_lll, uint16_t lazy); static uint8_t next_chan_use; static uint16_t data_chan_id; @@ -61,7 +62,6 @@ static uint32_t trx_performed_bitmask; static uint16_t cis_offset_first; static uint16_t cis_handle_curr; static uint8_t se_curr; -static uint8_t has_tx; #if defined(CONFIG_BT_CTLR_LE_ENC) static uint8_t mic_state; @@ -135,24 +135,6 @@ static int init_reset(void) return 0; } -static inline void lll_flush_tx(struct lll_conn_iso_stream *cis_lll) -{ - /* sn and nesn are 1-bit, only Least Significant bit is needed */ - uint8_t sn_update = cis_lll->tx.bn + 1U - cis_lll->tx.bn_curr; - - /* TODO we'll re-use sn_update when implementing flush timeout */ - cis_lll->sn += sn_update; -} - -static inline void lll_flush_rx(struct lll_conn_iso_stream *cis_lll) -{ - /* sn and nesn are 1-bit, only Least Significant bit is needed */ - uint8_t nesn_update = cis_lll->rx.bn + 1U - cis_lll->rx.bn_curr; - - /* TODO we'll re-use nesn_update when implementing flush timeout */ - cis_lll->nesn += nesn_update; -} - static int prepare_cb(struct lll_prepare_param *p) { struct lll_conn_iso_group *cig_lll = p->param; @@ -225,14 +207,10 @@ static int prepare_cb(struct lll_prepare_param *p) EVENT_US_TO_US_FRAC(cig_lll->window_widening_max_us); } - /* Adjust sn and nesn for skipped CIG events */ - /* sn and nesn are 1-bit, only Least Significant bit is needed */ - cis_lll->sn += (cis_lll->tx.bn * lazy); - cis_lll->nesn += cis_lll->rx.bn * lazy; - se_curr = 1U; - cis_lll->rx.bn_curr = 1U; - has_tx = 0U; + + /* Adjust sn and nesn for skipped CIG events */ + payload_count_lazy(cis_lll, lazy); /* Start setting up of Radio h/w */ radio_reset(); @@ -260,8 +238,9 @@ static int prepare_cb(struct lll_prepare_param *p) uint64_t payload_cnt; uint8_t pkt_flags; - payload_cnt = (cis_lll->event_count * cis_lll->rx.bn) + - (cis_lll->rx.bn_curr - 1U); + payload_cnt = cis_lll->rx.payload_count + + cis_lll->rx.bn_curr - 1U; + cis_lll->rx.ccm.counter = payload_cnt; pkt_flags = RADIO_PKT_CONF_FLAGS(RADIO_PKT_CONF_PDU_TYPE_CIS, @@ -372,9 +351,10 @@ static int prepare_cb(struct lll_prepare_param *p) /* Adjust the SN and NESN for skipped CIG events */ uint16_t cis_handle = cis_handle_curr; - while (true) { - /* FIXME: Update below implementation when supporting Flush Timeout */ - payload_count = cis_lll->event_count * cis_lll->tx.bn; + do { + payload_count = cis_lll->tx.payload_count + + cis_lll->tx.bn_curr - 1U; + do { link = memq_peek(cis_lll->memq_tx.head, cis_lll->memq_tx.tail, (void **)&tx); @@ -392,26 +372,22 @@ static int prepare_cb(struct lll_prepare_param *p) } } while (link); - cis_lll = ull_conn_iso_lll_stream_get_by_group(cig_lll, &cis_handle); + do { + cis_lll = ull_conn_iso_lll_stream_get_by_group(cig_lll, &cis_handle); + } while (cis_lll && !cis_lll->active); + if (!cis_lll) { break; } - if (cis_lll->active) { - /* sn and nesn are 1-bit, only Least Significant bit is needed */ - cis_lll->sn += cis_lll->tx.bn * lazy; - cis_lll->nesn += cis_lll->rx.bn * lazy; - - /* Adjust sn and nesn for canceled events */ - if (err) { - /* Adjust nesn when flushing Rx */ - /* FIXME: When Flush Timeout is implemented */ - if (cis_lll->rx.bn_curr <= cis_lll->rx.bn) { - lll_flush_rx(cis_lll); - } - } + /* Adjust sn and nesn for skipped CIG events */ + payload_count_lazy(cis_lll, lazy); + + /* Adjust sn and nesn for canceled events */ + if (err) { + payload_count_rx_flush_or_txrx_inc(cis_lll); } - }; + } while (cis_lll); /* Return if prepare callback cancelled */ if (err) { @@ -433,24 +409,21 @@ static void abort_cb(struct lll_prepare_param *prepare_param, void *param) /* NOTE: This is not a prepare being cancelled */ if (!prepare_param) { - struct lll_conn_iso_group *cig_lll = param; + struct lll_conn_iso_stream *next_cis_lll; struct lll_conn_iso_stream *cis_lll; + struct lll_conn_iso_group *cig_lll; - cis_lll = ull_conn_iso_lll_stream_get_by_group(cig_lll, NULL); - - /* FIXME: Consider Flush Timeout when resetting current burst number */ - if (!has_tx) { - has_tx = 1U; + cis_lll = ull_conn_iso_lll_stream_get(cis_handle_curr); + cig_lll = param; - /* Adjust nesn when flushing Tx */ - /* FIXME: When Flush Timeout is implemented */ - if (cis_lll->tx.bn_curr <= cis_lll->tx.bn) { - lll_flush_tx(cis_lll); + /* Adjust the SN, NESN and payload_count on abort for CISes */ + do { + next_cis_lll = ull_conn_iso_lll_stream_get_by_group(cig_lll, + &cis_handle_curr); + if (next_cis_lll && next_cis_lll->active) { + payload_count_rx_flush_or_txrx_inc(next_cis_lll); } - - /* Set to last burst number in previous event */ - cis_lll->tx.bn_curr = cis_lll->tx.bn; - } + } while (next_cis_lll); /* Perform event abort here. * After event has been cleanly aborted, clean up resources @@ -500,20 +473,9 @@ static void isr_rx(void *param) /* No Rx */ if (!trx_done) { - /* FIXME: Consider Flush Timeout when resetting current burst number */ - if (!has_tx) { - has_tx = 1U; - - /* Adjust nesn when flushing Tx */ - /* FIXME: When Flush Timeout is implemented */ - if (cis_lll->tx.bn_curr <= cis_lll->tx.bn) { - lll_flush_tx(cis_lll); - } - - /* Start transmitting new burst */ - cis_lll->tx.bn_curr = cis_lll->tx.bn; - } + payload_count_flush(cis_lll); + /* Next subevent or next CIS */ if (se_curr < cis_lll->nse) { radio_isr_set(isr_prepare_subevent, param); } else { @@ -562,17 +524,20 @@ static void isr_rx(void *param) pdu_rx = (void *)node_rx->pdu; /* Tx ACK */ - if (pdu_rx->nesn != cis_lll->sn) { - /* Increment sequence number */ + if ((pdu_rx->nesn != cis_lll->sn) && (cis_lll->tx.bn_curr <= cis_lll->tx.bn)) { cis_lll->sn++; - - /* Increment burst number */ - if (cis_lll->tx.bn_curr <= cis_lll->tx.bn) { - cis_lll->tx.bn_curr++; + cis_lll->tx.bn_curr++; + if ((cis_lll->tx.bn_curr > cis_lll->tx.bn) && + ((cis_lll->tx.payload_count / cis_lll->tx.bn) < + cis_lll->event_count)) { + cis_lll->tx.payload_count += cis_lll->tx.bn; + cis_lll->tx.bn_curr = 1U; } - /* TODO: Tx Ack */ - + /* TODO: Implement early Tx Ack. Currently Tx Ack + * generated as stale Tx Ack when payload count + * has elapsed. + */ } /* Handle valid ISO data Rx */ @@ -582,7 +547,6 @@ static void isr_rx(void *param) ull_iso_pdu_rx_alloc_peek(2U)) { struct node_rx_iso_meta *iso_meta; - /* Increment next expected sequence number */ cis_lll->nesn++; #if defined(CONFIG_BT_CTLR_LE_ENC) @@ -614,9 +578,8 @@ static void isr_rx(void *param) node_rx->hdr.type = NODE_RX_TYPE_ISO_PDU; node_rx->hdr.handle = cis_lll->handle; iso_meta = &node_rx->hdr.rx_iso_meta; - iso_meta->payload_number = (cis_lll->event_count * - cis_lll->rx.bn) + - (cis_lll->rx.bn_curr - 1U); + iso_meta->payload_number = cis_lll->rx.payload_count + + cis_lll->rx.bn_curr - 1U; iso_meta->timestamp = cis_lll->offset + HAL_TICKER_TICKS_TO_US(radio_tmr_start_get()) + radio_tmr_aa_restore() - cis_offset_first - @@ -632,46 +595,19 @@ static void isr_rx(void *param) iso_rx_sched(); #endif /* CONFIG_BT_CTLR_LOW_LAT_ULL */ - /* Increment burst number */ cis_lll->rx.bn_curr++; - - /* Handle NULL PDU indication received */ - } else if (pdu_rx->npi) { - /* Source could not send ISO data, increment NESN as if - * we received and expect to receive the next PDU in the - * burst. - */ - if (cis_lll->rx.bn_curr <= cis_lll->rx.bn) { - /* Increment next expected serial number */ - cis_lll->nesn++; - - /* Increment burst number */ - cis_lll->rx.bn_curr++; + if ((cis_lll->rx.bn_curr > cis_lll->rx.bn) && + ((cis_lll->rx.payload_count / cis_lll->rx.bn) < cis_lll->event_count)) { + cis_lll->rx.payload_count += cis_lll->rx.bn; + cis_lll->rx.bn_curr = 1U; } - - /* Not NPI, or more than the BN, or no free Rx ISO PDU buffers. - */ - } else { - /* Do nothing, ignore the Rx buffer */ } /* Close Isochronous Event */ cie = cie || pdu_rx->cie; } - /* FIXME: Consider Flush Timeout when resetting current burst number */ - if (!has_tx) { - has_tx = 1U; - - /* Adjust nesn when flushing Tx */ - /* FIXME: When Flush Timeout is implemented */ - if (cis_lll->tx.bn_curr <= cis_lll->tx.bn) { - lll_flush_tx(cis_lll); - } - - /* Start transmitting new burst */ - cis_lll->tx.bn_curr = 1U; - } + payload_count_flush(cis_lll); /* Close Isochronous Event */ cie = cie || ((cis_lll->rx.bn_curr > cis_lll->rx.bn) && @@ -696,8 +632,7 @@ static void isr_rx(void *param) memq_link_t *link; payload_index = cis_lll->tx.bn_curr - 1U; - payload_count = cis_lll->event_count * cis_lll->tx.bn + - payload_index; + payload_count = cis_lll->tx.payload_count + payload_index; link = memq_peek_n(cis_lll->memq_tx.head, cis_lll->memq_tx.tail, payload_index, (void **)&tx); @@ -801,6 +736,7 @@ static void isr_rx(void *param) &data_chan_prn_s, &data_chan_remap_idx); } else { + struct lll_conn_iso_stream *next_cis_lll; struct lll_conn_iso_group *cig_lll; uint16_t event_counter; uint16_t cis_handle; @@ -809,34 +745,34 @@ static void isr_rx(void *param) cig_lll = ull_conn_iso_lll_group_get_by_stream(cis_lll); cis_handle = cis_handle_curr; do { - cis_lll = ull_conn_iso_lll_stream_get_by_group(cig_lll, &cis_handle); - } while (cis_lll && !cis_lll->active); + next_cis_lll = ull_conn_iso_lll_stream_get_by_group(cig_lll, &cis_handle); + } while (next_cis_lll && !next_cis_lll->active); - if (!cis_lll) { + if (!next_cis_lll) { /* ISO Event Done */ radio_isr_set(isr_done, param); return; } + payload_count_rx_flush_or_txrx_inc(cis_lll); + cis_handle_curr = cis_handle; /* Event counter value, 0-15 bit of cisEventCounter */ - event_counter = cis_lll->event_count; + event_counter = next_cis_lll->event_count; /* Calculate the radio channel to use for next CIS ISO event */ - data_chan_id = lll_chan_id(cis_lll->access_addr); + data_chan_id = lll_chan_id(next_cis_lll->access_addr); next_chan_use = lll_chan_iso_event(event_counter, data_chan_id, conn_lll->data_chan_map, conn_lll->data_chan_count, &data_chan_prn_s, &data_chan_remap_idx); - /* Reset indices for the next CIS */ - se_curr = 0U; /* isr_tx() will increase se_curr */ - cis_lll->tx.bn_curr = 1U; /* FIXME: may be this should be previous event value? */ - cis_lll->rx.bn_curr = 1U; - has_tx = 0U; + /* Next CIS, se_curr is incremented in isr_tx() */ + cis_lll = next_cis_lll; + se_curr = 0U; } /* Schedule next subevent reception */ @@ -894,8 +830,9 @@ static void isr_tx(void *param) uint64_t payload_count; uint8_t pkt_flags; - payload_count = (cis_lll->event_count * cis_lll->rx.bn) + - (cis_lll->rx.bn_curr - 1U); + payload_count = cis_lll->rx.payload_count + + cis_lll->rx.bn_curr - 1U; + cis_lll->rx.ccm.counter = payload_count; pkt_flags = RADIO_PKT_CONF_FLAGS(RADIO_PKT_CONF_PDU_TYPE_CIS, @@ -996,6 +933,7 @@ static void isr_tx(void *param) static void next_cis_prepare(void *param) { + struct lll_conn_iso_stream *next_cis_lll; struct lll_conn_iso_stream *cis_lll; struct lll_conn_iso_group *cig_lll; uint16_t cis_handle; @@ -1005,12 +943,13 @@ static void next_cis_prepare(void *param) /* Check for next active CIS */ cig_lll = ull_conn_iso_lll_group_get_by_stream(cis_lll); + next_cis_lll = cis_lll; cis_handle = cis_handle_curr; do { - cis_lll = ull_conn_iso_lll_stream_get_by_group(cig_lll, &cis_handle); - } while (cis_lll && !cis_lll->active); + next_cis_lll = ull_conn_iso_lll_stream_get_by_group(cig_lll, &cis_handle); + } while (next_cis_lll && !next_cis_lll->active); - if (!cis_lll) { + if (!next_cis_lll) { /* ISO Event Done */ radio_isr_set(isr_done, param); @@ -1019,7 +958,7 @@ static void next_cis_prepare(void *param) cis_handle_curr = cis_handle; - radio_isr_set(isr_prepare_subevent_next_cis, cis_lll); + radio_isr_set(isr_prepare_subevent_next_cis, next_cis_lll); } static void isr_prepare_subevent(void *param) @@ -1071,11 +1010,8 @@ static void isr_prepare_subevent_next_cis(void *param) &data_chan_prn_s, &data_chan_remap_idx); - /* Reset indices for the next CIS */ - se_curr = 0U; /* isr_prepare_subevent_common() will increase se_curr */ - cis_lll->tx.bn_curr = 1U; /* FIXME: may be this should be previous event value? */ - cis_lll->rx.bn_curr = 1U; - has_tx = 0U; + /* se_curr is incremented in isr_prepare_subevent_common() */ + se_curr = 0U; isr_prepare_subevent_common(param); } @@ -1111,8 +1047,9 @@ static void isr_prepare_subevent_common(void *param) uint64_t payload_count; uint8_t pkt_flags; - payload_count = (cis_lll->event_count * cis_lll->rx.bn) + - (cis_lll->rx.bn_curr - 1U); + payload_count = cis_lll->rx.payload_count + + cis_lll->rx.bn_curr - 1U; + cis_lll->rx.ccm.counter = payload_count; pkt_flags = RADIO_PKT_CONF_FLAGS(RADIO_PKT_CONF_PDU_TYPE_CIS, @@ -1235,11 +1172,7 @@ static void isr_done(void *param) /* Get reference to CIS LLL context */ cis_lll = param; - /* Adjust nesn when flushing Rx */ - /* FIXME: When Flush Timeout is implemented */ - if (cis_lll->rx.bn_curr <= cis_lll->rx.bn) { - lll_flush_rx(cis_lll); - } + payload_count_rx_flush_or_txrx_inc(cis_lll); e = ull_event_done_extra_get(); LL_ASSERT(e); @@ -1275,3 +1208,177 @@ static void isr_done(void *param) lll_isr_cleanup(param); } + +static void payload_count_flush(struct lll_conn_iso_stream *cis_lll) +{ + if (cis_lll->tx.bn) { + uint64_t payload_count; + uint8_t u; + + payload_count = cis_lll->tx.payload_count + cis_lll->tx.bn_curr - 1U; + u = cis_lll->nse - ((cis_lll->nse / cis_lll->tx.bn) * + (cis_lll->tx.bn - 1U - + (payload_count % cis_lll->tx.bn))); + while (((((cis_lll->tx.payload_count / cis_lll->tx.bn) + cis_lll->tx.ft) < + (cis_lll->event_count + 1U)) || + ((((cis_lll->tx.payload_count / cis_lll->tx.bn) + cis_lll->tx.ft) == + (cis_lll->event_count + 1U)) && (u < se_curr))) && + (((cis_lll->tx.bn_curr < cis_lll->tx.bn) && + ((cis_lll->tx.payload_count / cis_lll->tx.bn) <= cis_lll->event_count)) || + ((cis_lll->tx.bn_curr == cis_lll->tx.bn) && + ((cis_lll->tx.payload_count / cis_lll->tx.bn) < cis_lll->event_count)))) { + /* sn and nesn are 1-bit, only Least Significant bit is needed */ + cis_lll->sn++; + cis_lll->tx.bn_curr++; + if (cis_lll->tx.bn_curr > cis_lll->tx.bn) { + cis_lll->tx.payload_count += cis_lll->tx.bn; + cis_lll->tx.bn_curr = 1U; + } + + payload_count = cis_lll->tx.payload_count + cis_lll->tx.bn_curr - 1U; + u = cis_lll->nse - ((cis_lll->nse / cis_lll->tx.bn) * + (cis_lll->tx.bn - 1U - + (payload_count % cis_lll->tx.bn))); + } + } + + if (cis_lll->rx.bn) { + uint64_t payload_count; + uint8_t u; + + payload_count = cis_lll->rx.payload_count + cis_lll->rx.bn_curr - 1U; + u = cis_lll->nse - ((cis_lll->nse / cis_lll->rx.bn) * + (cis_lll->rx.bn - 1U - + (payload_count % cis_lll->rx.bn))); + if ((((cis_lll->rx.payload_count / cis_lll->rx.bn) + cis_lll->rx.ft) == + (cis_lll->event_count + 1U)) && (u <= se_curr) && + (((cis_lll->rx.bn_curr < cis_lll->rx.bn) && + ((cis_lll->rx.payload_count / cis_lll->rx.bn) <= cis_lll->event_count)) || + ((cis_lll->rx.bn_curr == cis_lll->rx.bn) && + ((cis_lll->rx.payload_count / cis_lll->rx.bn) < cis_lll->event_count)))) { + /* sn and nesn are 1-bit, only Least Significant bit is needed */ + cis_lll->nesn++; + cis_lll->rx.bn_curr++; + if (cis_lll->rx.bn_curr > cis_lll->rx.bn) { + cis_lll->rx.payload_count += cis_lll->rx.bn; + cis_lll->rx.bn_curr = 1U; + } + } + } +} + +static void payload_count_rx_flush_or_txrx_inc(struct lll_conn_iso_stream *cis_lll) +{ + if (cis_lll->tx.bn) { + if (((cis_lll->tx.payload_count / cis_lll->tx.bn) + cis_lll->tx.bn_curr) > + (cis_lll->event_count + cis_lll->tx.bn)) { + cis_lll->tx.payload_count += cis_lll->tx.bn; + cis_lll->tx.bn_curr = 1U; + } + } + + if (cis_lll->rx.bn) { + uint64_t payload_count; + uint8_t u; + + if (((cis_lll->rx.payload_count / cis_lll->rx.bn) + cis_lll->rx.bn_curr) > + (cis_lll->event_count + cis_lll->rx.bn)) { + cis_lll->rx.payload_count += cis_lll->rx.bn; + cis_lll->rx.bn_curr = 1U; + + return; + } + + payload_count = cis_lll->rx.payload_count + cis_lll->rx.bn_curr - 1U; + u = cis_lll->nse - ((cis_lll->nse / cis_lll->rx.bn) * + (cis_lll->rx.bn - 1U - + (payload_count % cis_lll->rx.bn))); + while ((((cis_lll->rx.payload_count / cis_lll->rx.bn) + cis_lll->rx.ft) < + (cis_lll->event_count + 1U)) || + ((((cis_lll->rx.payload_count / cis_lll->rx.bn) + cis_lll->rx.ft) == + (cis_lll->event_count + 1U)) && (u <= (cis_lll->nse + 1U)))) { + /* sn and nesn are 1-bit, only Least Significant bit is needed */ + cis_lll->nesn++; + cis_lll->rx.bn_curr++; + if (cis_lll->rx.bn_curr > cis_lll->rx.bn) { + cis_lll->rx.payload_count += cis_lll->rx.bn; + cis_lll->rx.bn_curr = 1U; + } + + payload_count = cis_lll->rx.payload_count + cis_lll->rx.bn_curr - 1U; + u = cis_lll->nse - ((cis_lll->nse / cis_lll->rx.bn) * + (cis_lll->rx.bn - 1U - + (payload_count % cis_lll->rx.bn))); + } + } +} + +static void payload_count_lazy(struct lll_conn_iso_stream *cis_lll, uint16_t lazy) +{ + if (cis_lll->tx.bn && lazy) { + uint16_t tx_lazy; + + tx_lazy = lazy; + while (tx_lazy--) { + uint64_t payload_count; + uint8_t u; + + payload_count = cis_lll->tx.payload_count + cis_lll->tx.bn_curr - 1U; + u = cis_lll->nse - ((cis_lll->nse / cis_lll->tx.bn) * + (cis_lll->tx.bn - 1U - + (payload_count % cis_lll->tx.bn))); + while (((((cis_lll->tx.payload_count / cis_lll->tx.bn) + cis_lll->tx.ft) < + (cis_lll->event_count + 1U)) || + ((((cis_lll->tx.payload_count / cis_lll->tx.bn) + cis_lll->tx.ft) == + (cis_lll->event_count + 1U)) && (u < (cis_lll->nse + 1U)))) && + ((cis_lll->tx.payload_count / cis_lll->tx.bn) < + cis_lll->event_count)) { + /* sn and nesn are 1-bit, only Least Significant bit is needed */ + cis_lll->sn++; + cis_lll->tx.bn_curr++; + if (cis_lll->tx.bn_curr > cis_lll->tx.bn) { + cis_lll->tx.payload_count += cis_lll->tx.bn; + cis_lll->tx.bn_curr = 1U; + } + + payload_count = cis_lll->tx.payload_count + + cis_lll->tx.bn_curr - 1U; + u = cis_lll->nse - ((cis_lll->nse / cis_lll->tx.bn) * + (cis_lll->tx.bn - 1U - + (payload_count % cis_lll->tx.bn))); + } + } + } + + if (cis_lll->rx.bn) { + while (lazy--) { + uint64_t payload_count; + uint8_t u; + + payload_count = cis_lll->rx.payload_count + cis_lll->rx.bn_curr - 1U; + u = cis_lll->nse - ((cis_lll->nse / cis_lll->rx.bn) * + (cis_lll->rx.bn - 1U - + (payload_count % cis_lll->rx.bn))); + while (((((cis_lll->rx.payload_count / cis_lll->rx.bn) + cis_lll->rx.ft) < + (cis_lll->event_count + 1U)) || + ((((cis_lll->rx.payload_count / cis_lll->rx.bn) + cis_lll->rx.ft) == + (cis_lll->event_count + 1U)) && (u <= (cis_lll->nse + 1U)))) && + ((cis_lll->rx.payload_count / cis_lll->rx.bn) < + cis_lll->event_count)) { + /* sn and nesn are 1-bit, only Least Significant bit is needed */ + cis_lll->nesn++; + cis_lll->rx.bn_curr++; + if (cis_lll->rx.bn_curr > cis_lll->rx.bn) { + cis_lll->rx.payload_count += cis_lll->rx.bn; + cis_lll->rx.bn_curr = 1U; + } + + payload_count = cis_lll->rx.payload_count + + cis_lll->rx.bn_curr - 1U; + u = cis_lll->nse - ((cis_lll->nse / cis_lll->rx.bn) * + (cis_lll->rx.bn - 1U - + (payload_count % cis_lll->rx.bn))); + } + } + } +} From 2694658063e3e5667cd8871632c23b268f71b54a Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Thu, 22 Jun 2023 22:36:05 +0530 Subject: [PATCH 274/421] [nrf fromtree] Bluetooth: Controller: Fix ISO Data timestamp when FT > 1 Fix ISO data timestamp to reflect the SDU reference point and not the ISO event anchor point when PDUs received after retransmissions. Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit e3ecab3142031383783764fbb9d9016931127e4a) Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit a9e55d8302d01ec1f61433d6f91375a718d89785) --- subsys/bluetooth/controller/ll_sw/lll_conn_iso.h | 3 +++ .../controller/ll_sw/nordic/lll/lll_central_iso.c | 7 ++++++- .../controller/ll_sw/nordic/lll/lll_peripheral_iso.c | 5 +++++ subsys/bluetooth/controller/ll_sw/ull_central_iso.c | 1 + subsys/bluetooth/controller/ll_sw/ull_peripheral_iso.c | 1 + 5 files changed, 16 insertions(+), 1 deletion(-) diff --git a/subsys/bluetooth/controller/ll_sw/lll_conn_iso.h b/subsys/bluetooth/controller/ll_sw/lll_conn_iso.h index 9822066f513..0321b96f638 100644 --- a/subsys/bluetooth/controller/ll_sw/lll_conn_iso.h +++ b/subsys/bluetooth/controller/ll_sw/lll_conn_iso.h @@ -77,6 +77,9 @@ struct lll_conn_iso_group { uint8_t role:1; /* 0: CENTRAL, 1: PERIPHERAL*/ uint8_t paused:1; /* 1: CIG is paused */ + /* ISO interval to calculate timestamp under FT > 1 */ + uint32_t iso_interval_us; + /* Accumulates LLL prepare callback latencies */ uint16_t latency_prepare; uint16_t latency_event; diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_central_iso.c b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_central_iso.c index d4f4c8c3262..4bf44a42cd9 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_central_iso.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_central_iso.c @@ -716,6 +716,7 @@ static void isr_rx(void *param) (cis_lll->rx.bn_curr <= cis_lll->rx.bn) && (pdu_rx->sn == cis_lll->nesn) && ull_iso_pdu_rx_alloc_peek(2U)) { + struct lll_conn_iso_group *cig_lll; struct node_rx_iso_meta *iso_meta; cis_lll->nesn++; @@ -753,6 +754,10 @@ static void isr_rx(void *param) iso_meta->timestamp = HAL_TICKER_TICKS_TO_US(radio_tmr_start_get()) + radio_tmr_ready_restore(); + cig_lll = ull_conn_iso_lll_group_get_by_stream(cis_lll); + iso_meta->timestamp -= (cis_lll->event_count - + (cis_lll->rx.payload_count / cis_lll->rx.bn)) * + cig_lll->iso_interval_us; iso_meta->timestamp %= HAL_TICKER_TICKS_TO_US(BIT(HAL_TICKER_CNTR_MSBIT + 1U)); iso_meta->status = 0U; @@ -788,8 +793,8 @@ static void isr_rx(void *param) isr_rx_next_subevent: if (cie || (se_curr == cis_lll->nse)) { - struct lll_conn_iso_stream *old_cis_lll; struct lll_conn_iso_stream *next_cis_lll; + struct lll_conn_iso_stream *old_cis_lll; struct lll_conn_iso_group *cig_lll; struct lll_conn *next_conn_lll; uint8_t phy; diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_peripheral_iso.c b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_peripheral_iso.c index 75af765f9d0..25401f5564e 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_peripheral_iso.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_peripheral_iso.c @@ -545,6 +545,7 @@ static void isr_rx(void *param) (cis_lll->rx.bn_curr <= cis_lll->rx.bn) && (pdu_rx->sn == cis_lll->nesn) && ull_iso_pdu_rx_alloc_peek(2U)) { + struct lll_conn_iso_group *cig_lll; struct node_rx_iso_meta *iso_meta; cis_lll->nesn++; @@ -584,6 +585,10 @@ static void isr_rx(void *param) HAL_TICKER_TICKS_TO_US(radio_tmr_start_get()) + radio_tmr_aa_restore() - cis_offset_first - addr_us_get(cis_lll->rx.phy); + cig_lll = ull_conn_iso_lll_group_get_by_stream(cis_lll); + iso_meta->timestamp -= (cis_lll->event_count - + (cis_lll->rx.payload_count / cis_lll->rx.bn)) * + cig_lll->iso_interval_us; iso_meta->timestamp %= HAL_TICKER_TICKS_TO_US(BIT(HAL_TICKER_CNTR_MSBIT + 1U)); iso_meta->status = 0U; diff --git a/subsys/bluetooth/controller/ll_sw/ull_central_iso.c b/subsys/bluetooth/controller/ll_sw/ull_central_iso.c index 8c516826e06..62a684bbfa9 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_central_iso.c +++ b/subsys/bluetooth/controller/ll_sw/ull_central_iso.c @@ -254,6 +254,7 @@ uint8_t ll_cig_parameters_commit(uint8_t cig_id, uint16_t *handles) } iso_interval_us = cig->iso_interval * ISO_INT_UNIT_US; + cig->lll.iso_interval_us = iso_interval_us; lll_hdr_init(&cig->lll, cig); max_se_length = 0U; diff --git a/subsys/bluetooth/controller/ll_sw/ull_peripheral_iso.c b/subsys/bluetooth/controller/ll_sw/ull_peripheral_iso.c index eeef778734b..a707341f41c 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_peripheral_iso.c +++ b/subsys/bluetooth/controller/ll_sw/ull_peripheral_iso.c @@ -191,6 +191,7 @@ uint8_t ull_peripheral_iso_acquire(struct ll_conn *acl, cig->iso_interval = sys_le16_to_cpu(req->iso_interval); iso_interval_us = cig->iso_interval * CONN_INT_UNIT_US; + cig->lll.iso_interval_us = iso_interval_us; cig->cig_id = req->cig_id; cig->lll.handle = LLL_HANDLE_INVALID; From 41b3a58b1641934eec748c66d57846f0e4ef56e0 Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Thu, 8 Jun 2023 10:17:33 +0530 Subject: [PATCH 275/421] [nrf fromtree] Bluetooth: Controller: Option to ignore Tx ISO Data Packet Seq Num Kconfig option to turn off ISO Data Packet Sequence Number use to place the ISO Data in the correct radio event, instead simply buffer it to next radio event. Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit 61d00467b469e816dfd6933bfef038422ddf36c7) Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit 25d7b75e319814171d5ec32d9f47c5e103b0ad22) --- .../bluetooth/controller/Kconfig.ll_sw_split | 9 +- subsys/bluetooth/controller/hci/hci.c | 108 +++++++++++++++--- .../controller/ll_sw/ull_central_iso.c | 3 + .../controller/ll_sw/ull_conn_iso_types.h | 4 + .../controller/ll_sw/ull_peripheral_iso.c | 3 + 5 files changed, 111 insertions(+), 16 deletions(-) diff --git a/subsys/bluetooth/controller/Kconfig.ll_sw_split b/subsys/bluetooth/controller/Kconfig.ll_sw_split index 3f6f3c10382..a7dade7a1db 100644 --- a/subsys/bluetooth/controller/Kconfig.ll_sw_split +++ b/subsys/bluetooth/controller/Kconfig.ll_sw_split @@ -499,7 +499,8 @@ config BT_CTLR_SCAN_ENABLE_STRICT config BT_CTLR_ISOAL_SN_STRICT bool "Enforce Strict Tx ISO Data Sequence Number use" - depends on BT_CTLR_ADV_ISO || BT_CTLR_CONN_ISO + depends on !BT_CTLR_ISOAL_PSN_IGNORE && (BT_CTLR_ADV_ISO || \ + BT_CTLR_CONN_ISO) default y help Enforce strict sequencing of released payloads based on the TX SDU's @@ -517,6 +518,12 @@ config BT_CTLR_ISOAL_SN_STRICT dropped. This will result in better delivery of data to the receiver but at the cost of creating skews in the received stream of SDUs. +config BT_CTLR_ISOAL_PSN_IGNORE + bool "Ignore Tx ISO Data Packet Sequence Number use" + depends on BT_CTLR_ADV_ISO || BT_CTLR_CONN_ISO + help + Ignore the use of Tx ISO Data Packet Sequence Number. + config BT_CTLR_ZLI bool "Use Zero Latency IRQs" depends on ZERO_LATENCY_IRQS diff --git a/subsys/bluetooth/controller/hci/hci.c b/subsys/bluetooth/controller/hci/hci.c index 0adbf5ff70c..b2c95271b2c 100644 --- a/subsys/bluetooth/controller/hci/hci.c +++ b/subsys/bluetooth/controller/hci/hci.c @@ -5657,8 +5657,6 @@ int hci_iso_handle(struct net_buf *buf, struct net_buf **evt) struct bt_hci_iso_data_hdr *iso_data_hdr; struct isoal_sdu_tx sdu_frag_tx; struct bt_hci_iso_hdr *iso_hdr; - struct ll_iso_datapath *dp_in; - struct ll_iso_stream_hdr *hdr; uint32_t *time_stamp; uint16_t handle; uint8_t pb_flag; @@ -5668,8 +5666,6 @@ int hci_iso_handle(struct net_buf *buf, struct net_buf **evt) iso_data_hdr = NULL; *evt = NULL; - hdr = NULL; - dp_in = NULL; if (buf->len < sizeof(*iso_hdr)) { LOG_ERR("No HCI ISO header"); @@ -5747,16 +5743,49 @@ int hci_iso_handle(struct net_buf *buf, struct net_buf **evt) * data path */ } else if (IS_CIS_HANDLE(handle)) { - struct ll_conn_iso_stream *cis = - ll_iso_stream_connected_get(handle); + struct ll_conn_iso_stream *cis; + struct ll_conn_iso_group *cig; + struct ll_iso_stream_hdr *hdr; + struct ll_iso_datapath *dp_in; + + cis = ll_iso_stream_connected_get(handle); if (!cis) { return -EINVAL; } - struct ll_conn_iso_group *cig = cis->group; - uint8_t event_offset; + cig = cis->group; - hdr = &(cis->hdr); +#if defined(CONFIG_BT_CTLR_ISOAL_PSN_IGNORE) + uint64_t event_count; + uint64_t pkt_seq_num; + + /* Catch up local pkt_seq_num with internal pkt_seq_num */ + event_count = cis->lll.event_count; + pkt_seq_num = event_count + 1U; + if (!(pb_flag & 0x01) && + (((pkt_seq_num - cis->pkt_seq_num) & + BIT64_MASK(39)) <= BIT64_MASK(38))) { + cis->pkt_seq_num = pkt_seq_num; + } else { + pkt_seq_num = cis->pkt_seq_num; + } + + /* Pre-increment, for next ISO data packet seq num comparison */ + if (pb_flag & 0x10) { + cis->pkt_seq_num++; + } + + /* Target next event to avoid overlapping with current event */ + pkt_seq_num++; + sdu_frag_tx.target_event = pkt_seq_num; + sdu_frag_tx.grp_ref_point = + isoal_get_wrapped_time_us(cig->cig_ref_point, + ((pkt_seq_num - event_count) * + cig->iso_interval * + ISO_INT_UNIT_US)); + +#else /* !CONFIG_BT_CTLR_ISOAL_PSN_IGNORE */ + uint8_t event_offset; /* We must ensure sufficient time for ISO-AL to fragment SDU and * deliver PDUs to the TX queue. By checking ull_ref_get, we @@ -5780,11 +5809,15 @@ int hci_iso_handle(struct net_buf *buf, struct net_buf **evt) } sdu_frag_tx.target_event = cis->lll.event_count + event_offset; - sdu_frag_tx.grp_ref_point = isoal_get_wrapped_time_us(cig->cig_ref_point, - (event_offset * cig->iso_interval * - ISO_INT_UNIT_US)); + sdu_frag_tx.grp_ref_point = + isoal_get_wrapped_time_us(cig->cig_ref_point, + (event_offset * + cig->iso_interval * + ISO_INT_UNIT_US)); +#endif /* !CONFIG_BT_CTLR_ISOAL_PSN_IGNORE */ /* Get controller's input data path for CIS */ + hdr = &(cis->hdr); dp_in = hdr->datapath_in; if (!dp_in || dp_in->path_id != BT_HCI_DATAPATH_ID_HCI) { LOG_ERR("Input data path not set for HCI"); @@ -5817,8 +5850,6 @@ int hci_iso_handle(struct net_buf *buf, struct net_buf **evt) struct ll_adv_iso_set *adv_iso; struct lll_adv_iso *lll_iso; uint16_t stream_handle; - uint8_t target_event; - uint8_t event_offset; uint16_t slen; /* FIXME: Code only expects header present */ @@ -5844,6 +5875,53 @@ int hci_iso_handle(struct net_buf *buf, struct net_buf **evt) return -EINVAL; } + lll_iso = &adv_iso->lll; + +#if defined(CONFIG_BT_CTLR_ISOAL_PSN_IGNORE) + uint64_t event_count; + uint64_t pkt_seq_num; + + /* Catch up local pkt_seq_num with internal pkt_seq_num */ + event_count = lll_iso->payload_count / lll_iso->bn; + pkt_seq_num = event_count; + if (!(pb_flag & 0x01) && + (((pkt_seq_num - stream->pkt_seq_num) & + BIT64_MASK(39)) <= BIT64_MASK(38))) { + stream->pkt_seq_num = pkt_seq_num; + } else { + pkt_seq_num = stream->pkt_seq_num; + } + + /* Pre-increment, for next ISO data packet seq num comparison */ + if (pb_flag & 0x10) { + stream->pkt_seq_num++; + } + + /* Target next event to avoid overlapping with current event */ + /* FIXME: Implement ISO Tx ack generation early in done compared + * to currently only in prepare. I.e. to ensure upper + * layer has the number of completed packet before the + * next BIG event, so as to supply new ISO data packets. + * Without which upper layers need extra buffers to + * buffer next ISO data packet. + * + * Enable below increment once early Tx ack is + * implemented. + * + * pkt_seq_num++; + */ + sdu_frag_tx.target_event = pkt_seq_num; + sdu_frag_tx.grp_ref_point = + isoal_get_wrapped_time_us(adv_iso->big_ref_point, + (((pkt_seq_num + 1U) - + event_count) * + lll_iso->iso_interval * + ISO_INT_UNIT_US)); + +#else /* !CONFIG_BT_CTLR_ISOAL_PSN_IGNORE */ + uint8_t target_event; + uint8_t event_offset; + /* Determine the target event and the first event offset after * datapath setup. * event_offset mitigates the possibility of first SDU being @@ -5861,7 +5939,6 @@ int hci_iso_handle(struct net_buf *buf, struct net_buf **evt) * BIG event by incrementing the previous elapsed big_ref_point * by one additional ISO interval. */ - lll_iso = &adv_iso->lll; target_event = lll_iso->payload_count / lll_iso->bn; event_offset = ull_ref_get(&adv_iso->ull) ? 0U : 1U; event_offset += lll_iso->latency_prepare; @@ -5872,6 +5949,7 @@ int hci_iso_handle(struct net_buf *buf, struct net_buf **evt) ((event_offset + 1U) * lll_iso->iso_interval * ISO_INT_UNIT_US)); +#endif /* !CONFIG_BT_CTLR_ISOAL_PSN_IGNORE */ /* Start Fragmentation */ /* FIXME: need to ensure ISO-AL returns proper isoal_status. diff --git a/subsys/bluetooth/controller/ll_sw/ull_central_iso.c b/subsys/bluetooth/controller/ll_sw/ull_central_iso.c index 62a684bbfa9..474b8d0dbe9 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_central_iso.c +++ b/subsys/bluetooth/controller/ll_sw/ull_central_iso.c @@ -883,6 +883,9 @@ uint8_t ull_central_iso_setup(uint16_t cis_handle, #endif /* !CONFIG_BT_CTLR_JIT_SCHEDULING */ cis->central.instant = instant; +#if defined(CONFIG_BT_CTLR_ISOAL_PSN_IGNORE) + cis->pkt_seq_num = 0U; +#endif /* CONFIG_BT_CTLR_ISOAL_PSN_IGNORE */ cis->lll.event_count = LLL_CONN_ISO_EVENT_COUNT_MAX; cis->lll.next_subevent = 0U; cis->lll.sn = 0U; diff --git a/subsys/bluetooth/controller/ll_sw/ull_conn_iso_types.h b/subsys/bluetooth/controller/ll_sw/ull_conn_iso_types.h index e8ca29da7af..39cee21d0b1 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_conn_iso_types.h +++ b/subsys/bluetooth/controller/ll_sw/ull_conn_iso_types.h @@ -48,6 +48,10 @@ struct ll_conn_iso_stream { */ uint8_t terminate_reason; uint8_t cis_id; + +#if defined(CONFIG_BT_CTLR_ISOAL_PSN_IGNORE) + uint64_t pkt_seq_num:39; +#endif /* CONFIG_BT_CTLR_ISOAL_PSN_IGNORE */ }; struct ll_conn_iso_group { diff --git a/subsys/bluetooth/controller/ll_sw/ull_peripheral_iso.c b/subsys/bluetooth/controller/ll_sw/ull_peripheral_iso.c index a707341f41c..843bf877935 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_peripheral_iso.c +++ b/subsys/bluetooth/controller/ll_sw/ull_peripheral_iso.c @@ -326,6 +326,9 @@ uint8_t ull_peripheral_iso_setup(struct pdu_data_llctrl_cis_ind *ind, cis->sync_delay = sys_get_le24(ind->cis_sync_delay); cis->offset = cis_offset; memcpy(cis->lll.access_addr, ind->aa, sizeof(ind->aa)); +#if defined(CONFIG_BT_CTLR_ISOAL_PSN_IGNORE) + cis->pkt_seq_num = 0U; +#endif /* CONFIG_BT_CTLR_ISOAL_PSN_IGNORE */ cis->lll.event_count = LLL_CONN_ISO_EVENT_COUNT_MAX; cis->lll.next_subevent = 0U; cis->lll.sn = 0U; From 227cc39f8b9b67c4f3bce67a3e85df5d24a49073 Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Fri, 4 Aug 2023 14:04:35 +0530 Subject: [PATCH 276/421] [nrf fromtree] tests: bsim: Bluetooth: Test RTN=2, FT=2, Per skip 2 SE in Controller Test RTN=2, FT=2 in Controller with 2 subevents dropped by peripheral. Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit 2935d3b731d551230c0dcdf13afed61f0716d601) Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit 29bd2a979f972f9dfa034d9c90d3e25d6b9cfa9e) --- .../ll_sw/nordic/lll/lll_peripheral_iso.c | 9 +++++- tests/bsim/bluetooth/ll/cis/Kconfig | 19 +++++++++++++ .../overlay-acl_first_ft_per_skip_2_se.conf | 9 ++++++ tests/bsim/bluetooth/ll/cis/prj.conf | 1 + tests/bsim/bluetooth/ll/cis/src/main.c | 28 ++++++++++++++----- ...onnected_iso_acl_first_ft_per_skip_2_se.sh | 24 ++++++++++++++++ tests/bsim/bluetooth/ll/compile.sh | 1 + 7 files changed, 83 insertions(+), 8 deletions(-) create mode 100644 tests/bsim/bluetooth/ll/cis/overlay-acl_first_ft_per_skip_2_se.conf create mode 100755 tests/bsim/bluetooth/ll/cis/tests_scripts/connected_iso_acl_first_ft_per_skip_2_se.sh diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_peripheral_iso.c b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_peripheral_iso.c index 25401f5564e..c33c82d4c70 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_peripheral_iso.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_peripheral_iso.c @@ -472,7 +472,14 @@ static void isr_rx(void *param) cis_lll = param; /* No Rx */ - if (!trx_done) { + if (!trx_done || +#if defined(CONFIG_TEST_FT_PER_SKIP_SUBEVENTS) + ((((cis_lll->event_count % 3U) < CONFIG_TEST_FT_PER_SKIP_EVENTS_COUNT) && + ((se_curr > cis_lll->nse) || (se_curr <= 2U))) || + (((cis_lll->event_count % 3U) < (CONFIG_TEST_FT_PER_SKIP_EVENTS_COUNT + 1U)) && + ((se_curr > cis_lll->nse) || (se_curr <= 1U)))) || +#endif + false) { payload_count_flush(cis_lll); /* Next subevent or next CIS */ diff --git a/tests/bsim/bluetooth/ll/cis/Kconfig b/tests/bsim/bluetooth/ll/cis/Kconfig index b59a46be4fc..532a26f5d52 100644 --- a/tests/bsim/bluetooth/ll/cis/Kconfig +++ b/tests/bsim/bluetooth/ll/cis/Kconfig @@ -16,6 +16,25 @@ config TEST_MULTIPLE_PERIPERAL_CIS help Multiple Peripheral CIS establishment. +config TEST_FT_SKIP_SUBEVENTS + bool + help + Skip central and/or peripheral subevent reception to test flush + timeout implementation. + +config TEST_FT_PER_SKIP_SUBEVENTS + bool "Skip peripheral role subevents to test Flush Timeout" + select TEST_FT_SKIP_SUBEVENTS + help + Skip peripheral role subevent reception to test flush timeout + implementation. + +config TEST_FT_PER_SKIP_EVENTS_COUNT + int "Skip peripheral ISO events count, all subevents in them" + depends on TEST_FT_PER_SKIP_SUBEVENTS + help + Skip peripheral ISO events count where all subevents are skipped. + config BT_CTLR_SCAN_UNRESERVED default y if TEST_CONNECT_ACL_FIRST help diff --git a/tests/bsim/bluetooth/ll/cis/overlay-acl_first_ft_per_skip_2_se.conf b/tests/bsim/bluetooth/ll/cis/overlay-acl_first_ft_per_skip_2_se.conf new file mode 100644 index 00000000000..bfbe36115f5 --- /dev/null +++ b/tests/bsim/bluetooth/ll/cis/overlay-acl_first_ft_per_skip_2_se.conf @@ -0,0 +1,9 @@ +CONFIG_TEST_USE_LEGACY_ADVERTISING=n +CONFIG_TEST_CONNECT_ACL_FIRST=y +CONFIG_TEST_FT_PER_SKIP_SUBEVENTS=y +CONFIG_TEST_FT_PER_SKIP_EVENTS_COUNT=1 +CONFIG_BT_MAX_CONN=1 +CONFIG_BT_ISO_MAX_CHAN=1 +CONFIG_BT_CTLR_LLCP_LOCAL_PROC_CTX_BUF_NUM=9 +CONFIG_BT_CTLR_ADVANCED_FEATURES=y +CONFIG_BT_CTLR_ISOAL_PSN_IGNORE=y diff --git a/tests/bsim/bluetooth/ll/cis/prj.conf b/tests/bsim/bluetooth/ll/cis/prj.conf index 0b6b764393b..a4d3c3e8c5f 100644 --- a/tests/bsim/bluetooth/ll/cis/prj.conf +++ b/tests/bsim/bluetooth/ll/cis/prj.conf @@ -13,6 +13,7 @@ CONFIG_BT_MAX_CONN=9 CONFIG_BT_ISO_MAX_CHAN=9 CONFIG_BT_ISO_TX_BUF_COUNT=18 CONFIG_BT_ISO_TX_MTU=120 +CONFIG_BT_ISO_RX_MTU=120 CONFIG_BT_BUF_CMD_TX_SIZE=255 CONFIG_BT_BUF_EVT_RX_SIZE=255 diff --git a/tests/bsim/bluetooth/ll/cis/src/main.c b/tests/bsim/bluetooth/ll/cis/src/main.c index a9538e3e9c6..720adc16ef9 100644 --- a/tests/bsim/bluetooth/ll/cis/src/main.c +++ b/tests/bsim/bluetooth/ll/cis/src/main.c @@ -53,6 +53,7 @@ static bt_addr_le_t peer_addr; #define ISO_INTERVAL_US 10000U #define ISO_LATENCY_MS DIV_ROUND_UP(ISO_INTERVAL_US, USEC_PER_MSEC) +#define ISO_LATENCY_FT_MS 20U #define BT_CONN_US_TO_INTERVAL(t) ((uint16_t)((t) * 4U / 5U / USEC_PER_MSEC)) @@ -103,7 +104,7 @@ static bt_addr_le_t peer_addr; #define NAME_LEN 30 -#define BUF_ALLOC_TIMEOUT (30) /* milliseconds */ +#define BUF_ALLOC_TIMEOUT (40) /* milliseconds */ NET_BUF_POOL_FIXED_DEFINE(tx_pool, CONFIG_BT_ISO_TX_BUF_COUNT, BT_ISO_SDU_BUF_SIZE(CONFIG_BT_ISO_TX_MTU), 8, NULL); @@ -300,8 +301,11 @@ static void iso_recv(struct bt_iso_chan *chan, const struct bt_iso_recv_info *in expected_seq_num[index] = seq_num; } - expected_seq_num[index]++; + expected_seq_num[index] += 1U; +#if defined(CONFIG_TEST_FT_SKIP_SUBEVENTS) + expected_seq_num[index] += ((CONFIG_TEST_FT_PER_SKIP_EVENTS_COUNT - 1U) * 2U); +#endif } else if (expected_seq_num[index] && expected_seq_num[index] < SEQ_NUM_MAX) { FAIL("%s: Invalid ISO data after valid ISO data reception.\n" @@ -361,7 +365,11 @@ static void test_cis_central(void) for (int i = 0; i < CONFIG_BT_ISO_MAX_CHAN; i++) { iso_tx[i].sdu = CONFIG_BT_ISO_TX_MTU; iso_tx[i].phy = BT_GAP_LE_PHY_2M; - iso_tx[i].rtn = 0U; + if (IS_ENABLED(CONFIG_TEST_FT_SKIP_SUBEVENTS)) { + iso_tx[i].rtn = 2U; + } else { + iso_tx[i].rtn = 0U; + } iso_tx[i].path = NULL; iso_qos[i].tx = &iso_tx[i]; @@ -381,7 +389,11 @@ static void test_cis_central(void) cig_param.sca = BT_GAP_SCA_UNKNOWN; cig_param.packing = 0U; cig_param.framing = 0U; - cig_param.latency = ISO_LATENCY_MS; + if (IS_ENABLED(CONFIG_TEST_FT_SKIP_SUBEVENTS)) { + cig_param.latency = ISO_LATENCY_FT_MS; + } else { + cig_param.latency = ISO_LATENCY_MS; + } cig_param.interval = ISO_INTERVAL_US; printk("Create CIG..."); @@ -404,7 +416,7 @@ static void test_cis_central(void) uint8_t conn_index; uint8_t chan; - printk("Start scanning..."); + printk("Start scanning (%d)...", i); err = bt_le_scan_start(BT_LE_SCAN_CUSTOM, NULL); if (err) { FAIL("Could not start scan: %d\n", err); @@ -510,7 +522,7 @@ static void test_cis_central(void) ret = bt_iso_chan_send(&iso_chan[chan], buf, seq_num, BT_ISO_TIMESTAMP_NONE); if (ret < 0) { - FAIL("Unable to broadcast data on channel %u" + FAIL("Unable to send data on channel %u" " : %d\n", chan, ret); net_buf_unref(buf); return; @@ -522,7 +534,7 @@ static void test_cis_central(void) } } - k_sleep(K_MSEC(100)); + k_sleep(K_MSEC(1000)); for (uint8_t chan = 0U; chan < CONFIG_BT_ISO_MAX_CHAN; chan++) { printk("ISO disconnect channel %u...", chan); @@ -587,6 +599,8 @@ static int iso_accept(const struct bt_iso_accept_info *info, *chan = &iso_chan_p[chan_count]; chan_count++; + printk("Accepted on channel %p\n", *chan); + return 0; } diff --git a/tests/bsim/bluetooth/ll/cis/tests_scripts/connected_iso_acl_first_ft_per_skip_2_se.sh b/tests/bsim/bluetooth/ll/cis/tests_scripts/connected_iso_acl_first_ft_per_skip_2_se.sh new file mode 100755 index 00000000000..307d865a117 --- /dev/null +++ b/tests/bsim/bluetooth/ll/cis/tests_scripts/connected_iso_acl_first_ft_per_skip_2_se.sh @@ -0,0 +1,24 @@ +#!/usr/bin/env bash +# Copyright 2020 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +source ${ZEPHYR_BASE}/tests/bsim/sh_common.source + +# Basic Connected ISO test: a Central connects to 1 Peripheral and tests RTN=2, +# FT=2, skips 2 subevents in the peripheral +simulation_id="connected_iso_acl_first_ft_per_skip_2_se" +verbosity_level=2 +EXECUTE_TIMEOUT=60 + +cd ${BSIM_OUT_PATH}/bin + +Execute ./bs_${BOARD}_tests_bsim_bluetooth_ll_cis_prj_conf_overlay-acl_first_ft_per_skip_2_se_conf \ + -v=${verbosity_level} -s=${simulation_id} -d=0 -testid=central + +Execute ./bs_${BOARD}_tests_bsim_bluetooth_ll_cis_prj_conf_overlay-acl_first_ft_per_skip_2_se_conf \ + -v=${verbosity_level} -s=${simulation_id} -d=1 -testid=peripheral + +Execute ./bs_2G4_phy_v1 -v=${verbosity_level} -s=${simulation_id} \ + -D=2 -sim_length=30e6 $@ + +wait_for_background_jobs diff --git a/tests/bsim/bluetooth/ll/compile.sh b/tests/bsim/bluetooth/ll/compile.sh index 2369192e0cc..28ca40b322c 100755 --- a/tests/bsim/bluetooth/ll/compile.sh +++ b/tests/bsim/bluetooth/ll/compile.sh @@ -39,6 +39,7 @@ app=tests/bsim/bluetooth/ll/cis conf_overlay=overlay-legacy_adv_acl_first.conf c app=tests/bsim/bluetooth/ll/cis conf_overlay=overlay-acl_group.conf compile app=tests/bsim/bluetooth/ll/cis conf_overlay=overlay-acl_group_acl_first.conf compile app=tests/bsim/bluetooth/ll/cis conf_overlay=overlay-peripheral_cis.conf compile +app=tests/bsim/bluetooth/ll/cis conf_overlay=overlay-acl_first_ft_per_skip_2_se.conf compile app=tests/bsim/bluetooth/ll/edtt/hci_test_app \ conf_file=prj_dut_llcp.conf compile From 5e04a9f2a3a99b319901d0eca3cdc361c75acc45 Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Fri, 4 Aug 2023 14:04:35 +0530 Subject: [PATCH 277/421] [nrf fromtree] tests: bsim: Bluetooth: Test RTN=2, FT=2, Cen skip 2 SE in Controller Test RTN=2, FT=2 in Controller with 2 subevents dropped by central. Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit 291cd03818e909c20fed720c4773c82c2eabbd71) Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit b6158c0004470aeca9c36a7bf4eb04193d0fa3d0) --- .../ll_sw/nordic/lll/lll_central_iso.c | 9 +- tests/bsim/bluetooth/ll/cis/Kconfig | 13 ++ .../overlay-acl_first_ft_cen_skip_2_se.conf | 9 ++ tests/bsim/bluetooth/ll/cis/src/main.c | 114 +++++++++++++++++- ...onnected_iso_acl_first_ft_cen_skip_2_se.sh | 24 ++++ tests/bsim/bluetooth/ll/compile.sh | 2 + 6 files changed, 164 insertions(+), 7 deletions(-) create mode 100644 tests/bsim/bluetooth/ll/cis/overlay-acl_first_ft_cen_skip_2_se.conf create mode 100755 tests/bsim/bluetooth/ll/cis/tests_scripts/connected_iso_acl_first_ft_cen_skip_2_se.sh diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_central_iso.c b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_central_iso.c index 4bf44a42cd9..9c2184b9942 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_central_iso.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_central_iso.c @@ -674,7 +674,14 @@ static void isr_rx(void *param) cis_lll = param; /* No Rx */ - if (!trx_done) { + if (!trx_done || +#if defined(CONFIG_TEST_FT_CEN_SKIP_SUBEVENTS) + ((((cis_lll->event_count % 3U) < CONFIG_TEST_FT_CEN_SKIP_EVENTS_COUNT) && + ((se_curr > cis_lll->nse) || (se_curr <= 2U))) || + (((cis_lll->event_count % 3U) < (CONFIG_TEST_FT_CEN_SKIP_EVENTS_COUNT + 1U)) && + ((se_curr > cis_lll->nse) || (se_curr <= 1U)))) || +#endif + false) { payload_count_flush(cis_lll); goto isr_rx_next_subevent; diff --git a/tests/bsim/bluetooth/ll/cis/Kconfig b/tests/bsim/bluetooth/ll/cis/Kconfig index 532a26f5d52..6076f88ae3c 100644 --- a/tests/bsim/bluetooth/ll/cis/Kconfig +++ b/tests/bsim/bluetooth/ll/cis/Kconfig @@ -35,6 +35,19 @@ config TEST_FT_PER_SKIP_EVENTS_COUNT help Skip peripheral ISO events count where all subevents are skipped. +config TEST_FT_CEN_SKIP_SUBEVENTS + bool "Skip central role subevents to test Flush Timeout" + select TEST_FT_SKIP_SUBEVENTS + help + Skip central role subevent reception to test flush timeout + implementation. + +config TEST_FT_CEN_SKIP_EVENTS_COUNT + int "Skip central ISO events count, all subevents in them" + depends on TEST_FT_CEN_SKIP_SUBEVENTS + help + Skip central ISO events count where all subevents are skipped. + config BT_CTLR_SCAN_UNRESERVED default y if TEST_CONNECT_ACL_FIRST help diff --git a/tests/bsim/bluetooth/ll/cis/overlay-acl_first_ft_cen_skip_2_se.conf b/tests/bsim/bluetooth/ll/cis/overlay-acl_first_ft_cen_skip_2_se.conf new file mode 100644 index 00000000000..194a23ffec6 --- /dev/null +++ b/tests/bsim/bluetooth/ll/cis/overlay-acl_first_ft_cen_skip_2_se.conf @@ -0,0 +1,9 @@ +CONFIG_TEST_USE_LEGACY_ADVERTISING=n +CONFIG_TEST_CONNECT_ACL_FIRST=y +CONFIG_TEST_FT_CEN_SKIP_SUBEVENTS=y +CONFIG_TEST_FT_CEN_SKIP_EVENTS_COUNT=1 +CONFIG_BT_MAX_CONN=1 +CONFIG_BT_ISO_MAX_CHAN=1 +CONFIG_BT_CTLR_LLCP_LOCAL_PROC_CTX_BUF_NUM=9 +CONFIG_BT_CTLR_ADVANCED_FEATURES=y +CONFIG_BT_CTLR_ISOAL_PSN_IGNORE=y diff --git a/tests/bsim/bluetooth/ll/cis/src/main.c b/tests/bsim/bluetooth/ll/cis/src/main.c index 720adc16ef9..15e102981d6 100644 --- a/tests/bsim/bluetooth/ll/cis/src/main.c +++ b/tests/bsim/bluetooth/ll/cis/src/main.c @@ -296,15 +296,19 @@ static void iso_recv(struct bt_iso_chan *chan, const struct bt_iso_recv_info *in seq_num = sys_get_le32(buf->data); if (info->flags & BT_ISO_FLAGS_VALID) { if (seq_num != expected_seq_num[index]) { - FAIL("ISO data miss match, expected %u actual %u\n", - expected_seq_num[index], seq_num); + if (expected_seq_num[index]) { + FAIL("ISO data miss match, expected %u actual %u\n", + expected_seq_num[index], seq_num); + } expected_seq_num[index] = seq_num; } expected_seq_num[index] += 1U; -#if defined(CONFIG_TEST_FT_SKIP_SUBEVENTS) +#if defined(CONFIG_TEST_FT_PER_SKIP_SUBEVENTS) expected_seq_num[index] += ((CONFIG_TEST_FT_PER_SKIP_EVENTS_COUNT - 1U) * 2U); +#elif defined(CONFIG_TEST_FT_CEN_SKIP_SUBEVENTS) + expected_seq_num[index] += ((CONFIG_TEST_FT_CEN_SKIP_EVENTS_COUNT - 1U) * 2U); #endif } else if (expected_seq_num[index] && expected_seq_num[index] < SEQ_NUM_MAX) { @@ -342,6 +346,7 @@ static struct bt_iso_chan_ops iso_ops = { static void test_cis_central(void) { struct bt_iso_chan_io_qos iso_tx[CONFIG_BT_ISO_MAX_CHAN]; + struct bt_iso_chan_io_qos iso_rx[CONFIG_BT_ISO_MAX_CHAN]; struct bt_iso_chan_qos iso_qos[CONFIG_BT_ISO_MAX_CHAN]; struct bt_iso_chan *channels[CONFIG_BT_ISO_MAX_CHAN]; struct bt_conn *conn_list[CONFIG_BT_MAX_CONN]; @@ -372,8 +377,27 @@ static void test_cis_central(void) } iso_tx[i].path = NULL; - iso_qos[i].tx = &iso_tx[i]; - iso_qos[i].rx = NULL; + if (!IS_ENABLED(CONFIG_TEST_FT_SKIP_SUBEVENTS) || + IS_ENABLED(CONFIG_TEST_FT_PER_SKIP_SUBEVENTS)) { + iso_qos[i].tx = &iso_tx[i]; + } else { + iso_qos[i].tx = NULL; + } + + iso_rx[i].sdu = CONFIG_BT_ISO_RX_MTU; + iso_rx[i].phy = BT_GAP_LE_PHY_2M; + if (IS_ENABLED(CONFIG_TEST_FT_SKIP_SUBEVENTS)) { + iso_rx[i].rtn = 2U; + } else { + iso_rx[i].rtn = 0U; + } + iso_rx[i].path = NULL; + + if (IS_ENABLED(CONFIG_TEST_FT_CEN_SKIP_SUBEVENTS)) { + iso_qos[i].rx = &iso_rx[i]; + } else { + iso_qos[i].rx = NULL; + } iso_chan[i].ops = &iso_ops; iso_chan[i].qos = &iso_qos[i]; @@ -406,6 +430,12 @@ static void test_cis_central(void) conn_count = 0U; +#if defined(CONFIG_TEST_FT_CEN_SKIP_SUBEVENTS) + for (uint8_t chan = 0U; chan < CONFIG_BT_ISO_MAX_CHAN; chan++) { + expected_seq_num[chan] = (CONFIG_TEST_FT_CEN_SKIP_EVENTS_COUNT - 1U) * 2U; + } +#endif + #if !defined(CONFIG_TEST_MULTIPLE_PERIPERAL_CIS) for (int i = 0; i < CONFIG_BT_MAX_CONN; i++) { #else @@ -493,6 +523,7 @@ static void test_cis_central(void) printk("connected to peer %d ISO channel.\n", chan); } +#if !defined(CONFIG_TEST_FT_SKIP_SUBEVENTS) || defined(CONFIG_TEST_FT_PER_SKIP_SUBEVENTS) for (uint16_t seq_num = 0U; seq_num < SEQ_NUM_MAX; seq_num++) { for (uint8_t chan = 0U; chan < CONFIG_BT_ISO_MAX_CHAN; chan++) { @@ -535,6 +566,9 @@ static void test_cis_central(void) } k_sleep(K_MSEC(1000)); +#else + k_sleep(K_SECONDS(11)); +#endif for (uint8_t chan = 0U; chan < CONFIG_BT_ISO_MAX_CHAN; chan++) { printk("ISO disconnect channel %u...", chan); @@ -573,6 +607,16 @@ static void test_cis_central(void) } #endif +#if defined(CONFIG_TEST_FT_CEN_SKIP_SUBEVENTS) + for (uint8_t chan = 0U; chan < CONFIG_BT_ISO_MAX_CHAN; chan++) { + if (expected_seq_num[chan] < SEQ_NUM_MAX) { + FAIL("ISO Data reception incomplete %u (%u).\n", + expected_seq_num[chan], SEQ_NUM_MAX); + return; + } + } +#endif + PASS("Central ISO tests Passed\n"); } @@ -613,6 +657,7 @@ static struct bt_iso_server iso_server = { static void test_cis_peripheral(void) { + struct bt_iso_chan_io_qos iso_tx_p[CONFIG_BT_ISO_MAX_CHAN]; int err; printk("Bluetooth initializing..."); @@ -624,7 +669,18 @@ static void test_cis_peripheral(void) printk("success.\n"); for (int i = 0; i < CONFIG_BT_ISO_MAX_CHAN; i++) { - iso_rx_p[i].sdu = CONFIG_BT_ISO_TX_MTU; + iso_tx_p[i].sdu = CONFIG_BT_ISO_TX_MTU; + iso_tx_p[i].phy = BT_GAP_LE_PHY_2M; + if (IS_ENABLED(CONFIG_TEST_FT_SKIP_SUBEVENTS)) { + iso_tx_p[i].rtn = 2U; + } else { + iso_tx_p[i].rtn = 0U; + } + iso_tx_p[i].path = NULL; + + iso_qos_p[i].tx = &iso_tx_p[i]; + + iso_rx_p[i].sdu = CONFIG_BT_ISO_RX_MTU; iso_qos_p[i].rx = &iso_rx_p[i]; @@ -698,7 +754,51 @@ static void test_cis_peripheral(void) #if defined(CONFIG_TEST_MULTIPLE_PERIPERAL_CIS) } +#endif + +#if defined(CONFIG_TEST_FT_CEN_SKIP_SUBEVENTS) + for (uint16_t seq_num = 0U; seq_num < SEQ_NUM_MAX; seq_num++) { + for (uint8_t chan = 0U; chan < CONFIG_BT_ISO_MAX_CHAN; chan++) { + uint8_t iso_data[CONFIG_BT_ISO_TX_MTU] = { 0, }; + struct net_buf *buf; + int ret; + buf = net_buf_alloc(&tx_pool, + K_MSEC(BUF_ALLOC_TIMEOUT)); + if (!buf) { + FAIL("Data buffer allocate timeout on channel" + " %u\n", chan); + return; + } + net_buf_reserve(buf, BT_ISO_CHAN_SEND_RESERVE); + sys_put_le32(seq_num, iso_data); + net_buf_add_mem(buf, iso_data, sizeof(iso_data)); + + ret = k_sem_take(&sem_iso_data, + K_MSEC(BUF_ALLOC_TIMEOUT)); + if (ret) { + FAIL("k_sem_take for ISO data sent failed.\n"); + return; + } + + printk("ISO send: seq_num %u, chan %u\n", seq_num, chan); + ret = bt_iso_chan_send(&iso_chan_p[chan], buf, + seq_num, BT_ISO_TIMESTAMP_NONE); + if (ret < 0) { + FAIL("Unable to send data on channel %u" + " : %d\n", chan, ret); + net_buf_unref(buf); + return; + } + } + + if ((seq_num % 100) == 0) { + printk("Sending value %u\n", seq_num); + } + } +#endif + +#if defined(CONFIG_TEST_MULTIPLE_PERIPERAL_CIS) for (uint8_t chan = 0U; chan < CONFIG_BT_ISO_MAX_CHAN; chan++) { #endif @@ -722,6 +822,7 @@ static void test_cis_peripheral(void) } printk("disconnected from peer device.\n"); +#if !defined(CONFIG_TEST_FT_SKIP_SUBEVENTS) || defined(CONFIG_TEST_FT_PER_SKIP_SUBEVENTS) #if defined(CONFIG_TEST_MULTIPLE_PERIPERAL_CIS) for (uint8_t chan = 0U; chan < CONFIG_BT_ISO_MAX_CHAN; chan++) { #else @@ -734,6 +835,7 @@ static void test_cis_peripheral(void) } #if defined(CONFIG_TEST_MULTIPLE_PERIPERAL_CIS) } +#endif #endif PASS("Peripheral ISO tests Passed\n"); diff --git a/tests/bsim/bluetooth/ll/cis/tests_scripts/connected_iso_acl_first_ft_cen_skip_2_se.sh b/tests/bsim/bluetooth/ll/cis/tests_scripts/connected_iso_acl_first_ft_cen_skip_2_se.sh new file mode 100755 index 00000000000..04ce474e812 --- /dev/null +++ b/tests/bsim/bluetooth/ll/cis/tests_scripts/connected_iso_acl_first_ft_cen_skip_2_se.sh @@ -0,0 +1,24 @@ +#!/usr/bin/env bash +# Copyright 2020 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +source ${ZEPHYR_BASE}/tests/bsim/sh_common.source + +# Basic Connected ISO test: a Central connects to 1 Peripheral and tests RTN=2, +# FT=2, skips 2 subevents in the central +simulation_id="connected_iso_acl_first_ft_cen_skip_2_se" +verbosity_level=2 +EXECUTE_TIMEOUT=60 + +cd ${BSIM_OUT_PATH}/bin + +Execute ./bs_${BOARD}_tests_bsim_bluetooth_ll_cis_prj_conf_overlay-acl_first_ft_cen_skip_2_se_conf \ + -v=${verbosity_level} -s=${simulation_id} -d=0 -testid=central + +Execute ./bs_${BOARD}_tests_bsim_bluetooth_ll_cis_prj_conf_overlay-acl_first_ft_cen_skip_2_se_conf \ + -v=${verbosity_level} -s=${simulation_id} -d=1 -testid=peripheral + +Execute ./bs_2G4_phy_v1 -v=${verbosity_level} -s=${simulation_id} \ + -D=2 -sim_length=30e6 $@ + +wait_for_background_jobs diff --git a/tests/bsim/bluetooth/ll/compile.sh b/tests/bsim/bluetooth/ll/compile.sh index 28ca40b322c..6d530d05d72 100755 --- a/tests/bsim/bluetooth/ll/compile.sh +++ b/tests/bsim/bluetooth/ll/compile.sh @@ -40,6 +40,8 @@ app=tests/bsim/bluetooth/ll/cis conf_overlay=overlay-acl_group.conf compile app=tests/bsim/bluetooth/ll/cis conf_overlay=overlay-acl_group_acl_first.conf compile app=tests/bsim/bluetooth/ll/cis conf_overlay=overlay-peripheral_cis.conf compile app=tests/bsim/bluetooth/ll/cis conf_overlay=overlay-acl_first_ft_per_skip_2_se.conf compile +app=tests/bsim/bluetooth/ll/cis conf_overlay=overlay-acl_first_ft_per_skip_4_se.conf compile +app=tests/bsim/bluetooth/ll/cis conf_overlay=overlay-acl_first_ft_cen_skip_2_se.conf compile app=tests/bsim/bluetooth/ll/edtt/hci_test_app \ conf_file=prj_dut_llcp.conf compile From a96ce9920c747042b8d5bd3a86c2a854c8e49706 Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Wed, 27 Sep 2023 11:21:26 +0200 Subject: [PATCH 278/421] [nrf fromtree] Bluetooth: Controller: Review rework flush timeout support Review rework changed related to flush timeout support. Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit a178aa9855bd9f9f33d822f95d0eb0c3a35ab26c) Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit 95d12af31a5afb5eef80546b43e9739227471cd7) --- subsys/bluetooth/controller/hci/hci.c | 44 +++- .../bluetooth/controller/ll_sw/lll_conn_iso.h | 28 ++- .../ll_sw/nordic/lll/lll_central_iso.c | 19 +- .../ll_sw/nordic/lll/lll_peripheral_iso.c | 8 + tests/bsim/bluetooth/ll/cis/src/main.c | 206 +++++++++--------- ...onnected_iso_acl_first_ft_cen_skip_2_se.sh | 2 +- ...onnected_iso_acl_first_ft_per_skip_2_se.sh | 2 +- 7 files changed, 181 insertions(+), 128 deletions(-) diff --git a/subsys/bluetooth/controller/hci/hci.c b/subsys/bluetooth/controller/hci/hci.c index b2c95271b2c..c3dd070720b 100644 --- a/subsys/bluetooth/controller/hci/hci.c +++ b/subsys/bluetooth/controller/hci/hci.c @@ -5762,6 +5762,18 @@ int hci_iso_handle(struct net_buf *buf, struct net_buf **evt) /* Catch up local pkt_seq_num with internal pkt_seq_num */ event_count = cis->lll.event_count; pkt_seq_num = event_count + 1U; + /* If pb_flag is BT_ISO_START (0b00) or BT_ISO_SINGLE (0b10) + * then we simply check that the pb_flag is an even value, and + * then pkt_seq_num is a future sequence number value compare + * to last recorded number in cis->pkt_seq_num. + * + * When (pkt_seq_num - stream->pkt_seq_num) is negative then + * BIT64(39) will be set (2's compliment value). The diff value + * less than or equal to BIT64_MASK(38) means the diff value is + * positive and hence pkt_seq_num is greater than + * stream->pkt_seq_num. This calculation is valid for when value + * rollover too. + */ if (!(pb_flag & 0x01) && (((pkt_seq_num - cis->pkt_seq_num) & BIT64_MASK(39)) <= BIT64_MASK(38))) { @@ -5770,12 +5782,17 @@ int hci_iso_handle(struct net_buf *buf, struct net_buf **evt) pkt_seq_num = cis->pkt_seq_num; } - /* Pre-increment, for next ISO data packet seq num comparison */ + /* Pre-increment, when pg_flag is BT_ISO_SINGLE (0b10) or + * BT_ISO_END (0b11) then we simple check if pb_flag has bit 1 + * is set, for next ISO data packet seq num comparison. + */ if (pb_flag & 0x10) { cis->pkt_seq_num++; } - /* Target next event to avoid overlapping with current event */ + /* Target next ISO event to avoid overlapping with, if any, + * current ISO event + */ pkt_seq_num++; sdu_frag_tx.target_event = pkt_seq_num; sdu_frag_tx.grp_ref_point = @@ -5817,7 +5834,7 @@ int hci_iso_handle(struct net_buf *buf, struct net_buf **evt) #endif /* !CONFIG_BT_CTLR_ISOAL_PSN_IGNORE */ /* Get controller's input data path for CIS */ - hdr = &(cis->hdr); + hdr = &cis->hdr; dp_in = hdr->datapath_in; if (!dp_in || dp_in->path_id != BT_HCI_DATAPATH_ID_HCI) { LOG_ERR("Input data path not set for HCI"); @@ -5884,6 +5901,18 @@ int hci_iso_handle(struct net_buf *buf, struct net_buf **evt) /* Catch up local pkt_seq_num with internal pkt_seq_num */ event_count = lll_iso->payload_count / lll_iso->bn; pkt_seq_num = event_count; + /* If pb_flag is BT_ISO_START (0b00) or BT_ISO_SINGLE (0b10) + * then we simply check that the pb_flag is an even value, and + * then pkt_seq_num is a future sequence number value compare + * to last recorded number in cis->pkt_seq_num. + * + * When (pkt_seq_num - stream->pkt_seq_num) is negative then + * BIT64(39) will be set (2's compliment value). The diff value + * less than or equal to BIT64_MASK(38) means the diff value is + * positive and hence pkt_seq_num is greater than + * stream->pkt_seq_num. This calculation is valid for when value + * rollover too. + */ if (!(pb_flag & 0x01) && (((pkt_seq_num - stream->pkt_seq_num) & BIT64_MASK(39)) <= BIT64_MASK(38))) { @@ -5892,12 +5921,17 @@ int hci_iso_handle(struct net_buf *buf, struct net_buf **evt) pkt_seq_num = stream->pkt_seq_num; } - /* Pre-increment, for next ISO data packet seq num comparison */ + /* Pre-increment, when pg_flag is BT_ISO_SINGLE (0b10) or + * BT_ISO_END (0b11) then we simple check if pb_flag has bit 1 + * is set, for next ISO data packet seq num comparison. + */ if (pb_flag & 0x10) { stream->pkt_seq_num++; } - /* Target next event to avoid overlapping with current event */ + /* Target next ISO event to avoid overlapping with, if any, + * current ISO event + */ /* FIXME: Implement ISO Tx ack generation early in done compared * to currently only in prepare. I.e. to ensure upper * layer has the number of completed packet before the diff --git a/subsys/bluetooth/controller/ll_sw/lll_conn_iso.h b/subsys/bluetooth/controller/ll_sw/lll_conn_iso.h index 0321b96f638..8a85ca7c6c9 100644 --- a/subsys/bluetooth/controller/ll_sw/lll_conn_iso.h +++ b/subsys/bluetooth/controller/ll_sw/lll_conn_iso.h @@ -15,8 +15,10 @@ struct lll_conn_iso_stream_rxtx { uint64_t ft:8; /* Flush timeout (FT) */ uint64_t bn:4; /* Burst number (BN) */ uint64_t phy:3; /* PHY */ - uint64_t rfu:1; - uint8_t bn_curr:4; /* Current burst number */ + uint64_t rfu0:1; + + uint8_t bn_curr:4; /* Current burst number */ + uint8_t rfu1:4; #if defined(CONFIG_BT_CTLR_LE_ENC) struct ccm ccm; @@ -73,20 +75,26 @@ struct lll_conn_iso_group { struct lll_hdr hdr; uint16_t handle; /* CIG handle (internal) */ - uint8_t num_cis:5; /* Number of CISes in this CIG */ - uint8_t role:1; /* 0: CENTRAL, 1: PERIPHERAL*/ - uint8_t paused:1; /* 1: CIG is paused */ - /* ISO interval to calculate timestamp under FT > 1 */ - uint32_t iso_interval_us; + /* Resumption information */ + uint16_t resume_cis; /* CIS handle to schedule at resume */ + + /* ISO group information */ + uint32_t num_cis:5; /* Number of CISes in this CIG */ + uint32_t role:1; /* 0: CENTRAL, 1: PERIPHERAL*/ + uint32_t paused:1; /* 1: CIG is paused */ + uint32_t rfu0:1; + + /* ISO interval to calculate timestamp under FT > 1, + * maximum ISO interval of 4 seconds can be represented in 22-bits. + */ + uint32_t iso_interval_us:22; + uint32_t rfu1:2; /* Accumulates LLL prepare callback latencies */ uint16_t latency_prepare; uint16_t latency_event; - /* Resumption information */ - uint16_t resume_cis; /* CIS handle to schedule at resume */ - #if defined(CONFIG_BT_CTLR_PERIPHERAL_ISO) /* Window widening. Relies on vendor specific conversion macros, e.g. * EVENT_US_FRAC_TO_TICKS(). diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_central_iso.c b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_central_iso.c index 9c2184b9942..751c3915fc2 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_central_iso.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_central_iso.c @@ -48,7 +48,7 @@ static void isr_prepare_subevent(void *param); static void isr_done(void *param); static void payload_count_flush(struct lll_conn_iso_stream *cis_lll); static void payload_count_flush_or_inc_on_close(struct lll_conn_iso_stream *cis_lll); -static void payload_count_lazy(struct lll_conn_iso_stream *cis_lll, uint16_t lazy); +static void payload_count_lazy_update(struct lll_conn_iso_stream *cis_lll, uint16_t lazy); static uint16_t next_cis_chan_remap_idx; static uint16_t next_cis_chan_prn_s; @@ -183,7 +183,7 @@ static int prepare_cb(struct lll_prepare_param *p) se_curr = 1U; /* Adjust the SN and NESN for skipped CIG events */ - payload_count_lazy(cis_lll, lazy); + payload_count_lazy_update(cis_lll, lazy); /* Start setting up of Radio h/w */ radio_reset(); @@ -370,7 +370,7 @@ static int prepare_cb(struct lll_prepare_param *p) cis_lll = ull_conn_iso_lll_stream_get_by_group(cig_lll, &cis_handle); if (cis_lll && cis_lll->active) { /* Adjust sn and nesn for skipped CIG events */ - payload_count_lazy(cis_lll, lazy); + payload_count_lazy_update(cis_lll, lazy); /* Adjust sn and nesn for canceled events */ if (err) { @@ -676,11 +676,20 @@ static void isr_rx(void *param) /* No Rx */ if (!trx_done || #if defined(CONFIG_TEST_FT_CEN_SKIP_SUBEVENTS) + /* Used by test code, + * to skip a number of events in every 3 event count when current subevent is less than + * or equal to 2 or when current subevent has completed all its NSE number of subevents. + * OR + * to skip a (number + 1) of events in every 3 event count when current subevent is less + * than or equal to 1 or when current subevent has completed all its NSE number of + * subevents. + */ ((((cis_lll->event_count % 3U) < CONFIG_TEST_FT_CEN_SKIP_EVENTS_COUNT) && ((se_curr > cis_lll->nse) || (se_curr <= 2U))) || + (((cis_lll->event_count % 3U) < (CONFIG_TEST_FT_CEN_SKIP_EVENTS_COUNT + 1U)) && ((se_curr > cis_lll->nse) || (se_curr <= 1U)))) || -#endif +#endif /* CONFIG_TEST_FT_CEN_SKIP_SUBEVENTS */ false) { payload_count_flush(cis_lll); @@ -1230,7 +1239,7 @@ static void payload_count_flush_or_inc_on_close(struct lll_conn_iso_stream *cis_ } } -static void payload_count_lazy(struct lll_conn_iso_stream *cis_lll, uint16_t lazy) +static void payload_count_lazy_update(struct lll_conn_iso_stream *cis_lll, uint16_t lazy) { if (cis_lll->tx.bn) { uint16_t tx_lazy; diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_peripheral_iso.c b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_peripheral_iso.c index c33c82d4c70..27ed4d1e42c 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_peripheral_iso.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_peripheral_iso.c @@ -474,6 +474,14 @@ static void isr_rx(void *param) /* No Rx */ if (!trx_done || #if defined(CONFIG_TEST_FT_PER_SKIP_SUBEVENTS) + /* Used by test code, + * to skip a number of events in every 3 event count when current subevent is less than + * or equal to 2 or when current subevent has completed all its NSE number of subevents. + * OR + * to skip a (number + 1) of events in every 3 event count when current subevent is less + * than or equal to 1 or when current subevent has completed all its NSE number of + * subevents. + */ ((((cis_lll->event_count % 3U) < CONFIG_TEST_FT_PER_SKIP_EVENTS_COUNT) && ((se_curr > cis_lll->nse) || (se_curr <= 2U))) || (((cis_lll->event_count % 3U) < (CONFIG_TEST_FT_PER_SKIP_EVENTS_COUNT + 1U)) && diff --git a/tests/bsim/bluetooth/ll/cis/src/main.c b/tests/bsim/bluetooth/ll/cis/src/main.c index 15e102981d6..b544546a404 100644 --- a/tests/bsim/bluetooth/ll/cis/src/main.c +++ b/tests/bsim/bluetooth/ll/cis/src/main.c @@ -352,7 +352,7 @@ static void test_cis_central(void) struct bt_conn *conn_list[CONFIG_BT_MAX_CONN]; struct bt_iso_cig_param cig_param; struct bt_iso_cig *cig; - uint8_t conn_count; + int conn_count; int err; printk("Bluetooth initializing..."); @@ -370,12 +370,12 @@ static void test_cis_central(void) for (int i = 0; i < CONFIG_BT_ISO_MAX_CHAN; i++) { iso_tx[i].sdu = CONFIG_BT_ISO_TX_MTU; iso_tx[i].phy = BT_GAP_LE_PHY_2M; + iso_tx[i].path = NULL; if (IS_ENABLED(CONFIG_TEST_FT_SKIP_SUBEVENTS)) { iso_tx[i].rtn = 2U; } else { iso_tx[i].rtn = 0U; } - iso_tx[i].path = NULL; if (!IS_ENABLED(CONFIG_TEST_FT_SKIP_SUBEVENTS) || IS_ENABLED(CONFIG_TEST_FT_PER_SKIP_SUBEVENTS)) { @@ -386,12 +386,12 @@ static void test_cis_central(void) iso_rx[i].sdu = CONFIG_BT_ISO_RX_MTU; iso_rx[i].phy = BT_GAP_LE_PHY_2M; + iso_rx[i].path = NULL; if (IS_ENABLED(CONFIG_TEST_FT_SKIP_SUBEVENTS)) { iso_rx[i].rtn = 2U; } else { iso_rx[i].rtn = 0U; } - iso_rx[i].path = NULL; if (IS_ENABLED(CONFIG_TEST_FT_CEN_SKIP_SUBEVENTS)) { iso_qos[i].rx = &iso_rx[i]; @@ -413,12 +413,12 @@ static void test_cis_central(void) cig_param.sca = BT_GAP_SCA_UNKNOWN; cig_param.packing = 0U; cig_param.framing = 0U; + cig_param.interval = ISO_INTERVAL_US; if (IS_ENABLED(CONFIG_TEST_FT_SKIP_SUBEVENTS)) { cig_param.latency = ISO_LATENCY_FT_MS; } else { cig_param.latency = ISO_LATENCY_MS; } - cig_param.interval = ISO_INTERVAL_US; printk("Create CIG..."); err = bt_iso_cig_create(&cig_param, &cig); @@ -428,10 +428,10 @@ static void test_cis_central(void) } printk("success.\n"); - conn_count = 0U; + conn_count = 0; #if defined(CONFIG_TEST_FT_CEN_SKIP_SUBEVENTS) - for (uint8_t chan = 0U; chan < CONFIG_BT_ISO_MAX_CHAN; chan++) { + for (int chan = 0; chan < CONFIG_BT_ISO_MAX_CHAN; chan++) { expected_seq_num[chan] = (CONFIG_TEST_FT_CEN_SKIP_EVENTS_COUNT - 1U) * 2U; } #endif @@ -443,8 +443,8 @@ static void test_cis_central(void) #endif struct bt_conn *conn; - uint8_t conn_index; - uint8_t chan; + int conn_index; + int chan; printk("Start scanning (%d)...", i); err = bt_le_scan_start(BT_LE_SCAN_CUSTOM, NULL); @@ -494,12 +494,12 @@ static void test_cis_central(void) #if defined(CONFIG_TEST_CONNECT_ACL_FIRST) } - for (uint8_t chan = 0U, conn_index = 0U; + for (int chan = 0, conn_index = 0; (conn_index < conn_count) && (chan < CONFIG_BT_ISO_MAX_CHAN); conn_index++, chan++) { #elif defined(CONFIG_TEST_MULTIPLE_PERIPERAL_CIS) - for (uint8_t chan = 0U, conn_index = 0U; + for (int chan = 0, conn_index = 0; (chan < CONFIG_BT_ISO_MAX_CHAN); chan++) { #endif @@ -523,70 +523,67 @@ static void test_cis_central(void) printk("connected to peer %d ISO channel.\n", chan); } -#if !defined(CONFIG_TEST_FT_SKIP_SUBEVENTS) || defined(CONFIG_TEST_FT_PER_SKIP_SUBEVENTS) - for (uint16_t seq_num = 0U; seq_num < SEQ_NUM_MAX; seq_num++) { - - for (uint8_t chan = 0U; chan < CONFIG_BT_ISO_MAX_CHAN; chan++) { - uint8_t iso_data[CONFIG_BT_ISO_TX_MTU] = { 0, }; - struct net_buf *buf; - int ret; - - buf = net_buf_alloc(&tx_pool, - K_MSEC(BUF_ALLOC_TIMEOUT)); - if (!buf) { - FAIL("Data buffer allocate timeout on channel" - " %u\n", chan); - return; - } - net_buf_reserve(buf, BT_ISO_CHAN_SEND_RESERVE); - sys_put_le32(seq_num, iso_data); - net_buf_add_mem(buf, iso_data, sizeof(iso_data)); - - ret = k_sem_take(&sem_iso_data, - K_MSEC(BUF_ALLOC_TIMEOUT)); - if (ret) { - FAIL("k_sem_take for ISO data sent failed.\n"); - return; + if (!IS_ENABLED(CONFIG_TEST_FT_SKIP_SUBEVENTS) || + IS_ENABLED(CONFIG_TEST_FT_PER_SKIP_SUBEVENTS)) { + for (uint16_t seq_num = 0U; seq_num < SEQ_NUM_MAX; seq_num++) { + + for (int chan = 0; chan < CONFIG_BT_ISO_MAX_CHAN; chan++) { + uint8_t iso_data[CONFIG_BT_ISO_TX_MTU] = { 0, }; + struct net_buf *buf; + int ret; + + buf = net_buf_alloc(&tx_pool, K_MSEC(BUF_ALLOC_TIMEOUT)); + if (!buf) { + FAIL("Data buffer allocate timeout on channel %d\n", chan); + return; + } + + net_buf_reserve(buf, BT_ISO_CHAN_SEND_RESERVE); + sys_put_le16(seq_num, iso_data); + net_buf_add_mem(buf, iso_data, sizeof(iso_data)); + + ret = k_sem_take(&sem_iso_data, K_MSEC(BUF_ALLOC_TIMEOUT)); + if (ret) { + FAIL("k_sem_take for ISO data sent failed.\n"); + return; + } + + printk("ISO send: seq_num %u, chan %d\n", seq_num, chan); + ret = bt_iso_chan_send(&iso_chan[chan], buf, + seq_num, BT_ISO_TIMESTAMP_NONE); + if (ret < 0) { + FAIL("Unable to send data on channel %d : %d\n", chan, ret); + net_buf_unref(buf); + return; + } } - printk("ISO send: seq_num %u, chan %u\n", seq_num, chan); - ret = bt_iso_chan_send(&iso_chan[chan], buf, - seq_num, BT_ISO_TIMESTAMP_NONE); - if (ret < 0) { - FAIL("Unable to send data on channel %u" - " : %d\n", chan, ret); - net_buf_unref(buf); - return; + if ((seq_num % 100) == 0) { + printk("Sending value %u\n", seq_num); } } - if ((seq_num % 100) == 0) { - printk("Sending value %u\n", seq_num); - } + k_sleep(K_MSEC(1000)); + } else { + k_sleep(K_SECONDS(11)); } - k_sleep(K_MSEC(1000)); -#else - k_sleep(K_SECONDS(11)); -#endif - - for (uint8_t chan = 0U; chan < CONFIG_BT_ISO_MAX_CHAN; chan++) { - printk("ISO disconnect channel %u...", chan); + for (int chan = 0; chan < CONFIG_BT_ISO_MAX_CHAN; chan++) { + printk("ISO disconnect channel %d...", chan); err = bt_iso_chan_disconnect(&iso_chan[chan]); if (err) { - FAIL("Failed to disconnect channel %u (%d)\n", - chan, err); + FAIL("Failed to disconnect channel %d (%d)\n", chan, err); return; } printk("success\n"); - printk("Waiting for ISO channel disconnect %u...", chan); + printk("Waiting for ISO channel disconnect %d...", chan); err = k_sem_take(&sem_iso_disc, K_FOREVER); if (err) { FAIL("failed (err %d)\n", err); return; } - printk("disconnected to peer %u ISO channel.\n", chan); + printk("disconnected to peer %d ISO channel.\n", chan); } bt_conn_foreach(BT_CONN_TYPE_LE, disconnect, NULL); @@ -607,15 +604,15 @@ static void test_cis_central(void) } #endif -#if defined(CONFIG_TEST_FT_CEN_SKIP_SUBEVENTS) - for (uint8_t chan = 0U; chan < CONFIG_BT_ISO_MAX_CHAN; chan++) { - if (expected_seq_num[chan] < SEQ_NUM_MAX) { - FAIL("ISO Data reception incomplete %u (%u).\n", - expected_seq_num[chan], SEQ_NUM_MAX); - return; + if (IS_ENABLED(CONFIG_TEST_FT_CEN_SKIP_SUBEVENTS)) { + for (int chan = 0; chan < CONFIG_BT_ISO_MAX_CHAN; chan++) { + if (expected_seq_num[chan] < SEQ_NUM_MAX) { + FAIL("ISO Data reception incomplete %u (%u).\n", + expected_seq_num[chan], SEQ_NUM_MAX); + return; + } } } -#endif PASS("Central ISO tests Passed\n"); } @@ -671,12 +668,12 @@ static void test_cis_peripheral(void) for (int i = 0; i < CONFIG_BT_ISO_MAX_CHAN; i++) { iso_tx_p[i].sdu = CONFIG_BT_ISO_TX_MTU; iso_tx_p[i].phy = BT_GAP_LE_PHY_2M; + iso_tx_p[i].path = NULL; if (IS_ENABLED(CONFIG_TEST_FT_SKIP_SUBEVENTS)) { iso_tx_p[i].rtn = 2U; } else { iso_tx_p[i].rtn = 0U; } - iso_tx_p[i].path = NULL; iso_qos_p[i].tx = &iso_tx_p[i]; @@ -741,7 +738,7 @@ static void test_cis_peripheral(void) printk("connected to peer central.\n"); #if defined(CONFIG_TEST_MULTIPLE_PERIPERAL_CIS) - for (uint8_t chan = 0U; chan < CONFIG_BT_ISO_MAX_CHAN; chan++) { + for (int chan = 0; chan < CONFIG_BT_ISO_MAX_CHAN; chan++) { #endif printk("Waiting for ISO channel connection..."); @@ -756,50 +753,47 @@ static void test_cis_peripheral(void) } #endif -#if defined(CONFIG_TEST_FT_CEN_SKIP_SUBEVENTS) - for (uint16_t seq_num = 0U; seq_num < SEQ_NUM_MAX; seq_num++) { - for (uint8_t chan = 0U; chan < CONFIG_BT_ISO_MAX_CHAN; chan++) { - uint8_t iso_data[CONFIG_BT_ISO_TX_MTU] = { 0, }; - struct net_buf *buf; - int ret; - - buf = net_buf_alloc(&tx_pool, - K_MSEC(BUF_ALLOC_TIMEOUT)); - if (!buf) { - FAIL("Data buffer allocate timeout on channel" - " %u\n", chan); - return; - } - net_buf_reserve(buf, BT_ISO_CHAN_SEND_RESERVE); - sys_put_le32(seq_num, iso_data); - net_buf_add_mem(buf, iso_data, sizeof(iso_data)); - - ret = k_sem_take(&sem_iso_data, - K_MSEC(BUF_ALLOC_TIMEOUT)); - if (ret) { - FAIL("k_sem_take for ISO data sent failed.\n"); - return; + if (IS_ENABLED(CONFIG_TEST_FT_CEN_SKIP_SUBEVENTS)) { + for (uint16_t seq_num = 0U; seq_num < SEQ_NUM_MAX; seq_num++) { + for (int chan = 0; chan < CONFIG_BT_ISO_MAX_CHAN; chan++) { + uint8_t iso_data[CONFIG_BT_ISO_TX_MTU] = { 0, }; + struct net_buf *buf; + int ret; + + buf = net_buf_alloc(&tx_pool, K_MSEC(BUF_ALLOC_TIMEOUT)); + if (!buf) { + FAIL("Data buffer allocate timeout on channel %d\n", chan); + return; + } + + net_buf_reserve(buf, BT_ISO_CHAN_SEND_RESERVE); + sys_put_le16(seq_num, iso_data); + net_buf_add_mem(buf, iso_data, sizeof(iso_data)); + + ret = k_sem_take(&sem_iso_data, K_MSEC(BUF_ALLOC_TIMEOUT)); + if (ret) { + FAIL("k_sem_take for ISO data sent failed.\n"); + return; + } + + printk("ISO send: seq_num %u, chan %d\n", seq_num, chan); + ret = bt_iso_chan_send(&iso_chan_p[chan], buf, seq_num, + BT_ISO_TIMESTAMP_NONE); + if (ret < 0) { + FAIL("Unable to send data on channel %d : %d\n", chan, ret); + net_buf_unref(buf); + return; + } } - printk("ISO send: seq_num %u, chan %u\n", seq_num, chan); - ret = bt_iso_chan_send(&iso_chan_p[chan], buf, - seq_num, BT_ISO_TIMESTAMP_NONE); - if (ret < 0) { - FAIL("Unable to send data on channel %u" - " : %d\n", chan, ret); - net_buf_unref(buf); - return; + if ((seq_num % 100) == 0) { + printk("Sending value %u\n", seq_num); } } - - if ((seq_num % 100) == 0) { - printk("Sending value %u\n", seq_num); - } } -#endif #if defined(CONFIG_TEST_MULTIPLE_PERIPERAL_CIS) - for (uint8_t chan = 0U; chan < CONFIG_BT_ISO_MAX_CHAN; chan++) { + for (int chan = 0; chan < CONFIG_BT_ISO_MAX_CHAN; chan++) { #endif printk("Waiting for ISO channel disconnect..."); @@ -824,13 +818,13 @@ static void test_cis_peripheral(void) #if !defined(CONFIG_TEST_FT_SKIP_SUBEVENTS) || defined(CONFIG_TEST_FT_PER_SKIP_SUBEVENTS) #if defined(CONFIG_TEST_MULTIPLE_PERIPERAL_CIS) - for (uint8_t chan = 0U; chan < CONFIG_BT_ISO_MAX_CHAN; chan++) { + for (int chan = 0; chan < CONFIG_BT_ISO_MAX_CHAN; chan++) { #else - uint8_t chan = 0U; + int chan = 0; #endif if (expected_seq_num[chan] < SEQ_NUM_MAX) { - FAIL("ISO Data reception incomplete %u (%u).\n", - expected_seq_num[chan], SEQ_NUM_MAX); + FAIL("ISO Data reception incomplete %u (%u).\n", expected_seq_num[chan], + SEQ_NUM_MAX); return; } #if defined(CONFIG_TEST_MULTIPLE_PERIPERAL_CIS) diff --git a/tests/bsim/bluetooth/ll/cis/tests_scripts/connected_iso_acl_first_ft_cen_skip_2_se.sh b/tests/bsim/bluetooth/ll/cis/tests_scripts/connected_iso_acl_first_ft_cen_skip_2_se.sh index 04ce474e812..bb08f582574 100755 --- a/tests/bsim/bluetooth/ll/cis/tests_scripts/connected_iso_acl_first_ft_cen_skip_2_se.sh +++ b/tests/bsim/bluetooth/ll/cis/tests_scripts/connected_iso_acl_first_ft_cen_skip_2_se.sh @@ -1,5 +1,5 @@ #!/usr/bin/env bash -# Copyright 2020 Nordic Semiconductor ASA +# Copyright 2023 Nordic Semiconductor ASA # SPDX-License-Identifier: Apache-2.0 source ${ZEPHYR_BASE}/tests/bsim/sh_common.source diff --git a/tests/bsim/bluetooth/ll/cis/tests_scripts/connected_iso_acl_first_ft_per_skip_2_se.sh b/tests/bsim/bluetooth/ll/cis/tests_scripts/connected_iso_acl_first_ft_per_skip_2_se.sh index 307d865a117..84d3c5c4ed3 100755 --- a/tests/bsim/bluetooth/ll/cis/tests_scripts/connected_iso_acl_first_ft_per_skip_2_se.sh +++ b/tests/bsim/bluetooth/ll/cis/tests_scripts/connected_iso_acl_first_ft_per_skip_2_se.sh @@ -1,5 +1,5 @@ #!/usr/bin/env bash -# Copyright 2020 Nordic Semiconductor ASA +# Copyright 2023 Nordic Semiconductor ASA # SPDX-License-Identifier: Apache-2.0 source ${ZEPHYR_BASE}/tests/bsim/sh_common.source From 49afbcceeb53e75ca2be62e895b2b18bd5742993 Mon Sep 17 00:00:00 2001 From: Emil Gydesen Date: Tue, 3 Oct 2023 16:23:00 +0200 Subject: [PATCH 279/421] [nrf fromtree] Bluetooth: Controller: Remove unused terminate_ack Remove the terminate_ack from struct ll_conn since it is not used anywhere, and results in dead code. Signed-off-by: Emil Gydesen (cherry picked from commit 89db200117aa4d0604060d65318dcc0ab30b073d) Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit 233a142db54fb619749615eb3af4919dce59cc2e) --- subsys/bluetooth/controller/ll_sw/ull_central.c | 2 -- subsys/bluetooth/controller/ll_sw/ull_conn.c | 6 ------ subsys/bluetooth/controller/ll_sw/ull_conn_types.h | 1 - 3 files changed, 9 deletions(-) diff --git a/subsys/bluetooth/controller/ll_sw/ull_central.c b/subsys/bluetooth/controller/ll_sw/ull_central.c index b189c65fa21..7ea3c600ea6 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_central.c +++ b/subsys/bluetooth/controller/ll_sw/ull_central.c @@ -291,8 +291,6 @@ uint8_t ll_create_connection(uint16_t scan_interval, uint16_t scan_window, /* Setup the PRT reload */ ull_cp_prt_reload_set(conn, conn_interval_us); - conn->central.terminate_ack = 0U; - conn->llcp_terminate.reason_final = 0U; /* NOTE: use allocated link for generating dedicated * terminate ind rx node diff --git a/subsys/bluetooth/controller/ll_sw/ull_conn.c b/subsys/bluetooth/controller/ll_sw/ull_conn.c index 9d78af7acc1..1640c00e87e 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_conn.c +++ b/subsys/bluetooth/controller/ll_sw/ull_conn.c @@ -1044,12 +1044,6 @@ void ull_conn_done(struct node_rx_event_done *done) lll->latency_event = lll->latency; } #endif /* CONFIG_BT_PERIPHERAL */ - -#if defined(CONFIG_BT_CENTRAL) - } else if (reason_final) { - conn->central.terminate_ack = 1; -#endif /* CONFIG_BT_CENTRAL */ - } /* Reset connection failed to establish countdown */ diff --git a/subsys/bluetooth/controller/ll_sw/ull_conn_types.h b/subsys/bluetooth/controller/ll_sw/ull_conn_types.h index 12e16488f38..8fabab03378 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_conn_types.h +++ b/subsys/bluetooth/controller/ll_sw/ull_conn_types.h @@ -202,7 +202,6 @@ struct ll_conn { #if defined(CONFIG_BT_CTLR_CONN_META) uint8_t is_must_expire:1; #endif /* CONFIG_BT_CTLR_CONN_META */ - uint8_t terminate_ack:1; } central; #endif /* CONFIG_BT_CENTRAL */ }; From 5e6ae9f1a206335f50da010532f106693e189ffa Mon Sep 17 00:00:00 2001 From: Emil Gydesen Date: Tue, 3 Oct 2023 23:42:09 +0200 Subject: [PATCH 280/421] [nrf fromtree] Bluetooth: Controll: Fix dead code in ll_setup_iso_path In ll_setup_iso_path cis is only ever set if CONFIG_BT_CTLR_CONN_ISO is enabled, and similarly adv_stream is only ever set if CONFIG_BT_CTLR_ADV_ISO is enabled. The two assignments were reported as dead code by Coverity due to this, which has been fixed by guarding the code with the respective Kconfigs. Signed-off-by: Emil Gydesen (cherry picked from commit c6cecef12058b96ce9fe62b549e407c6b7c20949) Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit 512beaac5f83999ef76cc08c285d1ab479eccab1) --- subsys/bluetooth/controller/ll_sw/ull_iso.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/subsys/bluetooth/controller/ll_sw/ull_iso.c b/subsys/bluetooth/controller/ll_sw/ull_iso.c index 70d018e7e0c..b21a9d20721 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_iso.c +++ b/subsys/bluetooth/controller/ll_sw/ull_iso.c @@ -491,11 +491,11 @@ uint8_t ll_setup_iso_path(uint16_t handle, uint8_t path_dir, uint8_t path_id, pdu_release, &source_handle); if (!err) { - if (cis) { + if (IS_ENABLED(CONFIG_BT_CTLR_CONN_ISO) && cis != NULL) { cis->hdr.datapath_in = dp; } - if (adv_stream) { + if (IS_ENABLED(CONFIG_BT_CTLR_ADV_ISO) && adv_stream != NULL) { adv_stream->dp = dp; } From 4eefd65d6bebfcfbb64b0a2fa0b3aa6c882d2452 Mon Sep 17 00:00:00 2001 From: Andries Kruithof Date: Thu, 28 Sep 2023 13:35:34 +0200 Subject: [PATCH 281/421] [nrf fromtree] Bluetooth: controller: fix comparision of unsigned int to 0 Fix the coverity issue CWE570, comparison of unsigned int to 0 in the definition of IS_SYNC_ISO_HANDLE There is a potentially the same issue for IS_ADV_ISO_HANDLE, fixed that as well Signed-off-by: Andries Kruithof (cherry picked from commit c5d844fe41a78bcb361dbd1a11ffafe4de3de97e) Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit 7cd84fe1de54490028a92b73e8fe308c32e6712e) --- subsys/bluetooth/controller/ll_sw/ull_iso_types.h | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/subsys/bluetooth/controller/ll_sw/ull_iso_types.h b/subsys/bluetooth/controller/ll_sw/ull_iso_types.h index 18d9a0f7bfe..457ad1d2458 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_iso_types.h +++ b/subsys/bluetooth/controller/ll_sw/ull_iso_types.h @@ -9,11 +9,18 @@ #define LL_BIS_ADV_HANDLE_BASE BT_CTLR_ADV_ISO_STREAM_HANDLE_BASE #define LL_BIS_ADV_IDX_FROM_HANDLE(conn_handle) \ ((conn_handle) - (LL_BIS_ADV_HANDLE_BASE)) +/* Conditional compile to prevent coverity issue CWE570, comparison of unsigned int to 0 */ +#if (LL_BIS_ADV_HANDLE_BASE > 0) #define IS_ADV_ISO_HANDLE(conn_handle) \ (((conn_handle) >= (LL_BIS_ADV_HANDLE_BASE)) && \ ((conn_handle) <= ((LL_BIS_ADV_HANDLE_BASE) + \ (BT_CTLR_ADV_ISO_STREAM_MAX) - 1U))) #else +#define IS_ADV_ISO_HANDLE(conn_handle) \ + ((conn_handle) <= ((LL_BIS_ADV_HANDLE_BASE) + \ + (BT_CTLR_ADV_ISO_STREAM_MAX) - 1U)) +#endif /* LL_BIS_ADV_HANDLE_BASE */ +#else #define LL_BIS_ADV_IDX_FROM_HANDLE(conn_handle) 0U #define IS_ADV_ISO_HANDLE(conn_handle) 0U #endif /* CONFIG_BT_CTLR_ADV_ISO */ @@ -23,11 +30,18 @@ #define LL_BIS_SYNC_HANDLE_BASE BT_CTLR_SYNC_ISO_STREAM_HANDLE_BASE #define LL_BIS_SYNC_IDX_FROM_HANDLE(conn_handle) \ ((conn_handle) - (LL_BIS_SYNC_HANDLE_BASE)) +/* Conditional compile to prevent coverity issue CWE570, comparison of unsigned int to 0 */ +#if (LL_BIS_SYNC_HANDLE_BASE > 0) #define IS_SYNC_ISO_HANDLE(conn_handle) \ (((conn_handle) >= (LL_BIS_SYNC_HANDLE_BASE)) && \ ((conn_handle) <= ((LL_BIS_SYNC_HANDLE_BASE) + \ (BT_CTLR_SYNC_ISO_STREAM_MAX) - 1U))) #else +#define IS_SYNC_ISO_HANDLE(conn_handle) \ + ((conn_handle) <= ((LL_BIS_SYNC_HANDLE_BASE) + \ + (BT_CTLR_SYNC_ISO_STREAM_MAX) - 1U)) +#endif /* LL_BIS_SYNC_HANDLE_BASE */ +#else #define LL_BIS_SYNC_IDX_FROM_HANDLE(conn_handle) 0U #define IS_SYNC_ISO_HANDLE(conn_handle) 0U #endif /* CONFIG_BT_CTLR_SYNC_ISO */ From 9e70b2847662239880a1d0f6b69bde41298fbea7 Mon Sep 17 00:00:00 2001 From: Emil Gydesen Date: Wed, 4 Oct 2023 10:29:55 +0200 Subject: [PATCH 282/421] [nrf fromtree] Bluetooth: Controller: Make aa in radio_aa_set const Make the aa argument const to solve a Coverity issue that assumes that any value that is being byteswapped is tainted. Making the argument const should avoid this assumption from Coverity. Signed-off-by: Emil Gydesen (cherry picked from commit f4221d66c1985055319393dbc45bd7b519a23731) Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit 36940b6c9450b6fcee847a455a4c2c6967bb222d) --- subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio.c | 2 +- subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio.h | 2 +- .../bluetooth/controller/ll_sw/openisa/hal/RV32M1/radio/radio.c | 2 +- .../bluetooth/controller/ll_sw/openisa/hal/RV32M1/radio/radio.h | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio.c b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio.c index a657ab95dfe..c6becbe322f 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio.c @@ -382,7 +382,7 @@ void radio_whiten_iv_set(uint32_t iv) RADIO_PCNF1_WHITEEN_Msk; } -void radio_aa_set(uint8_t *aa) +void radio_aa_set(const uint8_t *aa) { NRF_RADIO->TXADDRESS = (((0UL) << RADIO_TXADDRESS_TXADDRESS_Pos) & diff --git a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio.h b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio.h index 4bf833b233a..fc355af1edc 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio.h +++ b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio.h @@ -70,7 +70,7 @@ int8_t radio_tx_power_max_get(void); int8_t radio_tx_power_floor(int8_t power); void radio_freq_chan_set(uint32_t chan); void radio_whiten_iv_set(uint32_t iv); -void radio_aa_set(uint8_t *aa); +void radio_aa_set(const uint8_t *aa); void radio_pkt_configure(uint8_t bits_len, uint8_t max_len, uint8_t flags); void radio_pkt_rx_set(void *rx_packet); void radio_pkt_tx_set(void *tx_packet); diff --git a/subsys/bluetooth/controller/ll_sw/openisa/hal/RV32M1/radio/radio.c b/subsys/bluetooth/controller/ll_sw/openisa/hal/RV32M1/radio/radio.c index 6107bfc9c68..ecdf17bbe43 100644 --- a/subsys/bluetooth/controller/ll_sw/openisa/hal/RV32M1/radio/radio.c +++ b/subsys/bluetooth/controller/ll_sw/openisa/hal/RV32M1/radio/radio.c @@ -684,7 +684,7 @@ void radio_whiten_iv_set(uint32_t iv) GENFSK->WHITEN_SZ_THR |= GENFSK_WHITEN_SZ_THR_WHITEN_SZ_THR(0); } -void radio_aa_set(uint8_t *aa) +void radio_aa_set(const uint8_t *aa) { /* Configure Access Address detection using NETWORK ADDRESS 0 */ GENFSK->NTW_ADR_0 = *((uint32_t *)aa); diff --git a/subsys/bluetooth/controller/ll_sw/openisa/hal/RV32M1/radio/radio.h b/subsys/bluetooth/controller/ll_sw/openisa/hal/RV32M1/radio/radio.h index 1168804bbd5..cc3fda99964 100644 --- a/subsys/bluetooth/controller/ll_sw/openisa/hal/RV32M1/radio/radio.h +++ b/subsys/bluetooth/controller/ll_sw/openisa/hal/RV32M1/radio/radio.h @@ -20,7 +20,7 @@ void radio_tx_power_set(uint32_t power); void radio_tx_power_max_set(void); void radio_freq_chan_set(uint32_t chan); void radio_whiten_iv_set(uint32_t iv); -void radio_aa_set(uint8_t *aa); +void radio_aa_set(const uint8_t *aa); void radio_pkt_configure(uint8_t bits_len, uint8_t max_len, uint8_t flags); void radio_pkt_rx_set(void *rx_packet); void radio_pkt_tx_set(void *tx_packet); From cc06a1088c2186089719036a62762adb9a2d9585 Mon Sep 17 00:00:00 2001 From: Emil Gydesen Date: Tue, 3 Oct 2023 15:35:40 +0200 Subject: [PATCH 283/421] [nrf fromtree] Bluetooth: Controller: Add hdl checks in isoal.c Add checks to verify the `hdl` parameters before accessing the sink and source arrays. Signed-off-by: Emil Gydesen (cherry picked from commit 147cef6660f2f368457447a0fdc94ea06ce268dd) Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit ad5350fc59100cd775cdc9bc09cf6030d0f1eccd) --- subsys/bluetooth/controller/ll_sw/isoal.c | 78 +++++++++++++++++------ 1 file changed, 57 insertions(+), 21 deletions(-) diff --git a/subsys/bluetooth/controller/ll_sw/isoal.c b/subsys/bluetooth/controller/ll_sw/isoal.c index d43233f0289..48ad0835074 100644 --- a/subsys/bluetooth/controller/ll_sw/isoal.c +++ b/subsys/bluetooth/controller/ll_sw/isoal.c @@ -226,8 +226,17 @@ static isoal_status_t isoal_sink_allocate(isoal_sink_handle_t *hdl) */ static void isoal_sink_deallocate(isoal_sink_handle_t hdl) { - isoal_global.sink_allocated[hdl] = ISOAL_ALLOC_STATE_FREE; - (void)memset(&isoal_global.sink_state[hdl], 0, sizeof(struct isoal_sink)); + if (hdl < ARRAY_SIZE(isoal_global.sink_allocated)) { + isoal_global.sink_allocated[hdl] = ISOAL_ALLOC_STATE_FREE; + } else { + LL_ASSERT(0); + } + + if (hdl < ARRAY_SIZE(isoal_global.sink_state)) { + (void)memset(&isoal_global.sink_state[hdl], 0, sizeof(struct isoal_sink)); + } else { + LL_ASSERT(0); + } } /** @@ -365,12 +374,16 @@ isoal_status_t isoal_sink_create( */ void isoal_sink_enable(isoal_sink_handle_t hdl) { - /* Reset bookkeeping state */ - memset(&isoal_global.sink_state[hdl].sdu_production, 0, - sizeof(isoal_global.sink_state[hdl].sdu_production)); + if (hdl < ARRAY_SIZE(isoal_global.sink_state)) { + /* Reset bookkeeping state */ + memset(&isoal_global.sink_state[hdl].sdu_production, 0, + sizeof(isoal_global.sink_state[hdl].sdu_production)); - /* Atomically enable */ - isoal_global.sink_state[hdl].sdu_production.mode = ISOAL_PRODUCTION_MODE_ENABLED; + /* Atomically enable */ + isoal_global.sink_state[hdl].sdu_production.mode = ISOAL_PRODUCTION_MODE_ENABLED; + } else { + LL_ASSERT(0); + } } /** @@ -379,8 +392,12 @@ void isoal_sink_enable(isoal_sink_handle_t hdl) */ void isoal_sink_disable(isoal_sink_handle_t hdl) { - /* Atomically disable */ - isoal_global.sink_state[hdl].sdu_production.mode = ISOAL_PRODUCTION_MODE_DISABLED; + if (hdl < ARRAY_SIZE(isoal_global.sink_state)) { + /* Atomically disable */ + isoal_global.sink_state[hdl].sdu_production.mode = ISOAL_PRODUCTION_MODE_DISABLED; + } else { + LL_ASSERT(0); + } } /** @@ -1442,7 +1459,13 @@ static void isoal_source_deallocate(isoal_source_handle_t hdl) struct isoal_pdu_production *pp; struct isoal_source *source; - source = &isoal_global.source_state[hdl]; + if (hdl < ARRAY_SIZE(isoal_global.source_state)) { + source = &isoal_global.source_state[hdl]; + } else { + LL_ASSERT(0); + return; + } + pp = &source->pdu_production; if (pp->pdu_available > 0) { @@ -1454,8 +1477,13 @@ static void isoal_source_deallocate(isoal_source_handle_t hdl) } } - isoal_global.source_allocated[hdl] = ISOAL_ALLOC_STATE_FREE; - (void)memset(&isoal_global.source_state[hdl], 0, sizeof(struct isoal_source)); + if (hdl < ARRAY_SIZE(isoal_global.source_allocated)) { + isoal_global.source_allocated[hdl] = ISOAL_ALLOC_STATE_FREE; + } else { + LL_ASSERT(0); + } + + (void)memset(source, 0, sizeof(struct isoal_source)); } /** @@ -1465,8 +1493,8 @@ static void isoal_source_deallocate(isoal_source_handle_t hdl) */ static isoal_status_t isoal_check_source_hdl_valid(isoal_source_handle_t hdl) { - if (hdl < CONFIG_BT_CTLR_ISOAL_SOURCES && - isoal_global.source_allocated[hdl] == ISOAL_ALLOC_STATE_TAKEN) { + if (hdl < ARRAY_SIZE(isoal_global.source_allocated) && + isoal_global.source_allocated[hdl] == ISOAL_ALLOC_STATE_TAKEN) { return ISOAL_STATUS_OK; } @@ -1560,12 +1588,16 @@ isoal_status_t isoal_source_create( */ void isoal_source_enable(isoal_source_handle_t hdl) { - /* Reset bookkeeping state */ - memset(&isoal_global.source_state[hdl].pdu_production, 0, - sizeof(isoal_global.source_state[hdl].pdu_production)); + if (hdl < ARRAY_SIZE(isoal_global.source_state)) { + /* Reset bookkeeping state */ + memset(&isoal_global.source_state[hdl].pdu_production, 0, + sizeof(isoal_global.source_state[hdl].pdu_production)); - /* Atomically enable */ - isoal_global.source_state[hdl].pdu_production.mode = ISOAL_PRODUCTION_MODE_ENABLED; + /* Atomically enable */ + isoal_global.source_state[hdl].pdu_production.mode = ISOAL_PRODUCTION_MODE_ENABLED; + } else { + LL_ASSERT(0); + } } /** @@ -1574,8 +1606,12 @@ void isoal_source_enable(isoal_source_handle_t hdl) */ void isoal_source_disable(isoal_source_handle_t hdl) { - /* Atomically disable */ - isoal_global.source_state[hdl].pdu_production.mode = ISOAL_PRODUCTION_MODE_DISABLED; + if (hdl < ARRAY_SIZE(isoal_global.source_state)) { + /* Atomically disable */ + isoal_global.source_state[hdl].pdu_production.mode = ISOAL_PRODUCTION_MODE_DISABLED; + } else { + LL_ASSERT(0); + } } /** From 009025d45d384fd1eacf3669c9a859627058b684 Mon Sep 17 00:00:00 2001 From: Carles Cufi Date: Thu, 5 Oct 2023 12:55:24 +0200 Subject: [PATCH 284/421] [nrf fromtree] Bluetooth: Controller: Remove legacy BT_CTLR_FAST_ENC option When the legacy LLCP implementation was removed this Kconfig option was mistakenly left over. Remove it now with all its users. Fixes #63212. Signed-off-by: Carles Cufi (cherry picked from commit a5e7ba356465cdf0b7f3387f5b46ddc016339250) Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit 62cc15553b6fc153b945c515a11a4976fbd22763) --- drivers/entropy/entropy_nrf5.c | 5 ----- drivers/entropy/entropy_smartbond.c | 5 ----- drivers/entropy/entropy_stm32.c | 9 +-------- subsys/bluetooth/controller/Kconfig.ll_sw_split | 12 ------------ tests/bluetooth/init/prj_ctlr_4_0.conf | 1 - tests/bluetooth/init/prj_ctlr_4_0_dbg.conf | 1 - tests/bluetooth/init/prj_ctlr_5_x_dbg.conf | 1 - tests/bluetooth/init/prj_ctlr_dbg.conf | 1 - tests/bluetooth/init/prj_ctlr_ticker.conf | 1 - tests/bluetooth/init/prj_ctlr_tiny.conf | 1 - 10 files changed, 1 insertion(+), 36 deletions(-) diff --git a/drivers/entropy/entropy_nrf5.c b/drivers/entropy/entropy_nrf5.c index 8febcfacb15..2f04bc06a37 100644 --- a/drivers/entropy/entropy_nrf5.c +++ b/drivers/entropy/entropy_nrf5.c @@ -116,10 +116,6 @@ static int random_byte_get(void) return retval; } -#pragma GCC push_options -#if defined(CONFIG_BT_CTLR_FAST_ENC) -#pragma GCC optimize ("Ofast") -#endif static uint16_t rng_pool_get(struct rng_pool *rngp, uint8_t *buf, uint16_t len) { uint32_t last = rngp->last; @@ -175,7 +171,6 @@ static uint16_t rng_pool_get(struct rng_pool *rngp, uint8_t *buf, uint16_t len) return len; } -#pragma GCC pop_options static int rng_pool_put(struct rng_pool *rngp, uint8_t byte) { diff --git a/drivers/entropy/entropy_smartbond.c b/drivers/entropy/entropy_smartbond.c index 0058baafce5..28b6f08e100 100644 --- a/drivers/entropy/entropy_smartbond.c +++ b/drivers/entropy/entropy_smartbond.c @@ -100,10 +100,6 @@ static int random_word_get(uint8_t buf[4]) return retval; } -#pragma GCC push_options -#if defined(CONFIG_BT_CTLR_FAST_ENC) -#pragma GCC optimize("Ofast") -#endif static uint16_t rng_pool_get(struct rng_pool *rngp, uint8_t *buf, uint16_t len) { uint32_t last = rngp->last; @@ -159,7 +155,6 @@ static uint16_t rng_pool_get(struct rng_pool *rngp, uint8_t *buf, uint16_t len) return len; } -#pragma GCC pop_options static int rng_pool_put(struct rng_pool *rngp, uint8_t byte) { diff --git a/drivers/entropy/entropy_stm32.c b/drivers/entropy/entropy_stm32.c index 9f2ad136203..7c342a09c23 100644 --- a/drivers/entropy/entropy_stm32.c +++ b/drivers/entropy/entropy_stm32.c @@ -377,13 +377,7 @@ static void pool_filling_work_handler(struct k_work *work) } } -#if defined(CONFIG_BT_CTLR_FAST_ENC) -#define __fast __attribute__((optimize("Ofast"))) -#else -#define __fast -#endif - -__fast static uint16_t rng_pool_get(struct rng_pool *rngp, uint8_t *buf, +static uint16_t rng_pool_get(struct rng_pool *rngp, uint8_t *buf, uint16_t len) { uint32_t last = rngp->last; @@ -448,7 +442,6 @@ __fast static uint16_t rng_pool_get(struct rng_pool *rngp, uint8_t *buf, return len; } -#undef __fast static int rng_pool_put(struct rng_pool *rngp, uint8_t byte) { diff --git a/subsys/bluetooth/controller/Kconfig.ll_sw_split b/subsys/bluetooth/controller/Kconfig.ll_sw_split index a7dade7a1db..e2975107f86 100644 --- a/subsys/bluetooth/controller/Kconfig.ll_sw_split +++ b/subsys/bluetooth/controller/Kconfig.ll_sw_split @@ -760,18 +760,6 @@ config BT_CTLR_PARAM_CHECK if BT_CONN -config BT_CTLR_FAST_ENC - bool "Fast Encryption Setup" - depends on BT_CTLR_LE_ENC - default y if BT_HCI_RAW - help - Enable connection encryption setup in 4 connection events. - Peripheral will respond to Encryption Request with Encryption Response - in the next connection event, and will transmit Start Encryption - Request PDU in the same connection event, hence completing encryption - setup in 4 connection events. Encrypted data would be transmitted as - fast as in 4th connection event from Encryption Request. - config BT_CTLR_LLCP_CONN int "Number of connections with worst-case overlapping procedures" default BT_MAX_CONN diff --git a/tests/bluetooth/init/prj_ctlr_4_0.conf b/tests/bluetooth/init/prj_ctlr_4_0.conf index ff3917be54b..4f9ec70d3bb 100644 --- a/tests/bluetooth/init/prj_ctlr_4_0.conf +++ b/tests/bluetooth/init/prj_ctlr_4_0.conf @@ -19,7 +19,6 @@ CONFIG_BT_CTLR_XTAL_ADVANCED=y CONFIG_BT_CTLR_SCHED_ADVANCED=y CONFIG_BT_CTLR_RADIO_ENABLE_FAST=n CONFIG_BT_CTLR_TIFS_HW=y -CONFIG_BT_CTLR_FAST_ENC=n CONFIG_BT_CTLR_CONN_RSSI=n CONFIG_BT_CTLR_ADV_INDICATION=n CONFIG_BT_CTLR_SCAN_REQ_NOTIFY=n diff --git a/tests/bluetooth/init/prj_ctlr_4_0_dbg.conf b/tests/bluetooth/init/prj_ctlr_4_0_dbg.conf index 4c101cc6e16..5fc61cf98c6 100644 --- a/tests/bluetooth/init/prj_ctlr_4_0_dbg.conf +++ b/tests/bluetooth/init/prj_ctlr_4_0_dbg.conf @@ -21,7 +21,6 @@ CONFIG_BT_CTLR_XTAL_ADVANCED=y CONFIG_BT_CTLR_SCHED_ADVANCED=y CONFIG_BT_CTLR_RADIO_ENABLE_FAST=n CONFIG_BT_CTLR_TIFS_HW=y -CONFIG_BT_CTLR_FAST_ENC=n CONFIG_BT_CTLR_CONN_RSSI=n CONFIG_BT_CTLR_ADV_INDICATION=n CONFIG_BT_CTLR_SCAN_REQ_NOTIFY=n diff --git a/tests/bluetooth/init/prj_ctlr_5_x_dbg.conf b/tests/bluetooth/init/prj_ctlr_5_x_dbg.conf index df0d006a13e..50f72889476 100644 --- a/tests/bluetooth/init/prj_ctlr_5_x_dbg.conf +++ b/tests/bluetooth/init/prj_ctlr_5_x_dbg.conf @@ -29,7 +29,6 @@ CONFIG_BT_CTLR_XTAL_ADVANCED=n CONFIG_BT_CTLR_SCHED_ADVANCED=y CONFIG_BT_CTLR_RADIO_ENABLE_FAST=y CONFIG_BT_CTLR_TIFS_HW=n -CONFIG_BT_CTLR_FAST_ENC=y CONFIG_BT_CTLR_TX_RETRY_DISABLE=y CONFIG_BT_CTLR_CONN_RSSI=y CONFIG_BT_CTLR_ADV_INDICATION=y diff --git a/tests/bluetooth/init/prj_ctlr_dbg.conf b/tests/bluetooth/init/prj_ctlr_dbg.conf index 6aff0965ce9..2f8224cdfea 100644 --- a/tests/bluetooth/init/prj_ctlr_dbg.conf +++ b/tests/bluetooth/init/prj_ctlr_dbg.conf @@ -23,7 +23,6 @@ CONFIG_BT_CTLR_XTAL_ADVANCED=n CONFIG_BT_CTLR_SCHED_ADVANCED=n CONFIG_BT_CTLR_RADIO_ENABLE_FAST=y CONFIG_BT_CTLR_TIFS_HW=n -CONFIG_BT_CTLR_FAST_ENC=y CONFIG_BT_CTLR_TX_RETRY_DISABLE=y CONFIG_BT_CTLR_CONN_RSSI=y CONFIG_BT_CTLR_ADV_INDICATION=y diff --git a/tests/bluetooth/init/prj_ctlr_ticker.conf b/tests/bluetooth/init/prj_ctlr_ticker.conf index d77f519406b..4e5b962231e 100644 --- a/tests/bluetooth/init/prj_ctlr_ticker.conf +++ b/tests/bluetooth/init/prj_ctlr_ticker.conf @@ -23,7 +23,6 @@ CONFIG_BT_CTLR_XTAL_ADVANCED=n CONFIG_BT_CTLR_SCHED_ADVANCED=n CONFIG_BT_CTLR_RADIO_ENABLE_FAST=y CONFIG_BT_CTLR_TIFS_HW=n -CONFIG_BT_CTLR_FAST_ENC=y CONFIG_BT_CTLR_TX_RETRY_DISABLE=y CONFIG_BT_CTLR_CONN_RSSI=y CONFIG_BT_CTLR_ADV_INDICATION=y diff --git a/tests/bluetooth/init/prj_ctlr_tiny.conf b/tests/bluetooth/init/prj_ctlr_tiny.conf index 7679de9a661..ce75583da16 100644 --- a/tests/bluetooth/init/prj_ctlr_tiny.conf +++ b/tests/bluetooth/init/prj_ctlr_tiny.conf @@ -22,7 +22,6 @@ CONFIG_BT_CTLR_XTAL_ADVANCED=n CONFIG_BT_CTLR_SCHED_ADVANCED=n CONFIG_BT_CTLR_RADIO_ENABLE_FAST=n CONFIG_BT_CTLR_TIFS_HW=y -CONFIG_BT_CTLR_FAST_ENC=n CONFIG_BT_CTLR_CONN_RSSI=n CONFIG_BT_CTLR_ADV_INDICATION=n CONFIG_BT_CTLR_SCAN_REQ_NOTIFY=n From 2b86f49ef42aec7d80c2842da5dc6414d0b0ecc1 Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Thu, 5 Oct 2023 09:42:31 +0200 Subject: [PATCH 285/421] [nrf fromtree] Bluetooth: Controller: Rename ticker reschedule variables Rename ticker reschedule in window variable to improve readability. Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit 7495846b625be792c9c28a1d59eaad391f7be15d) Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit 489e43adfe41004ad84971fb5fb5b1833ab59ee2) --- subsys/bluetooth/controller/ticker/ticker.c | 123 +++++++++++--------- 1 file changed, 69 insertions(+), 54 deletions(-) diff --git a/subsys/bluetooth/controller/ticker/ticker.c b/subsys/bluetooth/controller/ticker/ticker.c index e5c89dca905..9b5bb53a625 100644 --- a/subsys/bluetooth/controller/ticker/ticker.c +++ b/subsys/bluetooth/controller/ticker/ticker.c @@ -2326,43 +2326,46 @@ static uint8_t ticker_job_reschedule_in_window(struct ticker_instance *instance, uint32_t ticks_elapsed) { struct ticker_node *nodes; - uint8_t rescheduling = 1U; - uint8_t rescheduled = 0U; + uint8_t rescheduling; + uint8_t rescheduled; nodes = &instance->nodes[0]; /* Do until all pending re-schedules handled */ + rescheduling = 1U; + rescheduled = 0U; while (rescheduling) { - uint32_t ticks_to_expire_offset = 0U; - uint32_t ticks_start_offset = 0U; - uint32_t window_start_ticks = 0U; - uint32_t ticks_slot_window = 0U; - uint32_t ticks_to_expire = 0U; + struct ticker_node *ticker_resched; + uint32_t ticks_to_expire_offset; struct ticker_ext *ext_data; - struct ticker_node *ticker; - uint8_t ticker_id_head; + uint32_t ticks_start_offset; + uint32_t window_start_ticks; + uint32_t ticks_slot_window; + uint8_t ticker_id_resched; + uint32_t ticks_to_expire; uint8_t ticker_id_prev; - uint8_t ticker_id_iter; + uint8_t ticker_id_next; uint32_t ticks_slot; rescheduling = 0U; /* Find first pending re-schedule */ - ticker_id_head = instance->ticker_id_head; - while (ticker_id_head != TICKER_NULL) { - ticker = &nodes[ticker_id_head]; - if (TICKER_RESCHEDULE_PENDING(ticker)) { + ticker_id_resched = instance->ticker_id_head; + while (ticker_id_resched != TICKER_NULL) { + ticker_resched = &nodes[ticker_id_resched]; + if (TICKER_RESCHEDULE_PENDING(ticker_resched)) { /* Pending reschedule found */ break; } - ticker_id_head = ticker->next; + ticker_id_resched = ticker_resched->next; } - if (ticker_id_head == TICKER_NULL) { + if (ticker_id_resched == TICKER_NULL) { /* Done */ break; } /* Check for intersection with already active node */ + window_start_ticks = 0U; if (instance->ticks_slot_previous > ticks_elapsed) { /* Active node intersects - window starts after end of * active slot @@ -2371,7 +2374,7 @@ static uint8_t ticker_job_reschedule_in_window(struct ticker_instance *instance, ticks_elapsed; } - ticker_id_iter = nodes[ticker_id_head].next; + ticker_id_next = ticker_resched->next; /* If drift was applied to this node, this must be * taken into consideration. Reduce the window with @@ -2382,43 +2385,50 @@ static uint8_t ticker_job_reschedule_in_window(struct ticker_instance *instance, * ticker would have the best possible window to re-schedule in * and not be restricted to ticks_slot_window - ticks_drift. */ - ext_data = ticker->ext_data; + ext_data = ticker_resched->ext_data; if (ext_data->ticks_drift < ext_data->ticks_slot_window) { ticks_slot_window = ext_data->ticks_slot_window - ext_data->ticks_drift; } else { /* Window has been exhausted - we can't reschedule */ - ticker_id_iter = TICKER_NULL; + ticker_id_next = TICKER_NULL; + + /* Assignment will be unused when TICKER_NULL */ + ticks_slot_window = 0U; } /* Use ticker's reserved time ticks_slot, else for unreserved * tickers use the reschedule margin as ticks_slot. */ - if (ticker->ticks_slot) { - ticks_slot = ticker->ticks_slot; + if (ticker_resched->ticks_slot) { + ticks_slot = ticker_resched->ticks_slot; } else { - LL_ASSERT(TICKER_HAS_SLOT_WINDOW(ticker)); + LL_ASSERT(TICKER_HAS_SLOT_WINDOW(ticker_resched)); ticks_slot = HAL_TICKER_RESCHEDULE_MARGIN; } /* Try to find available slot for re-scheduling */ - while ((ticker_id_iter != TICKER_NULL) && + ticks_to_expire_offset = 0U; + ticks_start_offset = 0U; + ticks_to_expire = 0U; + while ((ticker_id_next != TICKER_NULL) && ((ticks_start_offset + ticks_slot) <= ticks_slot_window)) { - uint32_t window_end_ticks = 0U; - struct ticker_node *node; + struct ticker_node *ticker_next; + uint32_t window_end_ticks; - node = &nodes[ticker_id_iter]; - ticks_to_expire_offset += node->ticks_to_expire; + ticker_next = &nodes[ticker_id_next]; + ticks_to_expire_offset += ticker_next->ticks_to_expire; /* Skip other pending re-schedule nodes and * tickers with no reservation or not periodic */ - if (TICKER_RESCHEDULE_PENDING(node) || - !node->ticks_slot || - !node->ticks_periodic) { - ticker_id_iter = node->next; + if (TICKER_RESCHEDULE_PENDING(ticker_next) || + !ticker_next->ticks_slot || + !ticker_next->ticks_periodic) { + ticker_id_next = ticker_next->next; + continue; } @@ -2444,7 +2454,7 @@ static uint8_t ticker_job_reschedule_in_window(struct ticker_instance *instance, */ if (window_end_ticks > (ticks_start_offset + ticks_slot)) { - if (!ticker->ticks_slot) { + if (!ticker_resched->ticks_slot) { /* Place at start of window */ ticks_to_expire = window_start_ticks; } else { @@ -2477,10 +2487,10 @@ static uint8_t ticker_job_reschedule_in_window(struct ticker_instance *instance, */ ticks_start_offset += ticks_to_expire_offset; window_start_ticks = ticks_start_offset + - node->ticks_slot; + ticker_next->ticks_slot; ticks_to_expire_offset = 0U; - if (!ticker->ticks_slot) { + if (!ticker_resched->ticks_slot) { /* Try at the end of the next node */ ticks_to_expire = window_start_ticks; } else { @@ -2493,56 +2503,61 @@ static uint8_t ticker_job_reschedule_in_window(struct ticker_instance *instance, ticks_slot; } - ticker_id_iter = node->next; + ticker_id_next = ticker_next->next; } ext_data->ticks_drift += ticks_to_expire - - ticker->ticks_to_expire; - ticker->ticks_to_expire = ticks_to_expire; - ticker_id_iter = nodes[ticker_id_head].next; - ticker_id_prev = TICKER_NULL; + ticker_resched->ticks_to_expire; + ticker_resched->ticks_to_expire = ticks_to_expire; /* Place the ticker node sorted by expiration time and adjust * delta times */ - while (ticker_id_iter != TICKER_NULL) { - struct ticker_node *node; + ticker_id_next = ticker_resched->next; + ticker_id_prev = TICKER_NULL; + while (ticker_id_next != TICKER_NULL) { + struct ticker_node *ticker_next; - node = &nodes[ticker_id_iter]; - if (ticker->ticks_to_expire > node->ticks_to_expire) { + ticker_next = &nodes[ticker_id_next]; + if (ticker_resched->ticks_to_expire > + ticker_next->ticks_to_expire) { /* Node is after this - adjust delta */ - ticker->ticks_to_expire -= - node->ticks_to_expire; + ticker_resched->ticks_to_expire -= + ticker_next->ticks_to_expire; } else { /* Node is before this one */ - node->ticks_to_expire -= - ticker->ticks_to_expire; + ticker_next->ticks_to_expire -= + ticker_resched->ticks_to_expire; break; } - ticker_id_prev = ticker_id_iter; - ticker_id_iter = node->next; + ticker_id_prev = ticker_id_next; + ticker_id_next = ticker_next->next; } + /* If the node moved in the list, insert it */ if (ticker_id_prev != TICKER_NULL) { + LL_ASSERT(instance->ticker_id_head == + ticker_id_resched); + /* Node did not become the first - update head and * insert node after 'previous' */ - instance->ticker_id_head = nodes[ticker_id_head].next; + instance->ticker_id_head = ticker_resched->next; /* Link inserted node */ - nodes[ticker_id_head].next = nodes[ticker_id_prev].next; - nodes[ticker_id_prev].next = ticker_id_head; + ticker_resched->next = nodes[ticker_id_prev].next; + nodes[ticker_id_prev].next = ticker_id_resched; } /* Remove latency added in ticker_worker */ - ticker->lazy_current--; + ticker_resched->lazy_current--; /* Prevent repeated re-scheduling */ ext_data->reschedule_state = TICKER_RESCHEDULE_STATE_DONE; #if defined(CONFIG_BT_TICKER_EXT_EXPIRE_INFO) - ticker_mark_expire_info_outdated(instance, ticker_id_head); + ticker_mark_expire_info_outdated(instance, ticker_id_resched); #endif /* CONFIG_BT_TICKER_EXT_EXPIRE_INFO */ /* Check for other pending re-schedules and set exit flag */ From 730249a34382716d6593e50bbd03aa0c3c1561ac Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Thu, 5 Oct 2023 10:35:03 +0200 Subject: [PATCH 286/421] [nrf fromtree] Bluetooth: Controller: Fix leak in scheduled ticker node Fix leak in scheduled ticker node when rescheduling ticker nodes. Applications having active Extended Advertising or Observer role with the use of ticker reschedule in window feature would experience assertion check failure due to delayed radio event preparation or stalled controller with no active roles. Fix updating of the ticker linked list when handling rescheduled tickers. Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit e50748b67cd9d7d554d87bf27ceef0307f9d63ac) Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit 9cce789dee1302573d700ce391b24f0a55b7c7c7) --- subsys/bluetooth/controller/ticker/ticker.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/subsys/bluetooth/controller/ticker/ticker.c b/subsys/bluetooth/controller/ticker/ticker.c index 9b5bb53a625..83bd6437d59 100644 --- a/subsys/bluetooth/controller/ticker/ticker.c +++ b/subsys/bluetooth/controller/ticker/ticker.c @@ -2337,6 +2337,7 @@ static uint8_t ticker_job_reschedule_in_window(struct ticker_instance *instance, while (rescheduling) { struct ticker_node *ticker_resched; uint32_t ticks_to_expire_offset; + uint8_t ticker_id_resched_prev; struct ticker_ext *ext_data; uint32_t ticks_start_offset; uint32_t window_start_ticks; @@ -2350,6 +2351,7 @@ static uint8_t ticker_job_reschedule_in_window(struct ticker_instance *instance, rescheduling = 0U; /* Find first pending re-schedule */ + ticker_id_resched_prev = TICKER_NULL; ticker_id_resched = instance->ticker_id_head; while (ticker_id_resched != TICKER_NULL) { ticker_resched = &nodes[ticker_id_resched]; @@ -2357,6 +2359,8 @@ static uint8_t ticker_job_reschedule_in_window(struct ticker_instance *instance, /* Pending reschedule found */ break; } + + ticker_id_resched_prev = ticker_id_resched; ticker_id_resched = ticker_resched->next; } if (ticker_id_resched == TICKER_NULL) { @@ -2536,13 +2540,15 @@ static uint8_t ticker_job_reschedule_in_window(struct ticker_instance *instance, /* If the node moved in the list, insert it */ if (ticker_id_prev != TICKER_NULL) { - LL_ASSERT(instance->ticker_id_head == - ticker_id_resched); - - /* Node did not become the first - update head and - * insert node after 'previous' - */ - instance->ticker_id_head = ticker_resched->next; + /* Remove node from its current position in list */ + if (ticker_id_resched_prev != TICKER_NULL) { + /* Node was not at the head of the list */ + nodes[ticker_id_resched_prev].next = + ticker_resched->next; + } else { + /* Node was at the head, move head forward */ + instance->ticker_id_head = ticker_resched->next; + } /* Link inserted node */ ticker_resched->next = nodes[ticker_id_prev].next; From 68a8baa59b3e58f0e88623996868009d4e5f3741 Mon Sep 17 00:00:00 2001 From: Andries Kruithof Date: Thu, 8 Jun 2023 11:58:00 +0200 Subject: [PATCH 287/421] [nrf fromtree] Bluetooth: controller: fix failing EBQ advertising tests Updates the chaining for advertising. Instead of unconditionally adding a new PDU when new data is added we now instead fill the last PDU in the chain with the incoming data, only adding a new PDU when there is not enough room. This reduces the nr. of PDUs used for advertising, and also fixes some qualification failures Signed-off-by: Andries Kruithof (cherry picked from commit d00d44c92537938fe72e4cc19a05f8e752fb6097) Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit 8312c87dffa2661dbcc2b984bfe510412a283fca) --- .../src/broadcaster_multiple.c | 1 - .../bluetooth/controller/ll_sw/ull_adv_aux.c | 154 ++++++++++++------ tests/bsim/bluetooth/host/adv/chain/prj.conf | 5 +- 3 files changed, 111 insertions(+), 49 deletions(-) diff --git a/samples/bluetooth/broadcaster_multiple/src/broadcaster_multiple.c b/samples/bluetooth/broadcaster_multiple/src/broadcaster_multiple.c index 56cc210de78..d1c6d792e95 100644 --- a/samples/bluetooth/broadcaster_multiple/src/broadcaster_multiple.c +++ b/samples/bluetooth/broadcaster_multiple/src/broadcaster_multiple.c @@ -75,7 +75,6 @@ int broadcaster_multiple(void) printk("Bluetooth init failed (err %d)\n", err); return err; } - for (int index = 0; index < CONFIG_BT_EXT_ADV_MAX_ADV_SET; index++) { /* Use advertising set instance index as SID */ adv_param.sid = index; diff --git a/subsys/bluetooth/controller/ll_sw/ull_adv_aux.c b/subsys/bluetooth/controller/ll_sw/ull_adv_aux.c index 302dc6da785..0754a047207 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_adv_aux.c +++ b/subsys/bluetooth/controller/ll_sw/ull_adv_aux.c @@ -117,6 +117,7 @@ uint8_t ll_adv_aux_ad_data_set(uint8_t handle, uint8_t op, uint8_t frag_pref, uint8_t ad_len_overflow; uint8_t ad_len_chain; struct pdu_adv *pdu; + uint8_t ad_len = 0U; #endif /* CONFIG_BT_CTLR_ADV_AUX_PDU_LINK */ /* Get the advertising set instance */ @@ -301,7 +302,7 @@ uint8_t ll_adv_aux_ad_data_set(uint8_t handle, uint8_t op, uint8_t frag_pref, struct pdu_adv *pdu_chain_prev; struct pdu_adv *pdu_chain; uint16_t ad_len_total; - uint8_t ad_len_prev; + uint8_t ad_len_prev = 0U; /* Traverse to next set clear hdr data parameter */ val_ptr += sizeof(data); @@ -317,28 +318,22 @@ uint8_t ll_adv_aux_ad_data_set(uint8_t handle, uint8_t op, uint8_t frag_pref, ad_len_total = 0U; pdu_chain_prev = pdu_prev; pdu_chain = pdu; + /* make a copy of the previous chain, until we reach the end */ do { - /* Prepare for aux ptr field reference to be returned, hence - * second parameter will be for AD data field. - */ - *val_ptr = 0U; - (void)memset((void *)&val_ptr[ULL_ADV_HDR_DATA_DATA_PTR_OFFSET], - 0U, ULL_ADV_HDR_DATA_DATA_PTR_SIZE); + val_ptr = hdr_data; + *val_ptr++ = 0U; + (void)memset((void *)val_ptr, 0U, + ULL_ADV_HDR_DATA_DATA_PTR_SIZE); pdu_prev = pdu_chain_prev; pdu = pdu_chain; - /* Add Aux Ptr field if not already present */ err = ull_adv_aux_pdu_set_clear(adv, pdu_prev, pdu, - (ULL_ADV_PDU_HDR_FIELD_AD_DATA | - ULL_ADV_PDU_HDR_FIELD_AUX_PTR), - 0, hdr_data); - LL_ASSERT(!err || (err == BT_HCI_ERR_PACKET_TOO_LONG)); + ULL_ADV_PDU_HDR_FIELD_AD_DATA, + 0U, hdr_data); + ad_len_prev = hdr_data[ULL_ADV_HDR_DATA_LEN_OFFSET]; - /* Get PDUs previous AD data length */ - ad_len_prev = - hdr_data[ULL_ADV_HDR_DATA_AUX_PTR_PTR_OFFSET + - ULL_ADV_HDR_DATA_AUX_PTR_PTR_SIZE]; + LL_ASSERT(!err || (err == BT_HCI_ERR_PACKET_TOO_LONG)); /* Check of max supported AD data len */ ad_len_total += ad_len_prev; @@ -365,31 +360,10 @@ uint8_t ll_adv_aux_ad_data_set(uint8_t handle, uint8_t op, uint8_t frag_pref, (!pdu_chain_prev && !pdu_chain)); } while (pdu_chain_prev); - if (err == BT_HCI_ERR_PACKET_TOO_LONG) { - ad_len_overflow = - hdr_data[ULL_ADV_HDR_DATA_AUX_PTR_PTR_OFFSET + - ULL_ADV_HDR_DATA_AUX_PTR_PTR_SIZE + - ULL_ADV_HDR_DATA_DATA_PTR_OFFSET + - ULL_ADV_HDR_DATA_DATA_PTR_SIZE]; - - /* Prepare for aux ptr field reference to be returned, - * hence second parameter will be for AD data field. - * Fill it with reduced AD data length. - */ - *val_ptr = ad_len_prev - ad_len_overflow; - - /* AD data len in chain PDU */ - ad_len_chain = len; - - /* Proceed to add chain PDU */ - err = 0U; - } else { - /* No AD data overflow */ - ad_len_overflow = 0U; - - /* No AD data in chain PDU */ - ad_len_chain = 0U; - } + /* No AD data overflow */ + ad_len_overflow = 0U; + /* No AD data in chain PDU */ + ad_len_chain = 0U; } #else /* !CONFIG_BT_CTLR_ADV_AUX_PDU_LINK */ } else { @@ -411,8 +385,88 @@ uint8_t ll_adv_aux_ad_data_set(uint8_t handle, uint8_t op, uint8_t frag_pref, #if defined(CONFIG_BT_CTLR_ADV_AUX_PDU_LINK) if ((op == BT_HCI_LE_EXT_ADV_OP_INTERM_FRAG) || - (op == BT_HCI_LE_EXT_ADV_OP_LAST_FRAG) || - ad_len_overflow) { + (op == BT_HCI_LE_EXT_ADV_OP_LAST_FRAG)) { + /* in the previous step we duplicated the chain + * the next step is to append new data in the last existing pdu in the chain, + */ + + uint8_t chain_err = 0U; + + val_ptr = hdr_data; + *val_ptr++ = len; + (void)memcpy(val_ptr, &data, sizeof(data)); + + /* Append data to the last PDU */ + chain_err = ull_adv_aux_pdu_set_clear(adv, pdu_prev, pdu, + ULL_ADV_PDU_HDR_FIELD_AD_DATA_APPEND, + 0U, hdr_data); + + LL_ASSERT((!chain_err) || (chain_err == BT_HCI_ERR_PACKET_TOO_LONG)); + + /* FIXME: the code has become quite complex, an alternative and simpler + * implementation would be to first fill an array with all data that + * must be send, and create the chained PDUs from this array + */ + if (chain_err == BT_HCI_ERR_PACKET_TOO_LONG) { + /* We could not fit all the data, append as much as possible + * ad_len_overflow is how much overflows with the AUX ptr + */ + uint8_t ad_len_overflow_first_try; + const uint16_t chain_add_fields = ULL_ADV_PDU_HDR_FIELD_AD_DATA_APPEND | + ULL_ADV_PDU_HDR_FIELD_AUX_PTR; + + ad_len_overflow_first_try = hdr_data[ULL_ADV_HDR_DATA_DATA_PTR_OFFSET + + ULL_ADV_HDR_DATA_DATA_PTR_SIZE]; + + val_ptr = hdr_data; + *val_ptr++ = len; + (void)memcpy(val_ptr, &data, sizeof(data)); + val_ptr += sizeof(data); + *val_ptr++ = len; + (void)memcpy(val_ptr, &data, sizeof(data)); + chain_err = ull_adv_aux_pdu_set_clear(adv, pdu_prev, pdu, + chain_add_fields, + 0U, hdr_data); + ad_len_overflow = hdr_data[ULL_ADV_HDR_DATA_AUX_PTR_PTR_OFFSET + + ULL_ADV_HDR_DATA_AUX_PTR_PTR_SIZE + + ULL_ADV_HDR_DATA_DATA_PTR_OFFSET + + ULL_ADV_HDR_DATA_DATA_PTR_SIZE]; + + /* ad_len_overflow - ad_len_overflow_first_try is the size of + * the aux pointer + * ad_len_prev is how much data is already present, ad_len is how + * much data we can add to this PDU + */ + ad_len = PDU_AC_PAYLOAD_SIZE_MAX - ad_len_prev - + (ad_len_overflow - ad_len_overflow_first_try) - 4; + + val_ptr = hdr_data; + *val_ptr++ = ad_len; + (void)memcpy(val_ptr, &data, sizeof(data)); + val_ptr += sizeof(data); + *val_ptr++ = ad_len; + (void)memcpy(val_ptr, &data, sizeof(data)); + + /* we now know how much data we can add to the + * last PDU without getting an overflow + */ + chain_err = ull_adv_aux_pdu_set_clear(adv, pdu_prev, pdu, + chain_add_fields, + 0U, hdr_data); + LL_ASSERT(chain_err == 0U); + /* + * in the next PDU we still need to add ad_len_chain bytes of data + * but we do not have overflow, since we already added + * the exact amount that would fit + */ + ad_len_chain = len - ad_len; + ad_len_overflow = 0U; + } else { + ad_len_overflow = 0U; + } + } + + if (ad_len_chain || ad_len_overflow) { struct pdu_adv_com_ext_adv *com_hdr_chain; struct pdu_adv_com_ext_adv *com_hdr; struct pdu_adv_ext_hdr *hdr_chain; @@ -425,6 +479,7 @@ uint8_t ll_adv_aux_ad_data_set(uint8_t handle, uint8_t op, uint8_t frag_pref, uint16_t sec_len; uint8_t *dptr; + len = ad_len_chain; /* Get reference to flags in superior PDU */ com_hdr = &pdu->adv_ext_ind; if (com_hdr->ext_hdr_len) { @@ -450,6 +505,7 @@ uint8_t ll_adv_aux_ad_data_set(uint8_t handle, uint8_t op, uint8_t frag_pref, hdr_chain = (void *)&com_hdr_chain->ext_hdr_adv_data[0]; dptr_chain = (void *)hdr_chain; + LL_ASSERT(dptr_chain); /* Flags */ *dptr_chain = 0U; @@ -498,6 +554,7 @@ uint8_t ll_adv_aux_ad_data_set(uint8_t handle, uint8_t op, uint8_t frag_pref, if (ad_len_overflow) { uint8_t *ad_overflow; + val_ptr = hdr_data; /* Copy overflowed AD data from previous PDU into this * new chain PDU */ @@ -505,6 +562,7 @@ uint8_t ll_adv_aux_ad_data_set(uint8_t handle, uint8_t op, uint8_t frag_pref, &val_ptr[ULL_ADV_HDR_DATA_DATA_PTR_OFFSET], sizeof(ad_overflow)); ad_overflow += *val_ptr; + (void)memcpy(dptr_chain, ad_overflow, ad_len_overflow); dptr_chain += ad_len_overflow; @@ -529,8 +587,6 @@ uint8_t ll_adv_aux_ad_data_set(uint8_t handle, uint8_t op, uint8_t frag_pref, return err; } - /* AD data len in chain PDU besides the overflow */ - len = ad_len_chain; } /* Check AdvData overflow */ @@ -555,7 +611,13 @@ uint8_t ll_adv_aux_ad_data_set(uint8_t handle, uint8_t op, uint8_t frag_pref, pdu_chain->len = sec_len + ad_len_overflow + len; /* Fill AD Data in chain PDU */ - (void)memcpy(dptr_chain, data, len); + if (ad_len_overflow != 0U) { + (void)memcpy(dptr_chain, data, ad_len_overflow); + } + + if (ad_len_chain != 0U) { + (void)memcpy(dptr_chain, &data[ad_len + ad_len_overflow], ad_len_chain); + } /* Get reference to aux ptr in superior PDU */ (void)memcpy(&aux_ptr, diff --git a/tests/bsim/bluetooth/host/adv/chain/prj.conf b/tests/bsim/bluetooth/host/adv/chain/prj.conf index 3e7f11009c2..85861dccd66 100644 --- a/tests/bsim/bluetooth/host/adv/chain/prj.conf +++ b/tests/bsim/bluetooth/host/adv/chain/prj.conf @@ -30,8 +30,9 @@ CONFIG_BT_EXT_SCAN_BUF_SIZE=1650 # Set maximum scan data length for Extended Scanning in Bluetooth LE Controller CONFIG_BT_CTLR_SCAN_DATA_LEN_MAX=1650 -# Zephyr Bluetooth LE Controller needs 16 event buffers to generate Extended -# Advertising Report for receiving the complete 1650 bytes of data +# Zephyr Controller does not combine all the 1650 bytes before fragmenting them +# into 8 HCI reports, if a PDU has 255 bytes, it will generate 2 HCI reports +# and so we need to reserve 16 buffers CONFIG_BT_BUF_EVT_RX_COUNT=16 # Increase Zephyr Bluetooth LE Controller Rx buffer to receive complete chain From 8eefe7f80331b72b2bcf00113684fb60fbad906f Mon Sep 17 00:00:00 2001 From: Andries Kruithof Date: Mon, 2 Oct 2023 12:15:47 +0200 Subject: [PATCH 288/421] [nrf fromtree] Bluetooth: controller: change calc for data in PDU The existing formula for the amount of data that can be filled in in the current PDU is correct but confusing. Replace it with a simpler formula. Signed-off-by: Andries Kruithof (cherry picked from commit e8716bf793c45b5cc562161cdde8669e96643178) Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit 39a88e6bd34bb87e94cc995337dfc2725838ddbe) --- .../bluetooth/controller/ll_sw/ull_adv_aux.c | 31 +++++++++---------- 1 file changed, 14 insertions(+), 17 deletions(-) diff --git a/subsys/bluetooth/controller/ll_sw/ull_adv_aux.c b/subsys/bluetooth/controller/ll_sw/ull_adv_aux.c index 0754a047207..2480c286e4b 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_adv_aux.c +++ b/subsys/bluetooth/controller/ll_sw/ull_adv_aux.c @@ -411,13 +411,9 @@ uint8_t ll_adv_aux_ad_data_set(uint8_t handle, uint8_t op, uint8_t frag_pref, /* We could not fit all the data, append as much as possible * ad_len_overflow is how much overflows with the AUX ptr */ - uint8_t ad_len_overflow_first_try; const uint16_t chain_add_fields = ULL_ADV_PDU_HDR_FIELD_AD_DATA_APPEND | ULL_ADV_PDU_HDR_FIELD_AUX_PTR; - ad_len_overflow_first_try = hdr_data[ULL_ADV_HDR_DATA_DATA_PTR_OFFSET + - ULL_ADV_HDR_DATA_DATA_PTR_SIZE]; - val_ptr = hdr_data; *val_ptr++ = len; (void)memcpy(val_ptr, &data, sizeof(data)); @@ -427,18 +423,18 @@ uint8_t ll_adv_aux_ad_data_set(uint8_t handle, uint8_t op, uint8_t frag_pref, chain_err = ull_adv_aux_pdu_set_clear(adv, pdu_prev, pdu, chain_add_fields, 0U, hdr_data); - ad_len_overflow = hdr_data[ULL_ADV_HDR_DATA_AUX_PTR_PTR_OFFSET + - ULL_ADV_HDR_DATA_AUX_PTR_PTR_SIZE + - ULL_ADV_HDR_DATA_DATA_PTR_OFFSET + - ULL_ADV_HDR_DATA_DATA_PTR_SIZE]; - - /* ad_len_overflow - ad_len_overflow_first_try is the size of - * the aux pointer - * ad_len_prev is how much data is already present, ad_len is how - * much data we can add to this PDU + ad_len_chain = hdr_data[ULL_ADV_HDR_DATA_AUX_PTR_PTR_OFFSET + + ULL_ADV_HDR_DATA_AUX_PTR_PTR_SIZE + + ULL_ADV_HDR_DATA_DATA_PTR_OFFSET + + ULL_ADV_HDR_DATA_DATA_PTR_SIZE]; + + /* len is the total amount of datawe want to add + * ad_len_chain is the amount of data that does + * not fit in the current PDU + * the difference of the two is the amount that + * we can fit in the current PDU */ - ad_len = PDU_AC_PAYLOAD_SIZE_MAX - ad_len_prev - - (ad_len_overflow - ad_len_overflow_first_try) - 4; + ad_len = len - ad_len_chain; val_ptr = hdr_data; *val_ptr++ = ad_len; @@ -457,9 +453,10 @@ uint8_t ll_adv_aux_ad_data_set(uint8_t handle, uint8_t op, uint8_t frag_pref, /* * in the next PDU we still need to add ad_len_chain bytes of data * but we do not have overflow, since we already added - * the exact amount that would fit + * the exact amount that would fit. We explicitly set overflow to 0. + * FIXME: ad_len_overflow already should be 0, to be verified. We wait + * fixing this until rewriting this whole function */ - ad_len_chain = len - ad_len; ad_len_overflow = 0U; } else { ad_len_overflow = 0U; From 96efa92108ad91cec08e0c23b557433cfc0d6ddb Mon Sep 17 00:00:00 2001 From: Andries Kruithof Date: Tue, 18 Jul 2023 11:13:31 +0200 Subject: [PATCH 289/421] [nrf fromtree] Test: Bluetooth: controller: add CI testing for advertising chaining Update babblesim tests for testing chaining for advertising to ensure that we spill over to the next PDU Signed-off-by: Andries Kruithof (cherry picked from commit e04c963d9c2daf1c38e4498a19362cbed9375eea) Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit a18d656e24fb1f99b8f52039f9e197a9162f15e5) --- .../broadcaster_multiple/src/broadcaster_multiple.c | 10 +++++++++- tests/bsim/bluetooth/host/adv/chain/prj.conf | 6 +++--- tests/bsim/bluetooth/host/adv/chain/src/main.c | 10 +++++++++- 3 files changed, 21 insertions(+), 5 deletions(-) diff --git a/samples/bluetooth/broadcaster_multiple/src/broadcaster_multiple.c b/samples/bluetooth/broadcaster_multiple/src/broadcaster_multiple.c index d1c6d792e95..30fe35d3dec 100644 --- a/samples/bluetooth/broadcaster_multiple/src/broadcaster_multiple.c +++ b/samples/bluetooth/broadcaster_multiple/src/broadcaster_multiple.c @@ -47,11 +47,18 @@ BT_AD_DATA_FORMAT_LEN_SIZE - \ BT_AD_DATA_FORMAT_TYPE_SIZE - \ BT_DEVICE_NAME_AD_DATA_LEN))) - +/* + * Datalength is an integer, so BT_MFG_DATA_LEN can not be larger than 255. + * To ensure that we need to chain PDUs we therefore add manufacturer data + * twice when chaining is enabled + */ static uint8_t mfg_data[BT_MFG_DATA_LEN] = { 0xFF, 0xFF, }; static const struct bt_data ad[] = { BT_DATA(BT_DATA_MANUFACTURER_DATA, mfg_data, sizeof(mfg_data)), +#if defined(CONFIG_BT_CTLR_ADV_DATA_CHAIN) + BT_DATA(BT_DATA_MANUFACTURER_DATA, mfg_data, sizeof(mfg_data)), +#endif }; static struct bt_le_ext_adv *adv[CONFIG_BT_EXT_ADV_MAX_ADV_SET]; @@ -75,6 +82,7 @@ int broadcaster_multiple(void) printk("Bluetooth init failed (err %d)\n", err); return err; } + for (int index = 0; index < CONFIG_BT_EXT_ADV_MAX_ADV_SET; index++) { /* Use advertising set instance index as SID */ adv_param.sid = index; diff --git a/tests/bsim/bluetooth/host/adv/chain/prj.conf b/tests/bsim/bluetooth/host/adv/chain/prj.conf index 85861dccd66..82eb16e5db0 100644 --- a/tests/bsim/bluetooth/host/adv/chain/prj.conf +++ b/tests/bsim/bluetooth/host/adv/chain/prj.conf @@ -30,9 +30,9 @@ CONFIG_BT_EXT_SCAN_BUF_SIZE=1650 # Set maximum scan data length for Extended Scanning in Bluetooth LE Controller CONFIG_BT_CTLR_SCAN_DATA_LEN_MAX=1650 -# Zephyr Controller does not combine all the 1650 bytes before fragmenting them -# into 8 HCI reports, if a PDU has 255 bytes, it will generate 2 HCI reports -# and so we need to reserve 16 buffers +# The Zephyr Controller does not combine all the 1650 bytes before +# fragmenting into 8 HCI reports, if a PDU has 255 bytes, +# it will generate 2 HCI reports and so we need to reserve 16 buffers CONFIG_BT_BUF_EVT_RX_COUNT=16 # Increase Zephyr Bluetooth LE Controller Rx buffer to receive complete chain diff --git a/tests/bsim/bluetooth/host/adv/chain/src/main.c b/tests/bsim/bluetooth/host/adv/chain/src/main.c index 4475a069535..d58d2a3890f 100644 --- a/tests/bsim/bluetooth/host/adv/chain/src/main.c +++ b/tests/bsim/bluetooth/host/adv/chain/src/main.c @@ -34,8 +34,12 @@ #define NAME_LEN 30 #define BT_AD_DATA_NAME_SIZE (sizeof(CONFIG_BT_DEVICE_NAME) - 1U + 2U) #define BT_AD_DATA_MFG_DATA_SIZE (254U + 2U) +/* + * for testing chaining the manufacturing data is duplicated, hence DATA_LEN needs to + * add twice the size for this element + */ #define DATA_LEN MIN((BT_AD_DATA_NAME_SIZE + \ - BT_AD_DATA_MFG_DATA_SIZE), \ + BT_AD_DATA_MFG_DATA_SIZE + BT_AD_DATA_MFG_DATA_SIZE), \ CONFIG_BT_CTLR_ADV_DATA_LEN_MAX) static K_SEM_DEFINE(sem_recv, 0, 1); @@ -94,6 +98,7 @@ static void scan_recv(const struct bt_le_scan_recv_info *info, data_len = buf->len; if (data_len != DATA_LEN) { + printk("Received datalength: %d\n", data_len); return; } @@ -101,11 +106,13 @@ static void scan_recv(const struct bt_le_scan_recv_info *info, bt_data_parse(buf, data_cb, name); if (strcmp(name, CONFIG_BT_DEVICE_NAME)) { + printk("Wrong name %s\n", name); return; } for (uint8_t i = 0; i < sid_count; i++) { if (sid[i] == info->sid) { + printk("Received SID %d\n", info->sid); return; } } @@ -113,6 +120,7 @@ static void scan_recv(const struct bt_le_scan_recv_info *info, sid[sid_count++] = info->sid; if (sid_count < CONFIG_BT_EXT_ADV_MAX_ADV_SET) { + printk("Received advertising sets: %d\n", sid_count); return; } From 7b202de62b4f1ed8938747b4664972b02b565942 Mon Sep 17 00:00:00 2001 From: Alberto Escolar Piedras Date: Tue, 12 Sep 2023 09:43:08 +0200 Subject: [PATCH 290/421] [nrf fromtree] nrf5x_bsim: Add helper kconfig symbols for simulated nrf5340 Just like for the nrf52_bsim let's add helper kconfig symbols which can be used to identify we are running in a target that is compatible with the real HW but is not the real HW. Signed-off-by: Alberto Escolar Piedras (cherry picked from commit 0e8f97df49a497de4a71d681bc34f429b239862c) Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit 7f9da74cbc9552984bac1b7fc9d08823aaf2b90d) --- boards/posix/nrf52_bsim/Kconfig | 6 ++++++ soc/Kconfig | 12 ++++++++++-- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/boards/posix/nrf52_bsim/Kconfig b/boards/posix/nrf52_bsim/Kconfig index ea1b49bea0a..566520fafa0 100644 --- a/boards/posix/nrf52_bsim/Kconfig +++ b/boards/posix/nrf52_bsim/Kconfig @@ -26,3 +26,9 @@ config SOC_SERIES_BSIM_NRF52X depends on SOC_SERIES_BSIM_NRFXX help Any NRF52 simulated SOC with BabbleSim, based on the POSIX arch + +config SOC_SERIES_BSIM_NRF53X + bool + depends on SOC_SERIES_BSIM_NRFXX + help + Any NRF53 simulated SOC with BabbleSim, based on the POSIX arch diff --git a/soc/Kconfig b/soc/Kconfig index 20734c0f51f..33c2d0c29a4 100644 --- a/soc/Kconfig +++ b/soc/Kconfig @@ -24,8 +24,7 @@ source "subsys/logging/Kconfig.template.log_config" endmenu # The helper symbols below are put here due to an unusual setup: The simulated -# nrf52_bsim board uses the POSIX arch, but is compatible with Nordic ARM -# boards +# nrf5x_bsim boards use the POSIX arch, but are compatible with Nordic ARM boards config SOC_COMPATIBLE_NRF bool @@ -33,9 +32,18 @@ config SOC_COMPATIBLE_NRF config SOC_COMPATIBLE_NRF52X bool +config SOC_COMPATIBLE_NRF53X + bool + config SOC_COMPATIBLE_NRF52833 bool +config SOC_COMPATIBLE_NRF5340_CPUNET + bool + +config SOC_COMPATIBLE_NRF5340_CPUAPP + bool + # # SOC_*_LD: SoC specific Linker script additions # From ff4e15ae36af8fc8abe680e8a418f882d97e731d Mon Sep 17 00:00:00 2001 From: Alberto Escolar Piedras Date: Thu, 21 Sep 2023 08:45:38 +0200 Subject: [PATCH 291/421] [nrf fromtree] soc nordic_nrf: Select new compatible kconfig options Select the newly introduced nrf53 compatible kconfig options. These are common both for real HW and for simulated HW, allowing SW to behave appropriately for both. Signed-off-by: Alberto Escolar Piedras (cherry picked from commit c7c3c82aa0104c7063879d8d4a27a0d5c6b29c0a) Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit 509f1bc70c6a0ff7d706de9c049d32875d54eea2) --- soc/arm/nordic_nrf/nrf53/Kconfig.series | 1 + soc/arm/nordic_nrf/nrf53/Kconfig.soc | 2 ++ 2 files changed, 3 insertions(+) diff --git a/soc/arm/nordic_nrf/nrf53/Kconfig.series b/soc/arm/nordic_nrf/nrf53/Kconfig.series index 03e47bacf63..8ab81ad310b 100644 --- a/soc/arm/nordic_nrf/nrf53/Kconfig.series +++ b/soc/arm/nordic_nrf/nrf53/Kconfig.series @@ -6,6 +6,7 @@ config SOC_SERIES_NRF53X bool "Nordic Semiconductor nRF53 series MCU" select ARM + select SOC_COMPATIBLE_NRF53X select CPU_CORTEX_M33 select CPU_CORTEX_M_HAS_DWT select CPU_HAS_ARM_MPU diff --git a/soc/arm/nordic_nrf/nrf53/Kconfig.soc b/soc/arm/nordic_nrf/nrf53/Kconfig.soc index 2ad4a7add66..87d8a6d0c7a 100644 --- a/soc/arm/nordic_nrf/nrf53/Kconfig.soc +++ b/soc/arm/nordic_nrf/nrf53/Kconfig.soc @@ -10,11 +10,13 @@ config SOC_NRF5340_CPUAPP select CPU_HAS_FPU select ARMV8_M_DSP select HAS_POWEROFF + select SOC_COMPATIBLE_NRF5340_CPUAPP imply SOC_NRF53_RTC_PRETICK config SOC_NRF5340_CPUNET bool select ARM_ON_EXIT_CPU_IDLE + select SOC_COMPATIBLE_NRF5340_CPUNET imply SOC_NRF53_ANOMALY_160_WORKAROUND_NEEDED imply SOC_NRF53_RTC_PRETICK if !WDT_NRFX From 9530f3bfb97b911974d607a58bd00cdab7887fa3 Mon Sep 17 00:00:00 2001 From: Nirosharn Amarasinghe Date: Wed, 5 Jul 2023 16:13:20 +0200 Subject: [PATCH 292/421] [nrf fromtree] tests: bluetooth: controller: Test for framed TX in consecutive events Changes: -- Included a test to check TX in concesecutive events irrespective of the input target event -- Updated expected output of current tests for change in framed RX error handling which waiting for the start of an event Signed-off-by: Nirosharn Amarasinghe (cherry picked from commit ec2093862784369892b2a386c9399a0c98267858) Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit 791b3edfb4af63a2ec79f8a0f006e3d56894014a) --- .../ctrl_isoal/src/sub_sets/isoal_test_rx.c | 109 +-- .../ctrl_isoal/src/sub_sets/isoal_test_tx.c | 754 ++++++++++++++---- 2 files changed, 682 insertions(+), 181 deletions(-) diff --git a/tests/bluetooth/ctrl_isoal/src/sub_sets/isoal_test_rx.c b/tests/bluetooth/ctrl_isoal/src/sub_sets/isoal_test_rx.c index 2ce8862e1d4..5a3c60e0854 100644 --- a/tests/bluetooth/ctrl_isoal/src/sub_sets/isoal_test_rx.c +++ b/tests/bluetooth/ctrl_isoal/src/sub_sets/isoal_test_rx.c @@ -8332,27 +8332,30 @@ ZTEST(test_rx_framed, test_rx_framed_dbl_pdu_dbl_sdu_pdu_err1) */ ZTEST(test_rx_framed, test_rx_framed_dbl_pdu_dbl_sdu_pdu_err2) { + const uint8_t test_data_size = 33; + const uint8_t max_sdu_burst = 2; + + struct rx_sdu_frag_buffer rx_sdu_frag_buf[max_sdu_burst]; + struct isoal_sdu_buffer sdu_buffer[max_sdu_burst]; + isoal_sdu_status_t collated_status[max_sdu_burst]; struct rx_pdu_meta_buffer rx_pdu_meta_buf; - struct rx_sdu_frag_buffer rx_sdu_frag_buf; - struct isoal_sdu_buffer sdu_buffer; - isoal_sdu_status_t collated_status; + isoal_sdu_len_t sdu_size[max_sdu_burst]; + uint16_t total_sdu_size[max_sdu_burst]; + uint32_t sdu_timestamp[max_sdu_burst]; + uint8_t testdata[test_data_size]; isoal_sink_handle_t sink_hdl; uint32_t stream_sync_delay; uint32_t group_sync_delay; - isoal_sdu_len_t sdu_size; uint8_t iso_interval_int; uint16_t pdu_data_loc[5]; uint32_t iso_interval_us; uint64_t payload_number; - uint16_t total_sdu_size; uint32_t sdu_timeoffset; uint32_t pdu_timestamp; - uint32_t sdu_timestamp; uint16_t testdata_indx; uint16_t testdata_size; uint32_t sdu_interval; isoal_sdu_cnt_t seqn; - uint8_t testdata[33]; isoal_status_t err; uint32_t latency; uint8_t role; @@ -8371,12 +8374,14 @@ ZTEST(test_rx_framed, test_rx_framed_dbl_pdu_dbl_sdu_pdu_err2) /* PDU 1 -------------------------------------------------------------*/ isoal_test_init_rx_pdu_buffer(&rx_pdu_meta_buf); - isoal_test_init_rx_sdu_buffer(&rx_sdu_frag_buf); - init_test_data_buffer(testdata, 33); + isoal_test_init_rx_sdu_buffer(&rx_sdu_frag_buf[0]); + init_test_data_buffer(testdata, test_data_size); memset(pdu_data_loc, 0, sizeof(pdu_data_loc)); - sdu_buffer.dbuf = &rx_sdu_frag_buf; - sdu_buffer.size = TEST_RX_SDU_FRAG_PAYLOAD_MAX; + sdu_buffer[0].dbuf = &rx_sdu_frag_buf[0]; + sdu_buffer[0].size = TEST_RX_SDU_FRAG_PAYLOAD_MAX; + sdu_buffer[1].dbuf = &rx_sdu_frag_buf[1]; + sdu_buffer[1].size = TEST_RX_SDU_FRAG_PAYLOAD_MAX; payload_number = 1000 * BN; pdu_timestamp = 9249; latency = calc_rx_latency_by_role(role, @@ -8388,13 +8393,13 @@ ZTEST(test_rx_framed, test_rx_framed_dbl_pdu_dbl_sdu_pdu_err2) group_sync_delay); sdu_timeoffset = group_sync_delay - 50; /* PDU will have errors. Time stamp is only an approximation */ - sdu_timestamp = (uint32_t)((int64_t)pdu_timestamp + latency - iso_interval_us); + sdu_timestamp[0] = (uint32_t)((int64_t)pdu_timestamp + latency - iso_interval_us); seqn = 0; testdata_indx = 0; testdata_size = 23; - sdu_size = 0; - total_sdu_size = COLLATED_RX_SDU_INFO(sdu_size, sdu_size); - collated_status = + sdu_size[0] = 0; + total_sdu_size[0] = COLLATED_RX_SDU_INFO(sdu_size[0], sdu_size[0]); + collated_status[0] = COLLATED_RX_SDU_INFO(ISOAL_SDU_STATUS_LOST_DATA, ISOAL_SDU_STATUS_LOST_DATA); sink_hdl = basic_rx_test_setup(0xADAD, /* Handle */ @@ -8418,7 +8423,7 @@ ZTEST(test_rx_framed, test_rx_framed_dbl_pdu_dbl_sdu_pdu_err2) &rx_pdu_meta_buf.pdu_meta); /* Set callback function return values */ - push_custom_sink_sdu_alloc_test_output_buffer(&sdu_buffer); + push_custom_sink_sdu_alloc_test_output_buffer(&sdu_buffer[0]); sink_sdu_alloc_test_fake.return_val = ISOAL_STATUS_OK; sink_sdu_write_test_fake.return_val = ISOAL_STATUS_OK; sink_sdu_emit_test_fake.return_val = ISOAL_STATUS_OK; @@ -8428,25 +8433,14 @@ ZTEST(test_rx_framed, test_rx_framed_dbl_pdu_dbl_sdu_pdu_err2) zassert_equal(err, ISOAL_STATUS_OK, "err = 0x%02x", err); /* Test recombine (Black Box) */ - /* A new SDU should be allocated */ - ZASSERT_ISOAL_SDU_ALLOC_TEST(val, - &isoal_global.sink_state[sink_hdl], /* Sink */ - &rx_pdu_meta_buf.pdu_meta); /* PDU */ + /* A new SDU should not be allocated */ + ZASSERT_ISOAL_SDU_ALLOC_TEST_CALL_COUNT(0); /* SDU payload should not be written */ + ZASSERT_ISOAL_SDU_WRITE_TEST_CALL_COUNT(0); - /* SDU should be emitted */ - ZASSERT_ISOAL_SDU_EMIT_TEST(val, - &isoal_global.sink_state[sink_hdl], /* Sink */ - BT_ISO_SINGLE, /* Frag state */ - sdu_size, /* Frag size */ - ISOAL_SDU_STATUS_LOST_DATA, /* Frag status */ - sdu_timestamp, /* Timestamp */ - seqn, /* Seq. number */ - sdu_buffer.dbuf, /* Buffer */ - sdu_buffer.size, /* Buffer size */ - total_sdu_size, /* Total size */ - collated_status); /* SDU status */ + /* SDU should not be emitted */ + ZASSERT_ISOAL_SDU_EMIT_TEST_CALL_COUNT(0); /* Test recombine (White Box) */ zassert_equal(isoal_global.sink_state[sink_hdl].sdu_production.fsm, @@ -8457,18 +8451,17 @@ ZTEST(test_rx_framed, test_rx_framed_dbl_pdu_dbl_sdu_pdu_err2) /* PDU 2 -------------------------------------------------------------*/ isoal_test_init_rx_pdu_buffer(&rx_pdu_meta_buf); - isoal_test_init_rx_sdu_buffer(&rx_sdu_frag_buf); + isoal_test_init_rx_sdu_buffer(&rx_sdu_frag_buf[1]); payload_number++; sdu_timeoffset = get_next_time_offset(sdu_timeoffset, iso_interval_us, sdu_interval, false); - sdu_timestamp = (uint32_t)((int64_t)pdu_timestamp + latency - sdu_timeoffset); - seqn++; + sdu_timestamp[1] = (uint32_t)((int64_t)pdu_timestamp + latency - sdu_timeoffset); testdata_indx = testdata_size; testdata_size += 10; - sdu_size = 10; - total_sdu_size = COLLATED_RX_SDU_INFO(sdu_size, sdu_size); - collated_status = COLLATED_RX_SDU_INFO(ISOAL_SDU_STATUS_VALID, ISOAL_SDU_STATUS_VALID); + sdu_size[1] = 10; + total_sdu_size[1] = COLLATED_RX_SDU_INFO(sdu_size[1], sdu_size[1]); + collated_status[1] = COLLATED_RX_SDU_INFO(ISOAL_SDU_STATUS_VALID, ISOAL_SDU_STATUS_VALID); isoal_test_create_framed_pdu_base(payload_number, pdu_timestamp, @@ -8480,7 +8473,7 @@ ZTEST(test_rx_framed, test_rx_framed_dbl_pdu_dbl_sdu_pdu_err2) &rx_pdu_meta_buf.pdu_meta); /* Set callback function return values */ - push_custom_sink_sdu_alloc_test_output_buffer(&sdu_buffer); + push_custom_sink_sdu_alloc_test_output_buffer(&sdu_buffer[1]); sink_sdu_alloc_test_fake.return_val = ISOAL_STATUS_OK; sink_sdu_write_test_fake.return_val = ISOAL_STATUS_OK; sink_sdu_emit_test_fake.return_val = ISOAL_STATUS_OK; @@ -8490,14 +8483,38 @@ ZTEST(test_rx_framed, test_rx_framed_dbl_pdu_dbl_sdu_pdu_err2) zassert_equal(err, ISOAL_STATUS_OK, "err = 0x%02x", err); /* Test recombine (Black Box) */ + /* SDU 0 -------------------------------------------------------------*/ + /* A new SDU should be allocated */ + ZASSERT_ISOAL_SDU_ALLOC_TEST(history[0], + &isoal_global.sink_state[sink_hdl], /* Sink */ + &rx_pdu_meta_buf.pdu_meta); /* PDU */ + + /* SDU payload should not be written */ + + /* SDU should be emitted */ + ZASSERT_ISOAL_SDU_EMIT_TEST(history[0], + &isoal_global.sink_state[sink_hdl], /* Sink */ + BT_ISO_SINGLE, /* Frag state */ + sdu_size[0], /* Frag size */ + ISOAL_SDU_STATUS_LOST_DATA, /* Frag status */ + sdu_timestamp[0], /* Timestamp */ + seqn, /* Seq. number */ + sdu_buffer[0].dbuf, /* Buffer */ + sdu_buffer[0].size, /* Buffer size */ + total_sdu_size[0], /* Total size */ + collated_status[0]); /* SDU status */ + + /* SDU 1 -------------------------------------------------------------*/ + seqn++; /* A new SDU should be allocated */ ZASSERT_ISOAL_SDU_ALLOC_TEST(val, &isoal_global.sink_state[sink_hdl], /* Sink */ &rx_pdu_meta_buf.pdu_meta); /* PDU */ /* SDU payload should be written */ + ZASSERT_ISOAL_SDU_WRITE_TEST_CALL_COUNT(1); ZASSERT_ISOAL_SDU_WRITE_TEST(val, - &rx_sdu_frag_buf, /* SDU buffer */ + &rx_sdu_frag_buf[1], /* SDU buffer */ &rx_pdu_meta_buf.pdu[3 + pdu_data_loc[1]], /* PDU payload */ (testdata_size - testdata_indx)); /* Size */ @@ -8506,14 +8523,14 @@ ZTEST(test_rx_framed, test_rx_framed_dbl_pdu_dbl_sdu_pdu_err2) ZASSERT_ISOAL_SDU_EMIT_TEST(val, &isoal_global.sink_state[sink_hdl], /* Sink */ BT_ISO_SINGLE, /* Frag state */ - sdu_size, /* Frag size */ + sdu_size[1], /* Frag size */ ISOAL_SDU_STATUS_VALID, /* Frag status */ - sdu_timestamp, /* Timestamp */ + sdu_timestamp[1], /* Timestamp */ seqn, /* Seq. number */ - sdu_buffer.dbuf, /* Buffer */ - sdu_buffer.size, /* Buffer size */ - total_sdu_size, /* Total size */ - collated_status); /* SDU status */ + sdu_buffer[1].dbuf, /* Buffer */ + sdu_buffer[1].size, /* Buffer size */ + total_sdu_size[1], /* Total size */ + collated_status[1]); /* SDU status */ /* Test recombine (White Box) */ zassert_equal(isoal_global.sink_state[sink_hdl].sdu_production.fsm, diff --git a/tests/bluetooth/ctrl_isoal/src/sub_sets/isoal_test_tx.c b/tests/bluetooth/ctrl_isoal/src/sub_sets/isoal_test_tx.c index fe375b7accd..dc21c9b5d61 100644 --- a/tests/bluetooth/ctrl_isoal/src/sub_sets/isoal_test_tx.c +++ b/tests/bluetooth/ctrl_isoal/src/sub_sets/isoal_test_tx.c @@ -111,7 +111,8 @@ static void push_custom_source_pdu_write_test_sdu_payload(const uint8_t *data, c } static void check_next_custom_source_pdu_write_test_sdu_payload(const uint8_t *data, - const size_t length) + const size_t length, + const uint32_t line) { size_t pos = custom_source_pdu_write_test_sdu_payloads.pos; size_t buffer_size = custom_source_pdu_write_test_sdu_payloads.buffer_size; @@ -125,7 +126,8 @@ static void check_next_custom_source_pdu_write_test_sdu_payload(const uint8_t *d for (size_t i = 0; i < custom_source_pdu_write_test_sdu_payloads.out_size[pos]; i++) { zassert_equal(custom_source_pdu_write_test_sdu_payloads.out[pos][i], data[i], - "deviation at index %u, expected %u, got %u", + "[Line %lu] deviation at index %u, expected %u, got %u", + line, i, data[i], custom_source_pdu_write_test_sdu_payloads.out[pos][i]); @@ -193,7 +195,7 @@ static isoal_status_t custom_source_pdu_write_test(struct isoal_pdu_buffer *pdu_ _consume_len, \ source_pdu_write_test_fake.arg3_##_typ); \ check_next_custom_source_pdu_write_test_sdu_payload((const uint8_t *)_sdu_payload, \ - _consume_len); + _consume_len, __LINE__); #define ZASSERT_PDU_WRITE_TEST_CALL_COUNT(_expected) \ zassert_equal(_expected, \ @@ -422,7 +424,7 @@ static isoal_source_handle_t basic_tx_test_setup(uint16_t handle, burst_number, flush_timeout, max_octets, - (iso_interval_int * CONN_INT_UNIT_US), + (iso_interval_int * ISO_INT_UNIT_US), sdu_interval, stream_sync_delay, group_sync_delay); @@ -536,8 +538,8 @@ ZTEST(test_tx_basics, test_source_isoal_test_create_destroy) max_octets = 40; sdu_interval_int = 1; iso_interval_int = 1; - iso_interval = iso_interval_int * CONN_INT_UNIT_US; - sdu_interval = sdu_interval_int * CONN_INT_UNIT_US; + iso_interval = iso_interval_int * ISO_INT_UNIT_US; + sdu_interval = sdu_interval_int * ISO_INT_UNIT_US; stream_sync_delay = iso_interval - 200; group_sync_delay = iso_interval - 50; @@ -606,8 +608,8 @@ ZTEST(test_tx_basics, test_source_isoal_test_create_destroy) max_octets += max_octets / 2; sdu_interval_int++; iso_interval_int = iso_interval_int * sdu_interval_int; - sdu_interval = (sdu_interval_int * CONN_INT_UNIT_US) - (framed ? 100 : 0); - iso_interval = iso_interval_int * CONN_INT_UNIT_US; + sdu_interval = (sdu_interval_int * ISO_INT_UNIT_US) - (framed ? 100 : 0); + iso_interval = iso_interval_int * ISO_INT_UNIT_US; stream_sync_delay = iso_interval - (200 * i); group_sync_delay = iso_interval - 50; } @@ -654,9 +656,9 @@ ZTEST(test_tx_basics, test_source_isoal_test_create_err) flush_timeout = 1; framed = false; iso_interval_int = 1; - sdu_interval = CONN_INT_UNIT_US; - stream_sync_delay = CONN_INT_UNIT_US - 200; - group_sync_delay = CONN_INT_UNIT_US - 50; + sdu_interval = ISO_INT_UNIT_US; + stream_sync_delay = ISO_INT_UNIT_US - 200; + group_sync_delay = ISO_INT_UNIT_US - 50; res = isoal_init(); zassert_equal(res, ISOAL_STATUS_OK, "res = 0x%02x", res); @@ -747,12 +749,12 @@ ZTEST(test_tx_unframed, test_tx_unframed_1_sdu_1_frag_1_pdu_maxPDU) /* Settings */ role = ISOAL_ROLE_PERIPHERAL; iso_interval_int = 1; - sdu_interval = CONN_INT_UNIT_US; + sdu_interval = ISO_INT_UNIT_US; max_octets = TEST_TX_PDU_PAYLOAD_MAX - 5; BN = 1; FT = 1; - stream_sync_delay = (iso_interval_int * CONN_INT_UNIT_US) - 200; - group_sync_delay = (iso_interval_int * CONN_INT_UNIT_US) - 50; + stream_sync_delay = (iso_interval_int * ISO_INT_UNIT_US) - 200; + group_sync_delay = (iso_interval_int * ISO_INT_UNIT_US) - 50; /* SDU Frag 1 --------------------------------------------------------*/ isoal_test_init_tx_pdu_buffer(&tx_pdu_meta_buf); @@ -764,7 +766,7 @@ ZTEST(test_tx_unframed, test_tx_unframed_1_sdu_1_frag_1_pdu_maxPDU) sdu_packet_number = 2000; event_number = 2000; sdu_timestamp = 9249; - ref_point = sdu_timestamp + (iso_interval_int * CONN_INT_UNIT_US) - 50; + ref_point = sdu_timestamp + (iso_interval_int * ISO_INT_UNIT_US) - 50; sdu_total_size = TEST_TX_PDU_PAYLOAD_MAX - 5; testdata_indx = 0; testdata_size = TEST_TX_PDU_PAYLOAD_MAX - 5; @@ -875,12 +877,12 @@ ZTEST(test_tx_unframed, test_tx_unframed_1_sdu_1_frag_1_pdu_bufSize) /* Settings */ role = ISOAL_ROLE_PERIPHERAL; iso_interval_int = 1; - sdu_interval = CONN_INT_UNIT_US; + sdu_interval = ISO_INT_UNIT_US; max_octets = TEST_TX_PDU_PAYLOAD_MAX + 5; BN = 1; FT = 1; - stream_sync_delay = (iso_interval_int * CONN_INT_UNIT_US) - 200; - group_sync_delay = (iso_interval_int * CONN_INT_UNIT_US) - 50; + stream_sync_delay = (iso_interval_int * ISO_INT_UNIT_US) - 200; + group_sync_delay = (iso_interval_int * ISO_INT_UNIT_US) - 50; /* SDU Frag 1 --------------------------------------------------------*/ isoal_test_init_tx_pdu_buffer(&tx_pdu_meta_buf); @@ -892,7 +894,7 @@ ZTEST(test_tx_unframed, test_tx_unframed_1_sdu_1_frag_1_pdu_bufSize) sdu_packet_number = 2000; event_number = 2000; sdu_timestamp = 9249; - ref_point = sdu_timestamp + (iso_interval_int * CONN_INT_UNIT_US) - 50; + ref_point = sdu_timestamp + (iso_interval_int * ISO_INT_UNIT_US) - 50; sdu_total_size = TEST_TX_PDU_PAYLOAD_MAX; testdata_indx = 0; testdata_size = TEST_TX_PDU_PAYLOAD_MAX; @@ -993,12 +995,12 @@ ZTEST(test_tx_unframed, test_tx_unframed_1_sdu_1_frag_3_pdu) /* Settings */ role = ISOAL_ROLE_PERIPHERAL; iso_interval_int = 1; - sdu_interval = CONN_INT_UNIT_US; + sdu_interval = ISO_INT_UNIT_US; max_octets = TEST_TX_PDU_PAYLOAD_MAX - 5; BN = 3; FT = 1; - stream_sync_delay = (iso_interval_int * CONN_INT_UNIT_US) - 200; - group_sync_delay = (iso_interval_int * CONN_INT_UNIT_US) - 50; + stream_sync_delay = (iso_interval_int * ISO_INT_UNIT_US) - 200; + group_sync_delay = (iso_interval_int * ISO_INT_UNIT_US) - 50; /* SDU Frag 1 --------------------------------------------------------*/ isoal_test_init_tx_pdu_buffer(&tx_pdu_meta_buf); @@ -1010,7 +1012,7 @@ ZTEST(test_tx_unframed, test_tx_unframed_1_sdu_1_frag_3_pdu) sdu_packet_number = 2000; event_number = 2000; sdu_timestamp = 9249; - ref_point = sdu_timestamp + (iso_interval_int * CONN_INT_UNIT_US) - 50; + ref_point = sdu_timestamp + (iso_interval_int * ISO_INT_UNIT_US) - 50; sdu_total_size = 100; testdata_indx = 0; testdata_size = 100; @@ -1152,12 +1154,12 @@ ZTEST(test_tx_unframed, test_tx_unframed_1_sdu_3_frag_1_pdu) /* Settings */ role = ISOAL_ROLE_PERIPHERAL; iso_interval_int = 1; - sdu_interval = CONN_INT_UNIT_US; + sdu_interval = ISO_INT_UNIT_US; max_octets = TEST_TX_PDU_PAYLOAD_MAX + 5; BN = 1; FT = 1; - stream_sync_delay = (iso_interval_int * CONN_INT_UNIT_US) - 200; - group_sync_delay = (iso_interval_int * CONN_INT_UNIT_US) - 50; + stream_sync_delay = (iso_interval_int * ISO_INT_UNIT_US) - 200; + group_sync_delay = (iso_interval_int * ISO_INT_UNIT_US) - 50; /* SDU Frag 1 --------------------------------------------------------*/ isoal_test_init_tx_pdu_buffer(&tx_pdu_meta_buf); @@ -1169,7 +1171,7 @@ ZTEST(test_tx_unframed, test_tx_unframed_1_sdu_3_frag_1_pdu) sdu_packet_number = 2000; event_number = 2000; sdu_timestamp = 9249; - ref_point = sdu_timestamp + (iso_interval_int * CONN_INT_UNIT_US) - 50; + ref_point = sdu_timestamp + (iso_interval_int * ISO_INT_UNIT_US) - 50; sdu_total_size = TEST_TX_PDU_PAYLOAD_MAX; testdata_indx = 0; testdata_size = TEST_TX_PDU_PAYLOAD_MAX / 3; @@ -1357,12 +1359,12 @@ ZTEST(test_tx_unframed, test_tx_unframed_1_sdu_3_frag_2_pdu) /* Settings */ role = ISOAL_ROLE_PERIPHERAL; iso_interval_int = 1; - sdu_interval = CONN_INT_UNIT_US; + sdu_interval = ISO_INT_UNIT_US; max_octets = TEST_TX_PDU_PAYLOAD_MAX + 5; BN = 2; FT = 1; - stream_sync_delay = (iso_interval_int * CONN_INT_UNIT_US) - 200; - group_sync_delay = (iso_interval_int * CONN_INT_UNIT_US) - 50; + stream_sync_delay = (iso_interval_int * ISO_INT_UNIT_US) - 200; + group_sync_delay = (iso_interval_int * ISO_INT_UNIT_US) - 50; /* SDU Frag 1 --------------------------------------------------------*/ isoal_test_init_tx_pdu_buffer(&tx_pdu_meta_buf[0]); @@ -1378,7 +1380,7 @@ ZTEST(test_tx_unframed, test_tx_unframed_1_sdu_3_frag_2_pdu) sdu_packet_number = 2000; event_number = 2000; sdu_timestamp = 9249; - ref_point = sdu_timestamp + (iso_interval_int * CONN_INT_UNIT_US) - 50; + ref_point = sdu_timestamp + (iso_interval_int * ISO_INT_UNIT_US) - 50; sdu_total_size = TEST_TX_PDU_PAYLOAD_MAX * 2; testdata_indx = 0; testdata_size = (TEST_TX_PDU_PAYLOAD_MAX * 2) / 3; @@ -1689,12 +1691,12 @@ ZTEST(test_tx_unframed, test_tx_unframed_2_sdu_1_frag_2_pdu_ts_wrap1) /* Settings */ role = ISOAL_ROLE_PERIPHERAL; iso_interval_int = 1; - sdu_interval = CONN_INT_UNIT_US; + sdu_interval = ISO_INT_UNIT_US; max_octets = TEST_TX_PDU_PAYLOAD_MAX - 5; BN = 1; FT = 1; - stream_sync_delay = (iso_interval_int * CONN_INT_UNIT_US) - 200; - group_sync_delay = (iso_interval_int * CONN_INT_UNIT_US) - 50; + stream_sync_delay = (iso_interval_int * ISO_INT_UNIT_US) - 200; + group_sync_delay = (iso_interval_int * ISO_INT_UNIT_US) - 50; /* SDU Frag 1 --------------------------------------------------------*/ isoal_test_init_tx_pdu_buffer(&tx_pdu_meta_buf); @@ -1821,7 +1823,7 @@ ZTEST(test_tx_unframed, test_tx_unframed_2_sdu_1_frag_2_pdu_ts_wrap1) /* Check TX Sync info */ tx_sync_seq_expected = 2; - tx_sync_timestamp_expected = (iso_interval_int * CONN_INT_UNIT_US) - 1; + tx_sync_timestamp_expected = (iso_interval_int * ISO_INT_UNIT_US) - 1; tx_sync_offset_expected = 0; err = isoal_tx_get_sync_info(source_hdl, &tx_sync_seq, &tx_sync_timestamp, &tx_sync_offset); @@ -1870,12 +1872,12 @@ ZTEST(test_tx_unframed, test_tx_unframed_2_sdu_3_frag_4_pdu) /* Settings */ role = ISOAL_ROLE_PERIPHERAL; iso_interval_int = 2; - sdu_interval = CONN_INT_UNIT_US; + sdu_interval = ISO_INT_UNIT_US; max_octets = TEST_TX_PDU_PAYLOAD_MAX + 5; BN = 4; FT = 1; - stream_sync_delay = (iso_interval_int * CONN_INT_UNIT_US) - 200; - group_sync_delay = (iso_interval_int * CONN_INT_UNIT_US) - 50; + stream_sync_delay = (iso_interval_int * ISO_INT_UNIT_US) - 200; + group_sync_delay = (iso_interval_int * ISO_INT_UNIT_US) - 50; /* SDU 1 Frag 1 ------------------------------------------------------*/ isoal_test_init_tx_pdu_buffer(&tx_pdu_meta_buf[0]); @@ -1891,7 +1893,7 @@ ZTEST(test_tx_unframed, test_tx_unframed_2_sdu_3_frag_4_pdu) sdu_packet_number = 2000; event_number = 2000; sdu_timestamp = 9249; - ref_point = sdu_timestamp + (iso_interval_int * CONN_INT_UNIT_US) - 50; + ref_point = sdu_timestamp + (iso_interval_int * ISO_INT_UNIT_US) - 50; sdu_total_size = TEST_TX_PDU_PAYLOAD_MAX * 2; testdata_indx = 0; testdata_size = (TEST_TX_PDU_PAYLOAD_MAX * 2) / 3; @@ -2264,12 +2266,12 @@ ZTEST(test_tx_unframed, test_tx_unframed_2_sdu_3_frag_4_pdu_padding) /* Settings */ role = ISOAL_ROLE_PERIPHERAL; iso_interval_int = 2; - sdu_interval = CONN_INT_UNIT_US; + sdu_interval = ISO_INT_UNIT_US; max_octets = TEST_TX_PDU_PAYLOAD_MAX + 5; BN = 8; FT = 1; - stream_sync_delay = (iso_interval_int * CONN_INT_UNIT_US) - 200; - group_sync_delay = (iso_interval_int * CONN_INT_UNIT_US) - 50; + stream_sync_delay = (iso_interval_int * ISO_INT_UNIT_US) - 200; + group_sync_delay = (iso_interval_int * ISO_INT_UNIT_US) - 50; /* SDU 1 Frag 1 ------------------------------------------------------*/ isoal_test_init_tx_pdu_buffer(&tx_pdu_meta_buf[0]); @@ -2289,7 +2291,7 @@ ZTEST(test_tx_unframed, test_tx_unframed_2_sdu_3_frag_4_pdu_padding) sdu_packet_number = 2000; event_number = 2000; sdu_timestamp = 9249; - ref_point = sdu_timestamp + (iso_interval_int * CONN_INT_UNIT_US) - 50; + ref_point = sdu_timestamp + (iso_interval_int * ISO_INT_UNIT_US) - 50; sdu_total_size = TEST_TX_PDU_PAYLOAD_MAX * 2; testdata_indx = 0; testdata_size = (TEST_TX_PDU_PAYLOAD_MAX * 2) / 3; @@ -2739,12 +2741,12 @@ ZTEST(test_tx_unframed, test_tx_unframed_1_zero_sdu_1_frag_1_pdu_maxPDU_padding) /* Settings */ role = ISOAL_ROLE_PERIPHERAL; iso_interval_int = 1; - sdu_interval = CONN_INT_UNIT_US; + sdu_interval = ISO_INT_UNIT_US; max_octets = TEST_TX_PDU_PAYLOAD_MAX - 5; BN = 3; FT = 1; - stream_sync_delay = (iso_interval_int * CONN_INT_UNIT_US) - 200; - group_sync_delay = (iso_interval_int * CONN_INT_UNIT_US) - 50; + stream_sync_delay = (iso_interval_int * ISO_INT_UNIT_US) - 200; + group_sync_delay = (iso_interval_int * ISO_INT_UNIT_US) - 50; /* SDU 1 Frag 1 ------------------------------------------------------*/ isoal_test_init_tx_pdu_buffer(&tx_pdu_meta_buf[0]); @@ -2764,7 +2766,7 @@ ZTEST(test_tx_unframed, test_tx_unframed_1_zero_sdu_1_frag_1_pdu_maxPDU_padding) sdu_packet_number = 2000; event_number = 2000; sdu_timestamp = 9249; - ref_point = sdu_timestamp + (iso_interval_int * CONN_INT_UNIT_US) - 50; + ref_point = sdu_timestamp + (iso_interval_int * ISO_INT_UNIT_US) - 50; sdu_total_size = 0; testdata_indx = 0; testdata_size = 0; @@ -2907,12 +2909,12 @@ ZTEST(test_tx_unframed, test_tx_unframed_1_sdu_1_frag_pdu_alloc_err) /* Settings */ role = ISOAL_ROLE_PERIPHERAL; iso_interval_int = 1; - sdu_interval = CONN_INT_UNIT_US; + sdu_interval = ISO_INT_UNIT_US; max_octets = TEST_TX_PDU_PAYLOAD_MAX - 5; BN = 1; FT = 1; - stream_sync_delay = (iso_interval_int * CONN_INT_UNIT_US) - 200; - group_sync_delay = (iso_interval_int * CONN_INT_UNIT_US) - 50; + stream_sync_delay = (iso_interval_int * ISO_INT_UNIT_US) - 200; + group_sync_delay = (iso_interval_int * ISO_INT_UNIT_US) - 50; /* SDU Frag 1 --------------------------------------------------------*/ isoal_test_init_tx_pdu_buffer(&tx_pdu_meta_buf); @@ -2924,7 +2926,7 @@ ZTEST(test_tx_unframed, test_tx_unframed_1_sdu_1_frag_pdu_alloc_err) sdu_packet_number = 2000; event_number = 2000; sdu_timestamp = 9249; - ref_point = sdu_timestamp + (iso_interval_int * CONN_INT_UNIT_US) - 50; + ref_point = sdu_timestamp + (iso_interval_int * ISO_INT_UNIT_US) - 50; sdu_total_size = TEST_TX_PDU_PAYLOAD_MAX - 5; testdata_indx = 0; testdata_size = TEST_TX_PDU_PAYLOAD_MAX - 5; @@ -3024,12 +3026,12 @@ ZTEST(test_tx_unframed, test_tx_unframed_1_sdu_1_frag_pdu_emit_err) /* Settings */ role = ISOAL_ROLE_PERIPHERAL; iso_interval_int = 1; - sdu_interval = CONN_INT_UNIT_US; + sdu_interval = ISO_INT_UNIT_US; max_octets = TEST_TX_PDU_PAYLOAD_MAX - 5; BN = 1; FT = 1; - stream_sync_delay = (iso_interval_int * CONN_INT_UNIT_US) - 200; - group_sync_delay = (iso_interval_int * CONN_INT_UNIT_US) - 50; + stream_sync_delay = (iso_interval_int * ISO_INT_UNIT_US) - 200; + group_sync_delay = (iso_interval_int * ISO_INT_UNIT_US) - 50; /* SDU Frag 1 --------------------------------------------------------*/ isoal_test_init_tx_pdu_buffer(&tx_pdu_meta_buf); @@ -3041,7 +3043,7 @@ ZTEST(test_tx_unframed, test_tx_unframed_1_sdu_1_frag_pdu_emit_err) sdu_packet_number = 2000; event_number = 2000; sdu_timestamp = 9249; - ref_point = sdu_timestamp + (iso_interval_int * CONN_INT_UNIT_US) - 50; + ref_point = sdu_timestamp + (iso_interval_int * ISO_INT_UNIT_US) - 50; sdu_total_size = TEST_TX_PDU_PAYLOAD_MAX - 5; testdata_indx = 0; testdata_size = TEST_TX_PDU_PAYLOAD_MAX - 5; @@ -3153,12 +3155,12 @@ ZTEST(test_tx_unframed, test_tx_unframed_4_sdu_1_frag_4_pdu_stream_loc) /* Settings */ role = ISOAL_ROLE_PERIPHERAL; iso_interval_int = 1; - sdu_interval = CONN_INT_UNIT_US / 2; + sdu_interval = ISO_INT_UNIT_US / 2; max_octets = TEST_TX_PDU_PAYLOAD_MAX - 5; BN = 2; FT = 1; - stream_sync_delay = (iso_interval_int * CONN_INT_UNIT_US) - 200; - group_sync_delay = (iso_interval_int * CONN_INT_UNIT_US) - 50; + stream_sync_delay = (iso_interval_int * ISO_INT_UNIT_US) - 200; + group_sync_delay = (iso_interval_int * ISO_INT_UNIT_US) - 50; /* SDU Frag 1 --------------------------------------------------------*/ /* Sets initial fragmentation status */ @@ -3171,7 +3173,7 @@ ZTEST(test_tx_unframed, test_tx_unframed_4_sdu_1_frag_4_pdu_stream_loc) event_number = 2000; sdu_packet_number = (event_number * BN); sdu_timestamp = 9249; - ref_point = sdu_timestamp + (iso_interval_int * CONN_INT_UNIT_US) - 50; + ref_point = sdu_timestamp + (iso_interval_int * ISO_INT_UNIT_US) - 50; sdu_total_size = 23; testdata_indx = 0; testdata_size = 23; @@ -3253,9 +3255,9 @@ ZTEST(test_tx_unframed, test_tx_unframed_4_sdu_1_frag_4_pdu_stream_loc) isoal_test_init_tx_pdu_buffer(&tx_pdu_meta_buf); isoal_test_init_tx_sdu_buffer(&tx_sdu_frag_buf); sdu_packet_number += 29; - sdu_timestamp += ((iso_interval_int * CONN_INT_UNIT_US) * 15) - sdu_interval; + sdu_timestamp += ((iso_interval_int * ISO_INT_UNIT_US) * 15) - sdu_interval; event_number += 15; - ref_point += (iso_interval_int * CONN_INT_UNIT_US) * 15; + ref_point += (iso_interval_int * ISO_INT_UNIT_US) * 15; sdu_total_size = 10; testdata_indx = testdata_size; testdata_size += 10; @@ -3303,7 +3305,7 @@ ZTEST(test_tx_unframed, test_tx_unframed_4_sdu_1_frag_4_pdu_stream_loc) /* Check TX Sync info */ tx_sync_seq_expected += 29; - tx_sync_timestamp_expected = ref_point - (iso_interval_int * CONN_INT_UNIT_US); + tx_sync_timestamp_expected = ref_point - (iso_interval_int * ISO_INT_UNIT_US); tx_sync_offset_expected = 0; err = isoal_tx_get_sync_info(source_hdl, &tx_sync_seq, &tx_sync_timestamp, &tx_sync_offset); @@ -3319,9 +3321,9 @@ ZTEST(test_tx_unframed, test_tx_unframed_4_sdu_1_frag_4_pdu_stream_loc) isoal_test_init_tx_sdu_buffer(&tx_sdu_frag_buf); /* Same SDU packet sequence number for testing */ /* Time stamp just before the exact multiple of the SDU interval */ - sdu_timestamp += ((iso_interval_int * CONN_INT_UNIT_US) * 15) - 1; + sdu_timestamp += ((iso_interval_int * ISO_INT_UNIT_US) * 15) - 1; event_number += 15; - ref_point += (iso_interval_int * CONN_INT_UNIT_US) * 15; + ref_point += (iso_interval_int * ISO_INT_UNIT_US) * 15; sdu_total_size = 10; testdata_indx = testdata_size; testdata_size += 10; @@ -3369,7 +3371,7 @@ ZTEST(test_tx_unframed, test_tx_unframed_4_sdu_1_frag_4_pdu_stream_loc) /* Check TX Sync info */ tx_sync_seq_expected += 30; - tx_sync_timestamp_expected = ref_point - (iso_interval_int * CONN_INT_UNIT_US); + tx_sync_timestamp_expected = ref_point - (iso_interval_int * ISO_INT_UNIT_US); tx_sync_offset_expected = 0; err = isoal_tx_get_sync_info(source_hdl, &tx_sync_seq, &tx_sync_timestamp, &tx_sync_offset); @@ -3388,9 +3390,9 @@ ZTEST(test_tx_unframed, test_tx_unframed_4_sdu_1_frag_4_pdu_stream_loc) * +1 (reset to exact multiple of SDU interval from the last SDU) * +1 (push the time stamp 1us beyond the multiple mark) */ - sdu_timestamp += ((iso_interval_int * CONN_INT_UNIT_US) * 15) + 1 + 1; + sdu_timestamp += ((iso_interval_int * ISO_INT_UNIT_US) * 15) + 1 + 1; event_number += 15; - ref_point += (iso_interval_int * CONN_INT_UNIT_US) * 15; + ref_point += (iso_interval_int * ISO_INT_UNIT_US) * 15; sdu_total_size = 10; testdata_indx = testdata_size; testdata_size += 10; @@ -3438,7 +3440,7 @@ ZTEST(test_tx_unframed, test_tx_unframed_4_sdu_1_frag_4_pdu_stream_loc) /* Check TX Sync info */ tx_sync_seq_expected += 30; - tx_sync_timestamp_expected = ref_point - (iso_interval_int * CONN_INT_UNIT_US); + tx_sync_timestamp_expected = ref_point - (iso_interval_int * ISO_INT_UNIT_US); tx_sync_offset_expected = 0; err = isoal_tx_get_sync_info(source_hdl, &tx_sync_seq, &tx_sync_timestamp, &tx_sync_offset); @@ -3490,12 +3492,12 @@ ZTEST(test_tx_framed, test_tx_framed_1_sdu_1_frag_1_pdu_maxPDU) /* Settings */ role = ISOAL_ROLE_PERIPHERAL; iso_interval_int = 1; - sdu_interval = CONN_INT_UNIT_US + 50; + sdu_interval = ISO_INT_UNIT_US + 50; max_octets = TEST_TX_PDU_PAYLOAD_MAX - 5; BN = 1; FT = 1; - stream_sync_delay = (iso_interval_int * CONN_INT_UNIT_US) - 200; - group_sync_delay = (iso_interval_int * CONN_INT_UNIT_US) - 50; + stream_sync_delay = (iso_interval_int * ISO_INT_UNIT_US) - 200; + group_sync_delay = (iso_interval_int * ISO_INT_UNIT_US) - 50; /* SDU Frag 1 --------------------------------------------------------*/ isoal_test_init_tx_pdu_buffer(&tx_pdu_meta_buf); @@ -3510,7 +3512,7 @@ ZTEST(test_tx_framed, test_tx_framed_1_sdu_1_frag_1_pdu_maxPDU) sdu_packet_number = 2000; event_number = 2000; sdu_timestamp = 9249; - ref_point = sdu_timestamp + (iso_interval_int * CONN_INT_UNIT_US) - 50; + ref_point = sdu_timestamp + (iso_interval_int * ISO_INT_UNIT_US) - 50; sdu_total_size = TEST_TX_PDU_PAYLOAD_MAX - 5 - (PDU_ISO_SEG_HDR_SIZE + PDU_ISO_SEG_TIMEOFFSET_SIZE); testdata_indx = 0; @@ -3645,12 +3647,12 @@ ZTEST(test_tx_framed, test_tx_framed_1_sdu_1_frag_1_pdu_bufSize) /* Settings */ role = ISOAL_ROLE_PERIPHERAL; iso_interval_int = 1; - sdu_interval = CONN_INT_UNIT_US + 50; + sdu_interval = ISO_INT_UNIT_US + 50; max_octets = TEST_TX_PDU_PAYLOAD_MAX + 5; BN = 1; FT = 1; - stream_sync_delay = (iso_interval_int * CONN_INT_UNIT_US) - 200; - group_sync_delay = (iso_interval_int * CONN_INT_UNIT_US) - 50; + stream_sync_delay = (iso_interval_int * ISO_INT_UNIT_US) - 200; + group_sync_delay = (iso_interval_int * ISO_INT_UNIT_US) - 50; /* SDU Frag 1 --------------------------------------------------------*/ isoal_test_init_tx_pdu_buffer(&tx_pdu_meta_buf); @@ -3665,7 +3667,7 @@ ZTEST(test_tx_framed, test_tx_framed_1_sdu_1_frag_1_pdu_bufSize) sdu_packet_number = 2000; event_number = 2000; sdu_timestamp = 9249; - ref_point = sdu_timestamp + (iso_interval_int * CONN_INT_UNIT_US) - 50; + ref_point = sdu_timestamp + (iso_interval_int * ISO_INT_UNIT_US) - 50; sdu_total_size = TEST_TX_PDU_PAYLOAD_MAX - (PDU_ISO_SEG_HDR_SIZE + PDU_ISO_SEG_TIMEOFFSET_SIZE); testdata_indx = 0; @@ -3791,12 +3793,12 @@ ZTEST(test_tx_framed, test_tx_framed_1_sdu_1_frag_3_pdu) /* Settings */ role = ISOAL_ROLE_PERIPHERAL; iso_interval_int = 1; - sdu_interval = CONN_INT_UNIT_US + 50; + sdu_interval = ISO_INT_UNIT_US + 50; max_octets = TEST_TX_PDU_PAYLOAD_MAX - 5; BN = 3; FT = 1; - stream_sync_delay = (iso_interval_int * CONN_INT_UNIT_US) - 200; - group_sync_delay = (iso_interval_int * CONN_INT_UNIT_US) - 50; + stream_sync_delay = (iso_interval_int * ISO_INT_UNIT_US) - 200; + group_sync_delay = (iso_interval_int * ISO_INT_UNIT_US) - 50; /* SDU Frag 1 --------------------------------------------------------*/ isoal_test_init_tx_pdu_buffer(&tx_pdu_meta_buf); @@ -3810,7 +3812,7 @@ ZTEST(test_tx_framed, test_tx_framed_1_sdu_1_frag_3_pdu) sdu_packet_number = 2000; event_number = 2000; sdu_timestamp = 9249; - ref_point = sdu_timestamp + (iso_interval_int * CONN_INT_UNIT_US) - 50; + ref_point = sdu_timestamp + (iso_interval_int * ISO_INT_UNIT_US) - 50; sdu_total_size = 100 - ((3 * PDU_ISO_SEG_HDR_SIZE) + PDU_ISO_SEG_TIMEOFFSET_SIZE); testdata_indx = 0; testdata_size = 100 - ((3 * PDU_ISO_SEG_HDR_SIZE) + PDU_ISO_SEG_TIMEOFFSET_SIZE); @@ -4022,12 +4024,12 @@ ZTEST(test_tx_framed, test_tx_framed_1_sdu_3_frag_1_pdu) /* Settings */ role = ISOAL_ROLE_PERIPHERAL; iso_interval_int = 1; - sdu_interval = CONN_INT_UNIT_US + 50; + sdu_interval = ISO_INT_UNIT_US + 50; max_octets = TEST_TX_PDU_PAYLOAD_MAX + 5; BN = 1; FT = 1; - stream_sync_delay = (iso_interval_int * CONN_INT_UNIT_US) - 200; - group_sync_delay = (iso_interval_int * CONN_INT_UNIT_US) - 50; + stream_sync_delay = (iso_interval_int * ISO_INT_UNIT_US) - 200; + group_sync_delay = (iso_interval_int * ISO_INT_UNIT_US) - 50; /* SDU Frag 1 --------------------------------------------------------*/ isoal_test_init_tx_pdu_buffer(&tx_pdu_meta_buf); @@ -4042,7 +4044,7 @@ ZTEST(test_tx_framed, test_tx_framed_1_sdu_3_frag_1_pdu) sdu_packet_number = 2000; event_number = 2000; sdu_timestamp = 9249; - ref_point = sdu_timestamp + (iso_interval_int * CONN_INT_UNIT_US) - 50; + ref_point = sdu_timestamp + (iso_interval_int * ISO_INT_UNIT_US) - 50; sdu_total_size = TEST_TX_PDU_PAYLOAD_MAX - (PDU_ISO_SEG_HDR_SIZE + PDU_ISO_SEG_TIMEOFFSET_SIZE); testdata_indx = 0; @@ -4281,12 +4283,12 @@ ZTEST(test_tx_framed, test_tx_framed_1_sdu_3_frag_2_pdu) /* Settings */ role = ISOAL_ROLE_PERIPHERAL; iso_interval_int = 1; - sdu_interval = CONN_INT_UNIT_US + 50; + sdu_interval = ISO_INT_UNIT_US + 50; max_octets = TEST_TX_PDU_PAYLOAD_MAX + 5; BN = 2; FT = 1; - stream_sync_delay = (iso_interval_int * CONN_INT_UNIT_US) - 200; - group_sync_delay = (iso_interval_int * CONN_INT_UNIT_US) - 50; + stream_sync_delay = (iso_interval_int * ISO_INT_UNIT_US) - 200; + group_sync_delay = (iso_interval_int * ISO_INT_UNIT_US) - 50; /* SDU Frag 1 --------------------------------------------------------*/ isoal_test_init_tx_pdu_buffer(&tx_pdu_meta_buf[0]); @@ -4305,7 +4307,7 @@ ZTEST(test_tx_framed, test_tx_framed_1_sdu_3_frag_2_pdu) sdu_packet_number = 2000; event_number = 2000; sdu_timestamp = 9249; - ref_point = sdu_timestamp + (iso_interval_int * CONN_INT_UNIT_US) - 50; + ref_point = sdu_timestamp + (iso_interval_int * ISO_INT_UNIT_US) - 50; sdu_total_size = (TEST_TX_PDU_PAYLOAD_MAX * 2) - ((PDU_ISO_SEG_HDR_SIZE * 2) + PDU_ISO_SEG_TIMEOFFSET_SIZE); testdata_indx = 0; @@ -4583,12 +4585,12 @@ ZTEST(test_tx_framed, test_tx_framed_2_sdu_3_frag_4_pdu) /* Settings */ role = ISOAL_ROLE_PERIPHERAL; iso_interval_int = 2; - sdu_interval = CONN_INT_UNIT_US + 50; + sdu_interval = ISO_INT_UNIT_US + 50; max_octets = TEST_TX_PDU_PAYLOAD_MAX + 5; BN = 4; FT = 1; - stream_sync_delay = (iso_interval_int * CONN_INT_UNIT_US) - 200; - group_sync_delay = (iso_interval_int * CONN_INT_UNIT_US) - 50; + stream_sync_delay = (iso_interval_int * ISO_INT_UNIT_US) - 200; + group_sync_delay = (iso_interval_int * ISO_INT_UNIT_US) - 50; /* SDU 1 Frag 1 ------------------------------------------------------*/ isoal_test_init_tx_pdu_buffer(&tx_pdu_meta_buf[0]); @@ -4607,7 +4609,7 @@ ZTEST(test_tx_framed, test_tx_framed_2_sdu_3_frag_4_pdu) sdu_packet_number = 2000; event_number = 2000; sdu_timestamp = 9249; - ref_point = 9249 + (iso_interval_int * CONN_INT_UNIT_US) - 50; + ref_point = 9249 + (iso_interval_int * ISO_INT_UNIT_US) - 50; sdu_total_size = (TEST_TX_PDU_PAYLOAD_MAX * 2) - ((PDU_ISO_SEG_HDR_SIZE * 2) + PDU_ISO_SEG_TIMEOFFSET_SIZE); testdata_indx = 0; @@ -4851,7 +4853,7 @@ ZTEST(test_tx_framed, test_tx_framed_2_sdu_3_frag_4_pdu) sdu_packet_number++; event_number = 2000; sdu_timestamp = 9249 + sdu_interval; - ref_point = 9249 + (iso_interval_int * CONN_INT_UNIT_US) - 50; + ref_point = 9249 + (iso_interval_int * ISO_INT_UNIT_US) - 50; sdu_total_size = (TEST_TX_PDU_PAYLOAD_MAX * 2) - ((PDU_ISO_SEG_HDR_SIZE * 2) + PDU_ISO_SEG_TIMEOFFSET_SIZE); testdata_indx = 0; @@ -5115,12 +5117,12 @@ ZTEST(test_tx_framed, test_tx_framed_2_sdu_3_frag_4_pdu_padding) /* Settings */ role = ISOAL_ROLE_PERIPHERAL; iso_interval_int = 2; - sdu_interval = CONN_INT_UNIT_US + 50; + sdu_interval = ISO_INT_UNIT_US + 50; max_octets = TEST_TX_PDU_PAYLOAD_MAX + 5; BN = 6; FT = 1; - stream_sync_delay = (iso_interval_int * CONN_INT_UNIT_US) - 200; - group_sync_delay = (iso_interval_int * CONN_INT_UNIT_US) - 50; + stream_sync_delay = (iso_interval_int * ISO_INT_UNIT_US) - 200; + group_sync_delay = (iso_interval_int * ISO_INT_UNIT_US) - 50; /* SDU 1 Frag 1 ------------------------------------------------------*/ isoal_test_init_tx_pdu_buffer(&tx_pdu_meta_buf[0]); @@ -5137,7 +5139,7 @@ ZTEST(test_tx_framed, test_tx_framed_2_sdu_3_frag_4_pdu_padding) sdu_packet_number = 2000; event_number = 2000; sdu_timestamp = 9249; - ref_point = 9249 + (iso_interval_int * CONN_INT_UNIT_US) - 50; + ref_point = 9249 + (iso_interval_int * ISO_INT_UNIT_US) - 50; sdu_total_size = testdata_size_max; testdata_indx = 0; testdata_size = testdata_size_max / number_of_sdu_frags; @@ -5374,7 +5376,7 @@ ZTEST(test_tx_framed, test_tx_framed_2_sdu_3_frag_4_pdu_padding) sdu_packet_number++; event_number = 2000; sdu_timestamp = 9249 + sdu_interval; - ref_point = 9249 + (iso_interval_int * CONN_INT_UNIT_US) - 50; + ref_point = 9249 + (iso_interval_int * ISO_INT_UNIT_US) - 50; sdu_total_size = testdata_size_max; testdata_indx = 0; testdata_size = testdata_size_max / number_of_sdu_frags; @@ -5661,12 +5663,12 @@ ZTEST(test_tx_framed, test_tx_framed_2_sdu_1_frag_2_pdu_refPoint2) /* Settings */ role = ISOAL_ROLE_PERIPHERAL; iso_interval_int = 1; - sdu_interval = CONN_INT_UNIT_US + 50; + sdu_interval = ISO_INT_UNIT_US + 50; max_octets = TEST_TX_PDU_PAYLOAD_MAX + 5; BN = 1; FT = 1; - stream_sync_delay = (iso_interval_int * CONN_INT_UNIT_US) - 200; - group_sync_delay = (iso_interval_int * CONN_INT_UNIT_US) - 50; + stream_sync_delay = (iso_interval_int * ISO_INT_UNIT_US) - 200; + group_sync_delay = (iso_interval_int * ISO_INT_UNIT_US) - 50; /* SDU 1 Frag 1 ------------------------------------------------------*/ isoal_test_init_tx_pdu_buffer(&tx_pdu_meta_buf); @@ -5682,7 +5684,7 @@ ZTEST(test_tx_framed, test_tx_framed_2_sdu_1_frag_2_pdu_refPoint2) sdu_packet_number = 2000; event_number = 2000; sdu_timestamp = 9249; - ref_point = sdu_timestamp + (iso_interval_int * CONN_INT_UNIT_US) - 50; + ref_point = sdu_timestamp + (iso_interval_int * ISO_INT_UNIT_US) - 50; sdu_total_size = TEST_TX_PDU_PAYLOAD_MAX - (PDU_ISO_SEG_HDR_SIZE + PDU_ISO_SEG_TIMEOFFSET_SIZE); testdata_indx = 0; @@ -5800,7 +5802,7 @@ ZTEST(test_tx_framed, test_tx_framed_2_sdu_1_frag_2_pdu_refPoint2) /* PDU 2 */ /* Advance the target event and the reference point to what it should be */ event_number++; - ref_point += iso_interval_int * CONN_INT_UNIT_US; + ref_point += iso_interval_int * ISO_INT_UNIT_US; payload_number++; seg_hdr[0].sc = 0; seg_hdr[0].cmplt = 0; @@ -5890,12 +5892,12 @@ ZTEST(test_tx_framed, test_tx_framed_1_sdu_1_frag_1_pdu_refPoint3) /* Settings */ role = ISOAL_ROLE_PERIPHERAL; iso_interval_int = 1; - sdu_interval = CONN_INT_UNIT_US + 50; + sdu_interval = ISO_INT_UNIT_US + 50; max_octets = TEST_TX_PDU_PAYLOAD_MAX + 5; BN = 1; FT = 1; - stream_sync_delay = (iso_interval_int * CONN_INT_UNIT_US) - 200; - group_sync_delay = (iso_interval_int * CONN_INT_UNIT_US) - 50; + stream_sync_delay = (iso_interval_int * ISO_INT_UNIT_US) - 200; + group_sync_delay = (iso_interval_int * ISO_INT_UNIT_US) - 50; /* SDU 1 Frag 1 ------------------------------------------------------*/ isoal_test_init_tx_pdu_buffer(&tx_pdu_meta_buf); @@ -5955,7 +5957,7 @@ ZTEST(test_tx_framed, test_tx_framed_1_sdu_1_frag_1_pdu_refPoint3) /* PDU 1 */ /* Advance the target event and the reference point to what it should be */ event_number++; - ref_point += iso_interval_int * CONN_INT_UNIT_US; + ref_point += iso_interval_int * ISO_INT_UNIT_US; payload_number = event_number * BN; seg_hdr[0].sc = 0; seg_hdr[0].cmplt = 0; @@ -6046,12 +6048,12 @@ ZTEST(test_tx_framed, test_tx_framed_2_sdu_1_frag_2_pdu_ts_wrap1) /* Settings */ role = ISOAL_ROLE_PERIPHERAL; iso_interval_int = 1; - sdu_interval = CONN_INT_UNIT_US + 50; + sdu_interval = ISO_INT_UNIT_US + 50; max_octets = TEST_TX_PDU_PAYLOAD_MAX + 5; BN = 1; FT = 1; - stream_sync_delay = (iso_interval_int * CONN_INT_UNIT_US) - 200; - group_sync_delay = (iso_interval_int * CONN_INT_UNIT_US) - 50; + stream_sync_delay = (iso_interval_int * ISO_INT_UNIT_US) - 200; + group_sync_delay = (iso_interval_int * ISO_INT_UNIT_US) - 50; /* SDU 1 Frag 1 ------------------------------------------------------*/ isoal_test_init_tx_pdu_buffer(&tx_pdu_meta_buf); @@ -6185,7 +6187,7 @@ ZTEST(test_tx_framed, test_tx_framed_2_sdu_1_frag_2_pdu_ts_wrap1) /* PDU 2 */ /* Advance the target event and the reference point to what it should be */ event_number++; - ref_point += iso_interval_int * CONN_INT_UNIT_US; + ref_point += iso_interval_int * ISO_INT_UNIT_US; payload_number++; seg_hdr[0].sc = 0; seg_hdr[0].cmplt = 0; @@ -6270,12 +6272,12 @@ ZTEST(test_tx_framed, test_tx_framed_1_zero_sdu_1_frag_1_pdu_maxPDU) /* Settings */ role = ISOAL_ROLE_PERIPHERAL; iso_interval_int = 1; - sdu_interval = CONN_INT_UNIT_US + 50; + sdu_interval = ISO_INT_UNIT_US + 50; max_octets = TEST_TX_PDU_PAYLOAD_MAX - 5; BN = 1; FT = 1; - stream_sync_delay = (iso_interval_int * CONN_INT_UNIT_US) - 200; - group_sync_delay = (iso_interval_int * CONN_INT_UNIT_US) - 50; + stream_sync_delay = (iso_interval_int * ISO_INT_UNIT_US) - 200; + group_sync_delay = (iso_interval_int * ISO_INT_UNIT_US) - 50; /* SDU Frag 1 --------------------------------------------------------*/ isoal_test_init_tx_pdu_buffer(&tx_pdu_meta_buf); @@ -6288,7 +6290,7 @@ ZTEST(test_tx_framed, test_tx_framed_1_zero_sdu_1_frag_1_pdu_maxPDU) sdu_packet_number = 2000; event_number = 2000; sdu_timestamp = 9249; - ref_point = sdu_timestamp + (iso_interval_int * CONN_INT_UNIT_US) - 50; + ref_point = sdu_timestamp + (iso_interval_int * ISO_INT_UNIT_US) - 50; sdu_total_size = TEST_TX_PDU_PAYLOAD_MAX - 5 - (PDU_ISO_SEG_HDR_SIZE + PDU_ISO_SEG_TIMEOFFSET_SIZE); testdata_indx = 0; @@ -6413,12 +6415,12 @@ ZTEST(test_tx_framed, test_tx_framed_1_zero_sdu_1_frag_1_pdu_padding) /* Settings */ role = ISOAL_ROLE_PERIPHERAL; iso_interval_int = 1; - sdu_interval = CONN_INT_UNIT_US + 50; + sdu_interval = ISO_INT_UNIT_US + 50; max_octets = TEST_TX_PDU_PAYLOAD_MAX - 5; BN = 3; FT = 1; - stream_sync_delay = (iso_interval_int * CONN_INT_UNIT_US) - 200; - group_sync_delay = (iso_interval_int * CONN_INT_UNIT_US) - 50; + stream_sync_delay = (iso_interval_int * ISO_INT_UNIT_US) - 200; + group_sync_delay = (iso_interval_int * ISO_INT_UNIT_US) - 50; /* SDU Frag 1 --------------------------------------------------------*/ isoal_test_init_tx_pdu_buffer(&tx_pdu_meta_buf[0]); @@ -6439,7 +6441,7 @@ ZTEST(test_tx_framed, test_tx_framed_1_zero_sdu_1_frag_1_pdu_padding) sdu_packet_number = 2000; event_number = 2000; sdu_timestamp = 9249; - ref_point = sdu_timestamp + (iso_interval_int * CONN_INT_UNIT_US) - 50; + ref_point = sdu_timestamp + (iso_interval_int * ISO_INT_UNIT_US) - 50; sdu_total_size = TEST_TX_PDU_PAYLOAD_MAX - 5 - (PDU_ISO_SEG_HDR_SIZE + PDU_ISO_SEG_TIMEOFFSET_SIZE); testdata_indx = 0; @@ -6598,12 +6600,12 @@ ZTEST(test_tx_framed, test_tx_framed_1_sdu_1_frag_pdu_alloc_err) /* Settings */ role = ISOAL_ROLE_PERIPHERAL; iso_interval_int = 1; - sdu_interval = CONN_INT_UNIT_US + 50; + sdu_interval = ISO_INT_UNIT_US + 50; max_octets = TEST_TX_PDU_PAYLOAD_MAX - 5; BN = 1; FT = 1; - stream_sync_delay = (iso_interval_int * CONN_INT_UNIT_US) - 200; - group_sync_delay = (iso_interval_int * CONN_INT_UNIT_US) - 50; + stream_sync_delay = (iso_interval_int * ISO_INT_UNIT_US) - 200; + group_sync_delay = (iso_interval_int * ISO_INT_UNIT_US) - 50; /* SDU Frag 1 --------------------------------------------------------*/ isoal_test_init_tx_pdu_buffer(&tx_pdu_meta_buf); @@ -6618,7 +6620,7 @@ ZTEST(test_tx_framed, test_tx_framed_1_sdu_1_frag_pdu_alloc_err) sdu_packet_number = 2000; event_number = 2000; sdu_timestamp = 9249; - ref_point = sdu_timestamp + (iso_interval_int * CONN_INT_UNIT_US) - 50; + ref_point = sdu_timestamp + (iso_interval_int * ISO_INT_UNIT_US) - 50; sdu_total_size = TEST_TX_PDU_PAYLOAD_MAX - 5 - (PDU_ISO_SEG_HDR_SIZE + PDU_ISO_SEG_TIMEOFFSET_SIZE); testdata_indx = 0; @@ -6726,12 +6728,12 @@ ZTEST(test_tx_framed, test_tx_framed_1_sdu_1_frag_pdu_emit_err) /* Settings */ role = ISOAL_ROLE_PERIPHERAL; iso_interval_int = 1; - sdu_interval = CONN_INT_UNIT_US + 50; + sdu_interval = ISO_INT_UNIT_US + 50; max_octets = TEST_TX_PDU_PAYLOAD_MAX - 5; BN = 1; FT = 1; - stream_sync_delay = (iso_interval_int * CONN_INT_UNIT_US) - 200; - group_sync_delay = (iso_interval_int * CONN_INT_UNIT_US) - 50; + stream_sync_delay = (iso_interval_int * ISO_INT_UNIT_US) - 200; + group_sync_delay = (iso_interval_int * ISO_INT_UNIT_US) - 50; /* SDU Frag 1 --------------------------------------------------------*/ isoal_test_init_tx_pdu_buffer(&tx_pdu_meta_buf); @@ -6746,7 +6748,7 @@ ZTEST(test_tx_framed, test_tx_framed_1_sdu_1_frag_pdu_emit_err) sdu_packet_number = 2000; event_number = 2000; sdu_timestamp = 9249; - ref_point = sdu_timestamp + (iso_interval_int * CONN_INT_UNIT_US) - 50; + ref_point = sdu_timestamp + (iso_interval_int * ISO_INT_UNIT_US) - 50; sdu_total_size = TEST_TX_PDU_PAYLOAD_MAX - 5 - (PDU_ISO_SEG_HDR_SIZE + PDU_ISO_SEG_TIMEOFFSET_SIZE); testdata_indx = 0; @@ -6879,8 +6881,8 @@ ZTEST(test_tx_framed, test_tx_framed_2_sdu_1_frag_pdu_timeout) max_octets = TEST_TX_PDU_PAYLOAD_MAX + 5; BN = 1; FT = 1; - stream_sync_delay = (iso_interval_int * CONN_INT_UNIT_US) - 200; - group_sync_delay = (iso_interval_int * CONN_INT_UNIT_US) - 50; + stream_sync_delay = (iso_interval_int * ISO_INT_UNIT_US) - 200; + group_sync_delay = (iso_interval_int * ISO_INT_UNIT_US) - 50; /* SDU 1 Frag 1 ------------------------------------------------------*/ isoal_test_init_tx_pdu_buffer(&tx_pdu_meta_buf); @@ -6893,7 +6895,7 @@ ZTEST(test_tx_framed, test_tx_framed_2_sdu_1_frag_pdu_timeout) sdu_packet_number = 0; event_number = 2000; sdu_timestamp = 9249; - ref_point = sdu_timestamp + (iso_interval_int * CONN_INT_UNIT_US) - 50; + ref_point = sdu_timestamp + (iso_interval_int * ISO_INT_UNIT_US) - 50; sdu_total_size = TEST_TX_PDU_PAYLOAD_MAX - (PDU_ISO_SEG_HDR_SIZE + PDU_ISO_SEG_TIMEOFFSET_SIZE); testdata_indx = 0; @@ -7056,7 +7058,7 @@ ZTEST(test_tx_framed, test_tx_framed_2_sdu_1_frag_pdu_timeout) event_number++; sdu_packet_number++; sdu_timestamp = sdu_timestamp + sdu_interval; - ref_point = ref_point + (iso_interval_int * CONN_INT_UNIT_US); + ref_point = ref_point + (iso_interval_int * ISO_INT_UNIT_US); sdu_total_size = 20; testdata_indx = testdata_size; testdata_size += 20; @@ -7129,6 +7131,488 @@ ZTEST(test_tx_framed, test_tx_framed_2_sdu_1_frag_pdu_timeout) isoal_global.source_state[source_hdl].session.handle); } +/** + * Test Suite : TX framed SDU segmentation + * + * Tests that consecutive events are used irrespective of the target event info + * as long as they are feasible. + */ +ZTEST(test_tx_framed, test_tx_framed_event_utilization_1) +{ + const uint8_t number_of_pdus = 3; + const uint8_t sdu_fragment_data_size = 25; + const uint8_t testdata_size_max = sdu_fragment_data_size * 4; + /* Two SDUs and one that would overflow into a new PDU */ + const uint8_t number_of_seg_hdr_buf = 3; + + struct tx_pdu_meta_buffer tx_pdu_meta_buf[number_of_pdus]; + struct pdu_iso_sdu_sh seg_hdr[number_of_seg_hdr_buf]; + struct isoal_pdu_buffer pdu_buffer[number_of_pdus]; + struct tx_sdu_frag_buffer tx_sdu_frag_buf; + uint8_t testdata[testdata_size_max]; + isoal_source_handle_t source_hdl; + isoal_sdu_len_t sdu_total_size; + isoal_pdu_len_t pdu_write_end; + uint32_t stream_sync_delay; + uint64_t sdu_packet_number; + uint32_t group_sync_delay; + uint64_t pdu_event_number; + uint8_t iso_interval_int; + uint32_t iso_interval_us; + uint64_t payload_number; + uint32_t pdu_ref_point; + uint32_t sdu_timestamp; + uint16_t testdata_indx; + uint16_t testdata_size; + uint16_t pdu_write_loc; + uint16_t sdu_read_loc; + uint64_t event_number; + uint32_t sdu_interval; + uint8_t sdu_fragments; + uint16_t pdu_hdr_loc; + uint32_t ref_point; + isoal_status_t err; + uint8_t max_octets; + uint8_t role; + uint8_t BN; + uint8_t FT; + + /* Settings */ + role = BT_CONN_ROLE_PERIPHERAL; + iso_interval_int = 1; + iso_interval_us = iso_interval_int * ISO_INT_UNIT_US; + sdu_interval = ISO_INT_UNIT_US - 50; /* Less than an ISO interval */ + max_octets = TEST_TX_PDU_PAYLOAD_MAX; + BN = 2; + FT = 1; + stream_sync_delay = iso_interval_us - 200; + group_sync_delay = iso_interval_us - 50; + + /* SDU 0 -------------------------------------------------------------*/ + isoal_test_init_tx_pdu_buffer(&tx_pdu_meta_buf[0]); + isoal_test_init_tx_pdu_buffer(&tx_pdu_meta_buf[1]); + isoal_test_init_tx_pdu_buffer(&tx_pdu_meta_buf[2]); + isoal_test_init_tx_sdu_buffer(&tx_sdu_frag_buf); + init_test_data_buffer(testdata, testdata_size_max); + (void)memset(&seg_hdr, 0, sizeof(seg_hdr)); + pdu_buffer[0].handle = (void *)&tx_pdu_meta_buf[0].node_tx; + pdu_buffer[0].pdu = (struct pdu_iso *)tx_pdu_meta_buf[0].node_tx.pdu; + pdu_buffer[0].size = TEST_TX_PDU_PAYLOAD_MAX; + pdu_buffer[1].handle = (void *)&tx_pdu_meta_buf[1].node_tx; + pdu_buffer[1].pdu = (struct pdu_iso *)tx_pdu_meta_buf[1].node_tx.pdu; + pdu_buffer[1].size = TEST_TX_PDU_PAYLOAD_MAX; + pdu_buffer[2].handle = (void *)&tx_pdu_meta_buf[2].node_tx; + pdu_buffer[2].pdu = (struct pdu_iso *)tx_pdu_meta_buf[2].node_tx.pdu; + pdu_buffer[2].size = TEST_TX_PDU_PAYLOAD_MAX; + sdu_packet_number = 0; + event_number = 5; + pdu_event_number = event_number; + sdu_timestamp = 9249; + ref_point = sdu_timestamp + iso_interval_us; + pdu_ref_point = ref_point; + sdu_total_size = sdu_fragment_data_size; + testdata_indx = 0; + testdata_size = sdu_fragment_data_size; + sdu_fragments = 0; + + source_hdl = basic_tx_test_setup(0xADAD, /* Handle */ + role, /* Role */ + true, /* Framed */ + BN, /* BN */ + FT, /* FT */ + max_octets, /* max_octets */ + sdu_interval, /* SDU Interval */ + iso_interval_int, /* ISO Interval */ + stream_sync_delay, /* Stream Sync Delay */ + group_sync_delay); /* Group Sync Delay */ + + isoal_test_create_sdu_fagment(BT_ISO_SINGLE, + &testdata[testdata_indx], + (testdata_size - testdata_indx), + sdu_total_size, + sdu_packet_number, + sdu_timestamp, + ref_point, + event_number, + &tx_sdu_frag_buf.sdu_tx); + + SET_NEXT_PDU_ALLOC_BUFFER(&pdu_buffer[0]); + SET_NEXT_PDU_ALLOC_BUFFER(&pdu_buffer[1]); + SET_NEXT_PDU_ALLOC_BUFFER(&pdu_buffer[0]); + SET_NEXT_PDU_ALLOC_BUFFER(&pdu_buffer[1]); + SET_NEXT_PDU_ALLOC_BUFFER(&pdu_buffer[2]); + SET_NEXT_PDU_ALLOC_BUFFER(&pdu_buffer[0]); + PDU_ALLOC_TEST_RETURNS(ISOAL_STATUS_OK); + PDU_WRITE_TEST_RETURNS(ISOAL_STATUS_OK); + PDU_EMIT_TEST_RETURNS(ISOAL_STATUS_OK); + PDU_RELEASE_TEST_RETURNS(ISOAL_STATUS_OK); + + err = isoal_tx_sdu_fragment(source_hdl, &tx_sdu_frag_buf.sdu_tx); + + zassert_equal(err, ISOAL_STATUS_OK, "err = 0x%02x", err); + + /* Test segmentation (Black Box) */ + /* Valid PDUs */ + /* PDU 0 */ + payload_number = event_number * BN; + seg_hdr[0].sc = 0; + seg_hdr[0].cmplt = 0; + seg_hdr[0].timeoffset = pdu_ref_point - sdu_timestamp; + seg_hdr[0].len = PDU_ISO_SEG_TIMEOFFSET_SIZE; + pdu_hdr_loc = 0; + pdu_write_loc = PDU_ISO_SEG_HDR_SIZE + PDU_ISO_SEG_TIMEOFFSET_SIZE; + sdu_read_loc = 0; + pdu_write_end = sdu_fragment_data_size + pdu_write_loc; + sdu_fragments++; + + ZASSERT_PDU_WRITE_TEST(history[0], + pdu_buffer[0], + pdu_hdr_loc, + &seg_hdr[0], + (PDU_ISO_SEG_HDR_SIZE + PDU_ISO_SEG_TIMEOFFSET_SIZE)); + + ZASSERT_PDU_WRITE_TEST(history[1], + pdu_buffer[0], + pdu_write_loc, + &testdata[sdu_read_loc], + (pdu_write_end - pdu_write_loc)); + + seg_hdr[0].cmplt = 1; + seg_hdr[0].len += (pdu_write_end - pdu_write_loc); + + ZASSERT_PDU_WRITE_TEST(history[2], + pdu_buffer[0], + pdu_hdr_loc, + &seg_hdr[0], + PDU_ISO_SEG_HDR_SIZE); + + /* PDU should not be emitted */ + ZASSERT_PDU_EMIT_TEST_CALL_COUNT(0); + + /* PDU release not expected (No Error) */ + ZASSERT_PDU_RELEASE_TEST_CALL_COUNT(0); + + /* SDU 1 -------------------------------------------------------------*/ + isoal_test_init_tx_sdu_buffer(&tx_sdu_frag_buf); + sdu_packet_number++; + event_number += 2; + ref_point += iso_interval_us * 2; + sdu_timestamp += sdu_interval; + testdata_indx = testdata_size; + testdata_size += sdu_fragment_data_size; + + isoal_test_create_sdu_fagment(BT_ISO_SINGLE, + &testdata[testdata_indx], + (testdata_size - testdata_indx), + sdu_total_size, + sdu_packet_number, + sdu_timestamp, + ref_point, + event_number, + &tx_sdu_frag_buf.sdu_tx); + + err = isoal_tx_sdu_fragment(source_hdl, &tx_sdu_frag_buf.sdu_tx); + + zassert_equal(err, ISOAL_STATUS_OK, "err = 0x%02x", err); + + /* Test segmentation (Black Box) */ + /* Valid PDUs */ + /* PDU 10 */ + pdu_hdr_loc = pdu_write_end; + seg_hdr[1].sc = 0; + seg_hdr[1].cmplt = 0; + seg_hdr[1].timeoffset = pdu_ref_point - sdu_timestamp; + seg_hdr[1].len = PDU_ISO_SEG_TIMEOFFSET_SIZE; + pdu_write_loc = pdu_write_end + (PDU_ISO_SEG_HDR_SIZE + PDU_ISO_SEG_TIMEOFFSET_SIZE); + pdu_write_end = TEST_TX_PDU_PAYLOAD_MAX; + sdu_read_loc = testdata_indx; + + ZASSERT_PDU_WRITE_TEST(history[3], + pdu_buffer[0], + pdu_hdr_loc, + &seg_hdr[1], + (PDU_ISO_SEG_HDR_SIZE + PDU_ISO_SEG_TIMEOFFSET_SIZE)); + + ZASSERT_PDU_WRITE_TEST(history[4], + pdu_buffer[0], + pdu_write_loc, + &testdata[sdu_read_loc], + (pdu_write_end - pdu_write_loc)); + + /* PDU should not be allocated */ + + seg_hdr[1].len += (pdu_write_end - pdu_write_loc); + + ZASSERT_PDU_WRITE_TEST(history[5], + pdu_buffer[0], + pdu_hdr_loc, + &seg_hdr[1], + PDU_ISO_SEG_HDR_SIZE); + + ZASSERT_PDU_EMIT_TEST(history[0], + &tx_pdu_meta_buf[0].node_tx, + payload_number, + sdu_fragments, + PDU_BIS_LLID_FRAMED, + pdu_write_end, + isoal_global.source_state[source_hdl].session.handle); + + /* PDU release not expected (No Error) */ + ZASSERT_PDU_RELEASE_TEST_CALL_COUNT(0); + + /* PDU 11 */ + payload_number++; + seg_hdr[2].sc = 1; + seg_hdr[2].cmplt = 0; + seg_hdr[2].timeoffset = 0; + seg_hdr[2].len = 0; + sdu_read_loc += (pdu_write_end - pdu_write_loc); + pdu_hdr_loc = 0; + pdu_write_end = testdata_size - testdata_indx - (pdu_write_end - pdu_write_loc) + + PDU_ISO_SEG_HDR_SIZE; + pdu_write_loc = PDU_ISO_SEG_HDR_SIZE; + sdu_fragments = 1; + + ZASSERT_PDU_WRITE_TEST(history[6], + pdu_buffer[1], + pdu_hdr_loc, + &seg_hdr[2], + PDU_ISO_SEG_HDR_SIZE); + + ZASSERT_PDU_WRITE_TEST(history[7], + pdu_buffer[1], + pdu_write_loc, + &testdata[sdu_read_loc], + (pdu_write_end - pdu_write_loc)); + + seg_hdr[2].cmplt = 1; + seg_hdr[2].len += (pdu_write_end - pdu_write_loc); + + ZASSERT_PDU_WRITE_TEST(history[8], + pdu_buffer[1], + pdu_hdr_loc, + &seg_hdr[2], + PDU_ISO_SEG_HDR_SIZE); + + /* PDU should not be emitted */ + ZASSERT_PDU_EMIT_TEST_CALL_COUNT(1); + + /* PDU release not expected (No Error) */ + ZASSERT_PDU_RELEASE_TEST_CALL_COUNT(0); + + /* SDU 2 -------------------------------------------------------------*/ + isoal_test_init_tx_pdu_buffer(&tx_pdu_meta_buf[0]); + isoal_test_init_tx_sdu_buffer(&tx_sdu_frag_buf); + sdu_packet_number++; + event_number += 2; + ref_point += iso_interval_us * 2; + sdu_timestamp += sdu_interval; + testdata_indx = testdata_size; + testdata_size += sdu_fragment_data_size; + + isoal_test_create_sdu_fagment(BT_ISO_SINGLE, + &testdata[testdata_indx], + (testdata_size - testdata_indx), + sdu_total_size, + sdu_packet_number, + sdu_timestamp, + ref_point, + event_number, + &tx_sdu_frag_buf.sdu_tx); + + err = isoal_tx_sdu_fragment(source_hdl, &tx_sdu_frag_buf.sdu_tx); + + zassert_equal(err, ISOAL_STATUS_OK, "err = 0x%02x", err); + + /* Test segmentation (Black Box) */ + /* Valid PDUs */ + /* PDU 11 */ + + ZASSERT_PDU_EMIT_TEST(history[1], + &tx_pdu_meta_buf[1].node_tx, + payload_number, + sdu_fragments, + PDU_BIS_LLID_FRAMED, + pdu_write_end, + isoal_global.source_state[source_hdl].session.handle); + + /* PDU release not expected (No Error) */ + ZASSERT_PDU_RELEASE_TEST_CALL_COUNT(0); + + /* PDU 12 */ + payload_number++; + pdu_event_number++; + pdu_ref_point += iso_interval_us; + seg_hdr[0].sc = 0; + seg_hdr[0].cmplt = 0; + seg_hdr[0].timeoffset = pdu_ref_point - sdu_timestamp; + seg_hdr[0].len = 3; + sdu_read_loc = testdata_indx; + pdu_hdr_loc = 0; + pdu_write_end = testdata_size - testdata_indx + PDU_ISO_SEG_HDR_SIZE + + PDU_ISO_SEG_TIMEOFFSET_SIZE; + pdu_write_loc = PDU_ISO_SEG_HDR_SIZE + PDU_ISO_SEG_TIMEOFFSET_SIZE; + sdu_fragments = 1; + + ZASSERT_PDU_WRITE_TEST(history[9], + pdu_buffer[0], + pdu_hdr_loc, + &seg_hdr[0], + (PDU_ISO_SEG_HDR_SIZE + PDU_ISO_SEG_TIMEOFFSET_SIZE)); + + ZASSERT_PDU_WRITE_TEST(history[10], + pdu_buffer[0], + pdu_write_loc, + &testdata[sdu_read_loc], + (pdu_write_end - pdu_write_loc)); + + seg_hdr[0].cmplt = 1; + seg_hdr[0].len += (pdu_write_end - pdu_write_loc); + + ZASSERT_PDU_WRITE_TEST(history[11], + pdu_buffer[0], + pdu_hdr_loc, + &seg_hdr[0], + PDU_ISO_SEG_HDR_SIZE); + + /* PDU should not be emitted */ + ZASSERT_PDU_EMIT_TEST_CALL_COUNT(2); + + /* PDU release not expected (No Error) */ + ZASSERT_PDU_RELEASE_TEST_CALL_COUNT(0); + + /* Send Event Timeout ----------------------------------------------- */ + isoal_tx_event_prepare(source_hdl, pdu_event_number - 1); + + /* PDU should not be emitted */ + ZASSERT_PDU_EMIT_TEST_CALL_COUNT(2); + + /* PDU release not expected (No Error) */ + ZASSERT_PDU_RELEASE_TEST_CALL_COUNT(0); + + /* SDU 3 -------------------------------------------------------------*/ + isoal_test_init_tx_pdu_buffer(&tx_pdu_meta_buf[1]); + isoal_test_init_tx_pdu_buffer(&tx_pdu_meta_buf[2]); + isoal_test_init_tx_sdu_buffer(&tx_sdu_frag_buf); + sdu_packet_number++; + event_number += 2; + ref_point += iso_interval_us * 2; + sdu_timestamp += sdu_interval; + sdu_total_size = sdu_fragment_data_size; + testdata_indx = testdata_size; + testdata_size += sdu_fragment_data_size; + + isoal_test_create_sdu_fagment(BT_ISO_SINGLE, + &testdata[testdata_indx], + (testdata_size - testdata_indx), + sdu_total_size, + sdu_packet_number, + sdu_timestamp, + ref_point, + event_number, + &tx_sdu_frag_buf.sdu_tx); + + err = isoal_tx_sdu_fragment(source_hdl, &tx_sdu_frag_buf.sdu_tx); + + zassert_equal(err, ISOAL_STATUS_OK, "err = 0x%02x", err); + + /* Test segmentation (Black Box) */ + /* Valid PDUs */ + /* PDU 12 */ + ZASSERT_PDU_EMIT_TEST(history[2], + &tx_pdu_meta_buf[0].node_tx, + payload_number, + sdu_fragments, + PDU_BIS_LLID_FRAMED, + pdu_write_end, + isoal_global.source_state[source_hdl].session.handle); + + /* PDU 13 */ + payload_number++; + + /* Padding PDU */ + ZASSERT_PDU_EMIT_TEST_CALL_COUNT(4); + ZASSERT_PDU_EMIT_TEST(history[3], + &tx_pdu_meta_buf[1].node_tx, + payload_number, + 0, + PDU_BIS_LLID_FRAMED, + 0, + isoal_global.source_state[source_hdl].session.handle); + + /* PDU release not expected (No Error) */ + ZASSERT_PDU_RELEASE_TEST_CALL_COUNT(0); + + /* PDU 14 */ + payload_number++; + pdu_event_number++; + pdu_ref_point += iso_interval_us; + seg_hdr[1].sc = 0; + seg_hdr[1].cmplt = 0; + seg_hdr[1].timeoffset = pdu_ref_point - sdu_timestamp; + seg_hdr[1].len = 3; + sdu_read_loc = testdata_indx; + pdu_hdr_loc = 0; + pdu_write_end = testdata_size - testdata_indx + PDU_ISO_SEG_HDR_SIZE + + PDU_ISO_SEG_TIMEOFFSET_SIZE; + pdu_write_loc = PDU_ISO_SEG_HDR_SIZE + PDU_ISO_SEG_TIMEOFFSET_SIZE; + sdu_fragments = 1; + + ZASSERT_PDU_WRITE_TEST(history[12], + pdu_buffer[2], + pdu_hdr_loc, + &seg_hdr[1], + PDU_ISO_SEG_HDR_SIZE + PDU_ISO_SEG_TIMEOFFSET_SIZE); + + ZASSERT_PDU_WRITE_TEST(history[13], + pdu_buffer[2], + pdu_write_loc, + &testdata[sdu_read_loc], + (pdu_write_end - pdu_write_loc)); + + seg_hdr[1].cmplt = 1; + seg_hdr[1].len += (pdu_write_end - pdu_write_loc); + + ZASSERT_PDU_WRITE_TEST(history[14], + pdu_buffer[2], + pdu_hdr_loc, + &seg_hdr[1], + PDU_ISO_SEG_HDR_SIZE); + + /* PDU should not be emitted */ + ZASSERT_PDU_EMIT_TEST_CALL_COUNT(4); + + /* PDU release not expected (No Error) */ + ZASSERT_PDU_RELEASE_TEST_CALL_COUNT(0); + + /* Send Event Timeout ----------------------------------------------- */ + isoal_tx_event_prepare(source_hdl, pdu_event_number); + + + ZASSERT_PDU_EMIT_TEST(history[4], + &tx_pdu_meta_buf[2].node_tx, + payload_number, + sdu_fragments, + PDU_BIS_LLID_FRAMED, + pdu_write_end, + isoal_global.source_state[source_hdl].session.handle); + + /* PDU 5 */ + payload_number++; + + /* Padding PDU */ + ZASSERT_PDU_EMIT_TEST(history[5], + &tx_pdu_meta_buf[0].node_tx, + payload_number, + 0, + PDU_BIS_LLID_FRAMED, + 0, + isoal_global.source_state[source_hdl].session.handle); + + /* PDU release not expected (No Error) */ + ZASSERT_PDU_RELEASE_TEST_CALL_COUNT(0); +} + /** * Test Suite : TX framed EBQ test IAL-CIS-FRA-PER-BV07C * @@ -7173,8 +7657,8 @@ ZTEST(test_tx_framed_ebq, test_tx_framed_cis_fra_per_bv07c) max_octets = TEST_TX_PDU_PAYLOAD_MAX + 5; BN = 1; FT = 1; - stream_sync_delay = (iso_interval_int * CONN_INT_UNIT_US) - 200; - group_sync_delay = (iso_interval_int * CONN_INT_UNIT_US) - 50; + stream_sync_delay = (iso_interval_int * ISO_INT_UNIT_US) - 200; + group_sync_delay = (iso_interval_int * ISO_INT_UNIT_US) - 50; /* SDU 1 Frag 1 ------------------------------------------------------*/ isoal_test_init_tx_pdu_buffer(&tx_pdu_meta_buf); @@ -7187,7 +7671,7 @@ ZTEST(test_tx_framed_ebq, test_tx_framed_cis_fra_per_bv07c) sdu_packet_number = 0; event_number = 0; sdu_timestamp = 9249; - ref_point = sdu_timestamp + (iso_interval_int * CONN_INT_UNIT_US) - 50; + ref_point = sdu_timestamp + (iso_interval_int * ISO_INT_UNIT_US) - 50; sdu_total_size = 10; testdata_indx = 0; testdata_size = 10; @@ -7350,7 +7834,7 @@ ZTEST(test_tx_framed_ebq, test_tx_framed_cis_fra_per_bv07c) event_number++; sdu_packet_number++; sdu_timestamp = sdu_timestamp + sdu_interval; - ref_point = ref_point + (iso_interval_int * CONN_INT_UNIT_US); + ref_point = ref_point + (iso_interval_int * ISO_INT_UNIT_US); sdu_total_size = 20; testdata_indx = testdata_size; testdata_size += 20; From 78f271634db1df8383b6e32e46e750c428e264fc Mon Sep 17 00:00:00 2001 From: Nirosharn Amarasinghe Date: Mon, 17 Jul 2023 16:19:46 +0200 Subject: [PATCH 293/421] [nrf fromtree] test: bluetooth: controller: Updated ISO-AL tests to cover endianness Changes: -- Changed RX tests and one TX test to cover endianness of the framed segment header fields -- Updated RX debug PDU print to include framed segment details Signed-off-by: Nirosharn Amarasinghe (cherry picked from commit 05ce650c856ec98ccbdaff7a72ccfe6ab33ad405) Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit 11a12a55149a39f01215593345448052bf812e4d) --- .../ctrl_isoal/src/isoal_test_common.c | 12 ++--- .../ctrl_isoal/src/isoal_test_debug.c | 44 ++++++++++++++++++- tests/bluetooth/ctrl_isoal/src/main.c | 2 + .../ctrl_isoal/src/sub_sets/isoal_test_tx.c | 36 ++++++++------- 4 files changed, 70 insertions(+), 24 deletions(-) diff --git a/tests/bluetooth/ctrl_isoal/src/isoal_test_common.c b/tests/bluetooth/ctrl_isoal/src/isoal_test_common.c index a20ba5fd084..35947656336 100644 --- a/tests/bluetooth/ctrl_isoal/src/isoal_test_common.c +++ b/tests/bluetooth/ctrl_isoal/src/isoal_test_common.c @@ -23,6 +23,7 @@ #include #include +#include #include "util/memq.h" @@ -109,7 +110,7 @@ void isoal_test_create_unframed_pdu(uint8_t llid, uint16_t isoal_test_insert_segment(bool sc, bool cmplt, uint32_t time_offset, uint8_t *dataptr, uint8_t length, struct isoal_pdu_rx *pdu_meta) { - struct pdu_iso_sdu_sh seg_hdr; + uint8_t seg_hdr[PDU_ISO_SEG_HDR_SIZE + PDU_ISO_SEG_TIMEOFFSET_SIZE]; uint16_t pdu_payload_size; uint8_t hdr_write_size; uint16_t pdu_data_loc; @@ -122,12 +123,13 @@ uint16_t isoal_test_insert_segment(bool sc, bool cmplt, uint32_t time_offset, ui zassert_true(pdu_payload_size <= TEST_RX_PDU_PAYLOAD_MAX, "pdu_payload_size (%d)", pdu_payload_size); - seg_hdr.sc = sc; - seg_hdr.cmplt = cmplt; - seg_hdr.len = length + (sc ? 0 : PDU_ISO_SEG_TIMEOFFSET_SIZE); + /* Write header independent of endian dependent structures */ + WRITE_BIT(seg_hdr[0], 0, sc); /* sc */ + WRITE_BIT(seg_hdr[0], 1, cmplt); /* cmplt */ + seg_hdr[1] = length + (sc ? 0 : PDU_ISO_SEG_TIMEOFFSET_SIZE); if (!sc) { - seg_hdr.timeoffset = time_offset; + sys_put_le24(time_offset, &seg_hdr[PDU_ISO_SEG_HDR_SIZE]); } memcpy(&pdu_meta->pdu->payload[pdu_meta->pdu->len], &seg_hdr, hdr_write_size); diff --git a/tests/bluetooth/ctrl_isoal/src/isoal_test_debug.c b/tests/bluetooth/ctrl_isoal/src/isoal_test_debug.c index 464d2586598..734af1ad7c0 100644 --- a/tests/bluetooth/ctrl_isoal/src/isoal_test_debug.c +++ b/tests/bluetooth/ctrl_isoal/src/isoal_test_debug.c @@ -52,6 +52,12 @@ void isoal_test_debug_print_rx_pdu(struct isoal_pdu_rx *pdu_meta) { zassert_not_null(pdu_meta, ""); + struct pdu_iso *pdu; + uint8_t seg_length; + + pdu = pdu_meta->pdu; + seg_length = 0; + PRINT("\n"); PRINT("PDU %04u (%10u) | %12s [%10s] %03u: ", (uint32_t) pdu_meta->meta->payload_number, @@ -60,8 +66,42 @@ void isoal_test_debug_print_rx_pdu(struct isoal_pdu_rx *pdu_meta) DU_ERR_TO_STR(pdu_meta->meta->status), pdu_meta->pdu->len); - for (int i = 0; i < pdu_meta->pdu->len; i++) { - PRINT("%02x ", pdu_meta->pdu->payload[i]); + for (uint8_t i = 0U; i < pdu->len; i++) { + if (seg_length == 0U && pdu->ll_id == PDU_BIS_LLID_FRAMED) { + seg_length = pdu->payload[i + 1U]; + PRINT("[%s %s %03u]", + pdu->payload[i] & BIT(0) ? "C" : "S", + pdu->payload[i] & BIT(1) ? "C" : "-", + pdu->payload[i + 1U]); + if ((pdu->payload[i] & BIT(0)) == 0U) { + PRINT("(%8uus)", + ((uint32_t)pdu->payload[i + 2U] + + ((uint32_t)pdu->payload[i + 3U] << 8) + + ((uint32_t)pdu->payload[i + 4U] << 16))); + } + + PRINT(" / "); + PRINT("[%02x %02x]", + pdu->payload[i], + pdu->payload[i + 1U]); + if ((pdu->payload[i] & BIT(0)) == 0U) { + PRINT("(%02x %02x %02x)", + (uint32_t)pdu->payload[i + 4U], + (uint32_t)pdu->payload[i + 3U], + (uint32_t)pdu->payload[i + 2U]); + } + + PRINT(" : "); + seg_length -= pdu->payload[i] & BIT(0) ? 0 : PDU_ISO_SEG_TIMEOFFSET_SIZE; + i += PDU_ISO_SEG_HDR_SIZE + + (pdu->payload[i] & BIT(0) ? 0 : PDU_ISO_SEG_TIMEOFFSET_SIZE); + } + + PRINT("%02x ", pdu->payload[i]); + seg_length--; + if (seg_length == 0 && pdu->ll_id == PDU_BIS_LLID_FRAMED) { + PRINT("\n%44s", ""); + } } PRINT("\n"); PRINT("\n"); diff --git a/tests/bluetooth/ctrl_isoal/src/main.c b/tests/bluetooth/ctrl_isoal/src/main.c index 92ca21ff199..08175eab153 100644 --- a/tests/bluetooth/ctrl_isoal/src/main.c +++ b/tests/bluetooth/ctrl_isoal/src/main.c @@ -18,6 +18,8 @@ #include #include +#include + #include DEFINE_FFF_GLOBALS; diff --git a/tests/bluetooth/ctrl_isoal/src/sub_sets/isoal_test_tx.c b/tests/bluetooth/ctrl_isoal/src/sub_sets/isoal_test_tx.c index dc21c9b5d61..3f57d8bccbc 100644 --- a/tests/bluetooth/ctrl_isoal/src/sub_sets/isoal_test_tx.c +++ b/tests/bluetooth/ctrl_isoal/src/sub_sets/isoal_test_tx.c @@ -3757,7 +3757,8 @@ ZTEST(test_tx_framed, test_tx_framed_1_sdu_1_frag_1_pdu_bufSize) * Test Suite : TX framed SDU segmentation * * Tests segmentation of a single SDU contained in a single fragment - * into three PDUs where Max PDU is less than the PDU buffer size + * into three PDUs where Max PDU is less than the PDU buffer size. Also tests + * endianness of the segment header. */ ZTEST(test_tx_framed, test_tx_framed_1_sdu_1_frag_3_pdu) { @@ -3854,10 +3855,11 @@ ZTEST(test_tx_framed, test_tx_framed_1_sdu_1_frag_3_pdu) /* Test segmentation (Black Box) */ /* Valid PDUs */ /* PDU 1 */ - seg_hdr[0].sc = 0; - seg_hdr[0].cmplt = 0; - seg_hdr[0].timeoffset = ref_point - sdu_timestamp; - seg_hdr[0].len = PDU_ISO_SEG_TIMEOFFSET_SIZE; + /* Test endianness */ + WRITE_BIT(((uint8_t *)&seg_hdr[0])[0], 0, 0); /* sc */ + WRITE_BIT(((uint8_t *)&seg_hdr[0])[0], 1, 0); /* cmplt */ + sys_put_le24(ref_point - sdu_timestamp, (uint8_t *)(&seg_hdr[0]) + PDU_ISO_SEG_HDR_SIZE); + ((uint8_t *)(&seg_hdr[0]))[1] = PDU_ISO_SEG_TIMEOFFSET_SIZE; /* len */ pdu_hdr_loc = 0; pdu_write_loc = PDU_ISO_SEG_HDR_SIZE + PDU_ISO_SEG_TIMEOFFSET_SIZE; sdu_read_loc = 0; @@ -3877,7 +3879,7 @@ ZTEST(test_tx_framed, test_tx_framed_1_sdu_1_frag_3_pdu) (pdu_write_size - pdu_write_loc)); seg_hdr[1] = seg_hdr[0]; - seg_hdr[1].len += (pdu_write_size - pdu_write_loc); + ((uint8_t *)(&seg_hdr[1]))[1] += (pdu_write_size - pdu_write_loc); ZASSERT_PDU_WRITE_TEST(history[2], pdu_buffer, @@ -3895,10 +3897,10 @@ ZTEST(test_tx_framed, test_tx_framed_1_sdu_1_frag_3_pdu) /* PDU 2 */ payload_number++; - seg_hdr[2].sc = 1; - seg_hdr[2].cmplt = 0; - seg_hdr[2].timeoffset = 0; - seg_hdr[2].len = 0; + WRITE_BIT(((uint8_t *)&seg_hdr[2])[0], 0, 1); /* sc */ + WRITE_BIT(((uint8_t *)&seg_hdr[2])[0], 1, 0); /* cmplt */ + sys_put_le24(0, (uint8_t *)(&seg_hdr[2]) + PDU_ISO_SEG_HDR_SIZE); + ((uint8_t *)(&seg_hdr[2]))[1] = 0; /* len */ pdu_hdr_loc = 0; sdu_read_loc += (pdu_write_size - pdu_write_loc); pdu_write_loc = PDU_ISO_SEG_HDR_SIZE; @@ -3918,7 +3920,7 @@ ZTEST(test_tx_framed, test_tx_framed_1_sdu_1_frag_3_pdu) (pdu_write_size - pdu_write_loc)); seg_hdr[3] = seg_hdr[2]; - seg_hdr[3].len += (pdu_write_size - pdu_write_loc); + ((uint8_t *)(&seg_hdr[3]))[1] += (pdu_write_size - pdu_write_loc); /* len */ ZASSERT_PDU_WRITE_TEST(history[5], pdu_buffer, @@ -3936,10 +3938,10 @@ ZTEST(test_tx_framed, test_tx_framed_1_sdu_1_frag_3_pdu) /* PDU 3 */ payload_number++; - seg_hdr[4].sc = 1; - seg_hdr[4].cmplt = 0; - seg_hdr[4].timeoffset = 0; - seg_hdr[4].len = 0; + WRITE_BIT(((uint8_t *)&seg_hdr[4])[0], 0, 1); /* sc */ + WRITE_BIT(((uint8_t *)&seg_hdr[4])[0], 1, 0); /* cmplt */ + sys_put_le24(0, (uint8_t *)(&seg_hdr[4]) + PDU_ISO_SEG_HDR_SIZE); + ((uint8_t *)(&seg_hdr[4]))[1] = 0; /* len */ pdu_hdr_loc = 0; sdu_read_loc += (pdu_write_size - pdu_write_loc); pdu_write_loc = PDU_ISO_SEG_HDR_SIZE; @@ -3962,8 +3964,8 @@ ZTEST(test_tx_framed, test_tx_framed_1_sdu_1_frag_3_pdu) (pdu_write_size - pdu_write_loc)); seg_hdr[5] = seg_hdr[4]; - seg_hdr[5].cmplt = 1; - seg_hdr[5].len += (pdu_write_size - pdu_write_loc); + WRITE_BIT(((uint8_t *)&seg_hdr[5])[0], 1, 1); /* cmplt */ + ((uint8_t *)(&seg_hdr[5]))[1] += (pdu_write_size - pdu_write_loc); /* len */ ZASSERT_PDU_WRITE_TEST(history[8], pdu_buffer, From cd59d4f291540089700dc1c04e7dd82f8de345a5 Mon Sep 17 00:00:00 2001 From: Nirosharn Amarasinghe Date: Wed, 19 Jul 2023 12:20:42 +0200 Subject: [PATCH 294/421] [nrf fromtree] tests: bluetooth: controller: ISO-AL selection of TX time stamps Unit tests for TX time stamp related decisions. Signed-off-by: Nirosharn Amarasinghe (cherry picked from commit 2260b651b65be683fc1e82aafeef166d97dde64a) Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit e95ce690ab6b5789f47871e98e549026143790d2) --- .../ctrl_isoal/src/isoal_test_debug.c | 1 + tests/bluetooth/ctrl_isoal/src/main.c | 2 +- .../ctrl_isoal/src/sub_sets/isoal_test_tx.c | 540 +++++++++++++++++- 3 files changed, 540 insertions(+), 3 deletions(-) diff --git a/tests/bluetooth/ctrl_isoal/src/isoal_test_debug.c b/tests/bluetooth/ctrl_isoal/src/isoal_test_debug.c index 734af1ad7c0..084677cf462 100644 --- a/tests/bluetooth/ctrl_isoal/src/isoal_test_debug.c +++ b/tests/bluetooth/ctrl_isoal/src/isoal_test_debug.c @@ -233,6 +233,7 @@ void isoal_test_debug_print_tx_sdu(struct isoal_sdu_tx *tx_sdu) PRINT("%02x ", buf[i]); } PRINT("\n"); + PRINT("Cntr TS. <%10u>\n", tx_sdu->cntr_time_stamp); PRINT(" Ref. <%10u>\n", tx_sdu->grp_ref_point); PRINT(" Event <%10u>\n", (uint32_t)tx_sdu->target_event); PRINT("\n"); diff --git a/tests/bluetooth/ctrl_isoal/src/main.c b/tests/bluetooth/ctrl_isoal/src/main.c index 08175eab153..8cbd36c509a 100644 --- a/tests/bluetooth/ctrl_isoal/src/main.c +++ b/tests/bluetooth/ctrl_isoal/src/main.c @@ -37,7 +37,7 @@ DEFINE_FFF_GLOBALS; ZTEST_SUITE(test_rx_basics, NULL, NULL, isoal_test_rx_common_before, NULL, NULL); ZTEST_SUITE(test_rx_unframed, NULL, NULL, isoal_test_rx_common_before, NULL, NULL); -ZTEST_SUITE(test_rx_framed, NULL, NULL, NULL, isoal_test_rx_common_before, NULL); +ZTEST_SUITE(test_rx_framed, NULL, NULL, isoal_test_rx_common_before, NULL, NULL); ZTEST_SUITE(test_tx_basics, NULL, NULL, isoal_test_tx_common_before, NULL, NULL); ZTEST_SUITE(test_tx_unframed, NULL, NULL, isoal_test_tx_common_before, NULL, NULL); diff --git a/tests/bluetooth/ctrl_isoal/src/sub_sets/isoal_test_tx.c b/tests/bluetooth/ctrl_isoal/src/sub_sets/isoal_test_tx.c index 3f57d8bccbc..c9a6fe67637 100644 --- a/tests/bluetooth/ctrl_isoal/src/sub_sets/isoal_test_tx.c +++ b/tests/bluetooth/ctrl_isoal/src/sub_sets/isoal_test_tx.c @@ -195,14 +195,14 @@ static isoal_status_t custom_source_pdu_write_test(struct isoal_pdu_buffer *pdu_ _consume_len, \ source_pdu_write_test_fake.arg3_##_typ); \ check_next_custom_source_pdu_write_test_sdu_payload((const uint8_t *)_sdu_payload, \ - _consume_len, __LINE__); + _consume_len, __LINE__) #define ZASSERT_PDU_WRITE_TEST_CALL_COUNT(_expected) \ zassert_equal(_expected, \ source_pdu_write_test_fake.call_count, \ "Expected %u, got %u", \ _expected, \ - source_pdu_write_test_fake.call_count); + source_pdu_write_test_fake.call_count) /*------------------ PDU Emit Callback --------------------------------------*/ /** @@ -480,6 +480,7 @@ static void isoal_test_create_sdu_fagment(uint8_t sdu_state, uint16_t sdu_total_length, uint16_t packet_number, uint32_t timestamp, + uint32_t cntr_timestamp, uint32_t ref_point, uint64_t target_event, struct isoal_sdu_tx *sdu_tx) @@ -488,6 +489,7 @@ static void isoal_test_create_sdu_fagment(uint8_t sdu_state, sdu_tx->packet_sn = packet_number; sdu_tx->iso_sdu_length = sdu_total_length; sdu_tx->time_stamp = timestamp; + sdu_tx->cntr_time_stamp = cntr_timestamp; sdu_tx->grp_ref_point = ref_point; sdu_tx->target_event = target_event; memcpy(sdu_tx->dbuf, dataptr, length); @@ -792,6 +794,7 @@ ZTEST(test_tx_unframed, test_tx_unframed_1_sdu_1_frag_1_pdu_maxPDU) sdu_total_size, sdu_packet_number, sdu_timestamp, + sdu_timestamp, ref_point, event_number, &tx_sdu_frag_buf.sdu_tx); @@ -920,6 +923,7 @@ ZTEST(test_tx_unframed, test_tx_unframed_1_sdu_1_frag_1_pdu_bufSize) sdu_total_size, sdu_packet_number, sdu_timestamp, + sdu_timestamp, ref_point, event_number, &tx_sdu_frag_buf.sdu_tx); @@ -1035,6 +1039,7 @@ ZTEST(test_tx_unframed, test_tx_unframed_1_sdu_1_frag_3_pdu) sdu_total_size, sdu_packet_number, sdu_timestamp, + sdu_timestamp, ref_point, event_number, &tx_sdu_frag_buf.sdu_tx); @@ -1195,6 +1200,7 @@ ZTEST(test_tx_unframed, test_tx_unframed_1_sdu_3_frag_1_pdu) sdu_total_size, sdu_packet_number, sdu_timestamp, + sdu_timestamp, ref_point, event_number, &tx_sdu_frag_buf.sdu_tx); @@ -1241,6 +1247,7 @@ ZTEST(test_tx_unframed, test_tx_unframed_1_sdu_3_frag_1_pdu) sdu_total_size, sdu_packet_number, sdu_timestamp, + sdu_timestamp, ref_point, event_number, &tx_sdu_frag_buf.sdu_tx); @@ -1284,6 +1291,7 @@ ZTEST(test_tx_unframed, test_tx_unframed_1_sdu_3_frag_1_pdu) sdu_total_size, sdu_packet_number, sdu_timestamp, + sdu_timestamp, ref_point, event_number, &tx_sdu_frag_buf.sdu_tx); @@ -1403,6 +1411,7 @@ ZTEST(test_tx_unframed, test_tx_unframed_1_sdu_3_frag_2_pdu) sdu_total_size, sdu_packet_number, sdu_timestamp, + sdu_timestamp, ref_point, event_number, &tx_sdu_frag_buf.sdu_tx); @@ -1451,6 +1460,7 @@ ZTEST(test_tx_unframed, test_tx_unframed_1_sdu_3_frag_2_pdu) sdu_total_size, sdu_packet_number, sdu_timestamp, + sdu_timestamp, ref_point, event_number, &tx_sdu_frag_buf.sdu_tx); @@ -1517,6 +1527,7 @@ ZTEST(test_tx_unframed, test_tx_unframed_1_sdu_3_frag_2_pdu) sdu_total_size, sdu_packet_number, sdu_timestamp, + sdu_timestamp, ref_point, event_number, &tx_sdu_frag_buf.sdu_tx); @@ -1734,6 +1745,7 @@ ZTEST(test_tx_unframed, test_tx_unframed_2_sdu_1_frag_2_pdu_ts_wrap1) sdu_total_size, sdu_packet_number, sdu_timestamp, + sdu_timestamp, ref_point, event_number, &tx_sdu_frag_buf.sdu_tx); @@ -1787,6 +1799,7 @@ ZTEST(test_tx_unframed, test_tx_unframed_2_sdu_1_frag_2_pdu_ts_wrap1) sdu_total_size, sdu_packet_number, sdu_timestamp, + sdu_timestamp, ref_point, event_number, &tx_sdu_frag_buf.sdu_tx); @@ -1916,6 +1929,7 @@ ZTEST(test_tx_unframed, test_tx_unframed_2_sdu_3_frag_4_pdu) sdu_total_size, sdu_packet_number, sdu_timestamp, + sdu_timestamp, ref_point, event_number, &tx_sdu_frag_buf.sdu_tx); @@ -1968,6 +1982,7 @@ ZTEST(test_tx_unframed, test_tx_unframed_2_sdu_3_frag_4_pdu) sdu_total_size, sdu_packet_number, sdu_timestamp, + sdu_timestamp, ref_point, event_number, &tx_sdu_frag_buf.sdu_tx); @@ -2030,6 +2045,7 @@ ZTEST(test_tx_unframed, test_tx_unframed_2_sdu_3_frag_4_pdu) sdu_total_size, sdu_packet_number, sdu_timestamp, + sdu_timestamp, ref_point, event_number, &tx_sdu_frag_buf.sdu_tx); @@ -2085,6 +2101,7 @@ ZTEST(test_tx_unframed, test_tx_unframed_2_sdu_3_frag_4_pdu) sdu_total_size, sdu_packet_number, sdu_timestamp, + sdu_timestamp, ref_point, event_number, &tx_sdu_frag_buf.sdu_tx); @@ -2128,6 +2145,7 @@ ZTEST(test_tx_unframed, test_tx_unframed_2_sdu_3_frag_4_pdu) sdu_total_size, sdu_packet_number, sdu_timestamp, + sdu_timestamp, ref_point, event_number, &tx_sdu_frag_buf.sdu_tx); @@ -2190,6 +2208,7 @@ ZTEST(test_tx_unframed, test_tx_unframed_2_sdu_3_frag_4_pdu) sdu_total_size, sdu_packet_number, sdu_timestamp, + sdu_timestamp, ref_point, event_number, &tx_sdu_frag_buf.sdu_tx); @@ -2314,6 +2333,7 @@ ZTEST(test_tx_unframed, test_tx_unframed_2_sdu_3_frag_4_pdu_padding) sdu_total_size, sdu_packet_number, sdu_timestamp, + sdu_timestamp, ref_point, event_number, &tx_sdu_frag_buf.sdu_tx); @@ -2370,6 +2390,7 @@ ZTEST(test_tx_unframed, test_tx_unframed_2_sdu_3_frag_4_pdu_padding) sdu_total_size, sdu_packet_number, sdu_timestamp, + sdu_timestamp, ref_point, event_number, &tx_sdu_frag_buf.sdu_tx); @@ -2432,6 +2453,7 @@ ZTEST(test_tx_unframed, test_tx_unframed_2_sdu_3_frag_4_pdu_padding) sdu_total_size, sdu_packet_number, sdu_timestamp, + sdu_timestamp, ref_point, event_number, &tx_sdu_frag_buf.sdu_tx); @@ -2527,6 +2549,7 @@ ZTEST(test_tx_unframed, test_tx_unframed_2_sdu_3_frag_4_pdu_padding) sdu_total_size, sdu_packet_number, sdu_timestamp, + sdu_timestamp, ref_point, event_number, &tx_sdu_frag_buf.sdu_tx); @@ -2569,6 +2592,7 @@ ZTEST(test_tx_unframed, test_tx_unframed_2_sdu_3_frag_4_pdu_padding) sdu_total_size, sdu_packet_number, sdu_timestamp, + sdu_timestamp, ref_point, event_number, &tx_sdu_frag_buf.sdu_tx); @@ -2631,6 +2655,7 @@ ZTEST(test_tx_unframed, test_tx_unframed_2_sdu_3_frag_4_pdu_padding) sdu_total_size, sdu_packet_number, sdu_timestamp, + sdu_timestamp, ref_point, event_number, &tx_sdu_frag_buf.sdu_tx); @@ -2792,6 +2817,7 @@ ZTEST(test_tx_unframed, test_tx_unframed_1_zero_sdu_1_frag_1_pdu_maxPDU_padding) sdu_total_size, sdu_packet_number, sdu_timestamp, + sdu_timestamp, ref_point, event_number, &tx_sdu_frag_buf.sdu_tx); @@ -2952,6 +2978,7 @@ ZTEST(test_tx_unframed, test_tx_unframed_1_sdu_1_frag_pdu_alloc_err) sdu_total_size, sdu_packet_number, sdu_timestamp, + sdu_timestamp, ref_point, event_number, &tx_sdu_frag_buf.sdu_tx); @@ -3069,6 +3096,7 @@ ZTEST(test_tx_unframed, test_tx_unframed_1_sdu_1_frag_pdu_emit_err) sdu_total_size, sdu_packet_number, sdu_timestamp, + sdu_timestamp, ref_point, event_number, &tx_sdu_frag_buf.sdu_tx); @@ -3199,6 +3227,7 @@ ZTEST(test_tx_unframed, test_tx_unframed_4_sdu_1_frag_4_pdu_stream_loc) sdu_total_size, sdu_packet_number, sdu_timestamp, + sdu_timestamp, ref_point, event_number, &tx_sdu_frag_buf.sdu_tx); @@ -3269,6 +3298,7 @@ ZTEST(test_tx_unframed, test_tx_unframed_4_sdu_1_frag_4_pdu_stream_loc) sdu_total_size, sdu_packet_number, sdu_timestamp, + sdu_timestamp, ref_point, event_number, &tx_sdu_frag_buf.sdu_tx); @@ -3335,6 +3365,7 @@ ZTEST(test_tx_unframed, test_tx_unframed_4_sdu_1_frag_4_pdu_stream_loc) sdu_total_size, sdu_packet_number, sdu_timestamp, + sdu_timestamp, ref_point, event_number, &tx_sdu_frag_buf.sdu_tx); @@ -3404,6 +3435,7 @@ ZTEST(test_tx_unframed, test_tx_unframed_4_sdu_1_frag_4_pdu_stream_loc) sdu_total_size, sdu_packet_number, sdu_timestamp, + sdu_timestamp, ref_point, event_number, &tx_sdu_frag_buf.sdu_tx); @@ -3451,6 +3483,470 @@ ZTEST(test_tx_unframed, test_tx_unframed_4_sdu_1_frag_4_pdu_stream_loc) zassert_equal(tx_sync_offset, tx_sync_offset_expected, "%u != %u", tx_sync_seq, 0); } +/** + * Test Suite : TX framed SDU segmentation + * + * Tests framed event selection + */ +#define RUN_TX_FRAMED_FIND_CORRECT_TX_EVENT() \ + out_sdus_skipped = isoal_tx_framed_find_correct_tx_event(source, \ + &tx_sdu_frag_buf.sdu_tx, \ + &out_payload_number, \ + &out_ref_point, \ + &out_time_offset); \ + \ + zassert_equal(out_payload_number, expect_payload_number, "%llu != %llu", \ + out_payload_number, expect_payload_number); \ + zassert_equal(out_ref_point, expect_ref_point, "%u != %u", \ + out_ref_point, expect_ref_point); \ + zassert_equal(out_time_offset, expect_time_offset, "%u != %u", \ + out_time_offset, expect_time_offset); \ + zassert_equal(out_sdus_skipped, expect_sdus_skipped, "%u .!= %u", \ + out_sdus_skipped, expect_sdus_skipped) + +ZTEST(test_tx_framed, test_tx_framed_find_correct_tx_event) +{ + const uint8_t number_of_pdus = 1; + const uint8_t testdata_size_max = MAX_FRAMED_PDU_PAYLOAD(number_of_pdus); + + struct tx_sdu_frag_buffer tx_sdu_frag_buf; + struct isoal_source_session *session; + uint8_t testdata[testdata_size_max]; + isoal_sdu_len_t in_sdu_total_size; + isoal_source_handle_t source_hdl; + struct isoal_pdu_production *pp; + uint64_t expect_payload_number; + struct isoal_source *source; + uint64_t out_payload_number; + uint32_t expect_time_offset; + uint8_t expect_sdus_skipped; + uint32_t expected_timestamp; + uint32_t stream_sync_delay; + uint32_t in_cntr_timestamp; + uint32_t group_sync_delay; + uint64_t in_sdu_packet_sn; + uint32_t in_sdu_timestamp; + uint32_t expect_ref_point; + uint64_t in_target_event; + uint32_t iso_interval_us; + uint8_t iso_interval_int; + uint32_t out_time_offset; + uint8_t out_sdus_skipped; + uint16_t testdata_indx; + uint16_t testdata_size; + uint32_t out_ref_point; + uint32_t sdu_interval; + uint32_t in_ref_point; + uint8_t max_octets; + uint8_t role; + uint8_t BN; + uint8_t FT; + + /* Settings */ + role = BT_CONN_ROLE_PERIPHERAL; + iso_interval_int = 1; + iso_interval_us = iso_interval_int * ISO_INT_UNIT_US; + sdu_interval = iso_interval_us + 50; + max_octets = TEST_TX_PDU_PAYLOAD_MAX - 5; + BN = 2; + FT = 1; + stream_sync_delay = (iso_interval_int * ISO_INT_UNIT_US) - 200; + group_sync_delay = (iso_interval_int * ISO_INT_UNIT_US) - 50; + + init_test_data_buffer(testdata, testdata_size_max); + + /* Create source */ + source_hdl = basic_tx_test_setup(0xADAD, /* Handle */ + role, /* Role */ + true, /* Framed */ + BN, /* BN */ + FT, /* FT */ + max_octets, /* max_octets */ + sdu_interval, /* SDU Interval */ + iso_interval_int, /* ISO Interval */ + stream_sync_delay, /* Stream Sync Delay */ + group_sync_delay); /* Group Sync Delay */ + + source = &isoal_global.source_state[source_hdl]; + session = &source->session; + pp = &source->pdu_production; + + in_sdu_total_size = testdata_size_max; + testdata_indx = 0; + testdata_size = testdata_size_max; + + /* Test : Selection of event for first SDU where + * -- Last SDU packet number is uninitialized + * -- Last SDU time stamp is uninitialized + * -- Payload number is uninitialized + * -- Target event and reference point are one event ahead + * -- Time stamp is valid + * -- Time stamp indicates that target event is feasible + * Expected: + * -- Target event is used for transmission and calculations are based + * on that + * -- Time offset is based on the SDUs time stamp + */ + in_sdu_packet_sn = 2000; + in_target_event = 2000; + in_sdu_timestamp = 9249; + in_cntr_timestamp = in_sdu_timestamp + 200; + in_ref_point = in_sdu_timestamp + iso_interval_us - 50; + + pp->initialized = 0U; + session->tx_time_stamp = 0; + session->tx_time_offset = 0; + session->last_input_sn = 0; + session->last_input_time_stamp = 0; + pp->payload_number = 0; + + expect_sdus_skipped = 0; + expect_payload_number = in_target_event * BN; + expect_ref_point = in_ref_point; + expected_timestamp = in_sdu_timestamp; + expect_time_offset = expect_ref_point - expected_timestamp; + + isoal_test_init_tx_sdu_buffer(&tx_sdu_frag_buf); + isoal_test_create_sdu_fagment(BT_ISO_SINGLE, + &testdata[testdata_indx], + (testdata_size - testdata_indx), + in_sdu_total_size, + in_sdu_packet_sn, + in_sdu_timestamp, + in_cntr_timestamp, + in_ref_point, + in_target_event, + &tx_sdu_frag_buf.sdu_tx); + + RUN_TX_FRAMED_FIND_CORRECT_TX_EVENT(); + + /* Test : Selection of event for first SDU where + * -- Last SDU packet number is uninitialized + * -- Last SDU time stamp is uninitialized + * -- Payload number ahead of target event + * -- Target event and reference point are one event behind + * current payload + * -- Time stamp is valid + * -- Time stamp indicates that target event is feasible + * Expected: + * -- Target event + 1 is selected based on the payload being ahead and + * calculations are based on that reference + * -- Time offset is based on the SDUs time stamp + */ + in_sdu_packet_sn = 2000; + in_target_event = 2000; + in_sdu_timestamp = 9249; + in_cntr_timestamp = in_sdu_timestamp + 200; + in_ref_point = in_sdu_timestamp + iso_interval_us - 50; + + pp->initialized = 0U; + session->tx_time_stamp = 0; + session->tx_time_offset = 0; + session->last_input_sn = 0; + session->last_input_time_stamp = 0; + pp->payload_number = (in_target_event + 1) * BN; + + expect_sdus_skipped = 0; + expect_payload_number = (in_target_event + 1) * BN; + expect_ref_point = in_ref_point + iso_interval_us; + expected_timestamp = in_sdu_timestamp; + expect_time_offset = expect_ref_point - expected_timestamp; + + isoal_test_init_tx_sdu_buffer(&tx_sdu_frag_buf); + isoal_test_create_sdu_fagment(BT_ISO_SINGLE, + &testdata[testdata_indx], + (testdata_size - testdata_indx), + in_sdu_total_size, + in_sdu_packet_sn, + in_sdu_timestamp, + in_cntr_timestamp, + in_ref_point, + in_target_event, + &tx_sdu_frag_buf.sdu_tx); + + RUN_TX_FRAMED_FIND_CORRECT_TX_EVENT(); + + /* Test : Selection of event for first SDU where + * -- Last SDU packet number is uninitialized + * -- Last SDU time stamp is uninitialized + * -- Payload number ahead of target event + * -- Target event and reference point are one event behind + * current payload + * -- Time stamp is invalid + * -- Controller time stamp indicates that target event is + * feasible + * Expected: + * -- Target event + 1 is selected based on the payload being ahead and + * calculations are based on that reference + * -- Time offset is based on the controller's capture time + */ + in_sdu_packet_sn = 2000; + in_target_event = 2000; + in_sdu_timestamp = 0; + in_cntr_timestamp = 9249 + 200; + in_ref_point = in_cntr_timestamp + iso_interval_us - 50; + + pp->initialized = 0U; + session->tx_time_stamp = 0; + session->tx_time_offset = 0; + session->last_input_sn = 0; + session->last_input_time_stamp = 0; + pp->payload_number = (in_target_event + 1) * BN; + + expect_sdus_skipped = 0; + expect_payload_number = (in_target_event + 1) * BN; + expect_ref_point = in_ref_point + iso_interval_us; + expected_timestamp = in_cntr_timestamp; + expect_time_offset = expect_ref_point - expected_timestamp; + + isoal_test_init_tx_sdu_buffer(&tx_sdu_frag_buf); + isoal_test_create_sdu_fagment(BT_ISO_SINGLE, + &testdata[testdata_indx], + (testdata_size - testdata_indx), + in_sdu_total_size, + in_sdu_packet_sn, + in_sdu_timestamp, + in_cntr_timestamp, + in_ref_point, + in_target_event, + &tx_sdu_frag_buf.sdu_tx); + + RUN_TX_FRAMED_FIND_CORRECT_TX_EVENT(); + + /* Test : Selection of event for a subsequent SDU where + * -- Last SDU packet number is in sequence + * -- Last SDU time stamp is in sequence + * -- Payload number is in sequence + * -- Target event and reference point are one event ahead of + * current payload + * -- Time stamp is valid + * -- Time stamp indicates that target event is feasible + * Expected: + * -- Target event is selected based on the time stamp and calculations + * are based on that reference + * -- Time offset is based on the SDUs time stamp + */ + in_sdu_packet_sn = 2000; + in_target_event = 2000; + in_sdu_timestamp = 9249; + in_cntr_timestamp = 9249 + 200; + in_ref_point = in_sdu_timestamp + iso_interval_us - 50; + + pp->initialized = 1U; + session->tx_time_stamp = 0; + session->tx_time_offset = 0; + session->last_input_sn = in_sdu_packet_sn - 1; + session->last_input_time_stamp = in_sdu_timestamp - sdu_interval; + pp->payload_number = (in_target_event - 1) * BN; + + expect_sdus_skipped = 0; + expect_payload_number = in_target_event * BN; + expect_ref_point = in_ref_point; + expected_timestamp = in_sdu_timestamp; + expect_time_offset = expect_ref_point - expected_timestamp; + + isoal_test_init_tx_sdu_buffer(&tx_sdu_frag_buf); + isoal_test_create_sdu_fagment(BT_ISO_SINGLE, + &testdata[testdata_indx], + (testdata_size - testdata_indx), + in_sdu_total_size, + in_sdu_packet_sn, + in_sdu_timestamp, + in_cntr_timestamp, + in_ref_point, + in_target_event, + &tx_sdu_frag_buf.sdu_tx); + + RUN_TX_FRAMED_FIND_CORRECT_TX_EVENT(); + + /* Test : Selection of event for a subsequent SDU where + * -- Last SDU packet number is not in sequence + * -- Last SDU time stamp is not in sequence + * -- Payload number is not in sequence + * -- Target event and reference point are two events ahead + * -- Time stamp is valid but at the border of the range + * -- Time stamp indicates that target event - 1 is feasible + * Expected: + * -- Target event - 1 is selected based on the time stamp and + * calculations are based on that reference + * -- Time offset is based on the SDUs time stamp + */ + in_sdu_packet_sn = 2000; + in_target_event = 2001; + in_sdu_timestamp = 9249; + in_cntr_timestamp = 9249 + sdu_interval + iso_interval_us; + in_ref_point = in_sdu_timestamp + (iso_interval_us * 2) - 50; + + pp->initialized = 1U; + session->tx_time_stamp = 0; + session->tx_time_offset = 0; + session->last_input_sn = in_sdu_packet_sn - 3; + session->last_input_time_stamp = in_sdu_timestamp - (sdu_interval * 2); + pp->payload_number = (in_target_event - 2) * BN; + + expect_sdus_skipped = in_sdu_packet_sn - session->last_input_sn - 1; + expect_payload_number = (in_target_event - 1) * BN; + expect_ref_point = in_ref_point - iso_interval_us; + expected_timestamp = in_sdu_timestamp; + expect_time_offset = expect_ref_point - expected_timestamp; + + isoal_test_init_tx_sdu_buffer(&tx_sdu_frag_buf); + isoal_test_create_sdu_fagment(BT_ISO_SINGLE, + &testdata[testdata_indx], + (testdata_size - testdata_indx), + in_sdu_total_size, + in_sdu_packet_sn, + in_sdu_timestamp, + in_cntr_timestamp, + in_ref_point, + in_target_event, + &tx_sdu_frag_buf.sdu_tx); + + RUN_TX_FRAMED_FIND_CORRECT_TX_EVENT(); + + /* Test : Selection of event for a subsequent SDU where + * -- Last SDU packet number is not in sequence + * -- Last SDU time stamp is not in sequence + * -- Payload number is not in sequence + * -- Target event and reference point are two events ahead + * -- Time stamp is invalid + * Expected: + * -- Target event is selected based on the time stamp calculated + * from the difference between time stamps and calculations are based + * on that reference + * -- Time offset is based on the SDUs time stamp + */ + in_sdu_packet_sn = 2000; + in_target_event = 2001; + in_sdu_timestamp = 9249; + in_cntr_timestamp = 9249 + sdu_interval + iso_interval_us + 1; + in_ref_point = in_sdu_timestamp + (iso_interval_us * 2) - 50; + + pp->initialized = 1U; + session->tx_time_stamp = in_ref_point - iso_interval_us; + session->tx_time_offset = session->tx_time_stamp - + (in_sdu_timestamp - sdu_interval); + session->last_input_sn = in_sdu_packet_sn - 3; + session->last_input_time_stamp = in_sdu_timestamp - (sdu_interval * 2); + pp->payload_number = (in_target_event - 2) * BN; + + expect_sdus_skipped = in_sdu_packet_sn - session->last_input_sn - 1; + expect_payload_number = in_target_event * BN; + expect_ref_point = in_ref_point; + expected_timestamp = session->tx_time_stamp - session->tx_time_offset + + (in_sdu_timestamp - session->last_input_time_stamp); + expect_time_offset = expect_ref_point - expected_timestamp; + + isoal_test_init_tx_sdu_buffer(&tx_sdu_frag_buf); + isoal_test_create_sdu_fagment(BT_ISO_SINGLE, + &testdata[testdata_indx], + (testdata_size - testdata_indx), + in_sdu_total_size, + in_sdu_packet_sn, + in_sdu_timestamp, + in_cntr_timestamp, + in_ref_point, + in_target_event, + &tx_sdu_frag_buf.sdu_tx); + + RUN_TX_FRAMED_FIND_CORRECT_TX_EVENT(); + + /* Test : Selection of event for a subsequent SDU where + * -- Last SDU packet number is not in sequence + * -- Last SDU time stamp has been projected as part of a + * burst + * -- Payload number is not in sequence + * -- Target event and reference point are two events ahead + * -- Time stamp is invalid + * -- Time stamp delta is invalid + * Expected: + * -- Target event + 1 is selected based on the time stamp calculated + * from the difference in packet sn and calculations are based + * on that reference + * -- Time offset is based on the SDUs time stamp + */ + in_sdu_packet_sn = 2000; + in_target_event = 2001; + in_sdu_timestamp = 9249; + in_cntr_timestamp = 9249 + sdu_interval + iso_interval_us + 1; + in_ref_point = in_sdu_timestamp + (iso_interval_us * 2) - 50; + + pp->initialized = 1U; + session->tx_time_stamp = in_ref_point - iso_interval_us; + session->tx_time_offset = session->tx_time_stamp - + (in_sdu_timestamp + sdu_interval); + session->last_input_sn = in_sdu_packet_sn - 1; + session->last_input_time_stamp = in_sdu_timestamp + (sdu_interval * 2); + pp->payload_number = (in_target_event - 2) * BN; + + expect_sdus_skipped = in_sdu_packet_sn - session->last_input_sn - 1; + expect_payload_number = (in_target_event + 1) * BN; + expect_ref_point = in_ref_point + iso_interval_us; + expected_timestamp = session->tx_time_stamp - session->tx_time_offset + sdu_interval; + expect_time_offset = expect_ref_point - expected_timestamp; + + isoal_test_init_tx_sdu_buffer(&tx_sdu_frag_buf); + isoal_test_create_sdu_fagment(BT_ISO_SINGLE, + &testdata[testdata_indx], + (testdata_size - testdata_indx), + in_sdu_total_size, + in_sdu_packet_sn, + in_sdu_timestamp, + in_cntr_timestamp, + in_ref_point, + in_target_event, + &tx_sdu_frag_buf.sdu_tx); + + RUN_TX_FRAMED_FIND_CORRECT_TX_EVENT(); + + /* Test : Selection of event for a subsequent SDU where + * -- Last SDU packet number is in sequence + * -- Last SDU time stamp has been projected as part of a + * burst + * -- Payload number is ahead of selected event + * -- Target event and reference point are two events ahead + * -- Time stamp is valid + * -- Time stamp indicates that target event - 1 is feasible + * Expected: + * -- Target event -1 is selected based on the time stamp and + * calculations are based on that reference + * -- Payload number continues from last + * -- Time offset is based on the SDUs time stamp + */ + in_sdu_packet_sn = 2000; + in_target_event = 2001; + in_sdu_timestamp = 9249; + in_cntr_timestamp = 9249; + in_ref_point = in_sdu_timestamp + (iso_interval_us * 2) - 50; + + pp->initialized = 1U; + session->tx_time_stamp = 0; + session->tx_time_offset = 0; + session->last_input_sn = in_sdu_packet_sn - 1; + session->last_input_time_stamp = in_sdu_timestamp - sdu_interval; + pp->payload_number = ((in_target_event - 1) * BN) + 1; + + expect_sdus_skipped = in_sdu_packet_sn - session->last_input_sn - 1; + expect_payload_number = pp->payload_number; + expect_ref_point = in_ref_point - iso_interval_us; + expected_timestamp = in_sdu_timestamp; + expect_time_offset = expect_ref_point - expected_timestamp; + + isoal_test_init_tx_sdu_buffer(&tx_sdu_frag_buf); + isoal_test_create_sdu_fagment(BT_ISO_SINGLE, + &testdata[testdata_indx], + (testdata_size - testdata_indx), + in_sdu_total_size, + in_sdu_packet_sn, + in_sdu_timestamp, + in_cntr_timestamp, + in_ref_point, + in_target_event, + &tx_sdu_frag_buf.sdu_tx); + + RUN_TX_FRAMED_FIND_CORRECT_TX_EVENT(); +} + /** * Test Suite : TX framed SDU segmentation * @@ -3537,6 +4033,7 @@ ZTEST(test_tx_framed, test_tx_framed_1_sdu_1_frag_1_pdu_maxPDU) sdu_total_size, sdu_packet_number, sdu_timestamp, + sdu_timestamp, ref_point, event_number, &tx_sdu_frag_buf.sdu_tx); @@ -3692,6 +4189,7 @@ ZTEST(test_tx_framed, test_tx_framed_1_sdu_1_frag_1_pdu_bufSize) sdu_total_size, sdu_packet_number, sdu_timestamp, + sdu_timestamp, ref_point, event_number, &tx_sdu_frag_buf.sdu_tx); @@ -3836,6 +4334,7 @@ ZTEST(test_tx_framed, test_tx_framed_1_sdu_1_frag_3_pdu) sdu_total_size, sdu_packet_number, sdu_timestamp, + sdu_timestamp, ref_point, event_number, &tx_sdu_frag_buf.sdu_tx); @@ -4073,6 +4572,7 @@ ZTEST(test_tx_framed, test_tx_framed_1_sdu_3_frag_1_pdu) sdu_total_size, sdu_packet_number, sdu_timestamp, + sdu_timestamp, ref_point, event_number, &tx_sdu_frag_buf.sdu_tx); @@ -4144,6 +4644,7 @@ ZTEST(test_tx_framed, test_tx_framed_1_sdu_3_frag_1_pdu) sdu_total_size, sdu_packet_number, sdu_timestamp, + sdu_timestamp, ref_point, event_number, &tx_sdu_frag_buf.sdu_tx); @@ -4198,6 +4699,7 @@ ZTEST(test_tx_framed, test_tx_framed_1_sdu_3_frag_1_pdu) sdu_total_size, sdu_packet_number, sdu_timestamp, + sdu_timestamp, ref_point, event_number, &tx_sdu_frag_buf.sdu_tx); @@ -4335,6 +4837,7 @@ ZTEST(test_tx_framed, test_tx_framed_1_sdu_3_frag_2_pdu) sdu_total_size, sdu_packet_number, sdu_timestamp, + sdu_timestamp, ref_point, event_number, &tx_sdu_frag_buf.sdu_tx); @@ -4408,6 +4911,7 @@ ZTEST(test_tx_framed, test_tx_framed_1_sdu_3_frag_2_pdu) sdu_total_size, sdu_packet_number, sdu_timestamp, + sdu_timestamp, ref_point, event_number, &tx_sdu_frag_buf.sdu_tx); @@ -4500,6 +5004,7 @@ ZTEST(test_tx_framed, test_tx_framed_1_sdu_3_frag_2_pdu) sdu_total_size, sdu_packet_number, sdu_timestamp, + sdu_timestamp, ref_point, event_number, &tx_sdu_frag_buf.sdu_tx); @@ -4637,6 +5142,7 @@ ZTEST(test_tx_framed, test_tx_framed_2_sdu_3_frag_4_pdu) sdu_total_size, sdu_packet_number, sdu_timestamp, + sdu_timestamp, ref_point, event_number, &tx_sdu_frag_buf.sdu_tx); @@ -4712,6 +5218,7 @@ ZTEST(test_tx_framed, test_tx_framed_2_sdu_3_frag_4_pdu) sdu_total_size, sdu_packet_number, sdu_timestamp, + sdu_timestamp, ref_point, event_number, &tx_sdu_frag_buf.sdu_tx); @@ -4804,6 +5311,7 @@ ZTEST(test_tx_framed, test_tx_framed_2_sdu_3_frag_4_pdu) sdu_total_size, sdu_packet_number, sdu_timestamp, + sdu_timestamp, ref_point, event_number, &tx_sdu_frag_buf.sdu_tx); @@ -4870,6 +5378,7 @@ ZTEST(test_tx_framed, test_tx_framed_2_sdu_3_frag_4_pdu) sdu_total_size, sdu_packet_number, sdu_timestamp, + sdu_timestamp, ref_point, event_number, &tx_sdu_frag_buf.sdu_tx); @@ -4936,6 +5445,7 @@ ZTEST(test_tx_framed, test_tx_framed_2_sdu_3_frag_4_pdu) sdu_total_size, sdu_packet_number, sdu_timestamp, + sdu_timestamp, ref_point, event_number, &tx_sdu_frag_buf.sdu_tx); @@ -5027,6 +5537,7 @@ ZTEST(test_tx_framed, test_tx_framed_2_sdu_3_frag_4_pdu) sdu_total_size, sdu_packet_number, sdu_timestamp, + sdu_timestamp, ref_point, event_number, &tx_sdu_frag_buf.sdu_tx); @@ -5164,6 +5675,7 @@ ZTEST(test_tx_framed, test_tx_framed_2_sdu_3_frag_4_pdu_padding) sdu_total_size, sdu_packet_number, sdu_timestamp, + sdu_timestamp, ref_point, event_number, &tx_sdu_frag_buf.sdu_tx); @@ -5236,6 +5748,7 @@ ZTEST(test_tx_framed, test_tx_framed_2_sdu_3_frag_4_pdu_padding) sdu_total_size, sdu_packet_number, sdu_timestamp, + sdu_timestamp, ref_point, event_number, &tx_sdu_frag_buf.sdu_tx); @@ -5327,6 +5840,7 @@ ZTEST(test_tx_framed, test_tx_framed_2_sdu_3_frag_4_pdu_padding) sdu_total_size, sdu_packet_number, sdu_timestamp, + sdu_timestamp, ref_point, event_number, &tx_sdu_frag_buf.sdu_tx); @@ -5390,6 +5904,7 @@ ZTEST(test_tx_framed, test_tx_framed_2_sdu_3_frag_4_pdu_padding) sdu_total_size, sdu_packet_number, sdu_timestamp, + sdu_timestamp, ref_point, event_number, &tx_sdu_frag_buf.sdu_tx); @@ -5451,6 +5966,7 @@ ZTEST(test_tx_framed, test_tx_framed_2_sdu_3_frag_4_pdu_padding) sdu_total_size, sdu_packet_number, sdu_timestamp, + sdu_timestamp, ref_point, event_number, &tx_sdu_frag_buf.sdu_tx); @@ -5541,6 +6057,7 @@ ZTEST(test_tx_framed, test_tx_framed_2_sdu_3_frag_4_pdu_padding) sdu_total_size, sdu_packet_number, sdu_timestamp, + sdu_timestamp, ref_point, event_number, &tx_sdu_frag_buf.sdu_tx); @@ -5711,6 +6228,7 @@ ZTEST(test_tx_framed, test_tx_framed_2_sdu_1_frag_2_pdu_refPoint2) sdu_total_size, sdu_packet_number, sdu_timestamp, + sdu_timestamp, ref_point, event_number, &tx_sdu_frag_buf.sdu_tx); @@ -5791,6 +6309,7 @@ ZTEST(test_tx_framed, test_tx_framed_2_sdu_1_frag_2_pdu_refPoint2) sdu_total_size, sdu_packet_number, sdu_timestamp, + sdu_timestamp, ref_point, event_number, &tx_sdu_frag_buf.sdu_tx); @@ -5940,6 +6459,7 @@ ZTEST(test_tx_framed, test_tx_framed_1_sdu_1_frag_1_pdu_refPoint3) sdu_total_size, sdu_packet_number, sdu_timestamp, + sdu_timestamp, ref_point, event_number, &tx_sdu_frag_buf.sdu_tx); @@ -6096,6 +6616,7 @@ ZTEST(test_tx_framed, test_tx_framed_2_sdu_1_frag_2_pdu_ts_wrap1) sdu_total_size, sdu_packet_number, sdu_timestamp, + sdu_timestamp, ref_point, event_number, &tx_sdu_frag_buf.sdu_tx); @@ -6176,6 +6697,7 @@ ZTEST(test_tx_framed, test_tx_framed_2_sdu_1_frag_2_pdu_ts_wrap1) sdu_total_size, sdu_packet_number, sdu_timestamp, + sdu_timestamp, ref_point, event_number, &tx_sdu_frag_buf.sdu_tx); @@ -6316,6 +6838,7 @@ ZTEST(test_tx_framed, test_tx_framed_1_zero_sdu_1_frag_1_pdu_maxPDU) sdu_total_size, sdu_packet_number, sdu_timestamp, + sdu_timestamp, ref_point, event_number, &tx_sdu_frag_buf.sdu_tx); @@ -6467,6 +6990,7 @@ ZTEST(test_tx_framed, test_tx_framed_1_zero_sdu_1_frag_1_pdu_padding) sdu_total_size, sdu_packet_number, sdu_timestamp, + sdu_timestamp, ref_point, event_number, &tx_sdu_frag_buf.sdu_tx); @@ -6647,6 +7171,7 @@ ZTEST(test_tx_framed, test_tx_framed_1_sdu_1_frag_pdu_alloc_err) sdu_total_size, sdu_packet_number, sdu_timestamp, + sdu_timestamp, ref_point, event_number, &tx_sdu_frag_buf.sdu_tx); @@ -6775,6 +7300,7 @@ ZTEST(test_tx_framed, test_tx_framed_1_sdu_1_frag_pdu_emit_err) sdu_total_size, sdu_packet_number, sdu_timestamp, + sdu_timestamp, ref_point, event_number, &tx_sdu_frag_buf.sdu_tx); @@ -6921,6 +7447,7 @@ ZTEST(test_tx_framed, test_tx_framed_2_sdu_1_frag_pdu_timeout) sdu_total_size, sdu_packet_number, sdu_timestamp, + sdu_timestamp, ref_point, event_number, &tx_sdu_frag_buf.sdu_tx); @@ -6997,6 +7524,7 @@ ZTEST(test_tx_framed, test_tx_framed_2_sdu_1_frag_pdu_timeout) sdu_total_size, sdu_packet_number, sdu_timestamp, + sdu_timestamp, ref_point, event_number, &tx_sdu_frag_buf.sdu_tx); @@ -7071,6 +7599,7 @@ ZTEST(test_tx_framed, test_tx_framed_2_sdu_1_frag_pdu_timeout) sdu_total_size, sdu_packet_number, sdu_timestamp, + sdu_timestamp, ref_point, event_number, &tx_sdu_frag_buf.sdu_tx); @@ -7234,6 +7763,7 @@ ZTEST(test_tx_framed, test_tx_framed_event_utilization_1) sdu_total_size, sdu_packet_number, sdu_timestamp, + sdu_timestamp, ref_point, event_number, &tx_sdu_frag_buf.sdu_tx); @@ -7309,6 +7839,7 @@ ZTEST(test_tx_framed, test_tx_framed_event_utilization_1) sdu_total_size, sdu_packet_number, sdu_timestamp, + sdu_timestamp, ref_point, event_number, &tx_sdu_frag_buf.sdu_tx); @@ -7418,6 +7949,7 @@ ZTEST(test_tx_framed, test_tx_framed_event_utilization_1) sdu_total_size, sdu_packet_number, sdu_timestamp, + sdu_timestamp, ref_point, event_number, &tx_sdu_frag_buf.sdu_tx); @@ -7510,6 +8042,7 @@ ZTEST(test_tx_framed, test_tx_framed_event_utilization_1) sdu_total_size, sdu_packet_number, sdu_timestamp, + sdu_timestamp, ref_point, event_number, &tx_sdu_frag_buf.sdu_tx); @@ -7696,6 +8229,7 @@ ZTEST(test_tx_framed_ebq, test_tx_framed_cis_fra_per_bv07c) sdu_total_size, sdu_packet_number, sdu_timestamp, + sdu_timestamp, ref_point, event_number, &tx_sdu_frag_buf.sdu_tx); @@ -7767,6 +8301,7 @@ ZTEST(test_tx_framed_ebq, test_tx_framed_cis_fra_per_bv07c) sdu_total_size, sdu_packet_number, sdu_timestamp, + sdu_timestamp, ref_point, event_number, &tx_sdu_frag_buf.sdu_tx); @@ -7847,6 +8382,7 @@ ZTEST(test_tx_framed_ebq, test_tx_framed_cis_fra_per_bv07c) sdu_total_size, sdu_packet_number, sdu_timestamp, + sdu_timestamp, ref_point, event_number, &tx_sdu_frag_buf.sdu_tx); From d1b4bbfe99dd4cf897c9d72d830ea99a894bc48c Mon Sep 17 00:00:00 2001 From: Nirosharn Amarasinghe Date: Mon, 14 Aug 2023 12:36:14 +0200 Subject: [PATCH 295/421] [nrf fromtree] tests: bluetooth: controller: Updated ISO-AL tests for length of err PDU Updated unit tests to match changes in ISO-AL that disregard the length of a received PDU with errors. Signed-off-by: Nirosharn Amarasinghe (cherry picked from commit 770f435e6881ea667466744c22d2ee9ca6f715ec) Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit c8610f518ed2ea44c275bca1b0c21bd6c3ac7cc1) --- .../ctrl_isoal/src/sub_sets/isoal_test_rx.c | 115 ++++++++---------- 1 file changed, 51 insertions(+), 64 deletions(-) diff --git a/tests/bluetooth/ctrl_isoal/src/sub_sets/isoal_test_rx.c b/tests/bluetooth/ctrl_isoal/src/sub_sets/isoal_test_rx.c index 5a3c60e0854..fdb86af1f5c 100644 --- a/tests/bluetooth/ctrl_isoal/src/sub_sets/isoal_test_rx.c +++ b/tests/bluetooth/ctrl_isoal/src/sub_sets/isoal_test_rx.c @@ -60,19 +60,19 @@ static isoal_status_t custom_sink_sdu_alloc_test(const struct isoal_sink *sink_c #define ZASSERT_ISOAL_SDU_ALLOC_TEST(_typ, _sink, _pdu) \ zassert_equal_ptr(_sink, \ sink_sdu_alloc_test_fake.arg0_##_typ, \ - "\t\t%p != %p", \ + "\t\tExpected alloc sink at %p, got %p.", \ _sink, \ sink_sdu_alloc_test_fake.arg0_##_typ); \ zassert_equal_ptr(_pdu, \ sink_sdu_alloc_test_fake.arg1_##_typ, \ - "\t\t%p != %p", \ + "\t\tExpected alloc PDU buffer at %p, got %p.", \ _pdu, \ sink_sdu_alloc_test_fake.arg1_##_typ) #define ZASSERT_ISOAL_SDU_ALLOC_TEST_CALL_COUNT(_expected) \ zassert_equal(_expected, \ sink_sdu_alloc_test_fake.call_count, \ - "Expected %u got %u", \ + "Expected alloc called %u times, actual %u.", \ _expected, \ sink_sdu_alloc_test_fake.call_count) @@ -125,59 +125,59 @@ static isoal_status_t custom_sink_sdu_emit_test(const struct isoal_sink *sink_ct _sdu_status) \ zassert_equal_ptr(_sink, \ sink_sdu_emit_test_fake.arg0_##_typ, \ - "\t\t%p != %p", \ + "\t\tExpected sink at %p, got %p.", \ _sink, \ sink_sdu_emit_test_fake.arg0_##_typ); \ zassert_equal(_state, \ sink_sdu_emit_test_handler_fake.arg1_##_typ.sdu_state, \ - "\t\t%d != %d", \ - _state, \ - sink_sdu_emit_test_handler_fake.arg1_##_typ.sdu_state); \ + "\t\tExpected SDU state '%s', got '%s'.", \ + STATE_TO_STR(_state), \ + STATE_TO_STR(sink_sdu_emit_test_handler_fake.arg1_##_typ.sdu_state)); \ zassert_equal(_frag_sz, \ sink_sdu_emit_test_handler_fake.arg1_##_typ.sdu_frag_size, \ - "\t\t%d != %d", \ + "\t\tExpected SDU frag of size %u, got %u.", \ _frag_sz, \ sink_sdu_emit_test_handler_fake.arg1_##_typ.sdu_frag_size); \ zassert_equal(_frag_status, \ sink_sdu_emit_test_handler_fake.arg1_##_typ.sdu.status, \ - "\t\t%d != %d", \ - _frag_status, \ - sink_sdu_emit_test_handler_fake.arg1_##_typ.sdu.status); \ + "\t\tExpected SDU with status '%s', got '%s'.", \ + DU_ERR_TO_STR(_frag_status), \ + DU_ERR_TO_STR(sink_sdu_emit_test_handler_fake.arg1_##_typ.sdu.status)); \ zassert_equal(_timestamp, \ sink_sdu_emit_test_handler_fake.arg1_##_typ.sdu.timestamp, \ - "\t\t%d != %d", \ + "\t\tExpected SDU with timestamp %u, got %u.", \ _timestamp, \ sink_sdu_emit_test_handler_fake.arg1_##_typ.sdu.timestamp); \ zassert_equal(_sn, \ sink_sdu_emit_test_handler_fake.arg1_##_typ.sdu.sn, \ - "\t\t%d != %d", \ + "\t\tExpected SDU with sequence number %u, got %u.", \ _sn, \ sink_sdu_emit_test_handler_fake.arg1_##_typ.sdu.sn); \ - zassert_equal(_dbuf, \ - sink_sdu_emit_test_handler_fake.arg1_##_typ.sdu.contents.dbuf, \ - "\t\t%p != %p", \ - _dbuf, \ - sink_sdu_emit_test_handler_fake.arg1_##_typ.sdu.contents.dbuf); \ + zassert_equal_ptr(_dbuf, \ + sink_sdu_emit_test_handler_fake.arg1_##_typ.sdu.contents.dbuf, \ + "\t\tExpected SDU data buffer at %p, got %p.", \ + _dbuf, \ + sink_sdu_emit_test_handler_fake.arg1_##_typ.sdu.contents.dbuf); \ zassert_equal(_dbuf_sz, \ sink_sdu_emit_test_handler_fake.arg1_##_typ.sdu.contents.size, \ - "\t\t%d != %d", \ + "\t\tExpected SDU data buffer of size %u, got %u.", \ _dbuf_sz, \ sink_sdu_emit_test_handler_fake.arg1_##_typ.sdu.contents.size); \ zassert_equal(_total_sz, \ sink_sdu_emit_test_handler_fake.arg2_##_typ.total_sdu_size, \ - "\t\t%d != %d", \ + "\t\tExpected total size of SDU %u,got %u.", \ _total_sz, \ sink_sdu_emit_test_handler_fake.arg2_##_typ.total_sdu_size); \ zassert_equal(_sdu_status, \ sink_sdu_emit_test_handler_fake.arg2_##_typ.collated_status, \ - "\t\t%d != %d", \ - _sdu_status, \ - sink_sdu_emit_test_handler_fake.arg2_##_typ.collated_status) + "\t\tExpected SDU with status '%s', got '%s'.", \ + DU_ERR_TO_STR(_sdu_status), \ + DU_ERR_TO_STR(sink_sdu_emit_test_handler_fake.arg2_##_typ.collated_status)) #define ZASSERT_ISOAL_SDU_EMIT_TEST_CALL_COUNT(_expected) \ zassert_equal(_expected, \ sink_sdu_emit_test_fake.call_count, \ - "Expected %u got %u", \ + "Expected emit called %u times, actual %u.", \ _expected, \ sink_sdu_emit_test_fake.call_count) @@ -212,24 +212,24 @@ custom_sink_sdu_write_test(void *dbuf, const uint8_t *pdu_payload, const size_t #define ZASSERT_ISOAL_SDU_WRITE_TEST(_typ, _frag_buf, _payload_buf, _length) \ zassert_equal_ptr(_frag_buf, \ sink_sdu_write_test_fake.arg0_##_typ, \ - "\t\t%p != %p", \ + "\t\tExpected write buffer at %p, got %p.", \ _frag_buf, \ sink_sdu_write_test_fake.arg0_##_typ); \ zassert_equal_ptr(_payload_buf, \ sink_sdu_write_test_fake.arg1_##_typ, \ - "\t\t%p != %p", \ + "\t\tExpected write source at %p, got %p.", \ _payload_buf, \ sink_sdu_write_test_fake.arg1_##_typ); \ zassert_equal(_length, \ sink_sdu_write_test_fake.arg2_##_typ, \ - "\t\t%d != %d", \ + "\t\tExpected write length of %u, got %u.", \ _length, \ sink_sdu_write_test_fake.arg2_##_typ) #define ZASSERT_ISOAL_SDU_WRITE_TEST_CALL_COUNT(_expected) \ zassert_equal(_expected, \ sink_sdu_write_test_fake.call_count, \ - "Expected %u got %u", \ + "Expected write called %u times, actual %u.", \ _expected, \ sink_sdu_write_test_fake.call_count) @@ -2767,7 +2767,7 @@ ZTEST(test_rx_unframed, test_rx_unframed_single_pdu_err) seqn = 0; testdata_indx = 0; testdata_size = 13; - sdu_size = 13; + sdu_size = 0; total_sdu_size = COLLATED_RX_SDU_INFO(sdu_size, sdu_size); collated_status = COLLATED_RX_SDU_INFO(ISOAL_SDU_STATUS_ERRORS, ISOAL_SDU_STATUS_ERRORS); @@ -2804,11 +2804,9 @@ ZTEST(test_rx_unframed, test_rx_unframed_single_pdu_err) &isoal_global.sink_state[sink_hdl], /* Sink */ &rx_pdu_meta_buf.pdu_meta); /* PDU */ - /* SDU payload should be written */ - ZASSERT_ISOAL_SDU_WRITE_TEST(val, - &rx_sdu_frag_buf, /* SDU buffer */ - &rx_pdu_meta_buf.pdu[3], /* PDU payload */ - (testdata_size - testdata_indx)); /* Size */ + /* SDU payload should not be written */ + ZASSERT_ISOAL_SDU_WRITE_TEST_CALL_COUNT(0); + /* SDU should be emitted */ ZASSERT_ISOAL_SDU_EMIT_TEST(val, &isoal_global.sink_state[sink_hdl], /* Sink */ @@ -2838,7 +2836,6 @@ ZTEST(test_rx_unframed, test_rx_unframed_single_pdu_err) sdu_timestamp = (uint32_t)((int64_t)pdu_timestamp + latency); testdata_indx = testdata_size; testdata_size += 10; - sdu_size = 10; total_sdu_size = COLLATED_RX_SDU_INFO(sdu_size, sdu_size); collated_status = COLLATED_RX_SDU_INFO(ISOAL_SDU_STATUS_LOST_DATA, ISOAL_SDU_STATUS_LOST_DATA); @@ -2866,11 +2863,9 @@ ZTEST(test_rx_unframed, test_rx_unframed_single_pdu_err) &isoal_global.sink_state[sink_hdl], /* Sink */ &rx_pdu_meta_buf.pdu_meta); /* PDU */ - /* SDU payload should be written */ - ZASSERT_ISOAL_SDU_WRITE_TEST(val, - &rx_sdu_frag_buf, /* SDU buffer */ - &rx_pdu_meta_buf.pdu[3], /* PDU payload */ - (testdata_size - testdata_indx)); /* Size */ + /* SDU payload should not be written */ + ZASSERT_ISOAL_SDU_WRITE_TEST_CALL_COUNT(0); + /* SDU should be emitted */ ZASSERT_ISOAL_SDU_EMIT_TEST(val, &isoal_global.sink_state[sink_hdl], /* Sink */ @@ -3239,7 +3234,6 @@ ZTEST(test_rx_unframed, test_rx_unframed_seq_pdu_err1) payload_number++; testdata_indx = testdata_size; testdata_size += 10; - sdu_size += 10; total_sdu_size = COLLATED_RX_SDU_INFO(sdu_size, sdu_size); collated_status = COLLATED_RX_SDU_INFO(ISOAL_SDU_STATUS_LOST_DATA, ISOAL_SDU_STATUS_LOST_DATA); @@ -3263,12 +3257,11 @@ ZTEST(test_rx_unframed, test_rx_unframed_seq_pdu_err1) /* Test recombine (Black Box) */ /* A new SDU should not be allocated */ + ZASSERT_ISOAL_SDU_ALLOC_TEST_CALL_COUNT(1); + + /* SDU payload should not be written */ + ZASSERT_ISOAL_SDU_WRITE_TEST_CALL_COUNT(1); - /* SDU payload should be written */ - ZASSERT_ISOAL_SDU_WRITE_TEST(val, - &rx_sdu_frag_buf, /* SDU buffer */ - &rx_pdu_meta_buf.pdu[3], /* PDU payload */ - (testdata_size - testdata_indx)); /* Size */ /* SDU should be emitted */ ZASSERT_ISOAL_SDU_EMIT_TEST(val, &isoal_global.sink_state[sink_hdl], /* Sink */ @@ -3535,7 +3528,7 @@ ZTEST(test_rx_unframed, test_rx_unframed_seq_pdu_err2) payload_number++; testdata_indx = testdata_size; testdata_size += 10; - sdu_size = 10; + sdu_size = 0; total_sdu_size = COLLATED_RX_SDU_INFO(sdu_size, 50); collated_status = COLLATED_RX_SDU_INFO(ISOAL_SDU_STATUS_LOST_DATA, ISOAL_SDU_STATUS_LOST_DATA); @@ -3565,11 +3558,9 @@ ZTEST(test_rx_unframed, test_rx_unframed_seq_pdu_err2) &isoal_global.sink_state[sink_hdl], /* Sink */ &rx_pdu_meta_buf.pdu_meta); /* PDU */ - /* SDU payload should be written */ - ZASSERT_ISOAL_SDU_WRITE_TEST(val, - &rx_sdu_frag_buf, /* SDU buffer */ - &rx_pdu_meta_buf.pdu[3], /* PDU payload */ - (testdata_size - testdata_indx)); /* Size */ + /* SDU payload should not be written */ + ZASSERT_ISOAL_SDU_WRITE_TEST_CALL_COUNT(1); + /* SDU should be emitted */ ZASSERT_ISOAL_SDU_EMIT_TEST(val, &isoal_global.sink_state[sink_hdl], /* Sink */ @@ -4569,7 +4560,7 @@ ZTEST(test_rx_unframed, test_rx_unframed_padding_error1) seqn = 0; testdata_indx = 0; testdata_size = 13; - sdu_size = 13; + sdu_size = 0; total_sdu_size = COLLATED_RX_SDU_INFO(sdu_size, sdu_size); collated_status = COLLATED_RX_SDU_INFO(ISOAL_SDU_STATUS_ERRORS, ISOAL_SDU_STATUS_ERRORS); @@ -4607,11 +4598,9 @@ ZTEST(test_rx_unframed, test_rx_unframed_padding_error1) &isoal_global.sink_state[sink_hdl], /* Sink */ &rx_pdu_meta_buf.pdu_meta); /* PDU */ - /* SDU payload should be written */ - ZASSERT_ISOAL_SDU_WRITE_TEST(val, - &rx_sdu_frag_buf, /* SDU buffer */ - &rx_pdu_meta_buf.pdu[3], /* PDU payload */ - (testdata_size - testdata_indx)); /* Size */ + /* SDU payload should not be written */ + ZASSERT_ISOAL_SDU_WRITE_TEST_CALL_COUNT(0); + /* SDU should be emitted */ ZASSERT_ISOAL_SDU_EMIT_TEST(val, &isoal_global.sink_state[sink_hdl], /* Sink */ @@ -5935,7 +5924,6 @@ ZTEST(test_rx_unframed, test_rx_unframed_dbl_pdu_invalid_llid2_pdu_err) payload_number++; testdata_indx = testdata_size; testdata_size += 10; - sdu_size += 10; total_sdu_size = COLLATED_RX_SDU_INFO(sdu_size, sdu_size); collated_status = COLLATED_RX_SDU_INFO(ISOAL_SDU_STATUS_ERRORS, ISOAL_SDU_STATUS_ERRORS); @@ -5958,12 +5946,11 @@ ZTEST(test_rx_unframed, test_rx_unframed_dbl_pdu_invalid_llid2_pdu_err) /* Test recombine (Black Box) */ /* A new SDU should not be allocated */ + ZASSERT_ISOAL_SDU_ALLOC_TEST_CALL_COUNT(1); + + /* SDU payload should not be written */ + ZASSERT_ISOAL_SDU_WRITE_TEST_CALL_COUNT(1); - /* SDU payload should be written */ - ZASSERT_ISOAL_SDU_WRITE_TEST(val, - &rx_sdu_frag_buf, /* SDU buffer */ - &rx_pdu_meta_buf.pdu[3], /* PDU payload */ - (testdata_size - testdata_indx)); /* Size */ /* SDU should be emitted */ ZASSERT_ISOAL_SDU_EMIT_TEST(val, &isoal_global.sink_state[sink_hdl], /* Sink */ From d03d84372b9ee34a6d22066899041c0da203d168 Mon Sep 17 00:00:00 2001 From: Nirosharn Amarasinghe Date: Fri, 8 Sep 2023 17:03:06 +0200 Subject: [PATCH 296/421] [nrf fromtree] tests: bluetooth: controller: Included kconfigs for ISO-AL logging Included kconfigs to set the ISO-AL logging level and control debug logging verbosity in ISO-AL unit tests. Signed-off-by: Nirosharn Amarasinghe (cherry picked from commit 467ec2e6b7b4f4a235cc0c401e378a50f735dfe1) Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit 5f8a4c085a3cbad114bc79fa80bdbc4c2b2790f0) --- tests/bluetooth/ctrl_isoal/Kconfig | 19 +++++++++++++++++++ tests/bluetooth/ctrl_isoal/prj.conf | 2 ++ 2 files changed, 21 insertions(+) diff --git a/tests/bluetooth/ctrl_isoal/Kconfig b/tests/bluetooth/ctrl_isoal/Kconfig index b7c10723b93..30049d53a5e 100644 --- a/tests/bluetooth/ctrl_isoal/Kconfig +++ b/tests/bluetooth/ctrl_isoal/Kconfig @@ -12,6 +12,25 @@ config BT_CTLR_CONN_ISO_GROUPS range 1 240 default 1 +config BT_CTLR_DEBUG_ISOAL + bool "[DEPRECATED] Bluetooth ISO-AL debug" + select DEPRECATED + depends on BT_CTLR_ISO + help + This option enables debug support for the Bluetooth ISO-AL. + +module = BT_CTLR_ISOAL +legacy-debug-sym = BT_CTLR_DEBUG_ISOAL +module-str = "Bluetooth Controller ISO-AL" +source "subsys/bluetooth/common/Kconfig.template.log_config_bt" + +config BT_CTLR_ISOAL_LOG_DBG_VERBOSE + bool "ISO-AL verbose debug logging" + depends on BT_CTLR_ISOAL_LOG_LEVEL = 4 + default n + help + Use this option to enable ISO-AL verbose debug logging. + config BT_CTLR_ISOAL_SINKS int "Number of Isochronous Adaptation Layer sinks (for unit tests)" diff --git a/tests/bluetooth/ctrl_isoal/prj.conf b/tests/bluetooth/ctrl_isoal/prj.conf index 5009e2785f8..2f429dd8c47 100644 --- a/tests/bluetooth/ctrl_isoal/prj.conf +++ b/tests/bluetooth/ctrl_isoal/prj.conf @@ -9,3 +9,5 @@ CONFIG_BT_CTLR_CONN_ISO=y CONFIG_BT_CTLR_ISOAL_SINKS=4 CONFIG_BT_CTLR_ISOAL_SOURCES=4 CONFIG_BT_CTLR_ISO_RX_SDU_BUFFERS=4 + +CONFIG_BT_CTLR_ISOAL_LOG_LEVEL_INF=y From fd1e8cfb37ef151b5421694bfde6857a8db18255 Mon Sep 17 00:00:00 2001 From: Andrzej Kuros Date: Tue, 10 Oct 2023 16:14:14 +0200 Subject: [PATCH 297/421] [nrf fromlist] nrf53: fix RTC pretick for RTC rescheduling by other interrupts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It might happen that while some interrupt handler other than for RTC0 or RTC1 (e.g. for RADIO) is executed, the scheduled pretick CC triggers. This starts pretick pulses due to the loop through IPC. The change in pretick schedule did not stop the pretick pulses going through IPC loop, what caused heavy increase in power consumption. This commit fixes this behavior. Added also clarifications for Kconfig option `SOC_NRF53_RTC_PRETICK`. Upstream PR: https://github.com/zephyrproject-rtos/zephyr/pull/63597 Signed-off-by: Andrzej Kuroś (cherry picked from commit fe1202def42eda65ca5b3a0f41836e9599b0b9c2) --- soc/arm/nordic_nrf/nrf53/Kconfig.soc | 6 +++++- soc/arm/nordic_nrf/nrf53/soc.c | 22 ++++++++++++---------- 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/soc/arm/nordic_nrf/nrf53/Kconfig.soc b/soc/arm/nordic_nrf/nrf53/Kconfig.soc index 87d8a6d0c7a..87d961d6fb3 100644 --- a/soc/arm/nordic_nrf/nrf53/Kconfig.soc +++ b/soc/arm/nordic_nrf/nrf53/Kconfig.soc @@ -58,7 +58,11 @@ config SOC_NRF53_RTC_PRETICK select ARM_ON_ENTER_CPU_IDLE_PREPARE_HOOK if SOC_NRF5340_CPUNET help Indicates that the pre-tick workaround for the anomaly 165 that affects - the nRF5340 SoC should be applied. + the nRF5340 SoC should be applied. The workaround applies to wake ups caused + by EVENTS_COMPARE and EVENTS_OVRFLW on RTC0 and RTC1 for which interrupts are + enabled through INTENSET register. The case when these events are generated + by EVTEN but without interrupts enabled through INTENSET is not handled. + The EVENTS_TICK event is not handled. if SOC_NRF53_RTC_PRETICK diff --git a/soc/arm/nordic_nrf/nrf53/soc.c b/soc/arm/nordic_nrf/nrf53/soc.c index c18228ac4fa..396ce79f49e 100644 --- a/soc/arm/nordic_nrf/nrf53/soc.c +++ b/soc/arm/nordic_nrf/nrf53/soc.c @@ -224,6 +224,15 @@ static bool cpu_idle_prepare_monitor_end(void) return __STREXB(0U, &cpu_idle_prepare_monitor_dummy); } +static void rtc_pretick_finish_previous(void) +{ + NRF_IPC->PUBLISH_RECEIVE[CONFIG_SOC_NRF53_RTC_PRETICK_IPC_CH_TO_NET] &= + ~IPC_PUBLISH_RECEIVE_EN_Msk; + + nrf_rtc_event_clear(NRF_RTC1, NRF_RTC_CHANNEL_EVENT_ADDR(RTC1_PRETICK_CC_CHAN)); +} + + void z_arm_on_enter_cpu_idle_prepare(void) { bool ok_to_sleep = true; @@ -263,6 +272,7 @@ void z_arm_on_enter_cpu_idle_prepare(void) if (rtc_pretick_cc_val != nrf_rtc_cc_get(NRF_RTC1, RTC1_PRETICK_CC_CHAN)) { /* The CC for pretick needs to be updated. */ + rtc_pretick_finish_previous(); nrf_rtc_cc_set(NRF_RTC1, RTC1_PRETICK_CC_CHAN, rtc_pretick_cc_val); if (rtc_ticks_to_next_event >= NRF_RTC_COUNTER_MAX/2) { @@ -406,22 +416,14 @@ static int rtc_pretick_cpuapp_init(void) } #else /* CONFIG_SOC_NRF5340_CPUNET */ -static void rtc_pretick_rtc_isr_hook(void) -{ - NRF_IPC->PUBLISH_RECEIVE[CONFIG_SOC_NRF53_RTC_PRETICK_IPC_CH_TO_NET] &= - ~IPC_PUBLISH_RECEIVE_EN_Msk; - - nrf_rtc_event_clear(NRF_RTC1, NRF_RTC_CHANNEL_EVENT_ADDR(RTC1_PRETICK_CC_CHAN)); -} - void rtc_pretick_rtc0_isr_hook(void) { - rtc_pretick_rtc_isr_hook(); + rtc_pretick_finish_previous(); } void rtc_pretick_rtc1_isr_hook(void) { - rtc_pretick_rtc_isr_hook(); + rtc_pretick_finish_previous(); } static int rtc_pretick_cpunet_init(void) From 009e4d56688790dce25ab360d5add0ef44e92bd5 Mon Sep 17 00:00:00 2001 From: Andrzej Kuros Date: Tue, 10 Oct 2023 20:14:30 +0200 Subject: [PATCH 298/421] [nrf fromlist] nrf5340: pretick decoupled from workaround anomaly 160 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Coupling in code between workarounds for anomaly 160 and anomaly 165 (pretick) is decreased. Upstream PR: https://github.com/zephyrproject-rtos/zephyr/pull/63597 Signed-off-by: Andrzej Kuroś (cherry picked from commit 1d4a51c2a893f84d17fcf78adb0bdbabe33e71e7) --- soc/arm/nordic_nrf/nrf53/Kconfig.soc | 1 + soc/arm/nordic_nrf/nrf53/soc.c | 9 ++++++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/soc/arm/nordic_nrf/nrf53/Kconfig.soc b/soc/arm/nordic_nrf/nrf53/Kconfig.soc index 87d961d6fb3..2cd934af324 100644 --- a/soc/arm/nordic_nrf/nrf53/Kconfig.soc +++ b/soc/arm/nordic_nrf/nrf53/Kconfig.soc @@ -53,6 +53,7 @@ config SOC_NRF53_ANOMALY_160_WORKAROUND config SOC_NRF53_RTC_PRETICK bool "Pre-tick workaround for nRF5340 anomaly 165" + depends on (SYS_CLOCK_EXISTS && SOC_NRF5340_CPUNET) || SOC_NRF5340_CPUAPP select NRFX_DPPI select ARM_ON_ENTER_CPU_IDLE_HOOK if SOC_NRF5340_CPUNET select ARM_ON_ENTER_CPU_IDLE_PREPARE_HOOK if SOC_NRF5340_CPUNET diff --git a/soc/arm/nordic_nrf/nrf53/soc.c b/soc/arm/nordic_nrf/nrf53/soc.c index 396ce79f49e..39d64d72cc2 100644 --- a/soc/arm/nordic_nrf/nrf53/soc.c +++ b/soc/arm/nordic_nrf/nrf53/soc.c @@ -133,6 +133,7 @@ static bool nrf53_anomaly_160_check(void) return true; } +#endif /* CONFIG_SOC_NRF53_ANOMALY_160_WORKAROUND */ #if defined(CONFIG_SOC_NRF53_RTC_PRETICK) && defined(CONFIG_SOC_NRF5340_CPUNET) @@ -337,6 +338,8 @@ void z_arm_on_enter_cpu_idle_prepare(void) } #endif /* CONFIG_SOC_NRF53_RTC_PRETICK && CONFIG_SOC_NRF5340_CPUNET */ +#if defined(CONFIG_SOC_NRF53_ANOMALY_160_WORKAROUND) || \ + (defined(CONFIG_SOC_NRF53_RTC_PRETICK) && defined(CONFIG_SOC_NRF5340_CPUNET)) bool z_arm_on_enter_cpu_idle(void) { bool ok_to_sleep = true; @@ -357,6 +360,7 @@ bool z_arm_on_enter_cpu_idle(void) } #endif +#if defined(CONFIG_SOC_NRF53_ANOMALY_160_WORKAROUND) if (ok_to_sleep) { ok_to_sleep = nrf53_anomaly_160_check(); @@ -371,6 +375,7 @@ bool z_arm_on_enter_cpu_idle(void) } #endif } +#endif /* CONFIG_SOC_NRF53_ANOMALY_160_WORKAROUND */ #if defined(CONFIG_SOC_NRF53_RTC_PRETICK) && defined(CONFIG_SOC_NRF5340_CPUNET) if (!ok_to_sleep) { @@ -382,7 +387,9 @@ bool z_arm_on_enter_cpu_idle(void) return ok_to_sleep; } -#endif /* CONFIG_SOC_NRF53_ANOMALY_160_WORKAROUND */ +#endif /* CONFIG_SOC_NRF53_ANOMALY_160_WORKAROUND || + * (CONFIG_SOC_NRF53_RTC_PRETICK && CONFIG_SOC_NRF5340_CPUNET) + */ #if CONFIG_SOC_NRF53_RTC_PRETICK #ifdef CONFIG_SOC_NRF5340_CPUAPP From 495c47634d7c2105b7dd21734ef4a87eb25ea932 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20G=C5=82=C4=85bek?= Date: Wed, 20 Sep 2023 12:12:50 +0200 Subject: [PATCH 299/421] [nrf fromtree] drivers: spi_nrfx_spis: Handle empty spi_buf_set structures properly MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit SPI API allows `spi_buf_set` structures with no buffers linked to them (with `.buffers = NULL`). Correct the spi_nrfx_spis driver so that it is able to deal with such structures. Signed-off-by: Andrzej Głąbek (cherry picked from commit eafe6a9a3101c187849849c4e0f3c3f9696ccdb0) (cherry picked from commit d21b65201c9b7b56aa8f565c810266f5e720fc04) --- drivers/spi/spi_nrfx_spis.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/spi/spi_nrfx_spis.c b/drivers/spi/spi_nrfx_spis.c index 6ba36a139a0..d2a61530f00 100644 --- a/drivers/spi/spi_nrfx_spis.c +++ b/drivers/spi/spi_nrfx_spis.c @@ -170,6 +170,8 @@ static int transceive(const struct device *dev, { struct spi_nrfx_data *dev_data = dev->data; const struct spi_nrfx_config *dev_config = dev->config; + const struct spi_buf *tx_buf = tx_bufs ? tx_bufs->buffers : NULL; + const struct spi_buf *rx_buf = rx_bufs ? rx_bufs->buffers : NULL; int error; spi_context_lock(&dev_data->ctx, asynchronous, cb, userdata, spi_cfg); @@ -181,8 +183,7 @@ static int transceive(const struct device *dev, (rx_bufs && rx_bufs->count > 1)) { LOG_ERR("Scattered buffers are not supported"); error = -ENOTSUP; - } else if (tx_bufs && tx_bufs->buffers[0].len && - !nrfx_is_in_ram(tx_bufs->buffers[0].buf)) { + } else if (tx_buf && tx_buf->len && !nrfx_is_in_ram(tx_buf->buf)) { LOG_ERR("Only buffers located in RAM are supported"); error = -ENOTSUP; } else { @@ -193,10 +194,10 @@ static int transceive(const struct device *dev, } error = prepare_for_transfer(dev, - tx_bufs ? tx_bufs->buffers[0].buf : NULL, - tx_bufs ? tx_bufs->buffers[0].len : 0, - rx_bufs ? rx_bufs->buffers[0].buf : NULL, - rx_bufs ? rx_bufs->buffers[0].len : 0); + tx_buf ? tx_buf->buf : NULL, + tx_buf ? tx_buf->len : 0, + rx_buf ? rx_buf->buf : NULL, + rx_buf ? rx_buf->len : 0); if (error == 0) { if (dev_config->wake_gpio.port) { /* Set the WAKE line low (tie it to ground) From a4670ff4eabc3517bda2bc34b25b97e2159c33dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20G=C5=82=C4=85bek?= Date: Thu, 28 Sep 2023 11:24:12 +0200 Subject: [PATCH 300/421] [nrf fromtree] tests: kernel: timer: jitter_drift: Restore initial alignment to tick MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is a follow-up to commit 4cc21e2f4aea2e37f4fea1216fe92ded9ba6d755. That short sleeping before starting the test was removed together with accuracy improvements (specifically, with moving of the first readout of the cycle counter). Nevertheless, this tick alignment it still needed, as without it in specific conditions the test may undesirably fail. Signed-off-by: Andrzej Głąbek (cherry picked from commit 222593f8c45683c29341e153fe518ba7ea22498e) (cherry picked from commit 7b739ac27ac6c1e26c48f6e9f144ec685a54149f) --- tests/kernel/timer/timer_behavior/src/jitter_drift.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/tests/kernel/timer/timer_behavior/src/jitter_drift.c b/tests/kernel/timer/timer_behavior/src/jitter_drift.c index cd6afaea00d..6d3e78d514b 100644 --- a/tests/kernel/timer/timer_behavior/src/jitter_drift.c +++ b/tests/kernel/timer/timer_behavior/src/jitter_drift.c @@ -121,6 +121,17 @@ static void do_test_using(void (*sample_collection_fn)(void)) periodic_idx = 0; k_sem_init(&periodic_sem, 0, 1); + + /* Align to tick boundary. Otherwise the first handler execution + * might turn out to be significantly late and cause the test to + * fail. This can happen if k_timer_start() is called right before + * the upcoming tick boundary and in consequence the tick passes + * between the moment when the kernel decides what tick to use for + * the next timeout and the moment when the system timer actually + * sets up that timeout. + */ + k_sleep(K_TICKS(1)); + sample_collection_fn(); k_sem_take(&periodic_sem, K_FOREVER); From 7e3e8dea4ba07c5730b6d037ba50ddede860bc1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20G=C5=82=C4=85bek?= Date: Fri, 6 Oct 2023 09:17:05 +0200 Subject: [PATCH 301/421] [nrf fromtree] bluetooth: common: Kconfig: Add missing dependency for BT_MONITOR MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This module calls `log_output_*` functions so it should enable the `LOG_OUTPUT` Kconfig option explicitly. Signed-off-by: Andrzej Głąbek (cherry picked from commit cb1b1ce7d111fe830eade1dfbd95229f10f99005) (cherry picked from commit 8513132483676fad66bff03e4c9933744250f1b4) --- subsys/bluetooth/common/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/subsys/bluetooth/common/Kconfig b/subsys/bluetooth/common/Kconfig index d72ce90afa6..bf4aee75e48 100644 --- a/subsys/bluetooth/common/Kconfig +++ b/subsys/bluetooth/common/Kconfig @@ -282,6 +282,7 @@ endif # BT_ASSERT config BT_MONITOR bool + select LOG_OUTPUT choice BT_DEBUG_TYPE prompt "Bluetooth debug type" From 74bdabf7e57a988ad740da44398cf93f7d5e0c79 Mon Sep 17 00:00:00 2001 From: Pavel Vasilyev Date: Tue, 10 Oct 2023 09:52:28 +0200 Subject: [PATCH 302/421] [nrf fromtree] Bluetooth: Mesh: Fix Upload Progress for already received fw In OOB upload, when Check Firmware OOB procedure completes successfully and the firmware is already received, we send Firmware Distribution Upload Status message with update Phase set to Transfer Success. In this case, we must set Upload Progress to 100%. This can't be done through the callback as the application layer doesn't yet know that the firmware is already received. This will happen by the exist from bt_mesh_dfd_srv_oob_check_complete function, which will return error code -EEXIST. Signed-off-by: Pavel Vasilyev (cherry picked from commit 9641864a200f83531fe0d0c866d53dda96c905ea) (cherry picked from commit 55152781e7bd1d3b361a6605dcad1e11ad27fcb9) --- subsys/bluetooth/mesh/dfd_srv.c | 32 +++++++++++++++++++++++++------- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/subsys/bluetooth/mesh/dfd_srv.c b/subsys/bluetooth/mesh/dfd_srv.c index 5d3ada4b4aa..a67a3a778ca 100644 --- a/subsys/bluetooth/mesh/dfd_srv.c +++ b/subsys/bluetooth/mesh/dfd_srv.c @@ -342,9 +342,10 @@ static int handle_apply(struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, return 0; } -static void upload_status_rsp(struct bt_mesh_dfd_srv *srv, - struct bt_mesh_msg_ctx *ctx, - enum bt_mesh_dfd_status status) +static void upload_status_rsp_with_progress(struct bt_mesh_dfd_srv *srv, + struct bt_mesh_msg_ctx *ctx, + enum bt_mesh_dfd_status status, + uint8_t progress) { BT_MESH_MODEL_BUF_DEFINE(rsp, BT_MESH_DFD_OP_UPLOAD_STATUS, DFD_UPLOAD_STATUS_MSG_MAXLEN); @@ -361,14 +362,13 @@ static void upload_status_rsp(struct bt_mesh_dfd_srv *srv, #ifdef CONFIG_BT_MESH_DFD_SRV_OOB_UPLOAD if (srv->upload.is_oob) { - net_buf_simple_add_u8(&rsp, - srv->cb->oob_progress_get(srv, srv->upload.slot) | BIT(7)); + net_buf_simple_add_u8(&rsp, progress | BIT(7)); net_buf_simple_add_mem(&rsp, srv->upload.oob.current_fwid, srv->upload.oob.current_fwid_len); } else #endif { - net_buf_simple_add_u8(&rsp, bt_mesh_blob_srv_progress(&srv->upload.blob)); + net_buf_simple_add_u8(&rsp, progress); net_buf_simple_add_mem(&rsp, srv->upload.slot->fwid, srv->upload.slot->fwid_len); } @@ -376,6 +376,24 @@ static void upload_status_rsp(struct bt_mesh_dfd_srv *srv, bt_mesh_model_send(srv->mod, ctx, &rsp, NULL, NULL); } +static void upload_status_rsp(struct bt_mesh_dfd_srv *srv, + struct bt_mesh_msg_ctx *ctx, + enum bt_mesh_dfd_status status) +{ + uint8_t progress; + +#ifdef CONFIG_BT_MESH_DFD_SRV_OOB_UPLOAD + if (srv->upload.is_oob) { + progress = srv->cb->oob_progress_get(srv, srv->upload.slot); + } else +#endif + { + progress = bt_mesh_blob_srv_progress(&srv->upload.blob); + } + + upload_status_rsp_with_progress(srv, ctx, status, progress); +} + static int handle_upload_get(struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { @@ -400,7 +418,7 @@ static inline int set_upload_fwid(struct bt_mesh_dfd_srv *srv, struct bt_mesh_ms case -EEXIST: /* Img with this fwid already is in list */ srv->upload.phase = BT_MESH_DFD_UPLOAD_PHASE_TRANSFER_SUCCESS; bt_mesh_dfu_slot_release(srv->upload.slot); - upload_status_rsp(srv, ctx, BT_MESH_DFD_SUCCESS); + upload_status_rsp_with_progress(srv, ctx, BT_MESH_DFD_SUCCESS, 100); break; case 0: srv->upload.phase = BT_MESH_DFD_UPLOAD_PHASE_TRANSFER_ACTIVE; From 4491262ebf889bf6bcb1ff2aed0c504a9f3cb17a Mon Sep 17 00:00:00 2001 From: Pavel Vasilyev Date: Tue, 10 Oct 2023 09:59:19 +0200 Subject: [PATCH 303/421] [nrf fromtree] Bluetooth: Mesh: Fix Fw Dist Upload OOB Start msg length check This message _at least_ 2 bytes long, but can be longer, thus BT_MESH_LEN_MIN should be used. Signed-off-by: Pavel Vasilyev (cherry picked from commit 1329a9d31292f3f2e5f4134e9cc61acb76daa5a9) (cherry picked from commit 96d61afdc45fd3f53b4a6ea85b74263002e7b6e7) --- subsys/bluetooth/mesh/dfd_srv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subsys/bluetooth/mesh/dfd_srv.c b/subsys/bluetooth/mesh/dfd_srv.c index a67a3a778ca..f060e263ace 100644 --- a/subsys/bluetooth/mesh/dfd_srv.c +++ b/subsys/bluetooth/mesh/dfd_srv.c @@ -761,7 +761,7 @@ const struct bt_mesh_model_op _bt_mesh_dfd_srv_op[] = { { BT_MESH_DFD_OP_APPLY, BT_MESH_LEN_EXACT(0), handle_apply }, { BT_MESH_DFD_OP_UPLOAD_GET, BT_MESH_LEN_EXACT(0), handle_upload_get }, { BT_MESH_DFD_OP_UPLOAD_START, BT_MESH_LEN_MIN(16), handle_upload_start }, - { BT_MESH_DFD_OP_UPLOAD_START_OOB, BT_MESH_LEN_EXACT(2), handle_upload_start_oob }, + { BT_MESH_DFD_OP_UPLOAD_START_OOB, BT_MESH_LEN_MIN(2), handle_upload_start_oob }, { BT_MESH_DFD_OP_UPLOAD_CANCEL, BT_MESH_LEN_EXACT(0), handle_upload_cancel }, { BT_MESH_DFD_OP_FW_GET, BT_MESH_LEN_MIN(0), handle_fw_get }, { BT_MESH_DFD_OP_FW_GET_BY_INDEX, BT_MESH_LEN_EXACT(2), handle_fw_get_by_index }, From a2744d2bdee2459cd9dd0ebec788a99d82b02f7b Mon Sep 17 00:00:00 2001 From: Pavel Vasilyev Date: Tue, 10 Oct 2023 10:52:46 +0200 Subject: [PATCH 304/421] [nrf fromtree] Bluetooth: Mesh: Ignore duplicate OOB upload request If a Fw Distribution Client sends the Upload OOB Start message, but the application layer didn't call bt_mesh_dfd_srv_oob_check_complete yet, we have no other option other than ignore the message. The next phase in this case could be Transfer Active, Transfer Success or Failed and it will be set only after Check Firmware OOB procedure completes. Signed-off-by: Pavel Vasilyev (cherry picked from commit 7154f356af59c3a1b61168b885a7b9f23b3f6404) (cherry picked from commit 63d1a0ee7753ac0a338156167b36bafbbe230fe2) --- include/zephyr/bluetooth/mesh/dfd_srv.h | 1 + subsys/bluetooth/mesh/dfd_srv.c | 12 +++++++++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/include/zephyr/bluetooth/mesh/dfd_srv.h b/include/zephyr/bluetooth/mesh/dfd_srv.h index da339c57ec6..666e0d8ad3d 100644 --- a/include/zephyr/bluetooth/mesh/dfd_srv.h +++ b/include/zephyr/bluetooth/mesh/dfd_srv.h @@ -228,6 +228,7 @@ struct bt_mesh_dfd_srv { struct bt_mesh_blob_srv blob; #ifdef CONFIG_BT_MESH_DFD_SRV_OOB_UPLOAD bool is_oob; + bool is_pending_oob_check; struct { uint8_t uri_len; uint8_t uri[CONFIG_BT_MESH_DFU_URI_MAXLEN]; diff --git a/subsys/bluetooth/mesh/dfd_srv.c b/subsys/bluetooth/mesh/dfd_srv.c index f060e263ace..f8dfaf0b97f 100644 --- a/subsys/bluetooth/mesh/dfd_srv.c +++ b/subsys/bluetooth/mesh/dfd_srv.c @@ -586,6 +586,11 @@ static int handle_upload_start_oob(struct bt_mesh_model *mod, struct bt_mesh_msg #endif upload_status_rsp(srv, ctx, BT_MESH_DFD_ERR_BUSY_WITH_UPLOAD); return 0; +#ifdef CONFIG_BT_MESH_DFD_SRV_OOB_UPLOAD + } else if (srv->upload.is_oob && srv->upload.is_pending_oob_check) { + /* Ignore the request if we didn't confirm the previous one. */ + return 0; +#endif } #ifdef CONFIG_BT_MESH_DFD_SRV_OOB_UPLOAD @@ -618,6 +623,8 @@ static int handle_upload_start_oob(struct bt_mesh_model *mod, struct bt_mesh_msg if (status != BT_MESH_DFD_SUCCESS) { upload_status_rsp(srv, ctx, status); bt_mesh_dfu_slot_release(srv->upload.slot); + } else { + srv->upload.is_pending_oob_check = true; } #else upload_status_rsp(srv, ctx, BT_MESH_DFD_ERR_URI_NOT_SUPPORTED); @@ -1211,13 +1218,16 @@ int bt_mesh_dfd_srv_oob_check_complete(struct bt_mesh_dfd_srv *srv, int err; if (slot != srv->upload.slot || !srv->upload.is_oob || - srv->upload.phase == BT_MESH_DFD_UPLOAD_PHASE_TRANSFER_ACTIVE) { + srv->upload.phase == BT_MESH_DFD_UPLOAD_PHASE_TRANSFER_ACTIVE || + !srv->upload.is_pending_oob_check) { /* This should not happen, unless the application calls the function with a * "wrong" pointer or at a wrong time. */ return -EINVAL; } + srv->upload.is_pending_oob_check = false; + if (status != BT_MESH_DFD_SUCCESS) { bt_mesh_dfu_slot_release(srv->upload.slot); upload_status_rsp(srv, &srv->upload.oob.ctx, status); From c97f38205f50eceac6b66359799e19df5b6aeb28 Mon Sep 17 00:00:00 2001 From: Pavel Vasilyev Date: Tue, 10 Oct 2023 07:57:32 +0200 Subject: [PATCH 305/421] [nrf fromtree] Bluetooth: Mesh: Release previously reserved slot before reserving again If the previous upload was in-band and it didn't complete, the slot will stay reserved. By design we release slot not at the end of the upload phase, but at the start of a new upload phase. This fixes DFU/SR/FD/BV-13-C. Signed-off-by: Pavel Vasilyev (cherry picked from commit d1c2ca252556fffd043dcdff2edb1277bcaedb31) (cherry picked from commit 2ab65215ceef910fffc81f74e67ae726306eb5f5) --- subsys/bluetooth/mesh/dfd_srv.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/subsys/bluetooth/mesh/dfd_srv.c b/subsys/bluetooth/mesh/dfd_srv.c index f8dfaf0b97f..cfcc82eb8d1 100644 --- a/subsys/bluetooth/mesh/dfd_srv.c +++ b/subsys/bluetooth/mesh/dfd_srv.c @@ -607,6 +607,13 @@ static int handle_upload_start_oob(struct bt_mesh_model *mod, struct bt_mesh_msg return 0; } + /* This will be a no-op if the slot state isn't RESERVED, which is + * what we want. + */ + if (srv->upload.slot) { + bt_mesh_dfu_slot_release(srv->upload.slot); + } + srv->upload.is_oob = true; srv->upload.slot = slot; memcpy(srv->upload.oob.uri, uri, uri_len); From 5640e9e33ab1bfaca4ed341b0d752518ed181de2 Mon Sep 17 00:00:00 2001 From: Pavel Vasilyev Date: Tue, 10 Oct 2023 08:54:48 +0200 Subject: [PATCH 306/421] [nrf fromtree] tests: bluetooth: tester: Add Upload OOB support for mesh tester This allow to run the following PTS test: - DFU/SR/FD/BV-06-C - DFU/SR/FD/BV-13-C - DFU/SR/FD/BV-14-C - DFU/SR/FD/BV-15-C - DFU/SR/FD/BV-16-C - DFU/SR/FD/BV-17-C - DFU/SR/FD/BV-18-C - DFU/SR/FD/BV-22-C Signed-off-by: Pavel Vasilyev (cherry picked from commit 1c1c5e22b73a2f628696d7e10e78e08c7468176f) (cherry picked from commit 3b705c2885cec71eca48ccfeb5823e712730856f) --- tests/bluetooth/tester/src/btp_mesh.c | 119 ++++++++++++++++++++++++++ 1 file changed, 119 insertions(+) diff --git a/tests/bluetooth/tester/src/btp_mesh.c b/tests/bluetooth/tester/src/btp_mesh.c index 662dca238c1..81c41dca708 100644 --- a/tests/bluetooth/tester/src/btp_mesh.c +++ b/tests/bluetooth/tester/src/btp_mesh.c @@ -162,13 +162,132 @@ static int dfd_srv_send(struct bt_mesh_dfd_srv *srv, return 0; } +#ifdef CONFIG_BT_MESH_DFD_SRV_OOB_UPLOAD +static struct { + uint8_t uri[CONFIG_BT_MESH_DFU_URI_MAXLEN]; + uint8_t uri_len; + uint8_t fwid[CONFIG_BT_MESH_DFU_FWID_MAXLEN]; + uint8_t fwid_len; + const struct bt_mesh_dfu_slot *slot; + uint8_t progress; + bool started; +} dfd_srv_oob_ctx; + +static void oob_check_handler(struct k_work *work); +static K_WORK_DEFINE(oob_check, oob_check_handler); +static void oob_store_handler(struct k_work *work); +static K_WORK_DEFINE(oob_store, oob_store_handler); + +static int dfd_srv_start_oob_upload(struct bt_mesh_dfd_srv *srv, + const struct bt_mesh_dfu_slot *slot, + const char *uri, uint8_t uri_len, + const uint8_t *fwid, uint16_t fwid_len) +{ + LOG_DBG("Start OOB Upload"); + + memcpy(dfd_srv_oob_ctx.uri, uri, uri_len); + dfd_srv_oob_ctx.uri_len = uri_len; + memcpy(dfd_srv_oob_ctx.fwid, fwid, fwid_len); + dfd_srv_oob_ctx.fwid_len = fwid_len; + dfd_srv_oob_ctx.slot = slot; + dfd_srv_oob_ctx.progress = 0; + dfd_srv_oob_ctx.started = true; + + k_work_submit(&oob_check); + + return BT_MESH_DFD_SUCCESS; +} + +static void dfd_srv_cancel_oob_upload(struct bt_mesh_dfd_srv *srv, + const struct bt_mesh_dfu_slot *slot) +{ + LOG_DBG("Cancel OOB Upload"); + + dfd_srv_oob_ctx.started = false; +} + +static uint8_t dfd_srv_oob_progress_get(struct bt_mesh_dfd_srv *srv, + const struct bt_mesh_dfu_slot *slot) +{ + uint8_t progress; + + if (dfd_srv_oob_ctx.started) { + progress = dfd_srv_oob_ctx.progress; + + dfd_srv_oob_ctx.progress = MIN(dfd_srv_oob_ctx.progress + 25, 99); + + if (dfd_srv_oob_ctx.progress == 99) { + k_work_submit(&oob_store); + } + } else { + progress = 0; + } + + LOG_DBG("OOB Progress Get (%sstarted: %d %%)", dfd_srv_oob_ctx.started ? "" : "not ", + progress); + return progress; +} +#endif /* CONFIG_BT_MESH_DFD_SRV_OOB_UPLOAD */ + static struct bt_mesh_dfd_srv_cb dfd_srv_cb = { .recv = dfd_srv_recv, .del = dfd_srv_del, .send = dfd_srv_send, +#ifdef CONFIG_BT_MESH_DFD_SRV_OOB_UPLOAD + .start_oob_upload = dfd_srv_start_oob_upload, + .cancel_oob_upload = dfd_srv_cancel_oob_upload, + .oob_progress_get = dfd_srv_oob_progress_get, +#endif }; static struct bt_mesh_dfd_srv dfd_srv = BT_MESH_DFD_SRV_INIT(&dfd_srv_cb); + +#ifdef CONFIG_BT_MESH_DFD_SRV_OOB_UPLOAD +#define SUPPORTED_SCHEME "http" + +static void oob_check_handler(struct k_work *work) +{ + uint8_t scheme[10]; + int i; + int status; + int err; + + for (i = 0; i < MIN(dfd_srv_oob_ctx.uri_len, sizeof(scheme)); i++) { + if (IN_RANGE(dfd_srv_oob_ctx.uri[i], 48, 57) || /* DIGIT */ + IN_RANGE(dfd_srv_oob_ctx.uri[i], 65, 90) || /* ALPHA UPPER CASE */ + IN_RANGE(dfd_srv_oob_ctx.uri[i], 97, 122) || /* ALPHA LOWER CASE */ + dfd_srv_oob_ctx.uri[i] == '.' || + dfd_srv_oob_ctx.uri[i] == '+' || + dfd_srv_oob_ctx.uri[i] == '-') { + scheme[i] = dfd_srv_oob_ctx.uri[i]; + } else { + break; + } + } + + if (i == dfd_srv_oob_ctx.uri_len || dfd_srv_oob_ctx.uri[i] != ':') { + status = BT_MESH_DFD_ERR_URI_MALFORMED; + } else if (i != strlen(SUPPORTED_SCHEME) || + memcmp(scheme, SUPPORTED_SCHEME, strlen(SUPPORTED_SCHEME))) { + status = BT_MESH_DFD_ERR_URI_NOT_SUPPORTED; + } else { + status = BT_MESH_DFD_SUCCESS; + } + + err = bt_mesh_dfd_srv_oob_check_complete(&dfd_srv, dfd_srv_oob_ctx.slot, status, + dfd_srv_oob_ctx.fwid, dfd_srv_oob_ctx.fwid_len); + LOG_DBG("OOB check completed (err %d)", err); +} + +static void oob_store_handler(struct k_work *work) +{ + int err; + + err = bt_mesh_dfd_srv_oob_store_complete(&dfd_srv, dfd_srv_oob_ctx.slot, true, + 10000, "metadata", 8); + LOG_DBG("OOB store completed (err %d)", err); +} +#endif /* CONFIG_BT_MESH_DFD_SRV_OOB_UPLOAD */ #endif #if defined(CONFIG_BT_MESH_BLOB_CLI) && !defined(CONFIG_BT_MESH_DFD_SRV) From e5ab2f9978ecfdde887735f5e59d28912a5ddb4d Mon Sep 17 00:00:00 2001 From: Pavel Vasilyev Date: Tue, 10 Oct 2023 09:50:18 +0200 Subject: [PATCH 307/421] [nrf fromtree] Bluetooth: Mesh: Print URI and FWID in Upload OOB Start msg this is useful for debugging. Signed-off-by: Pavel Vasilyev (cherry picked from commit 2c9fc043d712e23754f8605b04ef8d10e9fa8be6) (cherry picked from commit 49556cc0bdf2867ea58e854d1d97b4ba7f7fc0da) --- subsys/bluetooth/mesh/dfd_srv.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/subsys/bluetooth/mesh/dfd_srv.c b/subsys/bluetooth/mesh/dfd_srv.c index cfcc82eb8d1..2547c07a5b4 100644 --- a/subsys/bluetooth/mesh/dfd_srv.c +++ b/subsys/bluetooth/mesh/dfd_srv.c @@ -572,6 +572,10 @@ static int handle_upload_start_oob(struct bt_mesh_model *mod, struct bt_mesh_msg fwid_len = buf->len; fwid = net_buf_simple_pull_mem(buf, fwid_len); + LOG_DBG("Upload OOB Start"); + LOG_HEXDUMP_DBG(uri, uri_len, "URI"); + LOG_HEXDUMP_DBG(fwid, fwid_len, "FWID"); + if (upload_is_busy(srv)) { #ifdef CONFIG_BT_MESH_DFD_SRV_OOB_UPLOAD if (srv->upload.is_oob && From 6c895c5d3ee5b98453112f1855a646624211c68c Mon Sep 17 00:00:00 2001 From: Nikodem Kastelik Date: Thu, 12 Oct 2023 09:51:12 +0200 Subject: [PATCH 308/421] [nrf fromlist] manifest: update hal_nordic rev to fix nRF91 anomaly 7 New hal_nordic revision contains updated nrfx with an improvement to nRF91 anomaly 7 workaround. Upstream PR: https://github.com/zephyrproject-rtos/zephyr/pull/63841 Signed-off-by: Nikodem Kastelik (cherry picked from commit 86c95f4906c4caf3a5ad117d13f127b1381c18e8) --- west.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/west.yml b/west.yml index bed3b47cfe5..f5366678a0e 100644 --- a/west.yml +++ b/west.yml @@ -183,7 +183,7 @@ manifest: groups: - hal - name: hal_nordic - revision: 092eb78ed1b1551d8f480019b9c05d7371784578 + revision: 568a5e90b858a2e5b640b3fe6ab9b59dd2ce9f7f path: modules/hal/nordic groups: - hal From 1fc4225e4d05cc510aef22d8b69b918f559533f4 Mon Sep 17 00:00:00 2001 From: Pavel Vasilyev Date: Thu, 12 Oct 2023 10:36:45 +0200 Subject: [PATCH 309/421] [nrf fromtree] Bluetooth: Mesh: Fix Capabilities Status message with OOB upload enabled MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The `else` case was incorrectly excluded by preprocessor. Signed-off-by: Pavel Vasilyev (cherry picked from commit 5cf6218c627d35560afaa70a2162a5952f055bdb) Signed-off-by: Alperen Şener (cherry picked from commit c60135ad3ca03db8c4ddf38d08ea542e80ba3082) --- subsys/bluetooth/mesh/dfd_srv.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/subsys/bluetooth/mesh/dfd_srv.c b/subsys/bluetooth/mesh/dfd_srv.c index 2547c07a5b4..d225f67bb77 100644 --- a/subsys/bluetooth/mesh/dfd_srv.c +++ b/subsys/bluetooth/mesh/dfd_srv.c @@ -233,11 +233,10 @@ static int handle_capabilities_get(struct bt_mesh_model *mod, struct bt_mesh_msg net_buf_simple_add_mem(&rsp, srv->oob_schemes.schemes, srv->oob_schemes.count); } else -#else +#endif { net_buf_simple_add_u8(&rsp, 0); } -#endif bt_mesh_model_send(mod, ctx, &rsp, NULL, NULL); From a17674613fd86db048183888dc1f55f1b72875f2 Mon Sep 17 00:00:00 2001 From: Pavel Vasilyev Date: Thu, 12 Oct 2023 12:29:59 +0200 Subject: [PATCH 310/421] [nrf fromtree] Bluetooth: Mesh: Fix failing DFU/SR/FD/BV-08-C test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The `upload_status_rsp_with_progress` function uses the currently set slot pointer to set firmware id field in the message. If another upload starts but the firmware is already received, the slot API won't let us to set the fwid and will return an error code. In this case, the slot pointer stays invalid as fwid wasn't set, and `upload_status_rsp_with_progress` will not add fwid as the lenght is zero. Signed-off-by: Pavel Vasilyev (cherry picked from commit 0af523eba75fc5afece9539f576cc15b8b914dfe) Signed-off-by: Alperen Şener (cherry picked from commit 0d0fabd564ad5f2b90aa6fe56e040add479ce7f6) --- subsys/bluetooth/mesh/dfd_srv.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/subsys/bluetooth/mesh/dfd_srv.c b/subsys/bluetooth/mesh/dfd_srv.c index d225f67bb77..0a9ecba6cec 100644 --- a/subsys/bluetooth/mesh/dfd_srv.c +++ b/subsys/bluetooth/mesh/dfd_srv.c @@ -412,12 +412,20 @@ static inline int set_upload_fwid(struct bt_mesh_dfd_srv *srv, struct bt_mesh_ms case -EFBIG: /* Fwid too long */ case -EALREADY: /* Other server is in progress with this fwid */ bt_mesh_dfu_slot_release(srv->upload.slot); + srv->upload.slot = NULL; upload_status_rsp(srv, ctx, BT_MESH_DFD_ERR_INTERNAL); break; case -EEXIST: /* Img with this fwid already is in list */ srv->upload.phase = BT_MESH_DFD_UPLOAD_PHASE_TRANSFER_SUCCESS; bt_mesh_dfu_slot_release(srv->upload.slot); - upload_status_rsp_with_progress(srv, ctx, BT_MESH_DFD_SUCCESS, 100); + + err = bt_mesh_dfu_slot_get(fwid, fwid_len, &srv->upload.slot); + if (!err) { + upload_status_rsp_with_progress(srv, ctx, BT_MESH_DFD_SUCCESS, 100); + } else { + srv->upload.slot = NULL; + upload_status_rsp(srv, ctx, BT_MESH_DFD_ERR_INTERNAL); + } break; case 0: srv->upload.phase = BT_MESH_DFD_UPLOAD_PHASE_TRANSFER_ACTIVE; From 5fed002128563c138ff679fdb35ac1b4f9ecb064 Mon Sep 17 00:00:00 2001 From: Aleksandr Khromykh Date: Thu, 12 Oct 2023 13:13:40 +0200 Subject: [PATCH 311/421] [nrf fromtree] Bluetooth: Mesh: fix proxy solicitation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit makes workable proxy solicitation functionality only server part without dependencies on client part. Only on demand proxy server is required. Signed-off-by: Aleksandr Khromykh (cherry picked from commit 625faa7f03e7ac4a8c9795bfc03ba278010973df) Signed-off-by: Alperen Şener (cherry picked from commit 009d335d6c660919a3bcde72fa54a2a5fb071861) --- include/zephyr/bluetooth/uuid.h | 2 +- subsys/bluetooth/mesh/crypto.c | 2 +- subsys/bluetooth/mesh/proxy_srv.c | 4 +++- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/include/zephyr/bluetooth/uuid.h b/include/zephyr/bluetooth/uuid.h index 1fa8ece6466..cab12eac74b 100644 --- a/include/zephyr/bluetooth/uuid.h +++ b/include/zephyr/bluetooth/uuid.h @@ -587,7 +587,7 @@ struct bt_uuid_128 { /** * @brief Proxy Solicitation UUID value */ -#define BT_UUID_MESH_PROXY_SOLICITATION_VAL 0x7fcb +#define BT_UUID_MESH_PROXY_SOLICITATION_VAL 0x1859 /** * @brief Reconnection Configuration Service UUID value */ diff --git a/subsys/bluetooth/mesh/crypto.c b/subsys/bluetooth/mesh/crypto.c index e42717475c0..b79458f7ea2 100644 --- a/subsys/bluetooth/mesh/crypto.c +++ b/subsys/bluetooth/mesh/crypto.c @@ -419,7 +419,7 @@ int bt_mesh_net_decrypt(const struct bt_mesh_key *key, struct net_buf_simple *bu if (IS_ENABLED(CONFIG_BT_MESH_PROXY) && type == BT_MESH_NONCE_PROXY) { create_proxy_nonce(nonce, buf->data, iv_index); - } else if (IS_ENABLED(CONFIG_BT_MESH_PROXY_SOLICITATION) && + } else if (IS_ENABLED(CONFIG_BT_MESH_SOLICITATION) && type == BT_MESH_NONCE_SOLICITATION) { create_proxy_sol_nonce(nonce, buf->data); } else { diff --git a/subsys/bluetooth/mesh/proxy_srv.c b/subsys/bluetooth/mesh/proxy_srv.c index 62c46582fa0..12775b93651 100644 --- a/subsys/bluetooth/mesh/proxy_srv.c +++ b/subsys/bluetooth/mesh/proxy_srv.c @@ -698,9 +698,11 @@ static void gatt_proxy_solicited(struct bt_mesh_subnet *sub) if (sub->priv_net_id_sent > 0) { timeout = sub->priv_net_id_sent + MSEC_PER_SEC * bt_mesh_od_priv_proxy_get(); + remaining = MIN(timeout - now, INT32_MAX); + } else { + remaining = MSEC_PER_SEC * bt_mesh_od_priv_proxy_get(); } - remaining = MIN(timeout - now, INT32_MAX); if ((timeout > 0 && now > timeout) || (remaining / MSEC_PER_SEC < 1)) { LOG_DBG("Advertising Private Network ID timed out " "after solicitation"); From 7b5fbe1bc0b575d221003234f7772696fd9978cd Mon Sep 17 00:00:00 2001 From: Aleksandr Khromykh Date: Thu, 12 Oct 2023 13:17:01 +0200 Subject: [PATCH 312/421] [nrf fromtree] tests: bluetooth: tester: enable proxy solicitation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit enables proxy solicitation functionality (server part) for mesh proxy PTS tests. Signed-off-by: Aleksandr Khromykh (cherry picked from commit 917a3e6e6418515b80459c9d3c4e5e650c81362f) Signed-off-by: Alperen Şener (cherry picked from commit ab53aaac739e1588fd2b246e10b26cca9785e91d) --- tests/bluetooth/tester/overlay-mesh-v1d1.conf | 1 + tests/bluetooth/tester/src/btp_mesh.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/bluetooth/tester/overlay-mesh-v1d1.conf b/tests/bluetooth/tester/overlay-mesh-v1d1.conf index 978d1acd3df..52045ce34df 100644 --- a/tests/bluetooth/tester/overlay-mesh-v1d1.conf +++ b/tests/bluetooth/tester/overlay-mesh-v1d1.conf @@ -23,6 +23,7 @@ CONFIG_BT_MESH_DFU_SLOT_CNT=2 CONFIG_BT_MESH_PRIV_BEACONS=y CONFIG_BT_MESH_PRIV_BEACON_SRV=y CONFIG_BT_MESH_PRIV_BEACON_CLI=y +CONFIG_BT_MESH_OD_PRIV_PROXY_SRV=y CONFIG_BT_MESH_MODEL_EXTENSIONS=y CONFIG_BT_MESH_COMP_PAGE_1=y CONFIG_BT_MESH_COMP_PAGE_2=y diff --git a/tests/bluetooth/tester/src/btp_mesh.c b/tests/bluetooth/tester/src/btp_mesh.c index 81c41dca708..1d6f696f729 100644 --- a/tests/bluetooth/tester/src/btp_mesh.c +++ b/tests/bluetooth/tester/src/btp_mesh.c @@ -5081,7 +5081,7 @@ static const struct btp_handler handlers[] = { .func = srpl_clear }, #endif -#if defined(CONFIG_BT_MESH_SOLICITATION) +#if defined(CONFIG_BT_MESH_PROXY_SOLICITATION) { .opcode = BTP_MESH_PROXY_SOLICIT, .expect_len = sizeof(struct btp_proxy_solicit_cmd), From 52be85e04f3633e508156f79c8e13e87362c5a38 Mon Sep 17 00:00:00 2001 From: Aleksandr Khromykh Date: Thu, 12 Oct 2023 14:50:01 +0200 Subject: [PATCH 313/421] [nrf fromtree] Bluetooth: Mesh: improve solicitation debug logging MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commits adds debug logging for all reasons preventing of the proxy solicitation. Signed-off-by: Aleksandr Khromykh (cherry picked from commit 00457ae6c629ef138fd7b7ce10bdd1c0b07e4286) Signed-off-by: Alperen Şener (cherry picked from commit cf03a36001d50046c097c0c1b0c16b2713d48ea1) --- subsys/bluetooth/mesh/solicitation.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/subsys/bluetooth/mesh/solicitation.c b/subsys/bluetooth/mesh/solicitation.c index f6543dcb320..e2100fa42db 100644 --- a/subsys/bluetooth/mesh/solicitation.c +++ b/subsys/bluetooth/mesh/solicitation.c @@ -190,13 +190,14 @@ void bt_mesh_sol_recv(struct net_buf_simple *buf, uint8_t uuid_list_len) if (bt_mesh_gatt_proxy_get() == BT_MESH_GATT_PROXY_ENABLED || bt_mesh_priv_gatt_proxy_get() == BT_MESH_GATT_PROXY_ENABLED || bt_mesh_od_priv_proxy_get() == 0) { + LOG_DBG("Not soliciting"); return; } /* Get rid of ad_type that was checked in bt_mesh_scan_cb */ type = net_buf_simple_pull_u8(buf); if (type != BT_DATA_UUID16_SOME && type != BT_DATA_UUID16_ALL) { - LOG_ERR("Invalid type 0x%x, expected 0x%x or 0x%x", + LOG_DBG("Invalid type 0x%x, expected 0x%x or 0x%x", type, BT_DATA_UUID16_SOME, BT_DATA_UUID16_ALL); return; } @@ -215,6 +216,7 @@ void bt_mesh_sol_recv(struct net_buf_simple *buf, uint8_t uuid_list_len) } if (!sol_uuid_found) { + LOG_DBG("No solicitation UUID found"); return; } @@ -230,6 +232,7 @@ void bt_mesh_sol_recv(struct net_buf_simple *buf, uint8_t uuid_list_len) } if (buf->len <= reported_len - 3) { + LOG_DBG("Invalid length (%u) Solicitation PDU", buf->len); return; } @@ -237,12 +240,13 @@ void bt_mesh_sol_recv(struct net_buf_simple *buf, uint8_t uuid_list_len) } if (!svc_data_found) { + LOG_DBG("No solicitation service data found"); return; } type = net_buf_simple_pull_u8(buf); if (type != 0) { - LOG_ERR("Invalid type %d, expected 0x00", type); + LOG_DBG("Invalid type %d, expected 0x00", type); return; } From ea44fcffcc107ced832752c7f8f91ffc559b8b56 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alperen=20=C5=9Eener?= Date: Thu, 12 Oct 2023 16:27:47 +0200 Subject: [PATCH 314/421] [nrf fromlist] tests: bluetooth: tester: add page number to response MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PTS requires IUT to send requests with page number with 0xFF or the highest supported page number in order to retrieve all the composition data pages from the lower tester. This commit add the page number to the response, thus the upper tester can follow the last page number and send the next page request until page 0 is requested. Upstream PR: https://github.com/zephyrproject-rtos/zephyr/pull/63872 Signed-off-by: Alperen Şener (cherry picked from commit 2410ec17fe829207e9d1a9a1d2b2bc9f3c64ab4c) --- tests/bluetooth/tester/src/btp_mesh.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/bluetooth/tester/src/btp_mesh.c b/tests/bluetooth/tester/src/btp_mesh.c index 1d6f696f729..c43f19f04ce 100644 --- a/tests/bluetooth/tester/src/btp_mesh.c +++ b/tests/bluetooth/tester/src/btp_mesh.c @@ -2033,8 +2033,9 @@ static uint8_t composition_data_get(const void *cmd, uint16_t cmd_len, return BTP_STATUS_FAILED; } - memcpy(rp->data, comp->data, comp->len); - *rsp_len = comp->len; + rp->data[0] = page; + memcpy(rp->data + 1, comp->data, comp->len); + *rsp_len = comp->len + 1; return BTP_STATUS_SUCCESS; } From a0d7c03a96a5ed77ca937491207044d0e538ac38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20G=C5=82=C4=85bek?= Date: Fri, 13 Oct 2023 17:03:01 +0200 Subject: [PATCH 315/421] [nrf fromlist] modules: hal_nordic: cmake: Fix checking if uicr DT node is accessible MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit According to cmake documentation, in the `if()` expression the string evaluates to false unless its value is one of the true constants. Thus, the commands under `if(${uicr_path})` are never executed. Use `if(DEFINED uicr_path)` instead, since `uicr_path` is returned by `dt_nodelabel()` and it will be undefined if such node does not exist. Signed-off-by: Andrzej Głąbek Upstream PR: https://github.com/zephyrproject-rtos/zephyr/pull/63929 (cherry picked from commit 41e471d2b5746e49ca1dd6c1ba91a45c1f6d269b) --- modules/hal_nordic/nrfx/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/hal_nordic/nrfx/CMakeLists.txt b/modules/hal_nordic/nrfx/CMakeLists.txt index e98db561906..ca325c31770 100644 --- a/modules/hal_nordic/nrfx/CMakeLists.txt +++ b/modules/hal_nordic/nrfx/CMakeLists.txt @@ -116,7 +116,7 @@ endif() # doing the proper configuration sequence during system init dt_nodelabel(uicr_path NODELABEL "uicr") -if(${uicr_path}) +if(DEFINED uicr_path) dt_prop(nfct_pins_as_gpios PATH ${uicr_path} PROPERTY "nfct-pins-as-gpios") if(${nfct_pins_as_gpios}) zephyr_library_compile_definitions(CONFIG_NFCT_PINS_AS_GPIOS) From fc7f82d468f64955083d0e8ed307965020c70326 Mon Sep 17 00:00:00 2001 From: Carles Cufi Date: Thu, 28 Sep 2023 15:56:08 +0200 Subject: [PATCH 316/421] [nrf fromtree] dts: arm: nordic: Add support for ieee802154 in the nRF52820 radio The nRF52820 radio peripheral supports IEEE 802.15.4, add the required property and node to reflect this. See https://infocenter.nordicsemi.com/topic/ps_nrf52820/radio.html?cp=5_3_0_5_11 Signed-off-by: Carles Cufi (cherry picked from commit f39944933d8a3aa8761711e788cabfc07117377d) (cherry picked from commit 281acd0dacaa20711d68cbdabae48ebf76264b87) --- dts/arm/nordic/nrf52820.dtsi | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/dts/arm/nordic/nrf52820.dtsi b/dts/arm/nordic/nrf52820.dtsi index 6d2f5eb02fe..c3d05fc6ec1 100644 --- a/dts/arm/nordic/nrf52820.dtsi +++ b/dts/arm/nordic/nrf52820.dtsi @@ -88,9 +88,15 @@ interrupts = <1 NRF_DEFAULT_IRQ_PRIORITY>; status = "okay"; dfe-supported; + ieee802154-supported; ble-2mbps-supported; ble-coded-phy-supported; tx-high-power-supported; + + ieee802154: ieee802154 { + compatible = "nordic,nrf-ieee802154"; + status = "disabled"; + }; }; uart0: uart@40002000 { From 93c996c9b8653daee0e15d94ff81b8369d9efdeb Mon Sep 17 00:00:00 2001 From: Nikodem Kastelik Date: Tue, 17 Oct 2023 09:35:58 +0200 Subject: [PATCH 317/421] [nrf fromlist] manifest: update hal_nordic to fix nRF52820 nrfx_gpiote New hal_nordic revision contains updated nrfx with a fix to GPIOTE driver array out-of-bounds access on nRF52820. Upstream PR: https://github.com/zephyrproject-rtos/zephyr/pull/64014 Signed-off-by: Nikodem Kastelik (cherry picked from commit ed0fc63d8fb4eeb2094ae802259bc87e8a88f5d1) --- west.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/west.yml b/west.yml index f5366678a0e..909800d0aab 100644 --- a/west.yml +++ b/west.yml @@ -183,7 +183,7 @@ manifest: groups: - hal - name: hal_nordic - revision: 568a5e90b858a2e5b640b3fe6ab9b59dd2ce9f7f + revision: 427ee1a519e8a0844d0f78f7cbc8cdfc134ef00d path: modules/hal/nordic groups: - hal From d78ae6b7ad3e60ef3a63ad7b6e1ea8a01eb3f963 Mon Sep 17 00:00:00 2001 From: Pavel Vasilyev Date: Thu, 12 Oct 2023 16:07:08 +0200 Subject: [PATCH 318/421] [nrf fromlist] tests: bluetooth: tester: Fix BLOB server model pointer PTS uses BLOB server model instantiated by DFD server for MBT tests as it is the first BLOB server model in the device composition data. DFU server, which also has BLOB server model, is instantiated after DFD server. Upstream PR: https://github.com/zephyrproject-rtos/zephyr/pull/63904 Signed-off-by: Pavel Vasilyev (cherry picked from commit 83bc1016752ca2a678683f538afba51740fe0880) --- tests/bluetooth/tester/src/btp_mesh.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/bluetooth/tester/src/btp_mesh.c b/tests/bluetooth/tester/src/btp_mesh.c index c43f19f04ce..5eff344540e 100644 --- a/tests/bluetooth/tester/src/btp_mesh.c +++ b/tests/bluetooth/tester/src/btp_mesh.c @@ -4468,10 +4468,10 @@ static uint8_t blob_srv_recv(const void *cmd, uint16_t cmd_len, struct model_data *model_bound; int err; -#if defined(CONFIG_BT_MESH_DFU_SRV) - struct bt_mesh_blob_srv *srv = &dfu_srv.blob; -#elif defined(CONFIG_BT_MESH_DFD_SRV) +#if defined(CONFIG_BT_MESH_DFD_SRV) struct bt_mesh_blob_srv *srv = &dfd_srv.upload.blob; +#elif defined(CONFIG_BT_MESH_DFU_SRV) + struct bt_mesh_blob_srv *srv = &dfu_srv.blob; #endif model_bound = lookup_model_bound(BT_MESH_MODEL_ID_BLOB_SRV); From 834948da4a87ff41241bd325d685e4e474f511f4 Mon Sep 17 00:00:00 2001 From: Pavel Vasilyev Date: Mon, 16 Oct 2023 13:19:29 +0200 Subject: [PATCH 319/421] [nrf fromlist] Bluetooth: Mesh: Keep sending Partial Block Report message MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When the BLOB server is in Pull mode and all chunks were received for the current block, and the current block is the last block, then according to section 5.2.4 of MshMBTv1.0 the server should stop sending BLOB Partial Block Report messages if it determines that the client knows that the transfer is complete: ``` While the Pull BLOB State Machine is in the All Chunks Received state, the Pull BLOB State Machine continues to send the BLOB Partial Block Report messages until one of the following happens: • The Receive BLOB Timeout timer expires. • If the current block is not the last block, then the client starts a new block, in which case a new Pull BLOB State Machine is instantiated. • If the current block is the last block, then the server determines that the client knows the transfer is complete. For example, a higher-layer model may indicate that the client considers the transfer complete. ``` We currently don't have any OOB mean (for example, API) to determine whether the client knows that the transfer is complete. We also need to keep in mind that the Partial Block Report message can get lost so one transmission may not be enough. The client could immediately send BLOB Transfer Get message to get the transfer status, but this goes against its state machine defined in section 6.2.4.2, where a Block transmission completes when a BLOB Partial Block Report message is received with an empty list of requested chunks (table 6.4, figure 6.1). Because of this, we need to keep sending Partial Block Report messages. We can keep sending them at least until Block Report timer expires. If the client sends BLOB Transfer Get message, then it finished with sending the block and we can change the phase and finish the transfer. Upstream PR: https://github.com/zephyrproject-rtos/zephyr/pull/63904 Signed-off-by: Pavel Vasilyev (cherry picked from commit 7bd44ad937d2beb38246385c96361b4979ec7f33) --- subsys/bluetooth/mesh/blob_srv.c | 70 +++++++++++++++++++++++++------- 1 file changed, 56 insertions(+), 14 deletions(-) diff --git a/subsys/bluetooth/mesh/blob_srv.c b/subsys/bluetooth/mesh/blob_srv.c index 56a89472ea6..1e6cb9bc91a 100644 --- a/subsys/bluetooth/mesh/blob_srv.c +++ b/subsys/bluetooth/mesh/blob_srv.c @@ -251,6 +251,37 @@ static void resume(struct bt_mesh_blob_srv *srv) reset_timer(srv); } +static void end(struct bt_mesh_blob_srv *srv) +{ + phase_set(srv, BT_MESH_BLOB_XFER_PHASE_COMPLETE); + k_work_cancel_delayable(&srv->rx_timeout); + k_work_cancel_delayable(&srv->pull.report); + io_close(srv); + erase_state(srv); + + if (srv->cb && srv->cb->end) { + srv->cb->end(srv, srv->state.xfer.id, true); + } +} + +static bool all_blocks_received(struct bt_mesh_blob_srv *srv) +{ + for (int i = 0; i < ARRAY_SIZE(srv->state.blocks); ++i) { + if (srv->state.blocks[i]) { + return false; + } + } + + return true; +} + +static bool pull_mode_xfer_complete(struct bt_mesh_blob_srv *srv) +{ + return srv->state.xfer.mode == BT_MESH_BLOB_XFER_MODE_PULL && + srv->phase == BT_MESH_BLOB_XFER_PHASE_WAITING_FOR_CHUNK && + all_blocks_received(srv); +} + static void timeout(struct k_work *work) { struct bt_mesh_blob_srv *srv = @@ -260,6 +291,8 @@ static void timeout(struct k_work *work) if (srv->phase == BT_MESH_BLOB_XFER_PHASE_WAITING_FOR_START) { cancel(srv); + } else if (pull_mode_xfer_complete(srv)) { + end(srv); } else { suspend(srv); } @@ -388,6 +421,15 @@ static int handle_xfer_get(struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ct struct bt_mesh_blob_srv *srv = mod->user_data; LOG_DBG(""); + + if (pull_mode_xfer_complete(srv)) { + /* The client requested transfer. If we are in Pull mode and all blocks were + * received, we should change the Transfer state here to Complete so that the client + * receives the correct state. + */ + end(srv); + } + xfer_status_rsp(srv, ctx, BT_MESH_BLOB_SUCCESS); return 0; @@ -685,7 +727,7 @@ static int handle_chunk(struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, struct bt_mesh_blob_chunk chunk; size_t expected_size = 0; uint16_t idx; - int i, err; + int err; idx = net_buf_simple_pull_le16(buf); chunk.size = buf->len; @@ -745,26 +787,26 @@ static int handle_chunk(struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, atomic_clear_bit(srv->state.blocks, srv->block.number); - for (i = 0; i < ARRAY_SIZE(srv->state.blocks); ++i) { - if (!srv->state.blocks[i]) { - continue; - } - + if (!all_blocks_received(srv)) { phase_set(srv, BT_MESH_BLOB_XFER_PHASE_WAITING_FOR_BLOCK); store_state(srv); return 0; } - phase_set(srv, BT_MESH_BLOB_XFER_PHASE_COMPLETE); - k_work_cancel_delayable(&srv->rx_timeout); - k_work_cancel_delayable(&srv->pull.report); - io_close(srv); - erase_state(srv); - - if (srv->cb && srv->cb->end) { - srv->cb->end(srv, srv->state.xfer.id, true); + if (srv->state.xfer.mode == BT_MESH_BLOB_XFER_MODE_PULL) { + /* By spec (section 5.2.4), the BLOB Server stops sending BLOB Partial Block Report + * messages "If the current block is the last block, then the server determines that + * the client knows the transfer is complete. For example, a higher-layer model may + * indicate that the client considers the transfer complete." + * + * We don't have any way for higher-layer model to indicate that the transfer is + * complete. Therefore we need to keep sending Partial Block Report messages until + * the client sends BLOB Transfer Get message or the Block Timer expires. + */ + return 0; } + end(srv); return 0; } From 66324255acd8c12723aaf62b8a61c2e1fb17c8f5 Mon Sep 17 00:00:00 2001 From: Pavel Vasilyev Date: Wed, 18 Oct 2023 12:55:20 +0200 Subject: [PATCH 320/421] [nrf fromlist] tests: bluetooth: tester: Allow to compile mesh without LPN This can be needed to qualify features without LPN support. Upstream PR: https://github.com/zephyrproject-rtos/zephyr/pull/63904 Signed-off-by: Pavel Vasilyev (cherry picked from commit 1866de22ccdd68a369470156839e3f0f18f51339) --- subsys/bluetooth/host/testing.c | 2 ++ tests/bluetooth/tester/src/btp_mesh.c | 8 ++++++++ 2 files changed, 10 insertions(+) diff --git a/subsys/bluetooth/host/testing.c b/subsys/bluetooth/host/testing.c index c3121fd230d..3c118c51e0f 100644 --- a/subsys/bluetooth/host/testing.c +++ b/subsys/bluetooth/host/testing.c @@ -102,6 +102,7 @@ void bt_test_mesh_trans_incomp_timer_exp(void) } } +#if defined(CONFIG_BT_MESH_LOW_POWER) int bt_test_mesh_lpn_group_add(uint16_t group) { bt_mesh_lpn_group_add(group); @@ -115,6 +116,7 @@ int bt_test_mesh_lpn_group_remove(uint16_t *groups, size_t groups_count) return 0; } +#endif /* CONFIG_BT_MESH_LOW_POWER */ int bt_test_mesh_rpl_clear(void) { diff --git a/tests/bluetooth/tester/src/btp_mesh.c b/tests/bluetooth/tester/src/btp_mesh.c index 5eff344540e..bdc37c2f2e5 100644 --- a/tests/bluetooth/tester/src/btp_mesh.c +++ b/tests/bluetooth/tester/src/btp_mesh.c @@ -1553,6 +1553,7 @@ static uint8_t ivu_toggle_state(const void *cmd, uint16_t cmd_len, return BTP_STATUS_SUCCESS; } +#if defined(CONFIG_BT_MESH_LOW_POWER) static uint8_t lpn(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len) { @@ -1584,6 +1585,7 @@ static uint8_t lpn_poll(const void *cmd, uint16_t cmd_len, return BTP_STATUS_SUCCESS; } +#endif /* CONFIG_BT_MESH_LOW_POWER */ static uint8_t net_send(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len) @@ -1765,6 +1767,7 @@ static uint8_t model_send(const void *cmd, uint16_t cmd_len, } #if defined(CONFIG_BT_TESTING) +#if defined(CONFIG_BT_MESH_LOW_POWER) static uint8_t lpn_subscribe(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len) { @@ -1800,6 +1803,7 @@ static uint8_t lpn_unsubscribe(const void *cmd, uint16_t cmd_len, return BTP_STATUS_SUCCESS; } +#endif /* CONFIG_BT_MESH_LOW_POWER */ static uint8_t rpl_clear(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len) @@ -4579,6 +4583,7 @@ static const struct btp_handler handlers[] = { .expect_len = 0, .func = ivu_toggle_state, }, +#if defined(CONFIG_BT_MESH_LOW_POWER) { .opcode = BTP_MESH_LPN, .expect_len = sizeof(struct btp_mesh_lpn_set_cmd), @@ -4589,6 +4594,7 @@ static const struct btp_handler handlers[] = { .expect_len = 0, .func = lpn_poll, }, +#endif /* CONFIG_BT_MESH_LOW_POWER */ { .opcode = BTP_MESH_NET_SEND, .expect_len = BTP_HANDLER_LENGTH_VARIABLE, @@ -4900,6 +4906,7 @@ static const struct btp_handler handlers[] = { .func = va_del, }, #if defined(CONFIG_BT_TESTING) +#if defined(CONFIG_BT_MESH_LOW_POWER) { .opcode = BTP_MESH_LPN_SUBSCRIBE, .expect_len = sizeof(struct btp_mesh_lpn_subscribe_cmd), @@ -4910,6 +4917,7 @@ static const struct btp_handler handlers[] = { .expect_len = sizeof(struct btp_mesh_lpn_unsubscribe_cmd), .func = lpn_unsubscribe, }, +#endif /* CONFIG_BT_MESH_LOW_POWER */ { .opcode = BTP_MESH_RPL_CLEAR, .expect_len = 0, From 979569b82b96246889e67a17a4a7987710c4802e Mon Sep 17 00:00:00 2001 From: Ludvig Jordet Date: Tue, 17 Oct 2023 15:37:44 +0200 Subject: [PATCH 321/421] [nrf fromlist] Bluetooth: Mesh: Fix issue where dfu_cli could get stuck This fixes an issue where the DFU client could get stuck trying to transmit a message to servers if the DFU client was misconfigured, for instance missing application key or network key. Upstream PR: https://github.com/zephyrproject-rtos/zephyr/pull/64034 Signed-off-by: Ludvig Jordet (cherry picked from commit 0e9155dc6d3358376d8b3bb7c00b4a408d9206f1) --- subsys/bluetooth/mesh/dfu_cli.c | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/subsys/bluetooth/mesh/dfu_cli.c b/subsys/bluetooth/mesh/dfu_cli.c index 3805a04e450..4db7779116b 100644 --- a/subsys/bluetooth/mesh/dfu_cli.c +++ b/subsys/bluetooth/mesh/dfu_cli.c @@ -305,6 +305,23 @@ static void tx_end(int err, void *cb_data) blob_cli_broadcast_tx_complete(&cli->blob); } +static int tx(struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf, + const struct bt_mesh_send_cb *cb, struct bt_mesh_dfu_cli *cli) +{ + int err; + + err = bt_mesh_model_send(mod, ctx, buf, cb, cli); + if (err) { + LOG_ERR("Send err: %d", err); + if (cb) { + cb->end(err, cli); + } + return err; + } + + return 0; +} + static int info_get(struct bt_mesh_dfu_cli *cli, struct bt_mesh_msg_ctx *ctx, uint8_t idx, uint8_t max_count, const struct bt_mesh_send_cb *cb) @@ -314,7 +331,7 @@ static int info_get(struct bt_mesh_dfu_cli *cli, struct bt_mesh_msg_ctx *ctx, net_buf_simple_add_u8(&buf, idx); net_buf_simple_add_u8(&buf, max_count); - return bt_mesh_model_send(cli->mod, ctx, &buf, cb, cli); + return tx(cli->mod, ctx, &buf, cb, cli); } static void send_info_get(struct bt_mesh_blob_cli *b, uint16_t dst) @@ -352,7 +369,7 @@ static void send_update_start(struct bt_mesh_blob_cli *b, uint16_t dst) net_buf_simple_add_mem(&buf, cli->xfer.slot->metadata, cli->xfer.slot->metadata_len); - bt_mesh_model_send(cli->mod, &ctx, &buf, &send_cb, cli); + (void)tx(cli->mod, &ctx, &buf, &send_cb, cli); } static void send_update_get(struct bt_mesh_blob_cli *b, uint16_t dst) @@ -363,7 +380,7 @@ static void send_update_get(struct bt_mesh_blob_cli *b, uint16_t dst) BT_MESH_MODEL_BUF_DEFINE(buf, BT_MESH_DFU_OP_UPDATE_GET, 0); bt_mesh_model_msg_init(&buf, BT_MESH_DFU_OP_UPDATE_GET); - bt_mesh_model_send(cli->mod, &ctx, &buf, &send_cb, cli); + (void)tx(cli->mod, &ctx, &buf, &send_cb, cli); } static void send_update_cancel(struct bt_mesh_blob_cli *b, uint16_t dst) @@ -374,7 +391,7 @@ static void send_update_cancel(struct bt_mesh_blob_cli *b, uint16_t dst) BT_MESH_MODEL_BUF_DEFINE(buf, BT_MESH_DFU_OP_UPDATE_CANCEL, 0); bt_mesh_model_msg_init(&buf, BT_MESH_DFU_OP_UPDATE_CANCEL); - bt_mesh_model_send(cli->mod, &ctx, &buf, &send_cb, cli); + (void)tx(cli->mod, &ctx, &buf, &send_cb, cli); } static void send_update_apply(struct bt_mesh_blob_cli *b, uint16_t dst) @@ -385,7 +402,7 @@ static void send_update_apply(struct bt_mesh_blob_cli *b, uint16_t dst) BT_MESH_MODEL_BUF_DEFINE(buf, BT_MESH_DFU_OP_UPDATE_APPLY, 0); bt_mesh_model_msg_init(&buf, BT_MESH_DFU_OP_UPDATE_APPLY); - bt_mesh_model_send(cli->mod, &ctx, &buf, &send_cb, cli); + (void)tx(cli->mod, &ctx, &buf, &send_cb, cli); } /******************************************************************************* From 32a51d982e0b7eba7e458678a8246440b25c3916 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A5vard=20Reierstad?= Date: Wed, 18 Oct 2023 09:11:23 +0200 Subject: [PATCH 322/421] [nrf fromlist] Bluetooth: mesh: update model extension MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds a goto statement to ensure that model extensions are registered in Composition Data Page 1 if it is enabled. Upstream PR: https://github.com/zephyrproject-rtos/zephyr/pull/64065 Signed-off-by: Håvard Reierstad (cherry picked from commit 24edc9d74bad637452bceb9322b3b6f1611db4cb) --- subsys/bluetooth/mesh/access.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/subsys/bluetooth/mesh/access.c b/subsys/bluetooth/mesh/access.c index 63c4f76c392..6ca7dbe580b 100644 --- a/subsys/bluetooth/mesh/access.c +++ b/subsys/bluetooth/mesh/access.c @@ -1678,7 +1678,7 @@ int bt_mesh_model_extend(struct bt_mesh_model *extending_mod, struct bt_mesh_mod /* Check if a's list contains b */ for (it = a; (it != NULL) && (it->next != a); it = it->next) { if (it == b) { - return 0; + goto register_extension; } } @@ -1695,7 +1695,7 @@ int bt_mesh_model_extend(struct bt_mesh_model *extending_mod, struct bt_mesh_mod a->next = b; } - +register_extension: if (IS_ENABLED(CONFIG_BT_MESH_COMP_PAGE_1)) { return mod_rel_register(base_mod, extending_mod, RELATION_TYPE_EXT); } From 7ac418187369487f6fa633dab6d6c0a99913f479 Mon Sep 17 00:00:00 2001 From: Omkar Kulkarni Date: Mon, 23 Oct 2023 14:07:48 +0200 Subject: [PATCH 323/421] [nrf fromlist] Bluetooth: Mesh: FU Server should not update internal state on error According to conditions in the DFU spec section 6.1.3.7 (Sending a Firmware Update Status message) and in 'Idempotency' part of section 6.1.3.4 (Receiving a Firmware Update Start message), the FU Server should not update internal state when 'Wrong Phase' error condition is triggered. Upstream PR: https://github.com/zephyrproject-rtos/zephyr/pull/64258 Signed-off-by: Omkar Kulkarni (cherry picked from commit b4eef4da68a5c1f4b02c4d10ee0340375f775a14) --- subsys/bluetooth/mesh/dfu_srv.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/subsys/bluetooth/mesh/dfu_srv.c b/subsys/bluetooth/mesh/dfu_srv.c index 282a40074c9..462a777b46c 100644 --- a/subsys/bluetooth/mesh/dfu_srv.c +++ b/subsys/bluetooth/mesh/dfu_srv.c @@ -302,10 +302,10 @@ static int handle_start(struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, status = BT_MESH_DFU_ERR_WRONG_PHASE; } else { status = BT_MESH_DFU_SUCCESS; + srv->update.ttl = ttl; + srv->blob.state.xfer.id = blob_id; } - srv->update.ttl = ttl; - srv->blob.state.xfer.id = blob_id; LOG_WRN("Busy. Phase: %u", srv->update.phase); goto rsp; } From 2e2523efe52a7ac89f0567b8798fd857b1e71ae3 Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Mon, 9 Oct 2023 23:01:41 +0200 Subject: [PATCH 324/421] [nrf fromtree] tests: bluetooth: tester: Fix GATT read multiple Pass only speficied number of handler to read_params for GATT read multiple. This is to avoid sending invalid (zeros) handles in ATT_READ_MULTIPLE_REQ. This was affecting GATT/CL/GAR/BI-18-C and GATT/CL/GAR/BI-19-C qualification test cases. Signed-off-by: Szymon Janc (cherry picked from commit 4f57614cbddc66dbe264691352fe07223e3974e0) --- tests/bluetooth/tester/src/btp_gatt.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/bluetooth/tester/src/btp_gatt.c b/tests/bluetooth/tester/src/btp_gatt.c index 4d046cc3aad..6509ca7fe4b 100644 --- a/tests/bluetooth/tester/src/btp_gatt.c +++ b/tests/bluetooth/tester/src/btp_gatt.c @@ -1651,11 +1651,11 @@ static uint8_t read_multiple(const void *cmd, uint16_t cmd_len, return BTP_STATUS_FAILED; } - if (cp->handles_count > ARRAY_SIZE(handles)) { + if (cp->handles_count == 0 || cp->handles_count > ARRAY_SIZE(handles)) { return BTP_STATUS_FAILED; } - for (i = 0; i < ARRAY_SIZE(handles); i++) { + for (i = 0; i < cp->handles_count; i++) { handles[i] = sys_le16_to_cpu(cp->handles[i]); } @@ -1670,7 +1670,7 @@ static uint8_t read_multiple(const void *cmd, uint16_t cmd_len, } read_params.func = read_cb; - read_params.handle_count = i; + read_params.handle_count = cp->handles_count; read_params.multiple.handles = handles; /* not used in read func */ read_params.multiple.variable = false; read_params.chan_opt = BT_ATT_CHAN_OPT_NONE; From e806eda100b0d197eeb28be7716a0a4ed974cebf Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Mon, 16 Oct 2023 08:40:38 +0100 Subject: [PATCH 325/421] [nrf noup] samples: bluetooth: hci_pow_ctrl: Migrate child image config Migrates child image configuration for this sample over to sysbuild Signed-off-by: Jamie McCrae --- samples/bluetooth/hci_pwr_ctrl/sysbuild/hci_rpmsg.conf | 1 + 1 file changed, 1 insertion(+) create mode 100644 samples/bluetooth/hci_pwr_ctrl/sysbuild/hci_rpmsg.conf diff --git a/samples/bluetooth/hci_pwr_ctrl/sysbuild/hci_rpmsg.conf b/samples/bluetooth/hci_pwr_ctrl/sysbuild/hci_rpmsg.conf new file mode 100644 index 00000000000..e6749ae6399 --- /dev/null +++ b/samples/bluetooth/hci_pwr_ctrl/sysbuild/hci_rpmsg.conf @@ -0,0 +1 @@ +CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL=y From cb74dbeb3cb753bade9864233eb27bf229298e77 Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Mon, 16 Oct 2023 08:41:27 +0100 Subject: [PATCH 326/421] [nrf noup] samples: mgmt: mcumgr smp_svr: Migrate child image config Migrates child image configuration for this sample over to sysbuild Signed-off-by: Jamie McCrae --- .../subsys/mgmt/mcumgr/smp_svr/sysbuild/hci_rpmsg.conf | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 samples/subsys/mgmt/mcumgr/smp_svr/sysbuild/hci_rpmsg.conf diff --git a/samples/subsys/mgmt/mcumgr/smp_svr/sysbuild/hci_rpmsg.conf b/samples/subsys/mgmt/mcumgr/smp_svr/sysbuild/hci_rpmsg.conf new file mode 100644 index 00000000000..98260877332 --- /dev/null +++ b/samples/subsys/mgmt/mcumgr/smp_svr/sysbuild/hci_rpmsg.conf @@ -0,0 +1,10 @@ +# +# Copyright (c) 2022 Nordic Semiconductor +# +# SPDX-License-Identifier: Apache-2.0 +# + +CONFIG_BT_MAX_CONN=2 +CONFIG_BT_BUF_ACL_RX_SIZE=502 +CONFIG_BT_BUF_ACL_TX_SIZE=502 +CONFIG_BT_CTLR_DATA_LENGTH_MAX=251 From 9058a859d67b19c9d307943d8f206d917a37752a Mon Sep 17 00:00:00 2001 From: Krishna T Date: Tue, 21 Mar 2023 21:25:45 +0530 Subject: [PATCH 327/421] [nrf fromtree] scripts: ci: Fix for compliance with multi-user machine If in a server multiple users are running compliance then it throws errors as the filename "Kconfig.modules" and "Kconfig.dts" is owned by someone else. Fix this by creating a randomized Kconfig file and delete after use. Signed-off-by: Krishna T (cherry picked from commit 85e3a4ca6ae1993be975317515ee431dca02aae1) --- scripts/ci/check_compliance.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/scripts/ci/check_compliance.py b/scripts/ci/check_compliance.py index 74ddf19b2fb..1499d92eaf9 100755 --- a/scripts/ci/check_compliance.py +++ b/scripts/ci/check_compliance.py @@ -16,6 +16,7 @@ import tempfile import traceback import shlex +import shutil from yamllint import config, linter @@ -369,6 +370,8 @@ def parse_kconfig(self): if not os.path.exists(kconfig_path): self.error(kconfig_path + " not found") + kconfiglib_dir = tempfile.mkdtemp(prefix="kconfiglib_") + sys.path.insert(0, kconfig_path) # Import globally so that e.g. kconfiglib.Symbol can be referenced in # tests @@ -383,7 +386,7 @@ def parse_kconfig(self): os.environ["ARCH_DIR"] = "arch/" os.environ["BOARD_DIR"] = "boards/*/*" os.environ["ARCH"] = "*" - os.environ["KCONFIG_BINARY_DIR"] = tempfile.gettempdir() + os.environ["KCONFIG_BINARY_DIR"] = kconfiglib_dir os.environ['DEVICETREE_CONF'] = "dummy" os.environ['TOOLCHAIN_HAS_NEWLIB'] = "y" @@ -392,10 +395,9 @@ def parse_kconfig(self): os.environ["GENERATED_DTS_BOARD_CONF"] = "dummy" # For multi repo support - self.get_modules(os.path.join(tempfile.gettempdir(), "Kconfig.modules")) - + self.get_modules(os.path.join(kconfiglib_dir, "Kconfig.modules")) # For Kconfig.dts support - self.get_kconfig_dts(os.path.join(tempfile.gettempdir(), "Kconfig.dts")) + self.get_kconfig_dts(os.path.join(kconfiglib_dir, "Kconfig.dts")) # Tells Kconfiglib to generate warnings for all references to undefined # symbols within Kconfig files @@ -410,6 +412,9 @@ def parse_kconfig(self): except kconfiglib.KconfigError as e: self.failure(str(e)) raise EndTest + finally: + # Clean up the temporary directory + shutil.rmtree(kconfiglib_dir) def get_defined_syms(self, kconf): # Returns a set() with the names of all defined Kconfig symbols (with no From 4936f55987b49cedd92288f686410f374ed345d2 Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Mon, 17 Jul 2023 14:46:45 +0100 Subject: [PATCH 328/421] [nrf fromtree] sysbuild: Add support for MCUboot/app encryption keys Adds support for controlling the MCUboot (and application) signing key, and allows for generating encrypted updates. Signed-off-by: Jamie McCrae (cherry picked from commit 62f07c67d5689155c5bf649ac8653309e7f8bbad) --- .../MAIN_image_default.cmake | 3 +++ .../sysbuild/images/bootloader/CMakeLists.txt | 4 ++++ share/sysbuild/images/bootloader/Kconfig | 20 +++++++++++++++++-- 3 files changed, 25 insertions(+), 2 deletions(-) diff --git a/share/sysbuild/image_configurations/MAIN_image_default.cmake b/share/sysbuild/image_configurations/MAIN_image_default.cmake index a6bd72d7d1a..a2ae840ef97 100644 --- a/share/sysbuild/image_configurations/MAIN_image_default.cmake +++ b/share/sysbuild/image_configurations/MAIN_image_default.cmake @@ -9,6 +9,9 @@ set_config_bool(${ZCMAKE_APPLICATION} CONFIG_BOOTLOADER_MCUBOOT "${SB_CONFIG_BOO set_config_string(${ZCMAKE_APPLICATION} CONFIG_MCUBOOT_SIGNATURE_KEY_FILE "${SB_CONFIG_BOOT_SIGNATURE_KEY_FILE}" ) +set_config_string(${ZCMAKE_APPLICATION} CONFIG_MCUBOOT_ENCRYPTION_KEY_FILE + "${SB_CONFIG_BOOT_ENCRYPTION_KEY_FILE}" +) if(SB_CONFIG_BOOTLOADER_MCUBOOT) if("${SB_CONFIG_SIGNATURE_TYPE}" STREQUAL "NONE") diff --git a/share/sysbuild/images/bootloader/CMakeLists.txt b/share/sysbuild/images/bootloader/CMakeLists.txt index c00a8e97783..2a0f12f958d 100644 --- a/share/sysbuild/images/bootloader/CMakeLists.txt +++ b/share/sysbuild/images/bootloader/CMakeLists.txt @@ -15,4 +15,8 @@ if(SB_CONFIG_BOOTLOADER_MCUBOOT) sysbuild_add_dependencies(FLASH ${DEFAULT_IMAGE} ${image}) set_config_string(${image} CONFIG_BOOT_SIGNATURE_KEY_FILE "${SB_CONFIG_BOOT_SIGNATURE_KEY_FILE}") + set_config_bool(${image} CONFIG_BOOT_ENCRYPT_IMAGE "${SB_CONFIG_BOOT_ENCRYPTION}") + if(SB_CONFIG_BOOT_ENCRYPTION) + set_config_string(${image} CONFIG_BOOT_ENCRYPTION_KEY_FILE "${SB_CONFIG_BOOT_ENCRYPTION_KEY_FILE}") + endif() endif() diff --git a/share/sysbuild/images/bootloader/Kconfig b/share/sysbuild/images/bootloader/Kconfig index 19924a6ca18..e8c788f72c5 100644 --- a/share/sysbuild/images/bootloader/Kconfig +++ b/share/sysbuild/images/bootloader/Kconfig @@ -56,12 +56,28 @@ config BOOT_SIGNATURE_TYPE_ED25519 endchoice config BOOT_SIGNATURE_KEY_FILE - string "PEM key file" + string "Signing PEM key file" default "$(ZEPHYR_MCUBOOT_MODULE_DIR)/root-ec-p256.pem" if BOOT_SIGNATURE_TYPE_ECDSA_P256 default "$(ZEPHYR_MCUBOOT_MODULE_DIR)/root-ed25519.pem" if BOOT_SIGNATURE_TYPE_ED25519 default "$(ZEPHYR_MCUBOOT_MODULE_DIR)/root-rsa-2048.pem" if BOOT_SIGNATURE_TYPE_RSA default "" help - Absolute path to key file to use with MCUBoot. + Absolute path to signing key file to use with MCUBoot. + +config BOOT_ENCRYPTION + bool "Encrypted image support" + depends on !BOOT_SIGNATURE_TYPE_NONE + help + Support encrypted images. + +config BOOT_ENCRYPTION_KEY_FILE + string "Encryption PEM key file" + depends on BOOT_ENCRYPTION + default "$(ZEPHYR_MCUBOOT_MODULE_DIR)/enc-ec256-priv.pem" if BOOT_SIGNATURE_TYPE_ECDSA_P256 + default "$(ZEPHYR_MCUBOOT_MODULE_DIR)/enc-x25519-priv.pem" if BOOT_SIGNATURE_TYPE_ED25519 + default "$(ZEPHYR_MCUBOOT_MODULE_DIR)/enc-rsa2048-priv.pem" if BOOT_SIGNATURE_TYPE_RSA + default "" + help + Absolute path to encryption key file to use with MCUBoot. endif From 335beb0032206badd6cef214bbd82cdc0c51d49f Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Mon, 17 Jul 2023 14:54:22 +0100 Subject: [PATCH 329/421] [nrf fromtree] scripts: ci: check_compliance: Add sysbuild Kconfig exceptions Adds exceptions for Kconfigs which sysbuild uses when configuring MCUboot. Signed-off-by: Jamie McCrae (cherry picked from commit 97123c4f4a558967b067a2da50bc72c5f2fdb48a) --- scripts/ci/check_compliance.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/ci/check_compliance.py b/scripts/ci/check_compliance.py index 1499d92eaf9..07d7431dd65 100755 --- a/scripts/ci/check_compliance.py +++ b/scripts/ci/check_compliance.py @@ -633,6 +633,8 @@ def check_no_undef_outside_kconfig(self, kconf): # toolchain Kconfig which is sourced based on # Zephyr toolchain variant and therefore not # visible to compliance. + "BOOT_ENCRYPTION_KEY_FILE", # Used in sysbuild + "BOOT_ENCRYPT_IMAGE", # Used in sysbuild "BOOT_UPGRADE_ONLY", # Used in example adjusting MCUboot config, but # symbol is defined in MCUboot itself. "BOOT_SERIAL_BOOT_MODE", # Used in (sysbuild-based) test/ From 2a12aea553568d2b1683c2b329f0ac648661110a Mon Sep 17 00:00:00 2001 From: Nikodem Kastelik Date: Tue, 3 Oct 2023 16:04:43 +0200 Subject: [PATCH 330/421] [nrf fromtree] manifest: hal_nordic: Update hal_nordic revision Pull in nrfx 3.2.0 release Signed-off-by: Nikodem Kastelik (cherry picked from commit ec978348c5ea8e5a2a0f071cc6e6ca8e12fa8889) --- west.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/west.yml b/west.yml index 909800d0aab..44098dac030 100644 --- a/west.yml +++ b/west.yml @@ -183,7 +183,7 @@ manifest: groups: - hal - name: hal_nordic - revision: 427ee1a519e8a0844d0f78f7cbc8cdfc134ef00d + revision: 2ff8ce6e6ca131d87699dba260f3c0cc4a6cc365 path: modules/hal/nordic groups: - hal From 7931877e976a0a2a47a99a7701e7e1930b2bde0d Mon Sep 17 00:00:00 2001 From: Nikodem Kastelik Date: Tue, 3 Oct 2023 17:17:22 +0200 Subject: [PATCH 331/421] [nrf fromtree] manifest: tf-m: update to have atomics for nrfx port Refactored nrfx_uarte driver uses atomic types internally, so glue layer in TF-M needs to include them. Signed-off-by: Nikodem Kastelik (cherry picked from commit f4fcc1dc4c6303b21b7fb8c3f2a346aeef8ebcaf) --- west.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/west.yml b/west.yml index 44098dac030..1847e94b37c 100644 --- a/west.yml +++ b/west.yml @@ -331,7 +331,7 @@ manifest: groups: - debug - name: trusted-firmware-m - revision: 8b6146261fe2c0ad61154e20c7e338601eae2208 + revision: 33c0f47bcb19721a5c33e6fe1eee9225d00bb5bc path: modules/tee/tf-m/trusted-firmware-m groups: - tee From 82e15a98880869aa4a80c2104988480330d8d326 Mon Sep 17 00:00:00 2001 From: Nikodem Kastelik Date: Tue, 3 Oct 2023 16:52:55 +0200 Subject: [PATCH 332/421] [nrf fromtree] drivers: sensor: qdec_nrfx: Revert samplerdy workaround Underlying nrfx driver was modified so now it forwards the event to the user callback only if it was enabled. Signed-off-by: Nikodem Kastelik (cherry picked from commit 6a315a4b17c523f101a01fccde50967c02294650) --- drivers/sensor/qdec_nrfx/qdec_nrfx.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/drivers/sensor/qdec_nrfx/qdec_nrfx.c b/drivers/sensor/qdec_nrfx/qdec_nrfx.c index 81c3614fc05..b11ce70fb9c 100644 --- a/drivers/sensor/qdec_nrfx/qdec_nrfx.c +++ b/drivers/sensor/qdec_nrfx/qdec_nrfx.c @@ -135,13 +135,6 @@ static void qdec_nrfx_event_handler(nrfx_qdec_event_t event, void *p_context) unsigned int key; switch (event.type) { - case NRF_QDEC_EVENT_SAMPLERDY: - /* The underlying HAL driver may improperly forward an samplerdy event even if it's - * disabled in the configuration. Ignore the event to prevent error logs until the - * issue is fixed in HAL. - */ - break; - case NRF_QDEC_EVENT_REPORTRDY: accumulate(dev_data, event.data.report.acc); From 2831d726ec09ce354fca9ff83382f8bf94bfefb5 Mon Sep 17 00:00:00 2001 From: Nikodem Kastelik Date: Tue, 3 Oct 2023 16:59:20 +0200 Subject: [PATCH 333/421] [nrf fromtree] soc: arm: nordic_nrf: nrf53: align nrf_regulators Now more generic regulators API is available. Signed-off-by: Nikodem Kastelik (cherry picked from commit f3f2c113d1323fa0a82d30a9f1cb957b87fd185a) --- soc/arm/nordic_nrf/nrf53/soc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/soc/arm/nordic_nrf/nrf53/soc.c b/soc/arm/nordic_nrf/nrf53/soc.c index 39d64d72cc2..3542ef3e914 100644 --- a/soc/arm/nordic_nrf/nrf53/soc.c +++ b/soc/arm/nordic_nrf/nrf53/soc.c @@ -554,13 +554,13 @@ static int nordicsemi_nrf53_init(void) #endif #if defined(CONFIG_SOC_DCDC_NRF53X_APP) - nrf_regulators_dcdcen_set(NRF_REGULATORS, true); + nrf_regulators_vreg_enable_set(NRF_REGULATORS, NRF_REGULATORS_VREG_MAIN, true); #endif #if defined(CONFIG_SOC_DCDC_NRF53X_NET) - nrf_regulators_dcdcen_radio_set(NRF_REGULATORS, true); + nrf_regulators_vreg_enable_set(NRF_REGULATORS, NRF_REGULATORS_VREG_RADIO, true); #endif #if defined(CONFIG_SOC_DCDC_NRF53X_HV) - nrf_regulators_dcdcen_vddh_set(NRF_REGULATORS, true); + nrf_regulators_vreg_enable_set(NRF_REGULATORS, NRF_REGULATORS_VREG_HIGH, true); #endif #if defined(CONFIG_SOC_NRF_GPIO_FORWARDER_FOR_NRF5340) From 7b453aac8b078f938eefff92e5d0b4d9f481adfb Mon Sep 17 00:00:00 2001 From: Nikodem Kastelik Date: Tue, 3 Oct 2023 17:00:20 +0200 Subject: [PATCH 334/421] [nrf fromtree] samples: boards: nrf: nrfx_prs: align to new nrfx_uarte One of the nrfx_uarte event structure members was renamed, so the sample code has to be aligned. Signed-off-by: Nikodem Kastelik (cherry picked from commit c0ff691a3ca66a6eae56e7d03c2382f27e4b0281) --- samples/boards/nrf/nrfx_prs/src/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/boards/nrf/nrfx_prs/src/main.c b/samples/boards/nrf/nrfx_prs/src/main.c index 618c0718143..934bbbe834d 100644 --- a/samples/boards/nrf/nrfx_prs/src/main.c +++ b/samples/boards/nrf/nrfx_prs/src/main.c @@ -191,7 +191,7 @@ static bool spim_transfer(const uint8_t *tx_data, size_t tx_data_len, static void uarte_handler(const nrfx_uarte_event_t *p_event, void *p_context) { if (p_event->type == NRFX_UARTE_EVT_RX_DONE) { - received = p_event->data.rx.bytes; + received = p_event->data.rx.length; k_sem_give(&transfer_finished); } else if (p_event->type == NRFX_UARTE_EVT_ERROR) { received = 0; From bc160058effb4a887acbad987ff44cf6b7db3494 Mon Sep 17 00:00:00 2001 From: Nikodem Kastelik Date: Fri, 6 Oct 2023 09:55:58 +0200 Subject: [PATCH 335/421] [nrf fromtree] modules: hal_nordic: nrfx: enable GPIOTE1 for NS builds Now it is needed to explicitly use NRF_GPIOTE1 instance in nrfx_gpiote driver for non-secure builds. Signed-off-by: Nikodem Kastelik (cherry picked from commit 70db8cd12a794fa6f966c1e08a622ad5590a6880) --- modules/hal_nordic/nrfx/nrfx_config.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/modules/hal_nordic/nrfx/nrfx_config.h b/modules/hal_nordic/nrfx/nrfx_config.h index 4b7cabd7a98..29051ccf754 100644 --- a/modules/hal_nordic/nrfx/nrfx_config.h +++ b/modules/hal_nordic/nrfx/nrfx_config.h @@ -117,6 +117,12 @@ #ifdef CONFIG_NRFX_GPIOTE #define NRFX_GPIOTE_ENABLED 1 +#if (defined(CONFIG_SOC_SERIES_NRF91X) || defined(CONFIG_SOC_SERIES_NRF53X)) \ + && defined(NRF_TRUSTZONE_NONSECURE) +#define NRFX_GPIOTE1_ENABLED 1 +#else +#define NRFX_GPIOTE0_ENABLED 1 +#endif #endif #ifdef CONFIG_NRFX_GPIOTE_LOG #define NRFX_GPIOTE_CONFIG_LOG_ENABLED 1 From 729573484b5c74e6f4f83ccba5c63f80f96abad0 Mon Sep 17 00:00:00 2001 From: Nikodem Kastelik Date: Mon, 9 Oct 2023 11:18:17 +0200 Subject: [PATCH 336/421] [nrf fromtree] soc: arm: nordic_nrf: align nrf_power calls to new scheme Now the API to manage GPREGRET register is unified for all devices having one or more GPREGRET entries. Signed-off-by: Nikodem Kastelik (cherry picked from commit a4cbe9e9c6f9efe37dcca13083b040172205a716) --- soc/arm/nordic_nrf/nrf51/soc.c | 2 +- soc/arm/nordic_nrf/nrf52/soc.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/soc/arm/nordic_nrf/nrf51/soc.c b/soc/arm/nordic_nrf/nrf51/soc.c index 078a422c06b..2b22c95679f 100644 --- a/soc/arm/nordic_nrf/nrf51/soc.c +++ b/soc/arm/nordic_nrf/nrf51/soc.c @@ -29,7 +29,7 @@ LOG_MODULE_REGISTER(soc); */ void sys_arch_reboot(int type) { - nrf_power_gpregret_set(NRF_POWER, (uint8_t)type); + nrf_power_gpregret_set(NRF_POWER, 0, (uint8_t)type); NVIC_SystemReset(); } #endif diff --git a/soc/arm/nordic_nrf/nrf52/soc.c b/soc/arm/nordic_nrf/nrf52/soc.c index 52b97164e72..5f310e5f945 100644 --- a/soc/arm/nordic_nrf/nrf52/soc.c +++ b/soc/arm/nordic_nrf/nrf52/soc.c @@ -31,7 +31,7 @@ LOG_MODULE_REGISTER(soc); */ void sys_arch_reboot(int type) { - nrf_power_gpregret_set(NRF_POWER, (uint8_t)type); + nrf_power_gpregret_set(NRF_POWER, 0, (uint8_t)type); NVIC_SystemReset(); } #endif From e73ebd314f6f8a8df179f11fd5f500522acc94e4 Mon Sep 17 00:00:00 2001 From: Robert Lubos Date: Thu, 19 Oct 2023 10:59:03 +0200 Subject: [PATCH 337/421] [nrf fromtree] net: core: Set LL address on loopback packet In case packet is looped back to the stack, set LL address information on the packet, using the LL address set on the corresponding network interface, so that the information can be interpreted by the SOCK_DGRAM packet socket. Signed-off-by: Robert Lubos (cherry picked from commit dcf7b1905b9e2e3c4b277f6984d3fc166436d233) --- subsys/net/ip/net_core.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/subsys/net/ip/net_core.c b/subsys/net/ip/net_core.c index c94607b4485..1f6dac720af 100644 --- a/subsys/net/ip/net_core.c +++ b/subsys/net/ip/net_core.c @@ -211,6 +211,15 @@ static void init_rx_queues(void) /* Check if the IPv{4|6} addresses are proper. As this can be expensive, * make this optional. */ + +static inline void copy_ll_addr(struct net_pkt *pkt) +{ + memcpy(net_pkt_lladdr_src(pkt), net_pkt_lladdr_if(pkt), + sizeof(struct net_linkaddr)); + memcpy(net_pkt_lladdr_dst(pkt), net_pkt_lladdr_if(pkt), + sizeof(struct net_linkaddr)); +} + static inline int check_ip_addr(struct net_pkt *pkt) { uint8_t family = net_pkt_family(pkt); @@ -239,6 +248,9 @@ static inline int check_ip_addr(struct net_pkt *pkt) NET_IPV6_HDR(pkt)->dst); net_ipv6_addr_copy_raw(NET_IPV6_HDR(pkt)->dst, (uint8_t *)&addr); + net_pkt_set_ll_proto_type(pkt, ETH_P_IPV6); + copy_ll_addr(pkt); + return 1; } @@ -286,6 +298,9 @@ static inline int check_ip_addr(struct net_pkt *pkt) NET_IPV4_HDR(pkt)->dst); net_ipv4_addr_copy_raw(NET_IPV4_HDR(pkt)->dst, (uint8_t *)&addr); + net_pkt_set_ll_proto_type(pkt, ETH_P_IP); + copy_ll_addr(pkt); + return 1; } From 908794942947d049b61603b728f8f15af17e4873 Mon Sep 17 00:00:00 2001 From: Robert Lubos Date: Thu, 19 Oct 2023 11:38:58 +0200 Subject: [PATCH 338/421] [nrf fromtree] net: shell: Fix unexpected timeout on loopback ping In case ping is sent to own address, the request is looped back to the stack and served before ping work had a chance to reschedule. In result, when the final ping reply has been server, and ping operation finalized with `ping_done()`, the work was rescheduled one last time, causing the ping timeout to be reported. Fix this by rescheduling the work before sending the actual request, so that the reply handler can cancel the work properly in such case. Signed-off-by: Robert Lubos (cherry picked from commit c6fd2b2d4492241a8e84421092f15d59db147d9e) --- subsys/net/ip/net_shell.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/subsys/net/ip/net_shell.c b/subsys/net/ip/net_shell.c index e7af6e16632..87995ccabb3 100644 --- a/subsys/net/ip/net_shell.c +++ b/subsys/net/ip/net_shell.c @@ -4535,6 +4535,12 @@ static void ping_work(struct k_work *work) return; } + if (ctx->sequence < ctx->count) { + k_work_reschedule(&ctx->work, K_MSEC(ctx->interval)); + } else { + k_work_reschedule(&ctx->work, K_SECONDS(2)); + } + if (ctx->addr.family == AF_INET6) { ret = net_icmpv6_send_echo_request(ctx->iface, &ctx->addr.in6_addr, @@ -4560,12 +4566,6 @@ static void ping_work(struct k_work *work) ping_done(ctx); return; } - - if (ctx->sequence < ctx->count) { - k_work_reschedule(&ctx->work, K_MSEC(ctx->interval)); - } else { - k_work_reschedule(&ctx->work, K_SECONDS(2)); - } } #define ASCII_CTRL_C 0x03 From fabddf3a622625f39a71b9bb0377569e2fe230be Mon Sep 17 00:00:00 2001 From: Mariusz Poslinski Date: Thu, 26 Oct 2023 15:53:52 +0200 Subject: [PATCH 339/421] [nrf noup] testspec: remove HomeKit from NCS HomeKit Accessory Development Kit has been deprecated and removed from NCS. Signed-off-by: Mariusz Poslinski --- .github/test-spec.yml | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/.github/test-spec.yml b/.github/test-spec.yml index 62b92e74d0f..c01ae703adf 100644 --- a/.github/test-spec.yml +++ b/.github/test-spec.yml @@ -131,17 +131,6 @@ "CI-rs-test": - "**/*" -"CI-homekit-test": - - "modules/openthread/**/*" - - "samples/bluetooth/hci_rpmsg/**/*" - - "soc/arm/nordic_nrf/**/*" - - "subsys/net/**/*" - - "subsys/settings/**/*" - - any: - - "subsys/bluetooth/**/*" - - "!subsys/bluetooth/mesh/**/*" - - "!subsys/bluetooth/audio/**/*" - "CI-thread-test": - "include/zephyr/net/**/*" - "modules/mbedtls/**/*" From 5754cb6632da0d65c448362834f194ceb8b8493e Mon Sep 17 00:00:00 2001 From: Aleksander Wasaznik Date: Wed, 19 Jul 2023 15:35:12 +0200 Subject: [PATCH 340/421] [nrf fromtree] dts: bindings: Remove `reg` from `vnd,serial` `vnd,serial` is a virtual device which does not have an address. Signed-off-by: Aleksander Wasaznik (cherry picked from commit 0e83c66cefc5efe80675c0dcf13cfff5589d1fd0) --- dts/bindings/test/vnd,serial.yaml | 3 --- 1 file changed, 3 deletions(-) diff --git a/dts/bindings/test/vnd,serial.yaml b/dts/bindings/test/vnd,serial.yaml index dc2327b4827..c2d931b0ed7 100644 --- a/dts/bindings/test/vnd,serial.yaml +++ b/dts/bindings/test/vnd,serial.yaml @@ -5,9 +5,6 @@ compatible: "vnd,serial" include: uart-controller.yaml properties: - reg: - required: true - baud-rate: type: int From 3c923c5a170c793f8d8582224e7d1c988237247b Mon Sep 17 00:00:00 2001 From: Aleksander Wasaznik Date: Wed, 19 Jul 2023 15:43:26 +0200 Subject: [PATCH 341/421] [nrf fromtree] drivers: serial_test: Implement interrupt and async APIs This allows testing code that uses the UART interrupt-driven API and UART asynchronous API. Signed-off-by: Aleksander Wasaznik (cherry picked from commit 4d926ac041cea9a1947390c8a34cb7906e3da30f) --- drivers/serial/serial_test.c | 319 +++++++++++++++++++++- include/zephyr/drivers/uart/serial_test.h | 2 +- 2 files changed, 318 insertions(+), 3 deletions(-) diff --git a/drivers/serial/serial_test.c b/drivers/serial/serial_test.c index 95e036e5992..2ce4fb50f38 100644 --- a/drivers/serial/serial_test.c +++ b/drivers/serial/serial_test.c @@ -9,12 +9,21 @@ * devices for the "vnd,serial" devicetree compatible used in test code. */ +#include + +#include #include #include #include #include +#include #include +LOG_MODULE_REGISTER(mock_serial, CONFIG_LOG_DEFAULT_LEVEL); + +BUILD_ASSERT(!IS_ENABLED(CONFIG_UART_INTERRUPT_DRIVEN) || IS_ENABLED(CONFIG_RING_BUFFER)); +BUILD_ASSERT(!IS_ENABLED(CONFIG_UART_ASYNC_API) || IS_ENABLED(CONFIG_RING_BUFFER)); + #define DT_DRV_COMPAT vnd_serial struct serial_vnd_data { #ifdef CONFIG_RING_BUFFER @@ -23,8 +32,156 @@ struct serial_vnd_data { #endif serial_vnd_write_cb_t callback; void *callback_data; +#ifdef CONFIG_UART_INTERRUPT_DRIVEN + uart_irq_callback_user_data_t irq_isr; + bool irq_rx_enabled; + bool irq_tx_enabled; +#endif +#ifdef CONFIG_UART_ASYNC_API + uart_callback_t async_cb; + void *async_cb_user_data; + uint8_t *read_buf; + size_t read_size; + size_t read_position; +#endif }; +#ifdef CONFIG_UART_INTERRUPT_DRIVEN +static bool is_irq_rx_pending(const struct device *dev) +{ + struct serial_vnd_data *data = dev->data; + + return !ring_buf_is_empty(data->read_queue); +} + +static bool is_irq_tx_pending(const struct device *dev) +{ + struct serial_vnd_data *data = dev->data; + + return ring_buf_space_get(data->written) != 0; +} + +static void irq_process(const struct device *dev) +{ + struct serial_vnd_data *data = dev->data; + + for (;;) { + bool rx_rdy = is_irq_rx_pending(dev); + bool tx_rdy = is_irq_tx_pending(dev); + bool rx_int = rx_rdy && data->irq_rx_enabled; + bool tx_int = tx_rdy && data->irq_tx_enabled; + + LOG_DBG("rx_rdy %d tx_rdy %d", rx_rdy, tx_rdy); + LOG_DBG("rx_int %d tx_int %d", rx_int, tx_int); + + if (!(rx_int || tx_int)) { + break; + } + + LOG_DBG("isr"); + if (!data->irq_isr) { + LOG_ERR("no isr registered"); + break; + } + data->irq_isr(dev, NULL); + }; +} + +static void irq_rx_enable(const struct device *dev) +{ + struct serial_vnd_data *data = dev->data; + + data->irq_rx_enabled = true; + LOG_DBG("rx enabled"); + irq_process(dev); +} + +static void irq_rx_disable(const struct device *dev) +{ + struct serial_vnd_data *data = dev->data; + + data->irq_rx_enabled = false; + LOG_DBG("rx disabled"); +} + +static int irq_rx_ready(const struct device *dev) +{ + struct serial_vnd_data *data = dev->data; + bool ready = !ring_buf_is_empty(data->read_queue); + + LOG_DBG("rx ready: %d", ready); + return ready; +} + +static void irq_tx_enable(const struct device *dev) +{ + struct serial_vnd_data *data = dev->data; + + LOG_DBG("tx enabled"); + data->irq_tx_enabled = true; + irq_process(dev); +} + +static void irq_tx_disable(const struct device *dev) +{ + struct serial_vnd_data *data = dev->data; + + data->irq_tx_enabled = false; + LOG_DBG("tx disabled"); +} + +static int irq_tx_ready(const struct device *dev) +{ + struct serial_vnd_data *data = dev->data; + bool ready = (ring_buf_space_get(data->written) != 0); + + LOG_DBG("tx ready: %d", ready); + return ready; +} + +static void irq_callback_set(const struct device *dev, uart_irq_callback_user_data_t cb, + void *user_data) +{ + struct serial_vnd_data *data = dev->data; + + /* Not implemented. Ok because `user_data` is always NULL in the current + * implementation of core UART API. + */ + __ASSERT_NO_MSG(user_data == NULL); + +#if defined(CONFIG_UART_EXCLUSIVE_API_CALLBACKS) && defined(CONFIG_UART_ASYNC_API) + if (data->read_buf) { + LOG_ERR("Setting callback to NULL while asynchronous API is in use."); + } + data->async_cb = NULL; + data->async_cb_user_data = NULL; +#endif + + data->irq_isr = cb; + LOG_DBG("callback set"); +} + +static int fifo_fill(const struct device *dev, const uint8_t *tx_data, int size) +{ + struct serial_vnd_data *data = dev->data; + uint32_t write_len = ring_buf_put(data->written, tx_data, size); + + if (data->callback) { + data->callback(dev, data->callback_data); + } + return write_len; +} + +static int fifo_read(const struct device *dev, uint8_t *rx_data, const int size) +{ + struct serial_vnd_data *data = dev->data; + int read_len = ring_buf_get(data->read_queue, rx_data, size); + + LOG_HEXDUMP_DBG(rx_data, read_len, ""); + return read_len; +} +#endif /* CONFIG_UART_INTERRUPT_DRIVEN */ + static int serial_vnd_poll_in(const struct device *dev, unsigned char *c) { #ifdef CONFIG_RING_BUFFER @@ -59,15 +216,35 @@ static void serial_vnd_poll_out(const struct device *dev, unsigned char c) } } +#ifdef CONFIG_UART_ASYNC_API +static void async_rx_run(const struct device *dev); +#endif + #ifdef CONFIG_RING_BUFFER -int serial_vnd_queue_in_data(const struct device *dev, unsigned char *c, uint32_t size) +int serial_vnd_queue_in_data(const struct device *dev, const unsigned char *c, uint32_t size) { struct serial_vnd_data *data = dev->data; + int write_size; if (data == NULL || data->read_queue == NULL) { return -ENOTSUP; } - return ring_buf_put(data->read_queue, c, size); + write_size = ring_buf_put(data->read_queue, c, size); + + LOG_DBG("size %u write_size %u", size, write_size); + LOG_HEXDUMP_DBG(c, write_size, ""); + +#ifdef CONFIG_UART_INTERRUPT_DRIVEN + if (write_size > 0) { + irq_process(dev); + } +#endif + +#ifdef CONFIG_UART_ASYNC_API + async_rx_run(dev); +#endif + + return write_size; } uint32_t serial_vnd_out_data_size_get(const struct device *dev) @@ -130,6 +307,128 @@ static int serial_vnd_config_get(const struct device *dev, struct uart_config *c } #endif /* CONFIG_UART_USE_RUNTIME_CONFIGURE */ +#ifdef CONFIG_UART_ASYNC_API +static int serial_vnd_callback_set(const struct device *dev, uart_callback_t callback, + void *user_data) +{ + struct serial_vnd_data *data = dev->data; + + if (data == NULL) { + return -ENOTSUP; + } + +#if defined(CONFIG_UART_EXCLUSIVE_API_CALLBACKS) && defined(CONFIG_UART_INTERRUPT_DRIVEN) + data->irq_isr = cb; +#endif + + if (callback == NULL && data->read_buf) { + LOG_ERR("Setting callback to NULL while asynchronous API is in use."); + } + + data->async_cb = callback; + data->async_cb_user_data = user_data; + + return 0; +} + +static int serial_vnd_api_tx(const struct device *dev, const uint8_t *tx_data, size_t len, + int32_t timeout) +{ + struct serial_vnd_data *data = dev->data; + struct uart_event evt; + uint32_t write_len; + + if (data == NULL) { + return -ENOTSUP; + } + + if (data->async_cb == NULL) { + return -EINVAL; + } + + write_len = ring_buf_put(data->written, tx_data, len); + if (data->callback) { + data->callback(dev, data->callback_data); + } + + __ASSERT(write_len == len, "Ring buffer full. Async wait not implemented."); + + evt = (struct uart_event){ + .type = UART_TX_DONE, + .data.tx.buf = tx_data, + .data.tx.len = len, + }; + data->async_cb(dev, &evt, data->async_cb_user_data); + + return 0; +} + +static void async_rx_run(const struct device *dev) +{ + struct serial_vnd_data *data = dev->data; + struct uart_event evt; + uint32_t read_len; + uint32_t read_remaining; + + if (!data->read_buf) { + return; + } + + __ASSERT_NO_MSG(data->async_cb); + + read_remaining = data->read_size - data->read_position; + + read_len = ring_buf_get(data->read_queue, &data->read_buf[data->read_position], + read_remaining); + + if (read_len != 0) { + evt = (struct uart_event){ + .type = UART_RX_RDY, + .data.rx.buf = data->read_buf, + .data.rx.len = read_len, + .data.rx.offset = data->read_position, + }; + data->async_cb(dev, &evt, data->async_cb_user_data); + } + + data->read_position += read_len; + + if (data->read_position == data->read_size) { + data->read_buf = NULL; + evt = (struct uart_event){ + .type = UART_RX_DISABLED, + }; + data->async_cb(dev, &evt, data->async_cb_user_data); + } +} + +static int serial_vnd_rx_enable(const struct device *dev, uint8_t *read_buf, size_t read_size, + int32_t timeout) +{ + struct serial_vnd_data *data = dev->data; + + LOG_WRN("read_size %d", read_size); + + if (data == NULL) { + return -ENOTSUP; + } + + if (data->async_cb == NULL) { + return -EINVAL; + } + + __ASSERT(timeout == SYS_FOREVER_MS, "Async timeout not implemented."); + + data->read_buf = read_buf; + data->read_size = read_size; + data->read_position = 0; + + async_rx_run(dev); + + return 0; +} +#endif /* CONFIG_UART_ASYNC_API */ + static const struct uart_driver_api serial_vnd_api = { .poll_in = serial_vnd_poll_in, .poll_out = serial_vnd_poll_out, @@ -138,6 +437,22 @@ static const struct uart_driver_api serial_vnd_api = { .configure = serial_vnd_configure, .config_get = serial_vnd_config_get, #endif /* CONFIG_UART_USE_RUNTIME_CONFIGURE */ +#ifdef CONFIG_UART_INTERRUPT_DRIVEN + .irq_callback_set = irq_callback_set, + .irq_rx_enable = irq_rx_enable, + .irq_rx_disable = irq_rx_disable, + .irq_rx_ready = irq_rx_ready, + .irq_tx_enable = irq_tx_enable, + .irq_tx_disable = irq_tx_disable, + .irq_tx_ready = irq_tx_ready, + .fifo_read = fifo_read, + .fifo_fill = fifo_fill, +#endif /* CONFIG_UART_INTERRUPT_DRIVEN */ +#ifdef CONFIG_UART_ASYNC_API + .callback_set = serial_vnd_callback_set, + .tx = serial_vnd_api_tx, + .rx_enable = serial_vnd_rx_enable, +#endif /* CONFIG_UART_ASYNC_API */ }; #define VND_SERIAL_DATA_BUFFER(n) \ diff --git a/include/zephyr/drivers/uart/serial_test.h b/include/zephyr/drivers/uart/serial_test.h index 5e011d40321..ff1a2ad6181 100644 --- a/include/zephyr/drivers/uart/serial_test.h +++ b/include/zephyr/drivers/uart/serial_test.h @@ -29,7 +29,7 @@ extern "C" { * * @retval Number of bytes written. */ -int serial_vnd_queue_in_data(const struct device *dev, unsigned char *data, uint32_t size); +int serial_vnd_queue_in_data(const struct device *dev, const unsigned char *data, uint32_t size); /** * @brief Returns size of unread written data. From 237e871f948cb64089ec9d792d9cc5dd3377b85d Mon Sep 17 00:00:00 2001 From: Aleksander Wasaznik Date: Tue, 10 Jan 2023 10:11:09 +0100 Subject: [PATCH 342/421] [nrf fromtree] bluetooth: samples: Add hci_uart_async This sample is an alternative implementation of hci_uart. The new sample differs from the existing sample in that it uses the async UART API instead of the interrupt driven API. Included in this commit is a new test for HCI UART flow control. It's enabled for hci_uart_async. The test can excercise also the existing hci_uart sample (with some minimal changes to allow compiling in the mock controller and test suite). The existing hci_uart sample currently fails the flow control test. Signed-off-by: Aleksander Wasaznik (cherry picked from commit 347ce7aa7f6e4be8464a4c09c615ad7c4eaa6f9f) --- .../bluetooth/hci_uart_async/CMakeLists.txt | 10 + samples/bluetooth/hci_uart_async/README.rst | 158 +++++++ samples/bluetooth/hci_uart_async/app.overlay | 31 ++ .../bluetooth/hci_uart_async/debug.mixin.conf | 15 + samples/bluetooth/hci_uart_async/prj.conf | 25 ++ samples/bluetooth/hci_uart_async/sample.yaml | 19 + .../hci_uart_async/src/hci_uart_async.c | 403 ++++++++++++++++++ samples/bluetooth/hci_uart_async/src/main.c | 11 + tests/bluetooth/hci_uart_async/CMakeLists.txt | 15 + tests/bluetooth/hci_uart_async/app.overlay | 11 + .../hci_uart_async/boards/native_posix.conf | 3 + tests/bluetooth/hci_uart_async/prj.conf | 10 + .../hci_uart_async/src/test_hci_uart_async.c | 238 +++++++++++ tests/bluetooth/hci_uart_async/testcase.yaml | 6 + 14 files changed, 955 insertions(+) create mode 100644 samples/bluetooth/hci_uart_async/CMakeLists.txt create mode 100644 samples/bluetooth/hci_uart_async/README.rst create mode 100644 samples/bluetooth/hci_uart_async/app.overlay create mode 100644 samples/bluetooth/hci_uart_async/debug.mixin.conf create mode 100644 samples/bluetooth/hci_uart_async/prj.conf create mode 100644 samples/bluetooth/hci_uart_async/sample.yaml create mode 100644 samples/bluetooth/hci_uart_async/src/hci_uart_async.c create mode 100644 samples/bluetooth/hci_uart_async/src/main.c create mode 100644 tests/bluetooth/hci_uart_async/CMakeLists.txt create mode 100644 tests/bluetooth/hci_uart_async/app.overlay create mode 100644 tests/bluetooth/hci_uart_async/boards/native_posix.conf create mode 100644 tests/bluetooth/hci_uart_async/prj.conf create mode 100644 tests/bluetooth/hci_uart_async/src/test_hci_uart_async.c create mode 100644 tests/bluetooth/hci_uart_async/testcase.yaml diff --git a/samples/bluetooth/hci_uart_async/CMakeLists.txt b/samples/bluetooth/hci_uart_async/CMakeLists.txt new file mode 100644 index 00000000000..fe45a9cc371 --- /dev/null +++ b/samples/bluetooth/hci_uart_async/CMakeLists.txt @@ -0,0 +1,10 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) + +project(hci_uart_async) +target_sources(app PRIVATE + src/hci_uart_async.c + src/main.c +) diff --git a/samples/bluetooth/hci_uart_async/README.rst b/samples/bluetooth/hci_uart_async/README.rst new file mode 100644 index 00000000000..75bf586868d --- /dev/null +++ b/samples/bluetooth/hci_uart_async/README.rst @@ -0,0 +1,158 @@ +.. _bluetooth-hci-uart-async-sample: + +Bluetooth: HCI UART based on ASYNC UART +####################################### + +Expose a Zephyr Bluetooth Controller over a standard Bluetooth HCI UART interface. + +This sample performs the same basic function as the HCI UART sample, but it uses the UART_ASYNC_API +instead of UART_INTERRUPT_DRIVEN API. Not all boards implement both UART APIs, so the board support +of the HCI UART sample may be different. + +Requirements +************ + +* A board with BLE support + +Default UART settings +********************* + +By default the controller builds use the following settings: + +* Baudrate: 1Mbit/s +* 8 bits, no parity, 1 stop bit +* Hardware Flow Control (RTS/CTS) enabled + +Building and Running +******************** + +This sample can be found under :zephyr_file:`samples/bluetooth/hci_uart_async` +in the Zephyr tree and is built as a standard Zephyr application. + +Using the controller with emulators and BlueZ +********************************************* + +The instructions below show how to use a Nordic nRF5x device as a Zephyr BLE +controller and expose it to Linux's BlueZ. + +First, make sure you have a recent BlueZ version installed by following the +instructions in the :ref:`bluetooth_bluez` section. + +Now build and flash the sample for the Nordic nRF5x board of your choice. +All of the Nordic Development Kits come with a Segger IC that provides a +debugger interface and a CDC ACM serial port bridge. More information can be +found in :ref:`nordic_segger`. + +For example, to build for the nRF52832 Development Kit: + +.. zephyr-app-commands:: + :zephyr-app: samples/bluetooth/hci_uart_async + :board: nrf52dk_nrf52832 + :goals: build flash + +.. _bluetooth-hci-uart-async-qemu-posix: + +Using the controller with QEMU and Native POSIX +=============================================== + +In order to use the HCI UART controller with QEMU or Native POSIX you will need +to attach it to the Linux Host first. To do so simply build the sample and +connect the UART to the Linux machine, and then attach it with this command: + +.. code-block:: console + + sudo btattach -B /dev/ttyACM0 -S 1000000 -R + +.. note:: + Depending on the serial port you are using you will need to modify the + ``/dev/ttyACM0`` string to point to the serial device your controller is + connected to. + +.. note:: + The ``-R`` flag passed to ``btattach`` instructs the kernel to avoid + interacting with the controller and instead just be aware of it in order + to proxy it to QEMU later. + +If you are running :file:`btmon` you should see a brief log showing how the +Linux kernel identifies the attached controller. + +Once the controller is attached follow the instructions in the +:ref:`bluetooth_qemu_posix` section to use QEMU with it. + +.. _bluetooth-hci-uart-async-bluez: + +Using the controller with BlueZ +=============================== + +In order to use the HCI UART controller with BlueZ you will need to attach it +to the Linux Host first. To do so simply build the sample and connect the +UART to the Linux machine, and then attach it with this command: + +.. code-block:: console + + sudo btattach -B /dev/ttyACM0 -S 1000000 + +.. note:: + Depending on the serial port you are using you will need to modify the + ``/dev/ttyACM0`` string to point to the serial device your controller is + connected to. + +If you are running :file:`btmon` you should see a comprehensive log showing how +BlueZ loads and initializes the attached controller. + +Once the controller is attached follow the instructions in the +:ref:`bluetooth_ctlr_bluez` section to use BlueZ with it. + +Debugging the controller +======================== + +The sample can be debugged using RTT since the UART is reserved used by this +application. To enable debug over RTT the debug configuration file can be used. + +.. code-block:: console + + west build samples/bluetooth/hci_uart_async -- -DEXTRA_CONFIG='debug.mixin.conf' + +Then attach RTT as described here: :ref:`Using Segger J-Link ` + +Using the controller with the Zephyr host +========================================= + +This describes how to hook up a board running this sample to a board running +an application that uses the Zephyr host. + +On the controller side, the `zephyr,bt-c2h-uart` DTS property (in the `chosen` +block) is used to select which uart device to use. For example if we want to +keep the console logs, we can keep console on uart0 and the HCI on uart1 like +so: + +.. code-block:: dts + + / { + chosen { + zephyr,console = &uart0; + zephyr,shell-uart = &uart0; + zephyr,bt-c2h-uart = &uart1; + }; + }; + +On the host application, some config options need to be used to select the H4 +driver instead of the built-in controller: + +.. code-block:: kconfig + + CONFIG_BT_HCI=y + CONFIG_BT_CTLR=n + CONFIG_BT_H4=y + +Similarly, the `zephyr,bt-uart` DTS property selects which uart to use: + +.. code-block:: dts + + / { + chosen { + zephyr,console = &uart0; + zephyr,shell-uart = &uart0; + zephyr,bt-uart = &uart1; + }; + }; diff --git a/samples/bluetooth/hci_uart_async/app.overlay b/samples/bluetooth/hci_uart_async/app.overlay new file mode 100644 index 00000000000..e9a282ad78c --- /dev/null +++ b/samples/bluetooth/hci_uart_async/app.overlay @@ -0,0 +1,31 @@ +/* This is the default app device tree overlay. This file is ignored if + * there is a board-specific overlay in `./boards`. + * + * Most boards define a convenient `&uart0`. It's used here to make the + * sample 'just work' automatically for those boards. + */ + +bt_c2h_uart: &uart0 { + status = "okay"; + current-speed = <1000000>; + hw-flow-control; +}; + +/ { + chosen { + zephyr,bt-c2h-uart = &bt_c2h_uart; + }; +}; + +/* Some boards are by default assigning the &uart0 to these other + * functions. Removing the assignments will ensure a compilation error + * instead of accidental interference. + */ +/ { + chosen { + /delete-property/ zephyr,console; + /delete-property/ zephyr,shell-uart; + /delete-property/ zephyr,uart-mcumgr; + /delete-property/ zephyr,bt-mon-uart; + }; +}; diff --git a/samples/bluetooth/hci_uart_async/debug.mixin.conf b/samples/bluetooth/hci_uart_async/debug.mixin.conf new file mode 100644 index 00000000000..3255df74018 --- /dev/null +++ b/samples/bluetooth/hci_uart_async/debug.mixin.conf @@ -0,0 +1,15 @@ +CONFIG_ASSERT_ON_ERRORS=y +CONFIG_ASSERT=y +CONFIG_DEBUG_INFO=y +CONFIG_DEBUG_OPTIMIZATIONS=y +CONFIG_DEBUG_THREAD_INFO=y + +# Enable RTT console +CONFIG_RTT_CONSOLE=y + +CONFIG_LOG=y +CONFIG_LOG_BUFFER_SIZE=10000 + +# This outputs all HCI traffic to a separate RTT channel. Use `btmon +# --jlink` to read it out. Add `--priority 7` for debug logs. +CONFIG_BT_DEBUG_MONITOR_RTT=y diff --git a/samples/bluetooth/hci_uart_async/prj.conf b/samples/bluetooth/hci_uart_async/prj.conf new file mode 100644 index 00000000000..1de1a46535e --- /dev/null +++ b/samples/bluetooth/hci_uart_async/prj.conf @@ -0,0 +1,25 @@ +# hci_uart_async +CONFIG_SERIAL=y +CONFIG_UART_ASYNC_API=y + +# hci_raw (dependency of hci_uart) +CONFIG_BT=y +CONFIG_BT_HCI_RAW=y +CONFIG_BT_HCI_RAW_H4=y +CONFIG_BT_HCI_RAW_H4_ENABLE=y + +# Controller configuration. Modify these for your application's needs. +CONFIG_BT_MAX_CONN=16 +CONFIG_BT_BUF_ACL_RX_SIZE=255 +CONFIG_BT_BUF_CMD_TX_SIZE=255 +CONFIG_BT_BUF_EVT_DISCARDABLE_SIZE=255 + +# Send an initial HCI_Command_Complete event on boot without waiting for +# HCI_Reset. Make sure to use the same value for this setting in your +# host application. +#CONFIG_BT_WAIT_NOP=y + +# See `overlay.app`. The 'zephyr,console' chosen node is deleted there +# in case it has a interfering default. Those same boards set this +# config and it must be undone or the build will fail. +CONFIG_UART_CONSOLE=n diff --git a/samples/bluetooth/hci_uart_async/sample.yaml b/samples/bluetooth/hci_uart_async/sample.yaml new file mode 100644 index 00000000000..d0db2b90385 --- /dev/null +++ b/samples/bluetooth/hci_uart_async/sample.yaml @@ -0,0 +1,19 @@ +sample: + name: Bluetooth HCI UART Async + description: + This sample is a batteries-included example of a Bluetooth HCI UART + connectivity chip. + + It demonstrates a possible implementation of an HCI UART (H4) + interface on top of Zephyr's Bluetooth Raw API, and how to expose it + over a UART. + + This implementation is based on the Zephyr Asynchoronous UART API. +tests: + sample.bluetooth.hci_uart_async.nrf5: + harness: bluetooth + platform_allow: + - nrf52dk_nrf52832 + tags: + - uart + - bluetooth diff --git a/samples/bluetooth/hci_uart_async/src/hci_uart_async.c b/samples/bluetooth/hci_uart_async/src/hci_uart_async.c new file mode 100644 index 00000000000..4d276e42378 --- /dev/null +++ b/samples/bluetooth/hci_uart_async/src/hci_uart_async.c @@ -0,0 +1,403 @@ +/* Copyright (c) 2023 Nordic Semiconductor ASA + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include + +LOG_MODULE_REGISTER(hci_uart_async, LOG_LEVEL_DBG); + +static const struct device *const hci_uart_dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_bt_c2h_uart)); + +static K_THREAD_STACK_DEFINE(h2c_thread_stack, CONFIG_BT_HCI_TX_STACK_SIZE); +static struct k_thread h2c_thread; + +enum h4_type { + H4_CMD = 0x01, + H4_ACL = 0x02, + H4_SCO = 0x03, + H4_EVT = 0x04, + H4_ISO = 0x05, +}; + +struct k_poll_signal uart_h2c_rx_sig; +struct k_poll_signal uart_c2h_tx_sig; + +static K_FIFO_DEFINE(c2h_queue); + +/** Send raw data on c2h UART. + * + * Blocks until completion. Not thread-safe. + * + * @retval 0 on success + * @retval -EBUSY Another transmission is in progress. This a + * thread-safety violation. + * @retval -errno @ref uart_tx error. + */ +static int uart_c2h_tx(const uint8_t *data, size_t size) +{ + int err; + struct k_poll_signal *sig = &uart_c2h_tx_sig; + struct k_poll_event done[] = { + K_POLL_EVENT_INITIALIZER(K_POLL_TYPE_SIGNAL, K_POLL_MODE_NOTIFY_ONLY, sig), + }; + + k_poll_signal_reset(sig); + err = uart_tx(hci_uart_dev, data, size, SYS_FOREVER_US); + + if (err) { + LOG_ERR("uart c2h tx: err %d", err); + return err; + } + + err = k_poll(done, ARRAY_SIZE(done), K_FOREVER); + __ASSERT_NO_MSG(err == 0); + + return 0; +} + +/* Function expects that type is validated and only CMD, ISO or ACL will be used. */ +static uint32_t hci_payload_size(const uint8_t *hdr_buf, enum h4_type type) +{ + switch (type) { + case H4_CMD: + return ((const struct bt_hci_cmd_hdr *)hdr_buf)->param_len; + case H4_ACL: + return sys_le16_to_cpu(((const struct bt_hci_acl_hdr *)hdr_buf)->len); + case H4_ISO: + return bt_iso_hdr_len( + sys_le16_to_cpu(((const struct bt_hci_iso_hdr *)hdr_buf)->len)); + default: + LOG_ERR("Invalid type: %u", type); + return 0; + } +} + +static uint8_t hci_hdr_size(enum h4_type type) +{ + switch (type) { + case H4_CMD: + return sizeof(struct bt_hci_cmd_hdr); + case H4_ACL: + return sizeof(struct bt_hci_acl_hdr); + case H4_ISO: + return sizeof(struct bt_hci_iso_hdr); + default: + LOG_ERR("Unexpected h4 type: %u", type); + return 0; + } +} + +/** Send raw data on c2h UART. + * + * Blocks until either @p size has been received or special UART + * condition occurs on the UART RX line, like an UART break or parity + * error. + * + * Not thread-safe. + * + * @retval 0 on success + * @retval -EBUSY Another transmission is in progress. This a + * thread-safety violation. + * @retval -errno @ref uart_rx_enable error. + * @retval +stop_reason Special condition @ref uart_rx_stop_reason. + */ +static int uart_h2c_rx(uint8_t *dst, size_t size) +{ + int err; + struct k_poll_signal *sig = &uart_h2c_rx_sig; + struct k_poll_event done[] = { + K_POLL_EVENT_INITIALIZER(K_POLL_TYPE_SIGNAL, K_POLL_MODE_NOTIFY_ONLY, sig), + }; + + k_poll_signal_reset(sig); + err = uart_rx_enable(hci_uart_dev, dst, size, SYS_FOREVER_US); + + if (err) { + LOG_ERR("uart h2c rx: err %d", err); + return err; + } + + k_poll(done, ARRAY_SIZE(done), K_FOREVER); + return sig->result; +} + +/** Inject a HCI EVT Hardware error into the c2h packet stream. + * + * This uses `bt_recv`, just as if the controller is sending the error. + */ +static void send_hw_error(void) +{ + const uint8_t err_code = 0; + const uint8_t hci_evt_hw_err[] = {BT_HCI_EVT_HARDWARE_ERROR, + sizeof(struct bt_hci_evt_hardware_error), err_code}; + + struct net_buf *buf = bt_buf_get_rx(BT_BUF_EVT, K_FOREVER); + + net_buf_add_mem(buf, hci_evt_hw_err, sizeof(hci_evt_hw_err)); + + /* Inject the message into the c2h queue. */ + bt_recv(buf); + + /* The c2h thread will send the message at some point. The host + * will receive it and reset the controller. + */ +} + +static void recover_sync_by_reset_pattern(void) +{ + /* { H4_CMD, le_16(HCI_CMD_OP_RESET), len=0 } */ + const uint8_t h4_cmd_reset[] = {0x01, 0x03, 0x0C, 0x00}; + const uint32_t reset_pattern = sys_get_be32(h4_cmd_reset); + int err; + struct net_buf *h2c_cmd_reset; + uint32_t shift_register = 0; + + LOG_DBG("Looking for reset pattern"); + + while (shift_register != reset_pattern) { + uint8_t read_byte; + + uart_h2c_rx(&read_byte, sizeof(uint8_t)); + LOG_DBG("h2c: 0x%02x", read_byte); + shift_register = (shift_register * 0x100) + read_byte; + } + + LOG_DBG("Pattern found"); + h2c_cmd_reset = bt_buf_get_tx(BT_BUF_H4, K_FOREVER, h4_cmd_reset, sizeof(h4_cmd_reset)); + LOG_DBG("Fowarding reset"); + + err = bt_send(h2c_cmd_reset); + __ASSERT(!err, "Failed to send reset: %d", err); +} + +static void h2c_h4_transport(void) +{ + /* When entering this function, the h2c stream should be + * 'synchronized'. I.e. The stream should be at a H4 packet + * boundary. + * + * This function returns to signal a desynchronization. + * When this happens, the caller should resynchronize before + * entering this function again. It's up to the caller to decide + * how to resynchronize. + */ + + for (;;) { + int err; + struct net_buf *buf; + uint8_t h4_type; + uint8_t hdr_size; + uint8_t *hdr_buf; + uint16_t payload_size; + + LOG_DBG("h2c: listening"); + + /* Read H4 type. */ + err = uart_h2c_rx(&h4_type, sizeof(uint8_t)); + + if (err) { + return; + } + LOG_DBG("h2c: h4_type %d", h4_type); + + /* Allocate buf. */ + buf = bt_buf_get_tx(BT_BUF_H4, K_FOREVER, &h4_type, sizeof(h4_type)); + LOG_DBG("h2c: buf %p", buf); + + if (!buf) { + /* `h4_type` was invalid. */ + __ASSERT_NO_MSG(hci_hdr_size(h4_type) == 0); + + LOG_WRN("bt_buf_get_tx failed h4_type %d", h4_type); + return; + } + + /* Read HCI header. */ + hdr_size = hci_hdr_size(h4_type); + hdr_buf = net_buf_add(buf, hdr_size); + + err = uart_h2c_rx(hdr_buf, hdr_size); + if (err) { + net_buf_unref(buf); + return; + } + LOG_HEXDUMP_DBG(hdr_buf, hdr_size, "h2c: hci hdr"); + + /* Read HCI payload. */ + payload_size = hci_payload_size(hdr_buf, h4_type); + + LOG_DBG("h2c: payload_size %u", payload_size); + + if (payload_size <= net_buf_tailroom(buf)) { + uint8_t *payload_dst = net_buf_add(buf, payload_size); + + err = uart_h2c_rx(payload_dst, payload_size); + if (err) { + net_buf_unref(buf); + return; + } + LOG_HEXDUMP_DBG(payload_dst, payload_size, "h2c: hci payload"); + } else { + /* Discard oversize packet. */ + uint8_t *discard_dst; + uint16_t discard_size; + + LOG_WRN("h2c: Discarding oversize h4_type %d payload_size %d.", h4_type, + payload_size); + + /* Reset `buf` so all of it is available. */ + net_buf_reset(buf); + discard_dst = net_buf_tail(buf); + discard_size = net_buf_max_len(buf); + + while (payload_size) { + uint16_t read_size = MIN(payload_size, discard_size); + + err = uart_h2c_rx(discard_dst, read_size); + if (err) { + net_buf_unref(buf); + return; + } + + payload_size -= read_size; + } + + net_buf_unref(buf); + buf = NULL; + } + + LOG_DBG("h2c: packet done"); + + /* Route buf to Controller. */ + if (buf) { + err = bt_send(buf); + if (err) { + /* This is not a transport error. */ + LOG_ERR("bt_send err %d", err); + net_buf_unref(buf); + buf = NULL; + } + } + + k_yield(); + } +} + +static void h2c_thread_entry(void *p1, void *p2, void *p3) +{ + k_thread_name_set(k_current_get(), "HCI TX (h2c)"); + + for (;;) { + LOG_DBG("Synchronized"); + h2c_h4_transport(); + LOG_WRN("Desynchronized"); + send_hw_error(); + recover_sync_by_reset_pattern(); + } +} + +void callback(const struct device *dev, struct uart_event *evt, void *user_data) +{ + ARG_UNUSED(user_data); + + if (evt->type == UART_RX_DISABLED) { + (void)k_poll_signal_raise(&uart_h2c_rx_sig, 0); + } else if (evt->type == UART_RX_STOPPED) { + (void)k_poll_signal_raise(&uart_h2c_rx_sig, evt->data.rx_stop.reason); + } else if (evt->type == UART_TX_DONE) { + (void)k_poll_signal_raise(&uart_c2h_tx_sig, 0); + } +} + +static int hci_uart_init(void) +{ + int err; + + k_poll_signal_init(&uart_h2c_rx_sig); + k_poll_signal_init(&uart_c2h_tx_sig); + + LOG_DBG(""); + + if (!device_is_ready(hci_uart_dev)) { + LOG_ERR("HCI UART %s is not ready", hci_uart_dev->name); + return -EINVAL; + } + + BUILD_ASSERT(IS_ENABLED(CONFIG_UART_ASYNC_API)); + err = uart_callback_set(hci_uart_dev, callback, NULL); + + /* Note: Asserts if CONFIG_UART_ASYNC_API is not enabled for `hci_uart_dev`. */ + __ASSERT(!err, "err %d", err); + + return 0; +} + +SYS_INIT(hci_uart_init, APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEVICE); + +const struct { + uint8_t h4; + struct bt_hci_evt_hdr hdr; + struct bt_hci_evt_cmd_complete cc; +} __packed cc_evt = { + .h4 = H4_EVT, + .hdr = {.evt = BT_HCI_EVT_CMD_COMPLETE, .len = sizeof(struct bt_hci_evt_cmd_complete)}, + .cc = {.ncmd = 1, .opcode = sys_cpu_to_le16(BT_OP_NOP)}, +}; + +static void c2h_thread_entry(void) +{ + k_thread_name_set(k_current_get(), "HCI RX (c2h)"); + + if (IS_ENABLED(CONFIG_BT_WAIT_NOP)) { + uart_c2h_tx((char *)&cc_evt, sizeof(cc_evt)); + } + + for (;;) { + struct net_buf *buf; + + buf = net_buf_get(&c2h_queue, K_FOREVER); + uart_c2h_tx(buf->data, buf->len); + net_buf_unref(buf); + } +} + +void hci_uart_main(void) +{ + int err; + + err = bt_enable_raw(&c2h_queue); + __ASSERT_NO_MSG(!err); + + /* TX thread. */ + k_thread_create(&h2c_thread, h2c_thread_stack, K_THREAD_STACK_SIZEOF(h2c_thread_stack), + h2c_thread_entry, NULL, NULL, NULL, K_PRIO_COOP(7), 0, K_NO_WAIT); + + /* Reuse current thread as RX thread. */ + c2h_thread_entry(); +} diff --git a/samples/bluetooth/hci_uart_async/src/main.c b/samples/bluetooth/hci_uart_async/src/main.c new file mode 100644 index 00000000000..2d38d83e45c --- /dev/null +++ b/samples/bluetooth/hci_uart_async/src/main.c @@ -0,0 +1,11 @@ +/* Copyright (c) 2023 Nordic Semiconductor ASA + * SPDX-License-Identifier: Apache-2.0 + */ + +extern int hci_uart_main(void); + +int main(void) +{ + hci_uart_main(); + return 0; +} diff --git a/tests/bluetooth/hci_uart_async/CMakeLists.txt b/tests/bluetooth/hci_uart_async/CMakeLists.txt new file mode 100644 index 00000000000..2380f9f1152 --- /dev/null +++ b/tests/bluetooth/hci_uart_async/CMakeLists.txt @@ -0,0 +1,15 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) + +set(EXTRA_CONF_FILE + ../../../samples/bluetooth/hci_uart_async/prj.conf +) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) + +project(test_samples_bluetooth_hci_uart_async) +target_sources(app PRIVATE + ../../../samples/bluetooth/hci_uart_async/src/hci_uart_async.c + src/test_hci_uart_async.c +) diff --git a/tests/bluetooth/hci_uart_async/app.overlay b/tests/bluetooth/hci_uart_async/app.overlay new file mode 100644 index 00000000000..d9186722ba6 --- /dev/null +++ b/tests/bluetooth/hci_uart_async/app.overlay @@ -0,0 +1,11 @@ +/ { + chosen { + zephyr,bt-c2h-uart = &test_uart; + }; + + test_uart: test_uart { + compatible = "vnd,serial"; + status = "okay"; + buffer-size = <100>; + }; +}; diff --git a/tests/bluetooth/hci_uart_async/boards/native_posix.conf b/tests/bluetooth/hci_uart_async/boards/native_posix.conf new file mode 100644 index 00000000000..e638cd6a0ef --- /dev/null +++ b/tests/bluetooth/hci_uart_async/boards/native_posix.conf @@ -0,0 +1,3 @@ +# Print logs and test results on stdout. For some reason, this not the +# default when SERIAL=y. +CONFIG_LOG_BACKEND_NATIVE_POSIX=y diff --git a/tests/bluetooth/hci_uart_async/prj.conf b/tests/bluetooth/hci_uart_async/prj.conf new file mode 100644 index 00000000000..b038c7c4312 --- /dev/null +++ b/tests/bluetooth/hci_uart_async/prj.conf @@ -0,0 +1,10 @@ +CONFIG_BT_NO_DRIVER=y + +CONFIG_RING_BUFFER=y + +CONFIG_ASSERT=y +CONFIG_LOG=y +CONFIG_TEST=y + +CONFIG_ZTEST=y +CONFIG_ZTEST_NEW_API=y diff --git a/tests/bluetooth/hci_uart_async/src/test_hci_uart_async.c b/tests/bluetooth/hci_uart_async/src/test_hci_uart_async.c new file mode 100644 index 00000000000..1996aba177a --- /dev/null +++ b/tests/bluetooth/hci_uart_async/src/test_hci_uart_async.c @@ -0,0 +1,238 @@ +/* Copyright (c) 2023 Nordic Semiconductor ASA + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +#include +#include +#include + +#include + +#include +#include +#include + +#include +#include + +LOG_MODULE_REGISTER(test, LOG_LEVEL_DBG); + +/* This is a mock UART. Using `serial_vnd_...` on this simulates + * traffic from the external Host. + */ +static const struct device *const zephyr_bt_c2h_uart = DEVICE_DT_GET(DT_CHOSEN(zephyr_bt_c2h_uart)); + +/* The DUT is Sandwiched between the mock serial interface and a mock + * controller. {{{ + */ +static void serial_vnd_data_callback(const struct device *dev, void *user_data); +static int drv_send(struct net_buf *buf); +static int drv_open(void); +static const struct bt_hci_driver drv = { + .name = "Mock Controller", + .bus = BT_HCI_DRIVER_BUS_VIRTUAL, + .open = drv_open, + .send = drv_send, +}; +static int sys_init_hci_driver_register(void) +{ + serial_vnd_set_callback(zephyr_bt_c2h_uart, serial_vnd_data_callback, NULL); + bt_hci_driver_register(&drv); + return 0; +} +SYS_INIT(sys_init_hci_driver_register, POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE); +/* }}} */ + +/* Start the DUT "main thread". The settings for this thread are selected as + * true as possible to the real main thread. {{{ + */ +static struct k_thread hci_uart_thread; +static K_THREAD_PINNED_STACK_DEFINE(hci_uart_thread_stack, CONFIG_MAIN_STACK_SIZE); +static void hci_uart_thread_entry(void *p1, void *p2, void *p3) +{ + extern void hci_uart_main(void); + hci_uart_main(); +} +static int sys_init_spawn_hci_uart(void) +{ + k_thread_name_set(&hci_uart_thread, "hci_uart_main"); + k_thread_create(&hci_uart_thread, hci_uart_thread_stack, + K_THREAD_STACK_SIZEOF(hci_uart_thread_stack), hci_uart_thread_entry, NULL, + NULL, NULL, CONFIG_MAIN_THREAD_PRIORITY, 0, K_NO_WAIT); + return 0; +} +SYS_INIT(sys_init_spawn_hci_uart, POST_KERNEL, 64); +/* }}} */ + +/* Mock controller callbacks. {{{ */ + +static int drv_open(void) +{ + LOG_DBG("drv_open"); + return 0; +} + +/** This FIFO holds the references to all h2c packets the DUT has sent + * to the controller using #bt_send. + * + * Each test should mock a controller by calling #net_buf_get on this + * FIFO and simulate a controller's #bt_hci_driver::drv_send. The mocks + * should use #bt_recv to send c2h packets to the DUT. + */ +K_FIFO_DEFINE(drv_send_fifo); /* elem T: net_buf */ +static int drv_send(struct net_buf *buf) +{ + LOG_DBG("buf %p type %d len %u", buf, bt_buf_get_type(buf), buf->len); + LOG_HEXDUMP_DBG(buf->data, buf->len, "buf"); + + __ASSERT_NO_MSG(buf); + net_buf_put(&drv_send_fifo, buf); + return 0; +} + +/* }}} */ + +/* Mock UART c2h TX handler. {{{ */ + +static void serial_vnd_data_callback(const struct device *dev, void *user_data) +{ + uint32_t size = serial_vnd_out_data_size_get(dev); + uint8_t data[size]; + + serial_vnd_read_out_data(dev, data, size); + LOG_HEXDUMP_DBG(data, size, "uart tx"); + + /* If a test needs to look at the c2h UART traffic, it can be + * captured here. + */ +} + +/* }}} */ + +#define HCI_NORMAL_CMD_BUF_COUNT (CONFIG_BT_BUF_CMD_TX_COUNT - 1) +#define TEST_PARAM_HOST_COMPLETE_COUNT 10 +#define TIMEOUT_PRESUME_STUCK K_SECONDS(1) + +/** Corresponds to: + * - #bt_hci_cmd_hdr + */ +const uint8_t h4_msg_cmd_dummy1[] = { + 0x01, /* H4: opcode = CMD */ + 0x01, 0x00, /* H4: CMD: opcode = 1 */ + 0x00, /* H4: CMD: len = 0 */ +}; + +/** Corresponds to: + * - #bt_hci_cmd_hdr + * - #bt_hci_cp_host_num_completed_packets + */ +const uint8_t h4_msg_cmd_host_num_complete[] = { + 0x01, /* H4: opcode = CMD */ + 0x35, 0x0c, /* H4: CMD: opcode = BT_HCI_OP_HOST_NUM_COMPLETED_PACKETS */ + 0x05, /* H4: CMD: len = 5 */ + 0x01, /* H4: CMD: num_handles = 1 */ + 0x00, 0x00, /* H4: CMD: connection_handle = 0 */ + 0x01, 0x00, /* H4: CMD: num_complete = 1 */ +}; + +/** Corresponds to: + * - #bt_hci_evt_hdr + * - #bt_hci_evt_cmd_complete + */ +const uint8_t hci_msg_rx_evt_cmd_complete[] = { + BT_HCI_EVT_CMD_COMPLETE, /* EVT: opcode */ + 0x03, /* EVT: len */ + 0x01, /* EVT: CMDC: ncmd = 1 */ + /* EVT: CMDC: opcode */ + 0x00, + 0x00, +}; + +ZTEST_SUITE(hci_uart, NULL, NULL, NULL, NULL, NULL); +ZTEST(hci_uart, test_h2c_cmd_flow_control) +{ + /* This test assumes the DUT does not care about the contents of + * the HCI messages, other than the HCI type/endpoint and the + * size. This allows the test to cheat and skip the HCI Reset, + * connection setup etc and use dummy command-packets. + */ + + /* Send commands, saturating the controller's command pipeline. */ + for (uint16_t i = 0; i < HCI_NORMAL_CMD_BUF_COUNT; i++) { + int write_size = serial_vnd_queue_in_data(zephyr_bt_c2h_uart, h4_msg_cmd_dummy1, + sizeof(h4_msg_cmd_dummy1)); + __ASSERT_NO_MSG(write_size == sizeof(h4_msg_cmd_dummy1)); + } + + /* At this point, the HCI flow control limit for the cmd + * endpoint has been reached. It will remain so until the + * controller mock has sent a 'HCI Command Complete' event. + * + * But the 'HCI Host Number of Completed Packets' command is + * exempt from HCI flow control. (It's like it has its own + * endpoint, that has no flow control.) + * + * We now send several 'HCI Host Number of Completed Packets' + * packets before handling any commands in the controller. This + * tests whether the DUT is able to engage the lower transport + * flow controller (i.e. UART flow-control) or somehow handle + * the special packets out-of-order in real-time. + */ + for (uint16_t i = 0; i < TEST_PARAM_HOST_COMPLETE_COUNT; i++) { + int write_size = + serial_vnd_queue_in_data(zephyr_bt_c2h_uart, h4_msg_cmd_host_num_complete, + sizeof(h4_msg_cmd_host_num_complete)); + __ASSERT_NO_MSG(write_size == sizeof(h4_msg_cmd_host_num_complete)); + } + + LOG_DBG("All h2c packets queued on UART"); + + /* Then, we check that all packets are delivered without loss. */ + + /* Expect all the normal commands first. */ + for (uint16_t i = 0; i < HCI_NORMAL_CMD_BUF_COUNT; i++) { + /* The mock controller processes a command. */ + { + struct net_buf *buf = net_buf_get(&drv_send_fifo, TIMEOUT_PRESUME_STUCK); + + zassert_not_null(buf); + zassert_equal(buf->len, sizeof(h4_msg_cmd_dummy1) - 1, "Wrong length"); + zassert_mem_equal(buf->data, &h4_msg_cmd_dummy1[1], + sizeof(h4_msg_cmd_dummy1) - 1); + net_buf_unref(buf); + } + + /* The controller sends a HCI Command Complete response. */ + { + int err; + struct net_buf *buf = bt_buf_get_rx(BT_BUF_EVT, K_NO_WAIT); + + zassert_not_null(buf); + net_buf_add_mem(buf, hci_msg_rx_evt_cmd_complete, + sizeof(hci_msg_rx_evt_cmd_complete)); + err = bt_recv(buf); + zassert_equal(err, 0, "bt_recv failed"); + } + } + + /* Expect all the 'HCI Host Number of Completed Packets'. */ + for (uint16_t i = 0; i < TEST_PARAM_HOST_COMPLETE_COUNT; i++) { + /* The mock controller processes a 'HCI Host Number of Completed Packets'. */ + { + struct net_buf *buf = net_buf_get(&drv_send_fifo, TIMEOUT_PRESUME_STUCK); + + zassert_not_null(buf); + zassert_equal(buf->len, sizeof(h4_msg_cmd_host_num_complete) - 1, + "Wrong length"); + zassert_mem_equal(buf->data, &h4_msg_cmd_host_num_complete[1], + sizeof(h4_msg_cmd_dummy1) - 2); + net_buf_unref(buf); + } + + /* There is no response to 'HCI Host Number of Completed Packets'. */ + } + + LOG_DBG("All h2c packets received by controller."); +} diff --git a/tests/bluetooth/hci_uart_async/testcase.yaml b/tests/bluetooth/hci_uart_async/testcase.yaml new file mode 100644 index 00000000000..f7f4a6255eb --- /dev/null +++ b/tests/bluetooth/hci_uart_async/testcase.yaml @@ -0,0 +1,6 @@ +tests: + samples.bluetooth.hci_uart_async: + tags: bluetooth uart + harness: ztest + platform_allow: + - native_posix From 064421793433e85e7df854343f88d725673d3e14 Mon Sep 17 00:00:00 2001 From: Bjarki Arge Andreasen Date: Thu, 28 Sep 2023 15:54:47 +0200 Subject: [PATCH 343/421] [nrf fromtree] tests: build_all: modem: Patch dependencies preventing build Some dependencies where missing from the build_all test for the modem_cellular.c driver. These have been added. Signed-off-by: Bjarki Arge Andreasen (cherry picked from commit 7fb10c82cc90aab470fc6c2b502d8ffa20962302) --- tests/drivers/build_all/modem/modem_cellular.conf | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/drivers/build_all/modem/modem_cellular.conf b/tests/drivers/build_all/modem/modem_cellular.conf index e541af07e2d..3366fcf32d4 100644 --- a/tests/drivers/build_all/modem/modem_cellular.conf +++ b/tests/drivers/build_all/modem/modem_cellular.conf @@ -1,7 +1,10 @@ CONFIG_TEST=y CONFIG_TEST_RANDOM_GENERATOR=y CONFIG_SERIAL=y -CONFIG_UART_INTERRUPT_DRIVEN=y CONFIG_NETWORKING=y CONFIG_NET_L2_PPP=y CONFIG_MODEM=y +CONFIG_PM_DEVICE=y +CONFIG_MODEM_CELLULAR=y +CONFIG_UART_ASYNC_API=y +CONFIG_GPIO=y From 757f63ca7660671b008071e7e4eb504660b7c95d Mon Sep 17 00:00:00 2001 From: Bjarki Arge Andreasen Date: Thu, 28 Sep 2023 17:30:24 +0200 Subject: [PATCH 344/421] [nrf fromtree] drivers: serial: serial_test: Patch irq_isr set to undefined This commit fixes an error where the irq_isr callback is set to an undefined variable instead of NULL. Signed-off-by: Bjarki Arge Andreasen (cherry picked from commit ebd6681589711d1cc759ca3a90f5c54006a83b4d) --- drivers/serial/serial_test.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/serial/serial_test.c b/drivers/serial/serial_test.c index 2ce4fb50f38..f18421b00e5 100644 --- a/drivers/serial/serial_test.c +++ b/drivers/serial/serial_test.c @@ -318,7 +318,7 @@ static int serial_vnd_callback_set(const struct device *dev, uart_callback_t cal } #if defined(CONFIG_UART_EXCLUSIVE_API_CALLBACKS) && defined(CONFIG_UART_INTERRUPT_DRIVEN) - data->irq_isr = cb; + data->irq_isr = NULL; #endif if (callback == NULL && data->read_buf) { From 4748e5ed0abaa6e6d9c9e489e16608a9ae2216bf Mon Sep 17 00:00:00 2001 From: Bjarki Arge Andreasen Date: Thu, 28 Sep 2023 15:57:49 +0200 Subject: [PATCH 345/421] [nrf fromtree] drivers: serial: serial_test: Move ring buf dep to Kconfig This commit moves the dependency management between the RING_BUFFER and UART_ASYNC_API or UART_INTERRUPT_DRIVEN options to the Kconfig Kconfig.test. If either UART API options listed are selected, the RING_BUFFER option must be selected. This is now handled automatically by Kconfig instead of causing a build assert. The asserts where added with this PR #59880, and are removed in this commit. Signed-off-by: Bjarki Arge Andreasen (cherry picked from commit d118d19293658eb64ca2a9a36a2d3c2bd36d0065) --- drivers/serial/Kconfig.test | 1 + drivers/serial/serial_test.c | 3 --- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/serial/Kconfig.test b/drivers/serial/Kconfig.test index 5e7353ba65a..e7f38edc591 100644 --- a/drivers/serial/Kconfig.test +++ b/drivers/serial/Kconfig.test @@ -8,3 +8,4 @@ config SERIAL_TEST select SERIAL_HAS_DRIVER select SERIAL_SUPPORT_INTERRUPT select SERIAL_SUPPORT_ASYNC + select RING_BUFFER if (UART_INTERRUPT_DRIVEN || UART_ASYNC_API) diff --git a/drivers/serial/serial_test.c b/drivers/serial/serial_test.c index f18421b00e5..b1661cdfeef 100644 --- a/drivers/serial/serial_test.c +++ b/drivers/serial/serial_test.c @@ -21,9 +21,6 @@ LOG_MODULE_REGISTER(mock_serial, CONFIG_LOG_DEFAULT_LEVEL); -BUILD_ASSERT(!IS_ENABLED(CONFIG_UART_INTERRUPT_DRIVEN) || IS_ENABLED(CONFIG_RING_BUFFER)); -BUILD_ASSERT(!IS_ENABLED(CONFIG_UART_ASYNC_API) || IS_ENABLED(CONFIG_RING_BUFFER)); - #define DT_DRV_COMPAT vnd_serial struct serial_vnd_data { #ifdef CONFIG_RING_BUFFER From 2370c3921324b0f0a5b85979e4fdb13f5fb03f8a Mon Sep 17 00:00:00 2001 From: Bjarki Arge Andreasen Date: Thu, 28 Sep 2023 18:32:20 +0200 Subject: [PATCH 346/421] [nrf fromtree] tests: drivers: modem: Specify targets for cellular Many boards do not build properly if UART_ASYNC_API is enabled, which is causing an overly large list of targets to exclude for the build_all.modem.modem_cellular.build test suite. This commit instead specifies 4 emulated boards, two of 32-bit, two of 64-bit instead. Signed-off-by: Bjarki Arge Andreasen (cherry picked from commit b054d162f24f72c77ef14c6b52c6d40cceda801e) --- tests/drivers/build_all/modem/testcase.yaml | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/tests/drivers/build_all/modem/testcase.yaml b/tests/drivers/build_all/modem/testcase.yaml index 3614cb09655..8b42363b4ff 100644 --- a/tests/drivers/build_all/modem/testcase.yaml +++ b/tests/drivers/build_all/modem/testcase.yaml @@ -74,10 +74,9 @@ tests: - CONFIG_MODEM_IFACE_UART_ASYNC=y drivers.modem.modem_cellular.build: extra_args: CONF_FILE=modem_cellular.conf - platform_exclude: - - serpente - - particle_boron - - rak5010_nrf52840 - - litex_vexriscv - - ip_k66f + platform_allow: + - native_posix_64 + - native_posix + - qemu_x86 + - qemu_x86_64 min_ram: 36 From f1ee732cab5ebaa83ddf94f0d4c6f734d2684ea7 Mon Sep 17 00:00:00 2001 From: Bjarki Arge Andreasen Date: Thu, 28 Sep 2023 18:37:15 +0200 Subject: [PATCH 347/421] [nrf fromtree] drivers: serial: serial_test.c: Patch 64-bit incompat The serial_test.c driver uses size_t to store read_size, which becomes a 64-bit type when built for 64-bit architectures. This is incompatible with the print format %d which is 32-bit. Updated to %zd Signed-off-by: Bjarki Arge Andreasen (cherry picked from commit cc219c0132e31583ead7184c32d1af0283fb4637) --- drivers/serial/serial_test.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/serial/serial_test.c b/drivers/serial/serial_test.c index b1661cdfeef..b1bb46228be 100644 --- a/drivers/serial/serial_test.c +++ b/drivers/serial/serial_test.c @@ -404,7 +404,7 @@ static int serial_vnd_rx_enable(const struct device *dev, uint8_t *read_buf, siz { struct serial_vnd_data *data = dev->data; - LOG_WRN("read_size %d", read_size); + LOG_WRN("read_size %zd", read_size); if (data == NULL) { return -ENOTSUP; From be6be9bfb8076f29fc4f2be3a98074c8724e0c5f Mon Sep 17 00:00:00 2001 From: Joakim Andersson Date: Fri, 27 Oct 2023 10:29:16 +0200 Subject: [PATCH 348/421] Revert "[nrf noup] boards: thingy53_nrf5340: Enable MCUboot by default" This reverts commit 542ff4901b820fd0d8fc1e6264059962ebbf96bf. This revert is only done to be able to revert another patch without conflict. This commit will be re-applied. Signed-off-by: Joakim Andersson --- boards/arm/thingy53_nrf5340/Kconfig.defconfig | 6 ------ boards/arm/thingy53_nrf5340/thingy53_nrf5340_common.dtsi | 1 - 2 files changed, 7 deletions(-) diff --git a/boards/arm/thingy53_nrf5340/Kconfig.defconfig b/boards/arm/thingy53_nrf5340/Kconfig.defconfig index ec17fcff34a..3af93918add 100644 --- a/boards/arm/thingy53_nrf5340/Kconfig.defconfig +++ b/boards/arm/thingy53_nrf5340/Kconfig.defconfig @@ -8,12 +8,6 @@ if BOARD_THINGY53_NRF5340_CPUAPP || BOARD_THINGY53_NRF5340_CPUAPP_NS config BOARD default "thingy53_nrf5340_cpuapp" -config BOOTLOADER_MCUBOOT - default y if !MCUBOOT - -config BOARD_ENABLE_CPUNET - default y if !MCUBOOT - # By default, if we build for a Non-Secure version of the board, # enable building with TF-M as the Secure Execution Environment. config BUILD_WITH_TFM diff --git a/boards/arm/thingy53_nrf5340/thingy53_nrf5340_common.dtsi b/boards/arm/thingy53_nrf5340/thingy53_nrf5340_common.dtsi index 515fc3bea7b..341bb1305e1 100644 --- a/boards/arm/thingy53_nrf5340/thingy53_nrf5340_common.dtsi +++ b/boards/arm/thingy53_nrf5340/thingy53_nrf5340_common.dtsi @@ -16,7 +16,6 @@ zephyr,bt-hci-rpmsg-ipc = &ipc0; nordic,802154-spinel-ipc = &ipc0; zephyr,ieee802154 = &ieee802154; - nordic,pm-ext-flash = &mx25r64; }; buttons { From ed2c94088c71c21e7606bc9cc3c1648c7c004dd0 Mon Sep 17 00:00:00 2001 From: Joakim Andersson Date: Fri, 27 Oct 2023 10:31:59 +0200 Subject: [PATCH 349/421] Revert "[nrf noup] boards: Enable TF-M by default for nordic SoC NS boards" This reverts commit aa00769d7243809601ea7480a6f7c0cc72ebe82d. Signed-off-by: Joakim Andersson --- boards/arm/actinius_icarus/Kconfig.defconfig | 15 --------------- boards/arm/actinius_icarus_bee/Kconfig.defconfig | 15 --------------- boards/arm/actinius_icarus_som/Kconfig.defconfig | 15 --------------- .../circuitdojo_feather_nrf9160/Kconfig.defconfig | 15 --------------- .../sparkfun_thing_plus_nrf9160/Kconfig.defconfig | 15 --------------- boards/arm/thingy53_nrf5340/Kconfig.defconfig | 15 --------------- 6 files changed, 90 deletions(-) diff --git a/boards/arm/actinius_icarus/Kconfig.defconfig b/boards/arm/actinius_icarus/Kconfig.defconfig index 3b8093275da..6994aac280d 100644 --- a/boards/arm/actinius_icarus/Kconfig.defconfig +++ b/boards/arm/actinius_icarus/Kconfig.defconfig @@ -8,21 +8,6 @@ if BOARD_ACTINIUS_ICARUS || BOARD_ACTINIUS_ICARUS_NS config BOARD default "actinius_icarus" -# By default, if we build for a Non-Secure version of the board, -# enable building with TF-M as the Secure Execution Environment. -config BUILD_WITH_TFM - default y if BOARD_ACTINIUS_ICARUS_NS - -if BUILD_WITH_TFM - -# By default, if we build with TF-M, instruct build system to -# flash the combined TF-M (Secure) & Zephyr (Non Secure) image -config TFM_FLASH_MERGED_BINARY - bool - default y - -endif # BUILD_WITH_TFM - source "boards/common/actinius/Kconfig" # For the secure version of the board the firmware is linked at the beginning diff --git a/boards/arm/actinius_icarus_bee/Kconfig.defconfig b/boards/arm/actinius_icarus_bee/Kconfig.defconfig index 7b733d910d9..309a45a61d4 100644 --- a/boards/arm/actinius_icarus_bee/Kconfig.defconfig +++ b/boards/arm/actinius_icarus_bee/Kconfig.defconfig @@ -8,21 +8,6 @@ if BOARD_ACTINIUS_ICARUS_BEE || BOARD_ACTINIUS_ICARUS_BEE_NS config BOARD default "actinius_icarus_bee" -# By default, if we build for a Non-Secure version of the board, -# enable building with TF-M as the Secure Execution Environment. -config BUILD_WITH_TFM - default y if BOARD_ACTINIUS_ICARUS_BEE_NS - -if BUILD_WITH_TFM - -# By default, if we build with TF-M, instruct build system to -# flash the combined TF-M (Secure) & Zephyr (Non Secure) image -config TFM_FLASH_MERGED_BINARY - bool - default y - -endif # BUILD_WITH_TFM - source "boards/common/actinius/Kconfig" # For the secure version of the board the firmware is linked at the beginning diff --git a/boards/arm/actinius_icarus_som/Kconfig.defconfig b/boards/arm/actinius_icarus_som/Kconfig.defconfig index cc92427d24c..473acfea29f 100644 --- a/boards/arm/actinius_icarus_som/Kconfig.defconfig +++ b/boards/arm/actinius_icarus_som/Kconfig.defconfig @@ -8,21 +8,6 @@ if BOARD_ACTINIUS_ICARUS_SOM || BOARD_ACTINIUS_ICARUS_SOM_NS config BOARD default "actinius_icarus_som" -# By default, if we build for a Non-Secure version of the board, -# enable building with TF-M as the Secure Execution Environment. -config BUILD_WITH_TFM - default y if BOARD_ACTINIUS_ICARUS_SOM_NS - -if BUILD_WITH_TFM - -# By default, if we build with TF-M, instruct build system to -# flash the combined TF-M (Secure) & Zephyr (Non Secure) image -config TFM_FLASH_MERGED_BINARY - bool - default y - -endif # BUILD_WITH_TFM - source "boards/common/actinius/Kconfig" # For the secure version of the board the firmware is linked at the beginning diff --git a/boards/arm/circuitdojo_feather_nrf9160/Kconfig.defconfig b/boards/arm/circuitdojo_feather_nrf9160/Kconfig.defconfig index f37bfbf84fb..73648be3ef1 100644 --- a/boards/arm/circuitdojo_feather_nrf9160/Kconfig.defconfig +++ b/boards/arm/circuitdojo_feather_nrf9160/Kconfig.defconfig @@ -9,21 +9,6 @@ if BOARD_CIRCUITDOJO_FEATHER_NRF9160 || BOARD_CIRCUITDOJO_FEATHER_NRF9160_NS config BOARD default "circuitdojo_feather_nrf9160" -# By default, if we build for a Non-Secure version of the board, -# enable building with TF-M as the Secure Execution Environment. -config BUILD_WITH_TFM - default y if BOARD_CIRCUITDOJO_FEATHER_NRF9160_NS - -if BUILD_WITH_TFM - -# By default, if we build with TF-M, instruct build system to -# flash the combined TF-M (Secure) & Zephyr (Non Secure) image -config TFM_FLASH_MERGED_BINARY - bool - default y - -endif # BUILD_WITH_TFM - # For the secure version of the board the firmware is linked at the beginning # of the flash, or into the code-partition defined in DT if it is intended to # be loaded by MCUboot. If the secure firmware is to be combined with a non- diff --git a/boards/arm/sparkfun_thing_plus_nrf9160/Kconfig.defconfig b/boards/arm/sparkfun_thing_plus_nrf9160/Kconfig.defconfig index 3d98b1b4cb4..8ae5b832d89 100644 --- a/boards/arm/sparkfun_thing_plus_nrf9160/Kconfig.defconfig +++ b/boards/arm/sparkfun_thing_plus_nrf9160/Kconfig.defconfig @@ -9,21 +9,6 @@ if BOARD_SPARKFUN_THING_PLUS_NRF9160 || BOARD_SPARKFUN_THING_PLUS_NRF9160_NS config BOARD default "sparkfun_thing_plus_nrf9160" -# By default, if we build for a Non-Secure version of the board, -# enable building with TF-M as the Secure Execution Environment. -config BUILD_WITH_TFM - default y if BOARD_SPARKFUN_THING_PLUS_NRF9160_NS - -if BUILD_WITH_TFM - -# By default, if we build with TF-M, instruct build system to -# flash the combined TF-M (Secure) & Zephyr (Non Secure) image -config TFM_FLASH_MERGED_BINARY - bool - default y - -endif # BUILD_WITH_TFM - # For the secure version of the board the firmware is linked at the beginning # of the flash, or into the code-partition defined in DT if it is intended to # be loaded by MCUboot. If the secure firmware is to be combined with a non- diff --git a/boards/arm/thingy53_nrf5340/Kconfig.defconfig b/boards/arm/thingy53_nrf5340/Kconfig.defconfig index 3af93918add..6384d163d93 100644 --- a/boards/arm/thingy53_nrf5340/Kconfig.defconfig +++ b/boards/arm/thingy53_nrf5340/Kconfig.defconfig @@ -8,21 +8,6 @@ if BOARD_THINGY53_NRF5340_CPUAPP || BOARD_THINGY53_NRF5340_CPUAPP_NS config BOARD default "thingy53_nrf5340_cpuapp" -# By default, if we build for a Non-Secure version of the board, -# enable building with TF-M as the Secure Execution Environment. -config BUILD_WITH_TFM - default y if BOARD_THINGY53_NRF5340_CPUAPP_NS - -if BUILD_WITH_TFM - -# By default, if we build with TF-M, instruct build system to -# flash the combined TF-M (Secure) & Zephyr (Non Secure) image -config TFM_FLASH_MERGED_BINARY - bool - default y - -endif # BUILD_WITH_TFM - # Code Partition: # # For the secure version of the board the firmware is linked at the beginning From e0fab0305912c36f631b3ad55f4e8ffbf53bb450 Mon Sep 17 00:00:00 2001 From: Joakim Andersson Date: Fri, 29 Sep 2023 09:09:58 +0200 Subject: [PATCH 350/421] [nrf fromtree] boards: nrf5340dk_nrf5340: Add default HW flow control pins to uart1 Add the default HW flow control pins to the uart1 node. Signed-off-by: Joakim Andersson (cherry picked from commit 9ac85254961012dd6f26962c2bc1cade8f2abd8d) Signed-off-by: Joakim Andersson --- .../nrf5340_cpuapp_common-pinctrl.dtsi | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/boards/arm/nrf5340dk_nrf5340/nrf5340_cpuapp_common-pinctrl.dtsi b/boards/arm/nrf5340dk_nrf5340/nrf5340_cpuapp_common-pinctrl.dtsi index 6db9767c0dc..f93e3a69402 100644 --- a/boards/arm/nrf5340dk_nrf5340/nrf5340_cpuapp_common-pinctrl.dtsi +++ b/boards/arm/nrf5340dk_nrf5340/nrf5340_cpuapp_common-pinctrl.dtsi @@ -84,10 +84,12 @@ uart1_default: uart1_default { group1 { - psels = ; + psels = , + ; }; group2 { - psels = ; + psels = , + ; bias-pull-up; }; }; @@ -95,7 +97,9 @@ uart1_sleep: uart1_sleep { group1 { psels = , - ; + , + , + ; low-power-enable; }; }; From cf504c0167559b0ed749e6fee8c07fb153658db9 Mon Sep 17 00:00:00 2001 From: Joakim Andersson Date: Thu, 5 Oct 2023 13:11:13 +0200 Subject: [PATCH 351/421] [nrf fromtree] boards: Add uart1 pinctrl assignment to nrf5340 Audio DK Add uart1 pinctrl assignment to nrf5340 Audio DK. Assigned according to Schematic for this board. Uart1 pins needed by TF-M when using the NS board variant. Signed-off-by: Joakim Andersson (cherry picked from commit 32a1c89e2e1accf24aa4df93d1b4e7e988a3df5c) Signed-off-by: Joakim Andersson --- ...udio_dk_nrf5340_cpuapp_common-pinctrl.dtsi | 22 +++++++++++++++++++ ...rf5340_audio_dk_nrf5340_cpuapp_common.dtsi | 8 +++++++ 2 files changed, 30 insertions(+) diff --git a/boards/arm/nrf5340_audio_dk_nrf5340/nrf5340_audio_dk_nrf5340_cpuapp_common-pinctrl.dtsi b/boards/arm/nrf5340_audio_dk_nrf5340/nrf5340_audio_dk_nrf5340_cpuapp_common-pinctrl.dtsi index 46359082edd..5247c04429b 100644 --- a/boards/arm/nrf5340_audio_dk_nrf5340/nrf5340_audio_dk_nrf5340_cpuapp_common-pinctrl.dtsi +++ b/boards/arm/nrf5340_audio_dk_nrf5340/nrf5340_audio_dk_nrf5340_cpuapp_common-pinctrl.dtsi @@ -51,6 +51,28 @@ }; }; + uart1_default: uart1_default { + group1 { + psels = , + ; + }; + group2 { + psels = , + ; + bias-pull-up; + }; + }; + + uart1_sleep: uart1_sleep { + group1 { + psels = , + , + , + ; + low-power-enable; + }; + }; + i2c1_default: i2c1_default { group1 { psels = , diff --git a/boards/arm/nrf5340_audio_dk_nrf5340/nrf5340_audio_dk_nrf5340_cpuapp_common.dtsi b/boards/arm/nrf5340_audio_dk_nrf5340/nrf5340_audio_dk_nrf5340_cpuapp_common.dtsi index f529f16fbe8..df028fb75a2 100644 --- a/boards/arm/nrf5340_audio_dk_nrf5340/nrf5340_audio_dk_nrf5340_cpuapp_common.dtsi +++ b/boards/arm/nrf5340_audio_dk_nrf5340/nrf5340_audio_dk_nrf5340_cpuapp_common.dtsi @@ -141,6 +141,14 @@ pinctrl-names = "default", "sleep"; }; +arduino_serial: &uart1 { + compatible = "nordic,nrf-uarte"; + current-speed = <115200>; + pinctrl-0 = <&uart1_default>; + pinctrl-1 = <&uart1_sleep>; + pinctrl-names = "default", "sleep"; +}; + &i2c1 { compatible = "nordic,nrf-twim"; status = "okay"; From 9184096bd977feb4c31608ab67a3a47468e748c5 Mon Sep 17 00:00:00 2001 From: Joakim Andersson Date: Tue, 3 Oct 2023 16:59:14 +0200 Subject: [PATCH 352/421] [nrf fromtree] tfm: nordic_nrf: Add generic SoC support for nordic SoCs Add generic SoC support for the supported nordic SoCs: - nrf5340 - nrf9160 - nrf9120 Add generic SoC support by taking board specific configurations from zephyr devicetree and kconfig. Signed-off-by: Joakim Andersson (cherry picked from commit 33a44d0ed8acf805782df8c9a4b47b752ea68e8f) Signed-off-by: Joakim Andersson --- modules/trusted-firmware-m/Kconfig.tfm | 6 +- .../nordic_nrf/CMakeLists.txt | 67 +++++++++++++++++++ .../nordic_nrf/include/RTE_Device.h | 52 ++++++++++++++ .../nordic_nrf/include/device_cfg.h | 32 +++++++++ .../nordic_nrf/include/tfm_ioctl_api.h | 32 +++++++++ .../include/tfm_peripherals_config.h | 40 +++++++++++ .../nordic_nrf/include/tfm_read_ranges.h | 60 +++++++++++++++++ .../nordic_nrf/include/util/array.h | 20 ++++++ .../nordic_nrf/nrf5340_cpuapp/CMakeLists.txt | 12 ++++ .../nordic_nrf/nrf5340_cpuapp/config.cmake | 8 +++ .../nordic_nrf/nrf5340_cpuapp/preload.cmake | 7 ++ .../nordic_nrf/nrf9120/CMakeLists.txt | 12 ++++ .../nordic_nrf/nrf9120/config.cmake | 8 +++ .../nordic_nrf/nrf9120/preload.cmake | 7 ++ .../nordic_nrf/nrf9160/CMakeLists.txt | 12 ++++ .../nordic_nrf/nrf9160/config.cmake | 8 +++ .../nordic_nrf/nrf9160/preload.cmake | 7 ++ .../nordic_nrf/src/tfm_hal_platform.c | 13 ++++ .../nordic_nrf/src/tfm_platform_system.c | 38 +++++++++++ soc/arm/nordic_nrf/CMakeLists.txt | 4 ++ soc/arm/nordic_nrf/Kconfig | 7 ++ 21 files changed, 449 insertions(+), 3 deletions(-) create mode 100644 modules/trusted-firmware-m/nordic_nrf/CMakeLists.txt create mode 100644 modules/trusted-firmware-m/nordic_nrf/include/RTE_Device.h create mode 100644 modules/trusted-firmware-m/nordic_nrf/include/device_cfg.h create mode 100644 modules/trusted-firmware-m/nordic_nrf/include/tfm_ioctl_api.h create mode 100644 modules/trusted-firmware-m/nordic_nrf/include/tfm_peripherals_config.h create mode 100644 modules/trusted-firmware-m/nordic_nrf/include/tfm_read_ranges.h create mode 100644 modules/trusted-firmware-m/nordic_nrf/include/util/array.h create mode 100644 modules/trusted-firmware-m/nordic_nrf/nrf5340_cpuapp/CMakeLists.txt create mode 100644 modules/trusted-firmware-m/nordic_nrf/nrf5340_cpuapp/config.cmake create mode 100644 modules/trusted-firmware-m/nordic_nrf/nrf5340_cpuapp/preload.cmake create mode 100644 modules/trusted-firmware-m/nordic_nrf/nrf9120/CMakeLists.txt create mode 100644 modules/trusted-firmware-m/nordic_nrf/nrf9120/config.cmake create mode 100644 modules/trusted-firmware-m/nordic_nrf/nrf9120/preload.cmake create mode 100644 modules/trusted-firmware-m/nordic_nrf/nrf9160/CMakeLists.txt create mode 100644 modules/trusted-firmware-m/nordic_nrf/nrf9160/config.cmake create mode 100644 modules/trusted-firmware-m/nordic_nrf/nrf9160/preload.cmake create mode 100644 modules/trusted-firmware-m/nordic_nrf/src/tfm_hal_platform.c create mode 100644 modules/trusted-firmware-m/nordic_nrf/src/tfm_platform_system.c diff --git a/modules/trusted-firmware-m/Kconfig.tfm b/modules/trusted-firmware-m/Kconfig.tfm index a7276d79374..7fd1b348a74 100644 --- a/modules/trusted-firmware-m/Kconfig.tfm +++ b/modules/trusted-firmware-m/Kconfig.tfm @@ -9,9 +9,6 @@ config ZEPHYR_TRUSTED_FIRMWARE_M_MODULE config TFM_BOARD string - default "nordic_nrf/nrf9160dk_nrf9160" if BOARD_NRF9160DK_NRF9160_NS - default "nordic_nrf/nrf9161dk_nrf9161" if BOARD_NRF9161DK_NRF9161_NS - default "nordic_nrf/nrf5340dk_nrf5340_cpuapp" if BOARD_NRF5340DK_NRF5340_CPUAPP_NS default "nxp/lpcxpresso55s69" if BOARD_LPCXPRESSO55S69_CPU0 default "arm/mps2/an521" if BOARD_MPS2_AN521_CPU0_NS default "arm/mps3/an547" if BOARD_MPS3_AN547 @@ -21,6 +18,9 @@ config TFM_BOARD default "arm/musca_b1" if BOARD_MUSCA_B1 default "arm/musca_s1" if BOARD_MUSCA_S1 default "lairdconnectivity/bl5340_dvk_cpuapp" if BOARD_BL5340_DVK_CPUAPP_NS + default "${ZEPHYR_BASE}/modules/trusted-firmware-m/nordic_nrf/nrf9160" if SOC_NRF9160 + default "${ZEPHYR_BASE}/modules/trusted-firmware-m/nordic_nrf/nrf9120" if SOC_NRF9120 + default "${ZEPHYR_BASE}/modules/trusted-firmware-m/nordic_nrf/nrf5340_cpuapp" if SOC_NRF5340_CPUAPP help The board name used for building TFM. Building with TFM requires that TFM has been ported to the given board/SoC. diff --git a/modules/trusted-firmware-m/nordic_nrf/CMakeLists.txt b/modules/trusted-firmware-m/nordic_nrf/CMakeLists.txt new file mode 100644 index 00000000000..41dca2f15a9 --- /dev/null +++ b/modules/trusted-firmware-m/nordic_nrf/CMakeLists.txt @@ -0,0 +1,67 @@ +# +# Copyright (c) 2023, Nordic Semiconductor ASA. +# +# SPDX-License-Identifier: Apache-2.0 +# + +cmake_policy(SET CMP0076 NEW) +set(CMAKE_CURRENT_SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR}) + +set(partition_includes + ${Trusted\ Firmware\ M_SOURCE_DIR}/platform/ext/target/nordic_nrf/common/${NRF_SOC_VARIANT}/partition + ${CMAKE_BINARY_DIR}/../zephyr/include/generated +) + +set(board_includes + ${CMAKE_BINARY_DIR}/../zephyr/misc/generated/syscalls_links/include + ${ZEPHYR_BASE}/include +) + +target_include_directories(platform_region_defs + INTERFACE + ${partition_includes} +) + + +target_sources(platform_s + PRIVATE + $<$:${CMAKE_CURRENT_SOURCE_DIR}/src/tfm_platform_system.c> +) + +target_include_directories(platform_s + PUBLIC + services/include + include + ${partition_includes} + ${board_includes} +) + +target_include_directories(platform_ns + PUBLIC + include + include/util + ${partition_includes} + ${board_includes} +) + +if(BL2) + target_include_directories(platform_bl2 + PUBLIC + include + include/util + ${partition_includes} + ${board_includes} + ) +endif() + +if (TFM_PARTITION_PLATFORM) +install(FILES include/tfm_ioctl_api.h + DESTINATION ${TFM_INSTALL_PATH}/interface/include) +endif() + +#========================= tfm_spm ============================================# + +target_sources(tfm_spm + PRIVATE + src/tfm_hal_platform.c +) diff --git a/modules/trusted-firmware-m/nordic_nrf/include/RTE_Device.h b/modules/trusted-firmware-m/nordic_nrf/include/RTE_Device.h new file mode 100644 index 00000000000..ca886583fa9 --- /dev/null +++ b/modules/trusted-firmware-m/nordic_nrf/include/RTE_Device.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef __RTE_DEVICE_H +#define __RTE_DEVICE_H + +#include + +/* ARRAY_SIZE causes a conflict as it is defined both by TF-M and indirectly by devicetree.h */ +#undef ARRAY_SIZE +#include + +#define UART_PIN_INIT(node_id, prop, idx) \ + DT_PROP_BY_IDX(node_id, prop, idx), + +/* Configuration settings for Driver_USART0. */ +#if DOMAIN_NS == 1U + +#define RTE_USART0 1 + +#define RTE_USART0_PINS \ +{ \ + DT_FOREACH_CHILD_VARGS( \ + DT_PINCTRL_BY_NAME(DT_NODELABEL(uart0), default, 0), \ + DT_FOREACH_PROP_ELEM, psels, UART_PIN_INIT \ + ) \ +} + +#endif + +/* Configuration settings for Driver_USART1. */ +#if DT_PINCTRL_HAS_NAME(DT_NODELABEL(uart1), default) && DOMAIN_NS != 1U + +#define RTE_USART1 1 + +#define RTE_USART1_PINS \ +{ \ + DT_FOREACH_CHILD_VARGS( \ + DT_PINCTRL_BY_NAME(DT_NODELABEL(uart1), default, 0), \ + DT_FOREACH_PROP_ELEM, psels, UART_PIN_INIT \ + ) \ +} + +#endif + +/* Configuration settings for Driver_FLASH0. */ +#define RTE_FLASH0 1 + +#endif /* __RTE_DEVICE_H */ diff --git a/modules/trusted-firmware-m/nordic_nrf/include/device_cfg.h b/modules/trusted-firmware-m/nordic_nrf/include/device_cfg.h new file mode 100644 index 00000000000..9b766a35eb9 --- /dev/null +++ b/modules/trusted-firmware-m/nordic_nrf/include/device_cfg.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef DEVICE_CFG_H__ +#define DEVICE_CFG_H__ + +#include + +/* ARRAY_SIZE causes a conflict as it is defined both by TF-M and indirectly by devicetree.h */ +#undef ARRAY_SIZE +#include + +#if DOMAIN_NS == 1U +#define TFM_UART uart0 +#endif + +#if DOMAIN_NS != 1U +#define TFM_UART uart1 +#endif + +#define DEFAULT_UART_BAUDRATE DT_PROP_OR(DT_NODELABEL(TFM_UART), current_speed, 115200) + +#if DT_PROP(DT_NODELABEL(TFM_UART), hw_flow_control) +#define DEFAULT_UART_CONTROL ARM_USART_FLOW_CONTROL_RTS_CTS +#else +#define DEFAULT_UART_CONTROL 0 +#endif + +#endif /* DEVICE_CFG_H__ */ diff --git a/modules/trusted-firmware-m/nordic_nrf/include/tfm_ioctl_api.h b/modules/trusted-firmware-m/nordic_nrf/include/tfm_ioctl_api.h new file mode 100644 index 00000000000..c6c36ee927f --- /dev/null +++ b/modules/trusted-firmware-m/nordic_nrf/include/tfm_ioctl_api.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef TFM_IOCTL_API_H__ +#define TFM_IOCTL_API_H__ + +#include +#include +#include +#include + +/* Include core IOCTL services */ +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Board specific IOCTL services can be added here */ + +#ifdef __cplusplus +} +#endif + +/** + * @} + */ + +#endif /* TFM_IOCTL_API_H__ */ diff --git a/modules/trusted-firmware-m/nordic_nrf/include/tfm_peripherals_config.h b/modules/trusted-firmware-m/nordic_nrf/include/tfm_peripherals_config.h new file mode 100644 index 00000000000..577b583ad03 --- /dev/null +++ b/modules/trusted-firmware-m/nordic_nrf/include/tfm_peripherals_config.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef TFM_PERIPHERALS_CONFIG_H__ +#define TFM_PERIPHERALS_CONFIG_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef SECURE_UART1 +#define TFM_PERIPHERAL_UARTE1_SECURE 1 +#endif + +#if TEST_NS_SLIH_IRQ || TEST_NS_FLIH_IRQ +#define TFM_PERIPHERAL_TIMER0_SECURE 1 +#endif + +#ifdef PSA_API_TEST_IPC +#define TFM_PERIPHERAL_EGU5_SECURE 1 + +#define TFM_PERIPHERAL_WDT_SECURE 1 +#endif + +#if defined(NRF91_SERIES) + #include +#elif defined(NRF5340_XXAA_APPLICATION) + #include +#else + #error "Unknown device." +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* TFM_PERIPHERAL_CONFIG_H__ */ diff --git a/modules/trusted-firmware-m/nordic_nrf/include/tfm_read_ranges.h b/modules/trusted-firmware-m/nordic_nrf/include/tfm_read_ranges.h new file mode 100644 index 00000000000..43468c7fa31 --- /dev/null +++ b/modules/trusted-firmware-m/nordic_nrf/include/tfm_read_ranges.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef TFM_READ_RANGES_H__ +#define TFM_READ_RANGES_H__ + +#include + +#include + +#ifdef NRF_FICR_S_BASE + +#define FICR_BASE NRF_FICR_S_BASE + +#define FICR_INFO_ADDR (FICR_BASE + offsetof(NRF_FICR_Type, INFO)) +#define FICR_INFO_SIZE (sizeof(FICR_INFO_Type)) + +#if defined(FICR_NFC_TAGHEADER0_MFGID_Msk) +#define FICR_NFC_ADDR (FICR_BASE + offsetof(NRF_FICR_Type, NFC)) +#define FICR_NFC_SIZE (sizeof(FICR_NFC_Type)) +#endif + +#if defined(FICR_XOSC32MTRIM_SLOPE_Msk) +#define FICR_XOSC32MTRIM_ADDR (FICR_BASE + offsetof(NRF_FICR_Type, XOSC32MTRIM)) +#define FICR_XOSC32MTRIM_SIZE (sizeof(uint32_t)) +#endif + +/* Used by nrf_erratas.h */ +#define FICR_RESTRICTED_ADDR (FICR_BASE + 0x130) +#define FICR_RESTRICTED_SIZE 0x8 + +#if defined(FICR_SIPINFO_PARTNO_PARTNO_Pos) +#define FICR_SIPINFO_ADDR (FICR_BASE + offsetof(NRF_FICR_Type, SIPINFO)) +#define FICR_SIPINFO_SIZE (sizeof(FICR_SIPINFO_Type)) +#endif + +#endif /* NRF_FICR_S_BASE */ + +static const struct tfm_read_service_range ranges[] = { +#if defined(FICR_INFO_ADDR) + { .start = FICR_INFO_ADDR, .size = FICR_INFO_SIZE }, +#endif +#if defined(FICR_NFC_ADDR) + { .start = FICR_NFC_ADDR, .size = FICR_NFC_SIZE }, +#endif +#if defined(FICR_RESTRICTED_ADDR) + { .start = FICR_RESTRICTED_ADDR, .size = FICR_RESTRICTED_SIZE }, +#endif +#if defined(FICR_XOSC32MTRIM_ADDR) + { .start = FICR_XOSC32MTRIM_ADDR, .size = FICR_XOSC32MTRIM_SIZE }, +#endif +#if defined(FICR_SIPINFO_ADDR) + { .start = FICR_SIPINFO_ADDR, .size = FICR_SIPINFO_SIZE }, +#endif +}; + +#endif /* TFM_READ_RANGES_H__ */ diff --git a/modules/trusted-firmware-m/nordic_nrf/include/util/array.h b/modules/trusted-firmware-m/nordic_nrf/include/util/array.h new file mode 100644 index 00000000000..dc9a1f3dddf --- /dev/null +++ b/modules/trusted-firmware-m/nordic_nrf/include/util/array.h @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef __ARRAY_H__ +#define __ARRAY_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#ifdef __cplusplus +} +#endif + +#endif /* __ARRAY_H__ */ diff --git a/modules/trusted-firmware-m/nordic_nrf/nrf5340_cpuapp/CMakeLists.txt b/modules/trusted-firmware-m/nordic_nrf/nrf5340_cpuapp/CMakeLists.txt new file mode 100644 index 00000000000..279ea385996 --- /dev/null +++ b/modules/trusted-firmware-m/nordic_nrf/nrf5340_cpuapp/CMakeLists.txt @@ -0,0 +1,12 @@ +# +# Copyright (c) 2023, Nordic Semiconductor ASA. +# +# SPDX-License-Identifier: Apache-2.0 +# + +set(NRF_BOARD_SELECTED True) +set(NRF_SOC_VARIANT nrf5340) + +add_subdirectory(${Trusted\ Firmware\ M_SOURCE_DIR}/platform/ext/target/nordic_nrf/common/nrf5340 nrf5340) + +add_subdirectory(.. common) diff --git a/modules/trusted-firmware-m/nordic_nrf/nrf5340_cpuapp/config.cmake b/modules/trusted-firmware-m/nordic_nrf/nrf5340_cpuapp/config.cmake new file mode 100644 index 00000000000..b3e5d74181c --- /dev/null +++ b/modules/trusted-firmware-m/nordic_nrf/nrf5340_cpuapp/config.cmake @@ -0,0 +1,8 @@ +# +# Copyright (c) 2023, Nordic Semiconductor ASA. +# +# SPDX-License-Identifier: Apache-2.0 +# + +set(PLATFORM_PATH platform/ext/target/nordic_nrf/) +include(${PLATFORM_PATH}/common/nrf5340/config.cmake) diff --git a/modules/trusted-firmware-m/nordic_nrf/nrf5340_cpuapp/preload.cmake b/modules/trusted-firmware-m/nordic_nrf/nrf5340_cpuapp/preload.cmake new file mode 100644 index 00000000000..d9bd226eb65 --- /dev/null +++ b/modules/trusted-firmware-m/nordic_nrf/nrf5340_cpuapp/preload.cmake @@ -0,0 +1,7 @@ +# +# Copyright (c) 2023, Nordic Semiconductor ASA. +# +# SPDX-License-Identifier: Apache-2.0 +# + +include(platform/ext/target/nordic_nrf/common/nrf5340/preload.cmake) diff --git a/modules/trusted-firmware-m/nordic_nrf/nrf9120/CMakeLists.txt b/modules/trusted-firmware-m/nordic_nrf/nrf9120/CMakeLists.txt new file mode 100644 index 00000000000..a84c6fd9fd5 --- /dev/null +++ b/modules/trusted-firmware-m/nordic_nrf/nrf9120/CMakeLists.txt @@ -0,0 +1,12 @@ +# +# Copyright (c) 2023, Nordic Semiconductor ASA. +# +# SPDX-License-Identifier: Apache-2.0 +# + +set(NRF_BOARD_SELECTED True) +set(NRF_SOC_VARIANT nrf91) + +add_subdirectory(${Trusted\ Firmware\ M_SOURCE_DIR}/platform/ext/target/nordic_nrf/common/nrf91 nrf91) + +add_subdirectory(.. common) diff --git a/modules/trusted-firmware-m/nordic_nrf/nrf9120/config.cmake b/modules/trusted-firmware-m/nordic_nrf/nrf9120/config.cmake new file mode 100644 index 00000000000..3f58e7b89eb --- /dev/null +++ b/modules/trusted-firmware-m/nordic_nrf/nrf9120/config.cmake @@ -0,0 +1,8 @@ +# +# Copyright (c) 2023, Nordic Semiconductor ASA. +# +# SPDX-License-Identifier: Apache-2.0 +# + +set(PLATFORM_PATH platform/ext/target/nordic_nrf/) +include(${PLATFORM_PATH}/common/nrf91/config.cmake) diff --git a/modules/trusted-firmware-m/nordic_nrf/nrf9120/preload.cmake b/modules/trusted-firmware-m/nordic_nrf/nrf9120/preload.cmake new file mode 100644 index 00000000000..4b3c6ee79ab --- /dev/null +++ b/modules/trusted-firmware-m/nordic_nrf/nrf9120/preload.cmake @@ -0,0 +1,7 @@ +# +# Copyright (c) 2023, Nordic Semiconductor ASA. +# +# SPDX-License-Identifier: Apache-2.0 +# + +include(platform/ext/target/nordic_nrf/common/nrf9120/preload.cmake) diff --git a/modules/trusted-firmware-m/nordic_nrf/nrf9160/CMakeLists.txt b/modules/trusted-firmware-m/nordic_nrf/nrf9160/CMakeLists.txt new file mode 100644 index 00000000000..a84c6fd9fd5 --- /dev/null +++ b/modules/trusted-firmware-m/nordic_nrf/nrf9160/CMakeLists.txt @@ -0,0 +1,12 @@ +# +# Copyright (c) 2023, Nordic Semiconductor ASA. +# +# SPDX-License-Identifier: Apache-2.0 +# + +set(NRF_BOARD_SELECTED True) +set(NRF_SOC_VARIANT nrf91) + +add_subdirectory(${Trusted\ Firmware\ M_SOURCE_DIR}/platform/ext/target/nordic_nrf/common/nrf91 nrf91) + +add_subdirectory(.. common) diff --git a/modules/trusted-firmware-m/nordic_nrf/nrf9160/config.cmake b/modules/trusted-firmware-m/nordic_nrf/nrf9160/config.cmake new file mode 100644 index 00000000000..3f58e7b89eb --- /dev/null +++ b/modules/trusted-firmware-m/nordic_nrf/nrf9160/config.cmake @@ -0,0 +1,8 @@ +# +# Copyright (c) 2023, Nordic Semiconductor ASA. +# +# SPDX-License-Identifier: Apache-2.0 +# + +set(PLATFORM_PATH platform/ext/target/nordic_nrf/) +include(${PLATFORM_PATH}/common/nrf91/config.cmake) diff --git a/modules/trusted-firmware-m/nordic_nrf/nrf9160/preload.cmake b/modules/trusted-firmware-m/nordic_nrf/nrf9160/preload.cmake new file mode 100644 index 00000000000..364480a6f7f --- /dev/null +++ b/modules/trusted-firmware-m/nordic_nrf/nrf9160/preload.cmake @@ -0,0 +1,7 @@ +# +# Copyright (c) 2023, Nordic Semiconductor ASA. +# +# SPDX-License-Identifier: Apache-2.0 +# + +include(platform/ext/target/nordic_nrf/common/nrf9160/preload.cmake) diff --git a/modules/trusted-firmware-m/nordic_nrf/src/tfm_hal_platform.c b/modules/trusted-firmware-m/nordic_nrf/src/tfm_hal_platform.c new file mode 100644 index 00000000000..508c1945910 --- /dev/null +++ b/modules/trusted-firmware-m/nordic_nrf/src/tfm_hal_platform.c @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "tfm_hal_defs.h" +#include "tfm_hal_platform_common.h" + +enum tfm_hal_status_t tfm_hal_platform_init(void) +{ + return tfm_hal_platform_common_init(); +} diff --git a/modules/trusted-firmware-m/nordic_nrf/src/tfm_platform_system.c b/modules/trusted-firmware-m/nordic_nrf/src/tfm_platform_system.c new file mode 100644 index 00000000000..b96e1fe1188 --- /dev/null +++ b/modules/trusted-firmware-m/nordic_nrf/src/tfm_platform_system.c @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "platform/include/tfm_platform_system.h" +#include "cmsis.h" +#include "tfm_platform_hal_ioctl.h" +#include "tfm_ioctl_core_api.h" + +void tfm_platform_hal_system_reset(void) +{ + /* Reset the system */ + NVIC_SystemReset(); +} + +enum tfm_platform_err_t tfm_platform_hal_ioctl(tfm_platform_ioctl_req_t request, + psa_invec *in_vec, + psa_outvec *out_vec) +{ + /* Core IOCTL services */ + switch (request) { + case TFM_PLATFORM_IOCTL_READ_SERVICE: + return tfm_platform_hal_read_service(in_vec, out_vec); +#if defined(GPIO_PIN_CNF_MCUSEL_Msk) + case TFM_PLATFORM_IOCTL_GPIO_SERVICE: + return tfm_platform_hal_gpio_service(in_vec, out_vec); +#endif /* defined(GPIO_PIN_CNF_MCUSEL_Msk) */ + + + /* Board specific IOCTL services */ + + /* Not a supported IOCTL service.*/ + default: + return TFM_PLATFORM_ERR_NOT_SUPPORTED; + } +} diff --git a/soc/arm/nordic_nrf/CMakeLists.txt b/soc/arm/nordic_nrf/CMakeLists.txt index 4cfc162f7fd..47364b35ffb 100644 --- a/soc/arm/nordic_nrf/CMakeLists.txt +++ b/soc/arm/nordic_nrf/CMakeLists.txt @@ -21,4 +21,8 @@ if(CONFIG_BUILD_WITH_TFM) set_property(TARGET zephyr_property_target APPEND PROPERTY TFM_CMAKE_OPTIONS -DHAL_NORDIC_PATH=${ZEPHYR_HAL_NORDIC_MODULE_DIR} ) + + set_property(TARGET zephyr_property_target + APPEND PROPERTY TFM_CMAKE_OPTIONS -DZEPHYR_BASE=${ZEPHYR_BASE} + ) endif() diff --git a/soc/arm/nordic_nrf/Kconfig b/soc/arm/nordic_nrf/Kconfig index c2129db64b3..0e3b3e4ee6d 100644 --- a/soc/arm/nordic_nrf/Kconfig +++ b/soc/arm/nordic_nrf/Kconfig @@ -25,6 +25,13 @@ config NRF_SOC_SECURE_SUPPORTED For non-secure the functions must redirect to secure services exposed by the secure firmware. +config TFM_LOG_LEVEL_SILENCE + default y if !$(dt_nodelabel_has_prop,uart1,pinctrl-names) + depends on BUILD_WITH_TFM + help + Disable TF-M secure output if the uart1 node has not assigned GPIO + pins using pinctrl. + config NRF_MPU_FLASH_REGION_SIZE hex default 0x1000 From 4a3c39feef9ad6dcbb8fbe787f4aef5cc57fdbb3 Mon Sep 17 00:00:00 2001 From: Joakim Andersson Date: Thu, 5 May 2022 12:04:26 +0200 Subject: [PATCH 353/421] [nrf fromtree] boards: Enable TF-M by default for nordic SoC NS boards Enable TF-M by default for nordic nRF5340 and nrf9160 SoC boards. Signed-off-by: Joakim Andersson (cherry picked from commit 17fd1f8fba3bd862c53ca98f618ac574efef58dd) Signed-off-by: Joakim Andersson --- boards/arm/bl5340_dvk/Kconfig.defconfig | 15 --------------- boards/arm/nrf5340dk_nrf5340/Kconfig.defconfig | 15 --------------- boards/arm/nrf9160dk_nrf9160/Kconfig.defconfig | 15 --------------- boards/arm/nrf9161dk_nrf9161/Kconfig.defconfig | 15 --------------- soc/arm/nordic_nrf/Kconfig | 18 +++++++++++++++++- 5 files changed, 17 insertions(+), 61 deletions(-) diff --git a/boards/arm/bl5340_dvk/Kconfig.defconfig b/boards/arm/bl5340_dvk/Kconfig.defconfig index 38a06c8b91d..e033f718dba 100644 --- a/boards/arm/bl5340_dvk/Kconfig.defconfig +++ b/boards/arm/bl5340_dvk/Kconfig.defconfig @@ -13,21 +13,6 @@ config BOARD config I2C default GPIO || DAC -# By default, if we build for a Non-Secure version of the board, -# enable building with TF-M as the Secure Execution Environment. -config BUILD_WITH_TFM - default y if BOARD_BL5340_DVK_CPUAPP_NS - -if BUILD_WITH_TFM - -# By default, if we build with TF-M, instruct build system to -# flash the combined TF-M (Secure) & Zephyr (Non Secure) image -config TFM_FLASH_MERGED_BINARY - bool - default y - -endif # BUILD_WITH_TFM - # Code Partition: # # For the secure version of the board the firmware is linked at the beginning diff --git a/boards/arm/nrf5340dk_nrf5340/Kconfig.defconfig b/boards/arm/nrf5340dk_nrf5340/Kconfig.defconfig index d337e2f1a1c..09ebfbf50ba 100644 --- a/boards/arm/nrf5340dk_nrf5340/Kconfig.defconfig +++ b/boards/arm/nrf5340dk_nrf5340/Kconfig.defconfig @@ -8,21 +8,6 @@ if BOARD_NRF5340DK_NRF5340_CPUAPP || BOARD_NRF5340DK_NRF5340_CPUAPP_NS config BOARD default "nrf5340dk_nrf5340_cpuapp" if BOARD_NRF5340DK_NRF5340_CPUAPP || BOARD_NRF5340DK_NRF5340_CPUAPP_NS -# By default, if we build for a Non-Secure version of the board, -# enable building with TF-M as the Secure Execution Environment. -config BUILD_WITH_TFM - default y if BOARD_NRF5340DK_NRF5340_CPUAPP_NS - -if BUILD_WITH_TFM - -# By default, if we build with TF-M, instruct build system to -# flash the combined TF-M (Secure) & Zephyr (Non Secure) image -config TFM_FLASH_MERGED_BINARY - bool - default y - -endif # BUILD_WITH_TFM - # Code Partition: # # For the secure version of the board the firmware is linked at the beginning diff --git a/boards/arm/nrf9160dk_nrf9160/Kconfig.defconfig b/boards/arm/nrf9160dk_nrf9160/Kconfig.defconfig index cd052dc7a20..7d9046f63b5 100644 --- a/boards/arm/nrf9160dk_nrf9160/Kconfig.defconfig +++ b/boards/arm/nrf9160dk_nrf9160/Kconfig.defconfig @@ -8,21 +8,6 @@ if BOARD_NRF9160DK_NRF9160 || BOARD_NRF9160DK_NRF9160_NS config BOARD default "nrf9160dk_nrf9160" -# By default, if we build for a Non-Secure version of the board, -# enable building with TF-M as the Secure Execution Environment. -config BUILD_WITH_TFM - default y if BOARD_NRF9160DK_NRF9160_NS - -if BUILD_WITH_TFM - -# By default, if we build with TF-M, instruct build system to -# flash the combined TF-M (Secure) & Zephyr (Non Secure) image -config TFM_FLASH_MERGED_BINARY - bool - default y - -endif # BUILD_WITH_TFM - # For the secure version of the board the firmware is linked at the beginning # of the flash, or into the code-partition defined in DT if it is intended to # be loaded by MCUboot. If the secure firmware is to be combined with a non- diff --git a/boards/arm/nrf9161dk_nrf9161/Kconfig.defconfig b/boards/arm/nrf9161dk_nrf9161/Kconfig.defconfig index 2674e87cad4..ea7150ede5f 100644 --- a/boards/arm/nrf9161dk_nrf9161/Kconfig.defconfig +++ b/boards/arm/nrf9161dk_nrf9161/Kconfig.defconfig @@ -8,21 +8,6 @@ if BOARD_NRF9161DK_NRF9161 || BOARD_NRF9161DK_NRF9161_NS config BOARD default "nrf9161dk_nrf9161" -# By default, if we build for a Non-Secure version of the board, -# enable building with TF-M as the Secure Execution Environment. -config BUILD_WITH_TFM - default y if BOARD_NRF9161DK_NRF9161_NS - -if BUILD_WITH_TFM - -# By default, if we build with TF-M, instruct build system to -# flash the combined TF-M (Secure) & Zephyr (Non Secure) image -config TFM_FLASH_MERGED_BINARY - bool - default y - -endif # BUILD_WITH_TFM - # For the secure version of the board the firmware is linked at the beginning # of the flash, or into the code-partition defined in DT if it is intended to # be loaded by MCUboot. If the secure firmware is to be combined with a non- diff --git a/soc/arm/nordic_nrf/Kconfig b/soc/arm/nordic_nrf/Kconfig index 0e3b3e4ee6d..19e49c05454 100644 --- a/soc/arm/nordic_nrf/Kconfig +++ b/soc/arm/nordic_nrf/Kconfig @@ -25,13 +25,29 @@ config NRF_SOC_SECURE_SUPPORTED For non-secure the functions must redirect to secure services exposed by the secure firmware. +config BUILD_WITH_TFM + default y if TRUSTED_EXECUTION_NONSECURE + help + By default, if we build for a Non-Secure version of the board, + enable building with TF-M as the Secure Execution Environment. + +if BUILD_WITH_TFM + +config TFM_FLASH_MERGED_BINARY + default y + help + By default, if we build with TF-M, instruct build system to + flash the combined TF-M (Secure) & Zephyr (Non Secure) image + config TFM_LOG_LEVEL_SILENCE default y if !$(dt_nodelabel_has_prop,uart1,pinctrl-names) - depends on BUILD_WITH_TFM help Disable TF-M secure output if the uart1 node has not assigned GPIO pins using pinctrl. +endif # BUILD_WITH_TFM + + config NRF_MPU_FLASH_REGION_SIZE hex default 0x1000 From 5d85f6db2d5ec50922e809238e3b088da5727dcf Mon Sep 17 00:00:00 2001 From: Joakim Andersson Date: Wed, 4 Oct 2023 12:33:04 +0200 Subject: [PATCH 354/421] [nrf fromtree] doc: Remove note for missing tf-m/ns target support All nRF91 and nRF5340 boards (except the DKs) should support TF-M/_ns now. Signed-off-by: Joakim Andersson (cherry picked from commit 142dd9fb138d5156b2befe9bff340ffe975e8530) Signed-off-by: Joakim Andersson --- boards/arm/nrf5340_audio_dk_nrf5340/doc/index.rst | 3 --- boards/arm/nrf9160_innblue21/doc/index.rst | 3 --- boards/arm/nrf9160_innblue22/doc/index.rst | 3 --- boards/arm/sparkfun_thing_plus_nrf9160/doc/index.rst | 3 --- boards/arm/thingy53_nrf5340/doc/index.rst | 3 --- 5 files changed, 15 deletions(-) diff --git a/boards/arm/nrf5340_audio_dk_nrf5340/doc/index.rst b/boards/arm/nrf5340_audio_dk_nrf5340/doc/index.rst index 7718258eec2..3d8d2413e91 100644 --- a/boards/arm/nrf5340_audio_dk_nrf5340/doc/index.rst +++ b/boards/arm/nrf5340_audio_dk_nrf5340/doc/index.rst @@ -53,9 +53,6 @@ The nrf5340_audio_dk_nrf5340_cpuapp build target provides support for the applic core on the nRF5340 SoC. The nrf5340_audio_dk_nrf5340_cpunet build target provides support for the network core on the nRF5340 SoC. -.. note:: - Trusted Firmware-M (TF-M) and building the ``ns`` target is not supported for this board. - The `Nordic Semiconductor Infocenter`_ contains the processor's information and the datasheet. diff --git a/boards/arm/nrf9160_innblue21/doc/index.rst b/boards/arm/nrf9160_innblue21/doc/index.rst index 628166c409c..9ded085dc6f 100644 --- a/boards/arm/nrf9160_innblue21/doc/index.rst +++ b/boards/arm/nrf9160_innblue21/doc/index.rst @@ -104,9 +104,6 @@ have to set the IDAU (SPU) configuration to allow Non-Secure access to all CPU resources utilized by the Non-Secure application firmware. SPU configuration shall take place before jumping to the Non-Secure application. -.. note:: - Trusted Firmware-M (TF-M) and building the ``ns`` target is not supported for this board. - Building a Secure only application ================================== diff --git a/boards/arm/nrf9160_innblue22/doc/index.rst b/boards/arm/nrf9160_innblue22/doc/index.rst index ce3eb35d60f..06f6b6326f8 100644 --- a/boards/arm/nrf9160_innblue22/doc/index.rst +++ b/boards/arm/nrf9160_innblue22/doc/index.rst @@ -104,9 +104,6 @@ have to set the IDAU (SPU) configuration to allow Non-Secure access to all CPU resources utilized by the Non-Secure application firmware. SPU configuration shall take place before jumping to the Non-Secure application. -.. note:: - Trusted Firmware-M (TF-M) and building the ``ns`` target is not supported for this board. - Building a Secure only application ================================== diff --git a/boards/arm/sparkfun_thing_plus_nrf9160/doc/index.rst b/boards/arm/sparkfun_thing_plus_nrf9160/doc/index.rst index 44366c49a39..aa1a0e6279d 100644 --- a/boards/arm/sparkfun_thing_plus_nrf9160/doc/index.rst +++ b/boards/arm/sparkfun_thing_plus_nrf9160/doc/index.rst @@ -91,9 +91,6 @@ Building an application In most cases you'll want to use the ``ns`` target with any of the Zephyr or Nordic based examples. -.. note:: - Trusted Firmware-M (TF-M) and building the ``ns`` target is not supported for this board. - Some of the examples do not use secure mode, so they do not required the ``ns`` suffix. A great example of this is the `hello_world` below. diff --git a/boards/arm/thingy53_nrf5340/doc/index.rst b/boards/arm/thingy53_nrf5340/doc/index.rst index 3a77deee968..4544ea7ed79 100644 --- a/boards/arm/thingy53_nrf5340/doc/index.rst +++ b/boards/arm/thingy53_nrf5340/doc/index.rst @@ -22,9 +22,6 @@ The nrf5340dk_nrf5340_cpuapp build target provides support for the application core on the nRF5340 SoC. The nrf5340dk_nrf5340_cpunet build target provides support for the network core on the nRF5340 SoC. -.. note:: - Trusted Firmware-M (TF-M) and building the ``ns`` target is not supported for this board. - The `Nordic Semiconductor Infocenter`_ contains the processor's information and the datasheet. From f189c88320733cefc0dc25bff43bc854809fc81e Mon Sep 17 00:00:00 2001 From: Joakim Andersson Date: Tue, 24 Oct 2023 13:30:50 +0200 Subject: [PATCH 355/421] [nrf fromtree] boards: Fix nrf9160 NS flash partition layout Fix secure and non-secure images overlapping because of incompatible flash layout configurations. Align the board configurations to match the nRF9160 DK default partition layout. This enforces that the SPU alignment requirement is satisfied for the nrf9160 MCU. Signed-off-by: Joakim Andersson (cherry picked from commit dc431a7397a629c9fb7e3a27a803d11bf1103389) Signed-off-by: Joakim Andersson --- .../circuitdojo_feather_nrf9160_common.dtsi | 13 +++++-------- .../circuitdojo_feather_nrf9160_ns.yaml | 2 +- ...itdojo_feather_nrf9160_partition_conf.dtsi | 8 ++++---- .../nrf9160_innblue21_common.dtsi | 18 +++++++----------- .../nrf9160_innblue21_ns.yaml | 2 +- .../nrf9160_innblue21_partition_conf.dtsi | 8 ++++---- .../nrf9160_innblue22_common.dtsi | 19 ++++++++----------- .../nrf9160_innblue22_ns.yaml | 2 +- .../nrf9160_innblue22_partition_conf.dtsi | 8 ++++---- .../sparkfun_thing_plus_nrf9160_common.dtsi | 13 +++++-------- .../sparkfun_thing_plus_nrf9160_ns.yaml | 2 +- ...fun_thing_plus_nrf9160_partition_conf.dtsi | 8 ++++---- 12 files changed, 45 insertions(+), 58 deletions(-) diff --git a/boards/arm/circuitdojo_feather_nrf9160/circuitdojo_feather_nrf9160_common.dtsi b/boards/arm/circuitdojo_feather_nrf9160/circuitdojo_feather_nrf9160_common.dtsi index 33fdba4d865..00ce5dcf6c0 100644 --- a/boards/arm/circuitdojo_feather_nrf9160/circuitdojo_feather_nrf9160_common.dtsi +++ b/boards/arm/circuitdojo_feather_nrf9160/circuitdojo_feather_nrf9160_common.dtsi @@ -187,22 +187,19 @@ slot0_partition: partition@10000 { label = "image-0"; }; - slot0_ns_partition: partition@40000 { + slot0_ns_partition: partition@50000 { label = "image-0-nonsecure"; }; slot1_partition: partition@80000 { label = "image-1"; }; - slot1_ns_partition: partition@b0000 { + slot1_ns_partition: partition@c0000 { label = "image-1-nonsecure"; }; - scratch_partition: partition@f0000 { - label = "image-scratch"; - reg = <0x000f0000 0xa000>; - }; - storage_partition: partition@fa000 { + /* 0xf0000 to 0xf7fff reserved for TF-M partitions */ + storage_partition: partition@f8000 { label = "storage"; - reg = <0x000fa000 0x00006000>; + reg = <0x000f8000 0x00008000>; }; }; }; diff --git a/boards/arm/circuitdojo_feather_nrf9160/circuitdojo_feather_nrf9160_ns.yaml b/boards/arm/circuitdojo_feather_nrf9160/circuitdojo_feather_nrf9160_ns.yaml index c358a1d87fe..56905972e9f 100644 --- a/boards/arm/circuitdojo_feather_nrf9160/circuitdojo_feather_nrf9160_ns.yaml +++ b/boards/arm/circuitdojo_feather_nrf9160/circuitdojo_feather_nrf9160_ns.yaml @@ -7,7 +7,7 @@ toolchain: - xtools - zephyr ram: 128 -flash: 256 +flash: 192 supported: - i2c - pwm diff --git a/boards/arm/circuitdojo_feather_nrf9160/circuitdojo_feather_nrf9160_partition_conf.dtsi b/boards/arm/circuitdojo_feather_nrf9160/circuitdojo_feather_nrf9160_partition_conf.dtsi index e8cb6fc586e..007975132d6 100644 --- a/boards/arm/circuitdojo_feather_nrf9160/circuitdojo_feather_nrf9160_partition_conf.dtsi +++ b/boards/arm/circuitdojo_feather_nrf9160/circuitdojo_feather_nrf9160_partition_conf.dtsi @@ -23,19 +23,19 @@ */ &slot0_partition { - reg = <0x00010000 0x30000>; + reg = <0x00010000 0x40000>; }; &slot0_ns_partition { - reg = <0x00040000 0x40000>; + reg = <0x00050000 0x30000>; }; &slot1_partition { - reg = <0x00080000 0x30000>; + reg = <0x00080000 0x40000>; }; &slot1_ns_partition { - reg = <0x000b0000 0x40000>; + reg = <0x000c0000 0x30000>; }; /* Default SRAM planning when building for nRF9160 with diff --git a/boards/arm/nrf9160_innblue21/nrf9160_innblue21_common.dtsi b/boards/arm/nrf9160_innblue21/nrf9160_innblue21_common.dtsi index 0abfd4d6b9c..0ec5de5dfb1 100644 --- a/boards/arm/nrf9160_innblue21/nrf9160_innblue21_common.dtsi +++ b/boards/arm/nrf9160_innblue21/nrf9160_innblue21_common.dtsi @@ -168,27 +168,23 @@ boot_partition: partition@0 { label = "mcuboot"; - reg = <0x00000000 0xc000>; + reg = <0x00000000 0x10000>; }; - slot0_partition: partition@c000 { + slot0_partition: partition@10000 { label = "image-0"; }; - slot0_ns_partition: partition@3e000 { + slot0_ns_partition: partition@50000 { label = "image-0-nonsecure"; }; - slot1_partition: partition@7e000 { + slot1_partition: partition@80000 { label = "image-1"; }; - slot1_ns_partition: partition@b0000 { + slot1_ns_partition: partition@c0000 { label = "image-1-nonsecure"; }; - scratch_partition: partition@f0000 { - label = "image-scratch"; - reg = <0x000f0000 0xa000>; - }; - storage_partition: partition@fa000 { + storage_partition: partition@f8000 { label = "storage"; - reg = <0x000fa000 0x00006000>; + reg = <0x000f8000 0x00008000>; }; }; }; diff --git a/boards/arm/nrf9160_innblue21/nrf9160_innblue21_ns.yaml b/boards/arm/nrf9160_innblue21/nrf9160_innblue21_ns.yaml index 096821d8364..4584ad0e6a4 100644 --- a/boards/arm/nrf9160_innblue21/nrf9160_innblue21_ns.yaml +++ b/boards/arm/nrf9160_innblue21/nrf9160_innblue21_ns.yaml @@ -7,7 +7,7 @@ toolchain: - xtools - zephyr ram: 128 -flash: 256 +flash: 192 supported: - i2c - pwm diff --git a/boards/arm/nrf9160_innblue21/nrf9160_innblue21_partition_conf.dtsi b/boards/arm/nrf9160_innblue21/nrf9160_innblue21_partition_conf.dtsi index d3a30abdc76..2c64ba67a8a 100644 --- a/boards/arm/nrf9160_innblue21/nrf9160_innblue21_partition_conf.dtsi +++ b/boards/arm/nrf9160_innblue21/nrf9160_innblue21_partition_conf.dtsi @@ -22,19 +22,19 @@ */ &slot0_partition { - reg = <0x0000c000 0x30000>; + reg = <0x00010000 0x40000>; }; &slot0_ns_partition { - reg = <0x0003e000 0x40000>; + reg = <0x00050000 0x30000>; }; &slot1_partition { - reg = <0x0007e000 0x30000>; + reg = <0x00080000 0x40000>; }; &slot1_ns_partition { - reg = <0x000b0000 0x40000>; + reg = <0x000c0000 0x30000>; }; /* Default SRAM planning when building for nRF9160 with diff --git a/boards/arm/nrf9160_innblue22/nrf9160_innblue22_common.dtsi b/boards/arm/nrf9160_innblue22/nrf9160_innblue22_common.dtsi index 4582f975f5d..4738dd84a63 100644 --- a/boards/arm/nrf9160_innblue22/nrf9160_innblue22_common.dtsi +++ b/boards/arm/nrf9160_innblue22/nrf9160_innblue22_common.dtsi @@ -171,27 +171,24 @@ boot_partition: partition@0 { label = "mcuboot"; - reg = <0x00000000 0xc000>; + reg = <0x00000000 0x10000>; }; - slot0_partition: partition@c000 { + slot0_partition: partition@10000 { label = "image-0"; }; - slot0_ns_partition: partition@3e000 { + slot0_ns_partition: partition@50000 { label = "image-0-nonsecure"; }; - slot1_partition: partition@7e000 { + slot1_partition: partition@80000 { label = "image-1"; }; - slot1_ns_partition: partition@b0000 { + slot1_ns_partition: partition@c0000 { label = "image-1-nonsecure"; }; - scratch_partition: partition@f0000 { - label = "image-scratch"; - reg = <0x000f0000 0xa000>; - }; - storage_partition: partition@fa000 { + /* 0xf0000 to 0xf7fff reserved for TF-M partitions */ + storage_partition: partition@f8000 { label = "storage"; - reg = <0x000fa000 0x00006000>; + reg = <0x000f8000 0x00008000>; }; }; }; diff --git a/boards/arm/nrf9160_innblue22/nrf9160_innblue22_ns.yaml b/boards/arm/nrf9160_innblue22/nrf9160_innblue22_ns.yaml index 2ce0d6e3db2..0186c26a377 100644 --- a/boards/arm/nrf9160_innblue22/nrf9160_innblue22_ns.yaml +++ b/boards/arm/nrf9160_innblue22/nrf9160_innblue22_ns.yaml @@ -7,7 +7,7 @@ toolchain: - xtools - zephyr ram: 128 -flash: 256 +flash: 192 supported: - i2c - pwm diff --git a/boards/arm/nrf9160_innblue22/nrf9160_innblue22_partition_conf.dtsi b/boards/arm/nrf9160_innblue22/nrf9160_innblue22_partition_conf.dtsi index 3588a6a7ce1..b14640a02ec 100644 --- a/boards/arm/nrf9160_innblue22/nrf9160_innblue22_partition_conf.dtsi +++ b/boards/arm/nrf9160_innblue22/nrf9160_innblue22_partition_conf.dtsi @@ -22,19 +22,19 @@ */ &slot0_partition { - reg = <0x0000c000 0x30000>; + reg = <0x00010000 0x40000>; }; &slot0_ns_partition { - reg = <0x0003e000 0x40000>; + reg = <0x00050000 0x30000>; }; &slot1_partition { - reg = <0x0007e000 0x30000>; + reg = <0x00080000 0x40000>; }; &slot1_ns_partition { - reg = <0x000b0000 0x40000>; + reg = <0x000c0000 0x30000>; }; /* Default SRAM planning when building for nRF9160 with diff --git a/boards/arm/sparkfun_thing_plus_nrf9160/sparkfun_thing_plus_nrf9160_common.dtsi b/boards/arm/sparkfun_thing_plus_nrf9160/sparkfun_thing_plus_nrf9160_common.dtsi index b85c00ea5b2..2658ee5eaa4 100644 --- a/boards/arm/sparkfun_thing_plus_nrf9160/sparkfun_thing_plus_nrf9160_common.dtsi +++ b/boards/arm/sparkfun_thing_plus_nrf9160/sparkfun_thing_plus_nrf9160_common.dtsi @@ -185,22 +185,19 @@ slot0_partition: partition@10000 { label = "image-0"; }; - slot0_ns_partition: partition@40000 { + slot0_ns_partition: partition@50000 { label = "image-0-nonsecure"; }; slot1_partition: partition@80000 { label = "image-1"; }; - slot1_ns_partition: partition@b0000 { + slot1_ns_partition: partition@c0000 { label = "image-1-nonsecure"; }; - scratch_partition: partition@f0000 { - label = "image-scratch"; - reg = <0x000f0000 0xa000>; - }; - storage_partition: partition@fa000 { + /* 0xf0000 to 0xf7fff reserved for TF-M partitions */ + storage_partition: partition@f8000 { label = "storage"; - reg = <0x000fa000 0x00006000>; + reg = <0x000f8000 0x00008000>; }; }; }; diff --git a/boards/arm/sparkfun_thing_plus_nrf9160/sparkfun_thing_plus_nrf9160_ns.yaml b/boards/arm/sparkfun_thing_plus_nrf9160/sparkfun_thing_plus_nrf9160_ns.yaml index e667a231774..adbef49e2b0 100644 --- a/boards/arm/sparkfun_thing_plus_nrf9160/sparkfun_thing_plus_nrf9160_ns.yaml +++ b/boards/arm/sparkfun_thing_plus_nrf9160/sparkfun_thing_plus_nrf9160_ns.yaml @@ -7,7 +7,7 @@ toolchain: - xtools - zephyr ram: 128 -flash: 256 +flash: 192 supported: - i2c - pwm diff --git a/boards/arm/sparkfun_thing_plus_nrf9160/sparkfun_thing_plus_nrf9160_partition_conf.dtsi b/boards/arm/sparkfun_thing_plus_nrf9160/sparkfun_thing_plus_nrf9160_partition_conf.dtsi index 2422b2fdc52..64591fbf900 100644 --- a/boards/arm/sparkfun_thing_plus_nrf9160/sparkfun_thing_plus_nrf9160_partition_conf.dtsi +++ b/boards/arm/sparkfun_thing_plus_nrf9160/sparkfun_thing_plus_nrf9160_partition_conf.dtsi @@ -23,19 +23,19 @@ */ &slot0_partition { - reg = <0x00010000 0x30000>; + reg = <0x00010000 0x40000>; }; &slot0_ns_partition { - reg = <0x00040000 0x40000>; + reg = <0x00050000 0x30000>; }; &slot1_partition { - reg = <0x00080000 0x30000>; + reg = <0x00080000 0x40000>; }; &slot1_ns_partition { - reg = <0x000b0000 0x40000>; + reg = <0x000c0000 0x30000>; }; /* Default SRAM planning when building for nRF9160 with From ad501cb7ca3ce9951ea4fb21b4c21291e0680664 Mon Sep 17 00:00:00 2001 From: Joakim Andersson Date: Thu, 26 Oct 2023 10:57:30 +0200 Subject: [PATCH 356/421] [nrf fromtree] tfm: Add BL2 log level configuration and disable it with TFM silent conf Add choice for BL2 log level configuration. Silence TF-M BL2 logging when TF-M is configured to be silent. Signed-off-by: Joakim Andersson (cherry picked from commit 96c5052733be0eb73da2c47eb2c85e18ec54fca9) Signed-off-by: Joakim Andersson --- modules/trusted-firmware-m/CMakeLists.txt | 19 +++++++++++++++++++ modules/trusted-firmware-m/Kconfig.tfm | 15 +++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/modules/trusted-firmware-m/CMakeLists.txt b/modules/trusted-firmware-m/CMakeLists.txt index 0c01858f34d..f00116cda2c 100644 --- a/modules/trusted-firmware-m/CMakeLists.txt +++ b/modules/trusted-firmware-m/CMakeLists.txt @@ -101,6 +101,25 @@ if (CONFIG_BUILD_WITH_TFM) list(APPEND TFM_CMAKE_ARGS -DTFM_EXCEPTION_INFO_DUMP=OFF) endif() + if (CONFIG_TFM_BL2) + if (CONFIG_TFM_BL2_LOG_LEVEL_DEBUG) + set(TFM_BL2_LOG_LEVEL "DEBUG") + elseif (CONFIG_TFM_BL2_LOG_LEVEL_INFO) + set(TFM_BL2_LOG_LEVEL "INFO") + elseif (CONFIG_TFM_BL2_LOG_LEVEL_WARNING) + set(TFM_BL2_LOG_LEVEL "WARNING") + elseif (CONFIG_TFM_BL2_LOG_LEVEL_ERROR) + set(TFM_BL2_LOG_LEVEL "ERROR") + elseif (CONFIG_TFM_BL2_LOG_LEVEL_OFF OR CONFIG_TFM_LOG_LEVEL_SILENCE) + set(TFM_BL2_LOG_LEVEL "OFF") + endif() + + if (DEFINED TFM_BL2_LOG_LEVEL) + # BL2 uses MCUBOOT_LOG_LEVEL configuration + list(APPEND TFM_CMAKE_ARGS -DMCUBOOT_LOG_LEVEL=${TFM_BL2_LOG_LEVEL}) + endif() + endif() + if (CONFIG_TFM_PARTITION_LOG_LEVEL_DEBUG) set(TFM_PARTITION_LOG_LEVEL "TFM_PARTITION_LOG_LEVEL_DEBUG") elseif (CONFIG_TFM_PARTITION_LOG_LEVEL_INFO) diff --git a/modules/trusted-firmware-m/Kconfig.tfm b/modules/trusted-firmware-m/Kconfig.tfm index 7fd1b348a74..bafa5cf0bab 100644 --- a/modules/trusted-firmware-m/Kconfig.tfm +++ b/modules/trusted-firmware-m/Kconfig.tfm @@ -397,6 +397,21 @@ config ROM_START_OFFSET needs to be updated if TF-M switches to use a different header size for BL2. +choice TFM_BL2_LOG_LEVEL + prompt "BL2 Log Level" if !TFM_LOG_LEVEL_SILENCE + default TFM_BL2_LOG_LEVEL_INFO + config TFM_BL2_LOG_LEVEL_DEBUG + bool "Debug" + config TFM_BL2_LOG_LEVEL_INFO + bool "Info" + config TFM_BL2_LOG_LEVEL_WARNING + bool "Warning" + config TFM_BL2_LOG_LEVEL_ERROR + bool "Error" + config TFM_BL2_LOG_LEVEL_OFF + bool "Off" +endchoice + endif # !TFM_BL2 # Option to instruct flashing a merged binary consisting of BL2 (optionally), From ff85910bf8ed1aac0571bca0e7f206782234efbb Mon Sep 17 00:00:00 2001 From: Marek Pieta Date: Mon, 28 Nov 2022 15:31:33 +0100 Subject: [PATCH 357/421] [nrf noup] boards: thingy53_nrf5340: Enable MCUboot by default Change enables MCUboot bootloader by default to allow programming samples and applications without external programmer (using MCUboot serial recovery). Change also enables network core to prevent build failures when building MCUboot with nRF53 multi image DFU. Jira: NCSDK-18263 Signed-off-by: Marek Pieta Signed-off-by: Vinayak Kariappa Chettimada Signed-off-by: Johann Fischer (cherry picked from commit 46895493bf1b0988e44ea344f4420b543e307eae) (cherry picked from commit ff1db43269579e2a0bdc28c55f2c83d3ad58ebb7) Signed-off-by: Joakim Andersson --- boards/arm/thingy53_nrf5340/Kconfig.defconfig | 6 ++++++ boards/arm/thingy53_nrf5340/thingy53_nrf5340_common.dtsi | 1 + 2 files changed, 7 insertions(+) diff --git a/boards/arm/thingy53_nrf5340/Kconfig.defconfig b/boards/arm/thingy53_nrf5340/Kconfig.defconfig index 6384d163d93..b6080de9a80 100644 --- a/boards/arm/thingy53_nrf5340/Kconfig.defconfig +++ b/boards/arm/thingy53_nrf5340/Kconfig.defconfig @@ -8,6 +8,12 @@ if BOARD_THINGY53_NRF5340_CPUAPP || BOARD_THINGY53_NRF5340_CPUAPP_NS config BOARD default "thingy53_nrf5340_cpuapp" +config BOOTLOADER_MCUBOOT + default y if !MCUBOOT + +config BOARD_ENABLE_CPUNET + default y if !MCUBOOT + # Code Partition: # # For the secure version of the board the firmware is linked at the beginning diff --git a/boards/arm/thingy53_nrf5340/thingy53_nrf5340_common.dtsi b/boards/arm/thingy53_nrf5340/thingy53_nrf5340_common.dtsi index 341bb1305e1..515fc3bea7b 100644 --- a/boards/arm/thingy53_nrf5340/thingy53_nrf5340_common.dtsi +++ b/boards/arm/thingy53_nrf5340/thingy53_nrf5340_common.dtsi @@ -16,6 +16,7 @@ zephyr,bt-hci-rpmsg-ipc = &ipc0; nordic,802154-spinel-ipc = &ipc0; zephyr,ieee802154 = &ieee802154; + nordic,pm-ext-flash = &mx25r64; }; buttons { From b715be6b467b45eaa6f3688f2117a39a1e19985a Mon Sep 17 00:00:00 2001 From: Rodrigo Peixoto Date: Sat, 2 Sep 2023 13:35:14 -0300 Subject: [PATCH 358/421] [nrf fromtree] zbus: Add Message subscriber Besides the changed channel reference, the message subscribers receive a copy of the message during the VDED execution. ZBus guarantees message delivery for `MSG_SUBSCRIBERS`. Signed-off-by: Rodrigo Peixoto (cherry picked from commit 0b0aa435afc8b0102b437ae145203daada6c616b) Signed-off-by: Alexander Svensen --- include/zephyr/zbus/zbus.h | 68 +++++++++++++++++- subsys/zbus/Kconfig | 30 ++++++++ subsys/zbus/zbus.c | 144 +++++++++++++++++++++++++++++++------ 3 files changed, 219 insertions(+), 23 deletions(-) diff --git a/include/zephyr/zbus/zbus.h b/include/zephyr/zbus/zbus.h index 466a2ad9dcf..8a4188aa821 100644 --- a/include/zephyr/zbus/zbus.h +++ b/include/zephyr/zbus/zbus.h @@ -92,7 +92,8 @@ struct zbus_channel { */ enum __packed zbus_observer_type { ZBUS_OBSERVER_LISTENER_TYPE, - ZBUS_OBSERVER_SUBSCRIBER_TYPE + ZBUS_OBSERVER_SUBSCRIBER_TYPE, + ZBUS_OBSERVER_MSG_SUBSCRIBER_TYPE, }; /** @@ -127,6 +128,13 @@ struct zbus_observer { /** Observer callback function. It turns the observer into a listener. */ void (*const callback)(const struct zbus_channel *chan); + +#if defined(CONFIG_ZBUS_MSG_SUBSCRIBER) || defined(__DOXYGEN__) + /** Observer message FIFO. It turns the observer into a message subscriber. It only + * exists if the @kconfig{CONFIG_ZBUS_MSG_SUBSCRIBER} is enabled. + */ + struct k_fifo *const message_fifo; +#endif /* CONFIG_ZBUS_MSG_SUBSCRIBER */ }; }; @@ -156,8 +164,10 @@ struct zbus_channel_observation { #if defined(CONFIG_ZBUS_CHANNEL_NAME) #define ZBUS_CHANNEL_NAME_INIT(_name) .name = #_name, +#define _ZBUS_CHAN_NAME(_chan) (_chan)->name #else #define ZBUS_CHANNEL_NAME_INIT(_name) +#define _ZBUS_CHAN_NAME(_chan) "" #endif #if defined(CONFIG_ZBUS_OBSERVER_NAME) @@ -379,6 +389,37 @@ k_timeout_t _zbus_timeout_remainder(uint64_t end_ticks); */ #define ZBUS_LISTENER_DEFINE(_name, _cb) ZBUS_LISTENER_DEFINE_WITH_ENABLE(_name, _cb, true) +/** + * @brief Define and initialize a message subscriber. + * + * This macro defines an observer of @ref ZBUS_OBSERVER_SUBSCRIBER_TYPE type. It defines a FIFO + * where the subscriber will receive the message asynchronously and initialize the @ref + * zbus_observer defining the subscriber. + * + * @param[in] _name The subscriber's name. + * @param[in] _enable The subscriber's initial state. + */ +#define ZBUS_MSG_SUBSCRIBER_DEFINE_WITH_ENABLE(_name, _enable) \ + static K_FIFO_DEFINE(_zbus_observer_fifo_##_name); \ + STRUCT_SECTION_ITERABLE(zbus_observer, _name) = { \ + ZBUS_OBSERVER_NAME_INIT(_name) /* Name field */ \ + .type = ZBUS_OBSERVER_MSG_SUBSCRIBER_TYPE, \ + .enabled = _enable, \ + .message_fifo = &_zbus_observer_fifo_##_name, \ + } + +/** + * @brief Define and initialize an enabled message subscriber. + * + * This macro defines an observer of message subscriber type. It defines a FIFO where the + * subscriber will receive the message asynchronously and initialize the @ref + * zbus_observer defining the subscriber. The message subscribers are defined in the enabled state + * with this macro. + + * + * @param[in] _name The subscriber's name. + */ +#define ZBUS_MSG_SUBSCRIBER_DEFINE(_name) ZBUS_MSG_SUBSCRIBER_DEFINE_WITH_ENABLE(_name, true) /** * * @brief Publish to a channel @@ -741,6 +782,31 @@ static inline const char *zbus_obs_name(const struct zbus_observer *obs) int zbus_sub_wait(const struct zbus_observer *sub, const struct zbus_channel **chan, k_timeout_t timeout); +#if defined(CONFIG_ZBUS_MSG_SUBSCRIBER) || defined(__DOXYGEN__) + +/** + * @brief Wait for a channel message. + * + * This routine makes the subscriber wait for the new message in case of channel publication. + * + * @param[in] sub The subscriber's reference. + * @param[out] chan The notification channel's reference. + * @param[out] msg A reference to a copy of the published message. + * @param[in] timeout Waiting period for a notification arrival, + * or one of the special values, K_NO_WAIT and K_FOREVER. + * + * @retval 0 Message received. + * @retval -EINVAL The observer is not a subscriber. + * @retval -ENOMSG Could not retrieve the net_buf from the subscriber FIFO. + * @retval -EILSEQ Received an invalid channel reference. + * @retval -EFAULT A parameter is incorrect, or the function context is invalid (inside an ISR). The + * function only returns this value when the @kconfig{CONFIG_ZBUS_ASSERT_MOCK} is enabled. + */ +int zbus_sub_wait_msg(const struct zbus_observer *sub, const struct zbus_channel **chan, void *msg, + k_timeout_t timeout); + +#endif /* CONFIG_ZBUS_MSG_SUBSCRIBER */ + /** * * @brief Iterate over channels. diff --git a/subsys/zbus/Kconfig b/subsys/zbus/Kconfig index 622f89641a2..f250865b466 100644 --- a/subsys/zbus/Kconfig +++ b/subsys/zbus/Kconfig @@ -18,6 +18,36 @@ config ZBUS_CHANNEL_NAME config ZBUS_OBSERVER_NAME bool "Observer name field" +config ZBUS_MSG_SUBSCRIBER + select NET_BUF + bool "Message subscribers will receive all messages in sequence." + +if ZBUS_MSG_SUBSCRIBER + +choice + prompt "ZBus msg_subscribers buffer allocation" + +config ZBUS_MSG_SUBSCRIBER_NET_BUF_DYNAMIC + bool "Use heap to allocate msg_subscriber buffers data" + +config ZBUS_MSG_SUBSCRIBER_NET_BUF_STATIC + bool "Use fixed data size for msg_subscriber buffers pool" + +endchoice + +config ZBUS_MSG_SUBSCRIBER_NET_BUF_POOL_SIZE + default 16 + int "The count of net_buf available to be used simutaneously." + +if ZBUS_MSG_SUBSCRIBER_NET_BUF_STATIC + +config ZBUS_MSG_SUBSCRIBER_NET_BUF_STATIC_DATA_SIZE + int "The size of the biggest message used with ZBus." + +endif # ZBUS_MSG_SUBSCRIBER_NET_BUF_STATIC + +endif # ZBUS_MSG_SUBSCRIBER + config ZBUS_RUNTIME_OBSERVERS bool "Runtime observers support." default n diff --git a/subsys/zbus/zbus.c b/subsys/zbus/zbus.c index abaf92c8641..4ea2d986a3f 100644 --- a/subsys/zbus/zbus.c +++ b/subsys/zbus/zbus.c @@ -8,11 +8,47 @@ #include #include #include +#include #include LOG_MODULE_REGISTER(zbus, CONFIG_ZBUS_LOG_LEVEL); +#if defined(CONFIG_ZBUS_MSG_SUBSCRIBER) + +#if defined(CONFIG_ZBUS_MSG_SUBSCRIBER_NET_BUF_DYNAMIC) + +NET_BUF_POOL_HEAP_DEFINE(_zbus_msg_subscribers_pool, CONFIG_ZBUS_MSG_SUBSCRIBER_NET_BUF_POOL_SIZE, + sizeof(struct zbus_channel *), NULL); +BUILD_ASSERT(CONFIG_HEAP_MEM_POOL_SIZE > 0, "MSG_SUBSCRIBER feature requires heap memory pool."); + +static inline struct net_buf *_zbus_create_net_buf(struct net_buf_pool *pool, size_t size, + k_timeout_t timeout) +{ + return net_buf_alloc_len(&_zbus_msg_subscribers_pool, size, timeout); +} + +#else + +NET_BUF_POOL_FIXED_DEFINE(_zbus_msg_subscribers_pool, + (CONFIG_ZBUS_MSG_SUBSCRIBER_NET_BUF_STATIC_DATA_SIZE), + (CONFIG_ZBUS_MSG_SUBSCRIBER_NET_BUF_POOL_SIZE), + sizeof(struct zbus_channel *), NULL); + +static inline struct net_buf *_zbus_create_net_buf(struct net_buf_pool *pool, size_t size, + k_timeout_t timeout) +{ + __ASSERT(size <= CONFIG_ZBUS_MSG_SUBSCRIBER_NET_BUF_STATIC_DATA_SIZE, + "CONFIG_ZBUS_MSG_SUBSCRIBER_NET_BUF_STATIC_DATA_SIZE must be greater or equal to " + "%d", + (int)size); + return net_buf_alloc(&_zbus_msg_subscribers_pool, timeout); +} +#endif /* CONFIG_ZBUS_MSG_SUBSCRIBER_NET_BUF_DYNAMIC */ + +#endif /* CONFIG_ZBUS_MSG_SUBSCRIBER */ + int _zbus_init(void) { + const struct zbus_channel *curr = NULL; const struct zbus_channel *prev = NULL; @@ -44,32 +80,62 @@ int _zbus_init(void) SYS_INIT(_zbus_init, APPLICATION, CONFIG_ZBUS_CHANNELS_SYS_INIT_PRIORITY); static inline int _zbus_notify_observer(const struct zbus_channel *chan, - const struct zbus_observer *obs, k_timepoint_t end_time) + const struct zbus_observer *obs, k_timepoint_t end_time, + struct net_buf *buf) { - int err = 0; - - if (obs->type == ZBUS_OBSERVER_LISTENER_TYPE) { + switch (obs->type) { + case ZBUS_OBSERVER_LISTENER_TYPE: { obs->callback(chan); + break; + } + case ZBUS_OBSERVER_SUBSCRIBER_TYPE: { + return k_msgq_put(obs->queue, &chan, sys_timepoint_timeout(end_time)); + } +#if defined(CONFIG_ZBUS_MSG_SUBSCRIBER) + case ZBUS_OBSERVER_MSG_SUBSCRIBER_TYPE: { + struct net_buf *cloned_buf = net_buf_clone(buf, sys_timepoint_timeout(end_time)); - } else if (obs->type == ZBUS_OBSERVER_SUBSCRIBER_TYPE) { - err = k_msgq_put(obs->queue, &chan, sys_timepoint_timeout(end_time)); - } else { - CODE_UNREACHABLE; + if (cloned_buf == NULL) { + return -ENOMEM; + } + memcpy(net_buf_user_data(cloned_buf), &chan, sizeof(struct zbus_channel *)); + + net_buf_put(obs->message_fifo, cloned_buf); + + break; } - return err; +#endif /* CONFIG_ZBUS_MSG_SUBSCRIBER */ + + default: + _ZBUS_ASSERT(false, "Unreachable"); + } + return 0; } static inline int _zbus_vded_exec(const struct zbus_channel *chan, k_timepoint_t end_time) { int err = 0; int last_error = 0; - - _ZBUS_ASSERT(chan != NULL, "chan is required"); + struct net_buf *buf = NULL; /* Static observer event dispatcher logic */ struct zbus_channel_observation *observation; struct zbus_channel_observation_mask *observation_mask; +#if defined(CONFIG_ZBUS_MSG_SUBSCRIBER) + buf = _zbus_create_net_buf(&_zbus_msg_subscribers_pool, zbus_chan_msg_size(chan), + sys_timepoint_timeout(end_time)); + + _ZBUS_ASSERT(buf != NULL, "net_buf zbus_msg_subscribers_pool is " + "unavailable or heap is full"); + + net_buf_add_mem(buf, zbus_chan_msg(chan), zbus_chan_msg_size(chan)); +#endif /* CONFIG_ZBUS_MSG_SUBSCRIBER */ + + LOG_DBG("Notifing %s's observers. Starting VDED:", _ZBUS_CHAN_NAME(chan)); + + int __maybe_unused index = 0; + for (int16_t i = chan->data->observers_start_idx, limit = chan->data->observers_end_idx; i < limit; ++i) { STRUCT_SECTION_GET(zbus_channel_observation, i, &observation); @@ -83,15 +149,21 @@ static inline int _zbus_vded_exec(const struct zbus_channel *chan, k_timepoint_t continue; } - err = _zbus_notify_observer(chan, obs, end_time); - - _ZBUS_ASSERT(err == 0, - "could not deliver notification to observer %s. Error code %d", - _ZBUS_OBS_NAME(obs), err); + err = _zbus_notify_observer(chan, obs, end_time, buf); if (err) { last_error = err; + LOG_ERR("could not deliver notification to observer %s. Error code %d", + _ZBUS_OBS_NAME(obs), err); + if (err == -ENOMEM) { + if (IS_ENABLED(CONFIG_ZBUS_MSG_SUBSCRIBER)) { + net_buf_unref(buf); + } + return err; + } } + + LOG_DBG(" %d -> %s", index++, _ZBUS_OBS_NAME(obs)); } #if defined(CONFIG_ZBUS_RUNTIME_OBSERVERS) @@ -100,15 +172,13 @@ static inline int _zbus_vded_exec(const struct zbus_channel *chan, k_timepoint_t SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&chan->data->observers, obs_nd, tmp, node) { - _ZBUS_ASSERT(obs_nd != NULL, "observer node is NULL"); - const struct zbus_observer *obs = obs_nd->obs; if (!obs->enabled) { continue; } - err = _zbus_notify_observer(chan, obs, end_time); + err = _zbus_notify_observer(chan, obs, end_time, buf); if (err) { last_error = err; @@ -116,6 +186,8 @@ static inline int _zbus_vded_exec(const struct zbus_channel *chan, k_timepoint_t } #endif /* CONFIG_ZBUS_RUNTIME_OBSERVERS */ + IF_ENABLED(CONFIG_ZBUS_MSG_SUBSCRIBER, (net_buf_unref(buf);)) + return last_error; } @@ -215,15 +287,43 @@ int zbus_sub_wait(const struct zbus_observer *sub, const struct zbus_channel **c { _ZBUS_ASSERT(!k_is_in_isr(), "zbus cannot be used inside ISRs"); _ZBUS_ASSERT(sub != NULL, "sub is required"); + _ZBUS_ASSERT(sub->type == ZBUS_OBSERVER_SUBSCRIBER_TYPE, "sub must be a SUBSCRIBER"); + _ZBUS_ASSERT(sub->queue != NULL, "sub queue is required"); + _ZBUS_ASSERT(chan != NULL, "chan is required"); + + return k_msgq_get(sub->queue, chan, timeout); +} + +#if defined(CONFIG_ZBUS_MSG_SUBSCRIBER) + +int zbus_sub_wait_msg(const struct zbus_observer *sub, const struct zbus_channel **chan, void *msg, + k_timeout_t timeout) +{ + _ZBUS_ASSERT(!k_is_in_isr(), "zbus subscribers cannot be used inside ISRs"); + _ZBUS_ASSERT(sub != NULL, "sub is required"); + _ZBUS_ASSERT(sub->type == ZBUS_OBSERVER_MSG_SUBSCRIBER_TYPE, + "sub must be a MSG_SUBSCRIBER"); + _ZBUS_ASSERT(sub->message_fifo != NULL, "sub message_fifo is required"); _ZBUS_ASSERT(chan != NULL, "chan is required"); + _ZBUS_ASSERT(msg != NULL, "msg is required"); + + struct net_buf *buf = net_buf_get(sub->message_fifo, timeout); - if (sub->queue == NULL) { - return -EINVAL; + if (buf == NULL) { + return -ENOMSG; } - return k_msgq_get(sub->queue, chan, timeout); + *chan = *((struct zbus_channel **)net_buf_user_data(buf)); + + memcpy(msg, net_buf_remove_mem(buf, zbus_chan_msg_size(*chan)), zbus_chan_msg_size(*chan)); + + net_buf_unref(buf); + + return 0; } +#endif /* CONFIG_ZBUS_MSG_SUBSCRIBER */ + int zbus_obs_set_chan_notification_mask(const struct zbus_observer *obs, const struct zbus_channel *chan, bool masked) { From b552226dbe60943cd46e6ac598fbb81fda366317 Mon Sep 17 00:00:00 2001 From: Emil Gydesen Date: Wed, 11 Oct 2023 15:16:59 +0200 Subject: [PATCH 359/421] [nrf fromtree] Bluetooth: BAP: Broadcast Sink should not terminate the PA Sync When calling bt_bap_broadcast_sink_delete, the broadcast sink should not attempt to terminate the PA Sync. The PA sync can live on without the broadcast sink, just as the broadcast sink can live on without the PA sync (which is why the PA sync check was completely removed). Signed-off-by: Emil Gydesen (cherry picked from commit 73398490771970fc099f6f3724ef75fbb1fc8542) Signed-off-by: Alexander Svensen --- subsys/bluetooth/audio/bap_broadcast_sink.c | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/subsys/bluetooth/audio/bap_broadcast_sink.c b/subsys/bluetooth/audio/bap_broadcast_sink.c index 9866dfd1c57..0d92617f329 100644 --- a/subsys/bluetooth/audio/bap_broadcast_sink.c +++ b/subsys/bluetooth/audio/bap_broadcast_sink.c @@ -1076,8 +1076,6 @@ int bt_bap_broadcast_sink_stop(struct bt_bap_broadcast_sink *sink) int bt_bap_broadcast_sink_delete(struct bt_bap_broadcast_sink *sink) { - int err; - CHECKIF(sink == NULL) { LOG_DBG("sink is NULL"); return -EINVAL; @@ -1099,17 +1097,6 @@ int bt_bap_broadcast_sink_delete(struct bt_bap_broadcast_sink *sink) } } - if (sink->pa_sync == NULL) { - LOG_DBG("Broadcast sink is already deleted"); - return -EALREADY; - } - - err = bt_le_per_adv_sync_delete(sink->pa_sync); - if (err != 0) { - LOG_DBG("Failed to delete periodic advertising sync (err %d)", err); - return err; - } - /* Reset the broadcast sink */ broadcast_sink_cleanup(sink); From 7a9d7daf0af044b352a50feef529a5f45c285b91 Mon Sep 17 00:00:00 2001 From: Emil Gydesen Date: Thu, 12 Oct 2023 10:42:57 +0200 Subject: [PATCH 360/421] [nrf fromtree] Bluetooth: BAP: Broadcast sink: Clear pa_sync on PA terminated If the PA gets terminated, we clear the pa_sync field of the corresponding broadcast sink object. Signed-off-by: Emil Gydesen (cherry picked from commit c47b7f7936dc39b1d2369122c1ab669acef75bc9) Signed-off-by: Alexander Svensen --- subsys/bluetooth/audio/bap_broadcast_sink.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/subsys/bluetooth/audio/bap_broadcast_sink.c b/subsys/bluetooth/audio/bap_broadcast_sink.c index 0d92617f329..4fad67ce539 100644 --- a/subsys/bluetooth/audio/bap_broadcast_sink.c +++ b/subsys/bluetooth/audio/bap_broadcast_sink.c @@ -566,6 +566,16 @@ static void pa_recv(struct bt_le_per_adv_sync *sync, bt_data_parse(buf, pa_decode_base, (void *)sink); } +static void pa_term_cb(struct bt_le_per_adv_sync *sync, + const struct bt_le_per_adv_sync_term_info *info) +{ + struct bt_bap_broadcast_sink *sink = broadcast_sink_get_by_pa(sync); + + if (sink != NULL) { + sink->pa_sync = NULL; + } +} + static void update_recv_state_encryption(const struct bt_bap_broadcast_sink *sink) { struct bt_bap_scan_delegator_mod_src_param mod_src_param = { 0 }; @@ -1108,6 +1118,7 @@ static int broadcast_sink_init(void) static struct bt_le_per_adv_sync_cb cb = { .recv = pa_recv, .biginfo = biginfo_recv, + .term = pa_term_cb, }; bt_le_per_adv_sync_cb_register(&cb); From bbc2731680cc1a7088ea5410d9ff81de4f4fe34a Mon Sep 17 00:00:00 2001 From: Chaitanya Tata Date: Wed, 25 Oct 2023 22:12:33 +0530 Subject: [PATCH 361/421] [nrf fromtree] net: zperf: Distinguish between IPv4 and IPv6 address set failures Using a generic IP for address set failures is confusing, esp. two same prints (one for v4 and the other for v6), so, use explicit version. Signed-off-by: Chaitanya Tata (cherry picked from commit 6bd47ffb10cef4f5733e9a7849ccb48988e61d4b) --- subsys/net/lib/zperf/zperf_shell.c | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/subsys/net/lib/zperf/zperf_shell.c b/subsys/net/lib/zperf/zperf_shell.c index 3a8a9c61c4b..c1f0c6a4950 100644 --- a/subsys/net/lib/zperf/zperf_shell.c +++ b/subsys/net/lib/zperf/zperf_shell.c @@ -191,7 +191,7 @@ static int cmd_setip(const struct shell *sh, size_t argc, char *argv[]) if (zperf_get_ipv6_addr(argv[start + 1], argv[start + 2], &shell_ipv6) < 0) { shell_fprintf(sh, SHELL_WARNING, - "Unable to set IP\n"); + "Unable to set %s address (%s disabled)\n", "IPv6", "IPv4"); return 0; } @@ -208,7 +208,7 @@ static int cmd_setip(const struct shell *sh, size_t argc, char *argv[]) if (zperf_get_ipv4_addr(argv[start + 1], &shell_ipv4) < 0) { shell_fprintf(sh, SHELL_WARNING, - "Unable to set IP\n"); + "Unable to set %s address (%s disabled)\n", "IPv4", "IPv6"); return -ENOEXEC; } @@ -227,7 +227,7 @@ static int cmd_setip(const struct shell *sh, size_t argc, char *argv[]) if (zperf_get_ipv4_addr(argv[start + 1], &shell_ipv4) < 0) { shell_fprintf(sh, SHELL_WARNING, - "Unable to set IP\n"); + "Unable to set %s address\n", "IPv4"); return -ENOEXEC; } @@ -243,7 +243,7 @@ static int cmd_setip(const struct shell *sh, size_t argc, char *argv[]) if (zperf_get_ipv6_addr(argv[start + 1], argv[start + 2], &shell_ipv6) < 0) { shell_fprintf(sh, SHELL_WARNING, - "Unable to set IP\n"); + "Unable to set %s address\n", "IPv6"); return -ENOEXEC; } @@ -1114,7 +1114,7 @@ void zperf_shell_init(void) ret = net_addr_pton(AF_INET6, MY_IP6ADDR, &in6_addr_my.sin6_addr); if (ret < 0) { - NET_WARN("Unable to set IP"); + NET_WARN("Unable to set %s address\n", "IPv6"); } else { NET_INFO("Setting IP address %s", net_sprint_ipv6_addr(&in6_addr_my.sin6_addr)); @@ -1123,9 +1123,10 @@ void zperf_shell_init(void) ret = net_addr_pton(AF_INET6, DST_IP6ADDR, &in6_addr_dst.sin6_addr); if (ret < 0) { - NET_WARN("Unable to set IP %s", + NET_WARN("Unable to set destination %s address %s", + "IPv6", DST_IP6ADDR ? DST_IP6ADDR - : "(Default IPv6 destination address not set)"); + : "(not set)"); } else { NET_INFO("Setting destination IP address %s", net_sprint_ipv6_addr(&in6_addr_dst.sin6_addr)); @@ -1136,7 +1137,7 @@ void zperf_shell_init(void) ret = net_addr_pton(AF_INET, MY_IP4ADDR, &in4_addr_my.sin_addr); if (ret < 0) { - NET_WARN("Unable to set IP"); + NET_WARN("Unable to set %s address\n", "IPv4"); } else { NET_INFO("Setting IP address %s", net_sprint_ipv4_addr(&in4_addr_my.sin_addr)); @@ -1145,9 +1146,10 @@ void zperf_shell_init(void) ret = net_addr_pton(AF_INET, DST_IP4ADDR, &in4_addr_dst.sin_addr); if (ret < 0) { - NET_WARN("Unable to set IP %s", + NET_WARN("Unable to set destination %s address %s", + "IPv4", DST_IP4ADDR ? DST_IP4ADDR - : "(Default IPv4 destination address not set)"); + : "(not set)"); } else { NET_INFO("Setting destination IP address %s", net_sprint_ipv4_addr(&in4_addr_dst.sin_addr)); From b9b5d4751b8e10a932aec3fb8e658c27ac20bda7 Mon Sep 17 00:00:00 2001 From: Chaitanya Tata Date: Wed, 25 Oct 2023 22:14:26 +0530 Subject: [PATCH 362/421] [nrf fromtree] net: zperf: Set default IP addresses only if configured If the user has not configured then we see the error prints for the defaults always. Signed-off-by: Chaitanya Tata (cherry picked from commit dee1f2deaa71ae2595c4121500a95f06f8ce1c48) --- subsys/net/lib/zperf/zperf_shell.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/subsys/net/lib/zperf/zperf_shell.c b/subsys/net/lib/zperf/zperf_shell.c index c1f0c6a4950..bcf60dcf037 100644 --- a/subsys/net/lib/zperf/zperf_shell.c +++ b/subsys/net/lib/zperf/zperf_shell.c @@ -1110,7 +1110,7 @@ void zperf_shell_init(void) { int ret; - if (IS_ENABLED(CONFIG_NET_IPV6) && MY_IP6ADDR) { + if (IS_ENABLED(MY_IP4ADDR_SET) && MY_IP6ADDR) { ret = net_addr_pton(AF_INET6, MY_IP6ADDR, &in6_addr_my.sin6_addr); if (ret < 0) { @@ -1133,7 +1133,7 @@ void zperf_shell_init(void) } } - if (IS_ENABLED(CONFIG_NET_IPV4) && MY_IP4ADDR) { + if (IS_ENABLED(MY_IP4ADDR_SET) && MY_IP4ADDR) { ret = net_addr_pton(AF_INET, MY_IP4ADDR, &in4_addr_my.sin_addr); if (ret < 0) { From 5fac2b050b54701f9d73fefaba6ecd585aacbe43 Mon Sep 17 00:00:00 2001 From: Rahul Singh Date: Mon, 17 Jul 2023 09:45:39 +0100 Subject: [PATCH 363/421] [nrf fromtree] net: zperf: Add support for bind to host option for tcp/udp download The current zperf tcp/udp download command doesn't provide the option to bind the server to a specific host address. If there is more than one interface, it will not be possible to test each interface with zperf tcp/udp download command without building the Zpehyr. This patch will add support for zperf tcp/udp download command to bind server to host interface address. Signed-off-by: Rahul Singh (cherry picked from commit 6ef75a26eae2afb75062de1931affd8dce83afa9) --- include/zephyr/net/zperf.h | 1 + subsys/net/lib/zperf/zperf_shell.c | 63 ++++++++++++++++++----- subsys/net/lib/zperf/zperf_tcp_receiver.c | 24 ++++++--- subsys/net/lib/zperf/zperf_udp_receiver.c | 16 +++++- 4 files changed, 84 insertions(+), 20 deletions(-) diff --git a/include/zephyr/net/zperf.h b/include/zephyr/net/zperf.h index cd86541721e..fc809ae9278 100644 --- a/include/zephyr/net/zperf.h +++ b/include/zephyr/net/zperf.h @@ -43,6 +43,7 @@ struct zperf_upload_params { struct zperf_download_params { uint16_t port; + struct sockaddr addr; }; struct zperf_results { diff --git a/subsys/net/lib/zperf/zperf_shell.c b/subsys/net/lib/zperf/zperf_shell.c index bcf60dcf037..b32654f44bc 100644 --- a/subsys/net/lib/zperf/zperf_shell.c +++ b/subsys/net/lib/zperf/zperf_shell.c @@ -178,6 +178,39 @@ static int parse_ipv4_addr(const struct shell *sh, char *host, char *port, return 0; } +static int zperf_bind_host(const struct shell *sh, + size_t argc, char *argv[], + struct zperf_download_params *param) +{ + int ret; + + /* Parse options */ + if (argc >= 2) { + param->port = strtoul(argv[1], NULL, 10); + } else { + param->port = DEF_PORT; + } + + if (argc >= 3) { + char *addr_str = argv[2]; + struct sockaddr addr; + + memset(&addr, 0, sizeof(addr)); + + ret = net_ipaddr_parse(addr_str, strlen(addr_str), &addr); + if (ret < 0) { + shell_fprintf(sh, SHELL_WARNING, + "Cannot parse address \"%s\"\n", + addr_str); + return ret; + } + + memcpy(¶m->addr, &addr, sizeof(struct sockaddr)); + } + + return 0; +} + static int cmd_setip(const struct shell *sh, size_t argc, char *argv[]) { int start = 0; @@ -333,10 +366,12 @@ static int cmd_udp_download(const struct shell *sh, size_t argc, struct zperf_download_params param = { 0 }; int ret; - if (argc >= 2) { - param.port = strtoul(argv[1], NULL, 10); - } else { - param.port = DEF_PORT; + ret = zperf_bind_host(sh, argc, argv, ¶m); + if (ret < 0) { + shell_fprintf(sh, SHELL_WARNING, + "Unable to bind host.\n"); + shell_help(sh); + return -ENOEXEC; } ret = zperf_udp_download(¶m, udp_session_cb, (void *)sh); @@ -1072,10 +1107,12 @@ static int cmd_tcp_download(const struct shell *sh, size_t argc, struct zperf_download_params param = { 0 }; int ret; - if (argc >= 2) { - param.port = strtoul(argv[1], NULL, 10); - } else { - param.port = DEF_PORT; + ret = zperf_bind_host(sh, argc, argv, ¶m); + if (ret < 0) { + shell_fprintf(sh, SHELL_WARNING, + "Unable to bind host.\n"); + shell_help(sh); + return -ENOEXEC; } ret = zperf_tcp_download(¶m, tcp_session_cb, (void *)sh); @@ -1208,8 +1245,9 @@ SHELL_STATIC_SUBCMD_SET_CREATE(zperf_cmd_tcp, , cmd_tcp_upload2), SHELL_CMD(download, &zperf_cmd_tcp_download, - "[]\n" - "Example: tcp download 5001\n", + "[]: Server port to listen on/connect to\n" + "[]: Bind to , an interface address\n" + "Example: tcp download 5001 192.168.0.1\n", cmd_tcp_download), SHELL_SUBCMD_SET_END ); @@ -1266,8 +1304,9 @@ SHELL_STATIC_SUBCMD_SET_CREATE(zperf_cmd_udp, , cmd_udp_upload2), SHELL_CMD(download, &zperf_cmd_udp_download, - "[]\n" - "Example: udp download 5001\n", + "[]: Server port to listen on/connect to\n" + "[]: Bind to , an interface address\n" + "Example: udp download 5001 192.168.0.1\n", cmd_udp_download), SHELL_SUBCMD_SET_END ); diff --git a/subsys/net/lib/zperf/zperf_tcp_receiver.c b/subsys/net/lib/zperf/zperf_tcp_receiver.c index 25f9adc3494..614e1af6d03 100644 --- a/subsys/net/lib/zperf/zperf_tcp_receiver.c +++ b/subsys/net/lib/zperf/zperf_tcp_receiver.c @@ -46,6 +46,7 @@ static void *tcp_user_data; static bool tcp_server_running; static bool tcp_server_stop; static uint16_t tcp_server_port; +static struct sockaddr tcp_server_addr; static K_SEM_DEFINE(tcp_server_run, 0, 1); static void tcp_received(const struct sockaddr *addr, size_t datalen) @@ -150,6 +151,7 @@ static void tcp_server_session(void) if (IS_ENABLED(CONFIG_NET_IPV4)) { struct sockaddr_in *in4_addr = zperf_get_sin(); + const struct in_addr *addr = NULL; fds[SOCK_ID_IPV4_LISTEN].fd = zsock_socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); @@ -158,7 +160,12 @@ static void tcp_server_session(void) goto error; } - if (MY_IP4ADDR && strlen(MY_IP4ADDR)) { + addr = &net_sin(&tcp_server_addr)->sin_addr; + + if (!net_ipv4_is_addr_unspecified(addr)) { + memcpy(&in4_addr->sin_addr, addr, + sizeof(struct in_addr)); + } else if (MY_IP4ADDR && strlen(MY_IP4ADDR)) { /* Use Setting IP */ ret = zperf_get_ipv4_addr(MY_IP4ADDR, &in4_addr->sin_addr); @@ -167,9 +174,8 @@ static void tcp_server_session(void) goto use_existing_ipv4; } } else { - /* Use existing IP */ - const struct in_addr *addr; use_existing_ipv4: + /* Use existing IP */ addr = zperf_get_default_if_in4_addr(); if (!addr) { NET_ERR("Unable to get IPv4 by default"); @@ -197,6 +203,7 @@ static void tcp_server_session(void) if (IS_ENABLED(CONFIG_NET_IPV6)) { struct sockaddr_in6 *in6_addr = zperf_get_sin6(); + const struct in6_addr *addr = NULL; fds[SOCK_ID_IPV6_LISTEN].fd = zsock_socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP); @@ -205,7 +212,12 @@ static void tcp_server_session(void) goto error; } - if (MY_IP6ADDR && strlen(MY_IP6ADDR)) { + addr = &net_sin6(&tcp_server_addr)->sin6_addr; + + if (!net_ipv6_is_addr_unspecified(addr)) { + memcpy(&in6_addr->sin6_addr, addr, + sizeof(struct in6_addr)); + } else if (MY_IP6ADDR && strlen(MY_IP6ADDR)) { /* Use Setting IP */ ret = zperf_get_ipv6_addr(MY_IP6ADDR, MY_PREFIX_LEN_STR, @@ -215,9 +227,8 @@ static void tcp_server_session(void) goto use_existing_ipv6; } } else { - /* Use existing IP */ - const struct in6_addr *addr; use_existing_ipv6: + /* Use existing IP */ addr = zperf_get_default_if_in6_addr(); if (!addr) { NET_ERR("Unable to get IPv6 by default"); @@ -387,6 +398,7 @@ int zperf_tcp_download(const struct zperf_download_params *param, tcp_server_port = param->port; tcp_server_running = true; tcp_server_stop = false; + memcpy(&tcp_server_addr, ¶m->addr, sizeof(struct sockaddr)); k_sem_give(&tcp_server_run); diff --git a/subsys/net/lib/zperf/zperf_udp_receiver.c b/subsys/net/lib/zperf/zperf_udp_receiver.c index f96acde6f49..cf29760e1c6 100644 --- a/subsys/net/lib/zperf/zperf_udp_receiver.c +++ b/subsys/net/lib/zperf/zperf_udp_receiver.c @@ -48,6 +48,7 @@ static void *udp_user_data; static bool udp_server_running; static bool udp_server_stop; static uint16_t udp_server_port; +static struct sockaddr udp_server_addr; static K_SEM_DEFINE(udp_server_run, 0, 1); static inline void build_reply(struct zperf_udp_datagram *hdr, @@ -251,7 +252,12 @@ static void udp_server_session(void) goto error; } - if (MY_IP4ADDR && strlen(MY_IP4ADDR)) { + in4_addr = &net_sin(&udp_server_addr)->sin_addr; + + if (!net_ipv4_is_addr_unspecified(in4_addr)) { + memcpy(&in4_addr_my->sin_addr, in4_addr, + sizeof(struct in_addr)); + } else if (MY_IP4ADDR && strlen(MY_IP4ADDR)) { /* Use setting IP */ ret = zperf_get_ipv4_addr(MY_IP4ADDR, &in4_addr_my->sin_addr); @@ -301,7 +307,12 @@ static void udp_server_session(void) goto error; } - if (MY_IP6ADDR && strlen(MY_IP6ADDR)) { + in6_addr = &net_sin6(&udp_server_addr)->sin6_addr; + + if (!net_ipv6_is_addr_unspecified(in6_addr)) { + memcpy(&in6_addr_my->sin6_addr, in6_addr, + sizeof(struct in6_addr)); + } else if (MY_IP6ADDR && strlen(MY_IP6ADDR)) { /* Use setting IP */ ret = zperf_get_ipv6_addr(MY_IP6ADDR, MY_PREFIX_LEN_STR, @@ -441,6 +452,7 @@ int zperf_udp_download(const struct zperf_download_params *param, udp_server_port = param->port; udp_server_running = true; udp_server_stop = false; + memcpy(&udp_server_addr, ¶m->addr, sizeof(struct sockaddr)); k_sem_give(&udp_server_run); From 7ed5a305f4b4e741e855e3dbb89f3af30f2de115 Mon Sep 17 00:00:00 2001 From: Chaitanya Tata Date: Wed, 25 Oct 2023 23:18:50 +0530 Subject: [PATCH 364/421] [nrf fromtree] net: zperf: By default bind to any IP address Default behaviour should only bind to port independent of IP, this allows even multicast/broadcast L4 traffic to be received. User can always specify a specific address to bind using shell or Kconfig or API. Signed-off-by: Chaitanya Tata (cherry picked from commit a1024f6aebd90b1a218bf003c8b97e5e7c9b0472) --- subsys/net/lib/zperf/zperf_common.c | 21 ----------------- subsys/net/lib/zperf/zperf_internal.h | 3 --- subsys/net/lib/zperf/zperf_tcp_receiver.c | 27 ++++++---------------- subsys/net/lib/zperf/zperf_udp_receiver.c | 28 +++++++---------------- 4 files changed, 15 insertions(+), 64 deletions(-) diff --git a/subsys/net/lib/zperf/zperf_common.c b/subsys/net/lib/zperf/zperf_common.c index efe36cf69cd..29568eeef5b 100644 --- a/subsys/net/lib/zperf/zperf_common.c +++ b/subsys/net/lib/zperf/zperf_common.c @@ -109,27 +109,6 @@ int zperf_get_ipv4_addr(char *host, struct in_addr *addr) return 0; } - -const struct in_addr *zperf_get_default_if_in4_addr(void) -{ -#if CONFIG_NET_IPV4 - return net_if_ipv4_select_src_addr(NULL, - net_ipv4_unspecified_address()); -#else - return NULL; -#endif -} - -const struct in6_addr *zperf_get_default_if_in6_addr(void) -{ -#if CONFIG_NET_IPV6 - return net_if_ipv6_select_src_addr(NULL, - net_ipv6_unspecified_address()); -#else - return NULL; -#endif -} - int zperf_prepare_upload_sock(const struct sockaddr *peer_addr, int tos, int priority, int proto) { diff --git a/subsys/net/lib/zperf/zperf_internal.h b/subsys/net/lib/zperf/zperf_internal.h index 96dd9ea9123..592424a9446 100644 --- a/subsys/net/lib/zperf/zperf_internal.h +++ b/subsys/net/lib/zperf/zperf_internal.h @@ -95,9 +95,6 @@ struct sockaddr_in *zperf_get_sin(void); extern void connect_ap(char *ssid); -const struct in_addr *zperf_get_default_if_in4_addr(void); -const struct in6_addr *zperf_get_default_if_in6_addr(void); - int zperf_prepare_upload_sock(const struct sockaddr *peer_addr, int tos, int priority, int proto); diff --git a/subsys/net/lib/zperf/zperf_tcp_receiver.c b/subsys/net/lib/zperf/zperf_tcp_receiver.c index 614e1af6d03..6cc3374d0ae 100644 --- a/subsys/net/lib/zperf/zperf_tcp_receiver.c +++ b/subsys/net/lib/zperf/zperf_tcp_receiver.c @@ -171,18 +171,11 @@ static void tcp_server_session(void) &in4_addr->sin_addr); if (ret < 0) { NET_WARN("Unable to set IPv4"); - goto use_existing_ipv4; + goto use_any_ipv4; } } else { -use_existing_ipv4: - /* Use existing IP */ - addr = zperf_get_default_if_in4_addr(); - if (!addr) { - NET_ERR("Unable to get IPv4 by default"); - goto error; - } - memcpy(&in4_addr->sin_addr, addr, - sizeof(struct in_addr)); +use_any_ipv4: + in4_addr->sin_addr.s_addr = INADDR_ANY; } in4_addr->sin_port = htons(tcp_server_port); @@ -224,18 +217,12 @@ static void tcp_server_session(void) &in6_addr->sin6_addr); if (ret < 0) { NET_WARN("Unable to set IPv6"); - goto use_existing_ipv6; + goto use_any_ipv6; } } else { -use_existing_ipv6: - /* Use existing IP */ - addr = zperf_get_default_if_in6_addr(); - if (!addr) { - NET_ERR("Unable to get IPv6 by default"); - goto error; - } - memcpy(&in6_addr->sin6_addr, addr, - sizeof(struct in6_addr)); +use_any_ipv6: + memcpy(&in6_addr->sin6_addr, net_ipv6_unspecified_address(), + sizeof(struct in6_addr)); } in6_addr->sin6_port = htons(tcp_server_port); diff --git a/subsys/net/lib/zperf/zperf_udp_receiver.c b/subsys/net/lib/zperf/zperf_udp_receiver.c index cf29760e1c6..2724da4b1a9 100644 --- a/subsys/net/lib/zperf/zperf_udp_receiver.c +++ b/subsys/net/lib/zperf/zperf_udp_receiver.c @@ -263,18 +263,11 @@ static void udp_server_session(void) &in4_addr_my->sin_addr); if (ret < 0) { NET_WARN("Unable to set IPv4"); - goto use_existing_ipv4; + goto use_any_ipv4; } } else { - use_existing_ipv4: - /* Use existing IP */ - in4_addr = zperf_get_default_if_in4_addr(); - if (!in4_addr) { - NET_ERR("Unable to get IPv4 by default"); - goto error; - } - memcpy(&in4_addr_my->sin_addr, in4_addr, - sizeof(struct in_addr)); +use_any_ipv4: + in4_addr_my->sin_addr.s_addr = INADDR_ANY; } NET_INFO("Binding to %s", @@ -319,18 +312,13 @@ static void udp_server_session(void) &in6_addr_my->sin6_addr); if (ret < 0) { NET_WARN("Unable to set IPv6"); - goto use_existing_ipv6; + goto use_any_ipv6; } } else { - use_existing_ipv6: - /* Use existing IP */ - in6_addr = zperf_get_default_if_in6_addr(); - if (!in6_addr) { - NET_ERR("Unable to get IPv4 by default"); - goto error; - } - memcpy(&in6_addr_my->sin6_addr, in6_addr, - sizeof(struct in6_addr)); +use_any_ipv6: + memcpy(&in6_addr_my->sin6_addr, + net_ipv6_unspecified_address(), + sizeof(struct in6_addr)); } NET_INFO("Binding to %s", From f0b15a5617adc94c29466827aeac051f5f157e3f Mon Sep 17 00:00:00 2001 From: Chaitanya Tata Date: Thu, 2 Nov 2023 17:49:35 +0530 Subject: [PATCH 365/421] [nrf fromtree] net: zperf: Fix the check for IPv6 It was typo. Signed-off-by: Chaitanya Tata (cherry picked from commit d4d96b3df2e44b12aa64ee46edcf69339d5f63e2) --- subsys/net/lib/zperf/zperf_shell.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subsys/net/lib/zperf/zperf_shell.c b/subsys/net/lib/zperf/zperf_shell.c index b32654f44bc..b61501d0e9e 100644 --- a/subsys/net/lib/zperf/zperf_shell.c +++ b/subsys/net/lib/zperf/zperf_shell.c @@ -1147,7 +1147,7 @@ void zperf_shell_init(void) { int ret; - if (IS_ENABLED(MY_IP4ADDR_SET) && MY_IP6ADDR) { + if (IS_ENABLED(MY_IP6ADDR_SET) && MY_IP6ADDR) { ret = net_addr_pton(AF_INET6, MY_IP6ADDR, &in6_addr_my.sin6_addr); if (ret < 0) { From 2b1d418a6c8b17e028204bbefe4500f0286d46d4 Mon Sep 17 00:00:00 2001 From: Alexander Svensen Date: Mon, 6 Nov 2023 10:39:08 +0100 Subject: [PATCH 366/421] [nrf noup] testspec: Add audio - Add filter for audio tests Signed-off-by: Alexander Svensen --- .github/test-spec.yml | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/.github/test-spec.yml b/.github/test-spec.yml index c01ae703adf..007f4307aa9 100644 --- a/.github/test-spec.yml +++ b/.github/test-spec.yml @@ -218,3 +218,25 @@ - "subsys/bluetooth/**/*" - "!subsys/bluetooth/mesh/**/*" - "!subsys/bluetooth/audio/**/*" + +"CI-audio-test": + - "boards/arm/nrf5340_audio_dk_nrf5340/**/*" + - "drivers/flash/**/*" + - "drivers/spi/**/*" + - "drivers/gpio/**/*" + - "drivers/i2c/**/*" + - "drivers/watchdog/**/*" + - "include/dfu/**/*" + - "include/mgmt/mcumgr/**/*" + - "samples/bluetooth/hci_rpmsg/**/*" + - "soc/arm/nordic_nrf/**/*" + - "subsys/bluetooth/audio/**/*" + - "subsys/bluetooth/host/**/*" + - "subsys/dfu/**/*" + - "subsys/fs/**/*" + - "subsys/mgmt/mcumgr/**/*" + - "subsys/sd/**/*" + - "subsys/storage/**/*" + - "subsys/task_wdt/**/*" + - "subsys/usb/**/*" + - "subsys/zbus/**/*" From 902f4a417ae968e3fb1ebd97f72b1795c433a497 Mon Sep 17 00:00:00 2001 From: Chaitanya Tata Date: Fri, 3 Nov 2023 00:38:43 +0530 Subject: [PATCH 367/421] [nrf fromtree] wifi: shell: Fix default band value The enum is mainly to print output of band, so, the default value is 0 which means 2.4GHz, which is not correct when using it to configure like in connect. Fix the default value to unknown i.e., no user preference. This way we can use same enum for both set and get. Signed-off-by: Chaitanya Tata (cherry picked from commit 8c179870d426b18d24c8c359c52f8a30dd1bc0e5) --- subsys/net/l2/wifi/wifi_shell.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/subsys/net/l2/wifi/wifi_shell.c b/subsys/net/l2/wifi/wifi_shell.c index 592ac50cd8e..7c7bb7b01f6 100644 --- a/subsys/net/l2/wifi/wifi_shell.c +++ b/subsys/net/l2/wifi/wifi_shell.c @@ -341,6 +341,8 @@ static int __wifi_args_to_params(size_t argc, char *argv[], return -EINVAL; } + params->band = WIFI_FREQ_BAND_UNKNOWN; + /* SSID */ params->ssid = argv[0]; params->ssid_length = strlen(params->ssid); From d36ea76f95b7b50cc31b45f207b2716ea4302cb8 Mon Sep 17 00:00:00 2001 From: Chaitanya Tata Date: Fri, 3 Nov 2023 00:41:39 +0530 Subject: [PATCH 368/421] [nrf fromtree] wifi: shell: Move defaults to beginning This sets defaults first and then overrides if configured, easier to read. Signed-off-by: Chaitanya Tata (cherry picked from commit d12627e70f9f13d7dcdbac46886aede417a71cdd) --- subsys/net/l2/wifi/wifi_shell.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/subsys/net/l2/wifi/wifi_shell.c b/subsys/net/l2/wifi/wifi_shell.c index 7c7bb7b01f6..a9837bbaf6b 100644 --- a/subsys/net/l2/wifi/wifi_shell.c +++ b/subsys/net/l2/wifi/wifi_shell.c @@ -341,7 +341,10 @@ static int __wifi_args_to_params(size_t argc, char *argv[], return -EINVAL; } + /* Defaults */ params->band = WIFI_FREQ_BAND_UNKNOWN; + params->channel = WIFI_CHANNEL_ANY; + params->security = WIFI_SECURITY_TYPE_NONE; /* SSID */ params->ssid = argv[0]; @@ -362,8 +365,6 @@ static int __wifi_args_to_params(size_t argc, char *argv[], } idx++; - } else { - params->channel = WIFI_CHANNEL_ANY; } /* PSK (optional) */ @@ -402,8 +403,6 @@ static int __wifi_args_to_params(size_t argc, char *argv[], params->psk_length > WIFI_SAE_PSWD_MAX_LEN)) { return -EINVAL; } - } else { - params->security = WIFI_SECURITY_TYPE_NONE; } From df801013e317c988eb4a1fad2e8a6e2a438c10d5 Mon Sep 17 00:00:00 2001 From: Maciej Perkowski Date: Wed, 6 Sep 2023 16:52:16 +0200 Subject: [PATCH 369/421] [nrf fromtree] twister: Add "path" entry to json test report "Path" is a path (relative to zephyr) to a directory with test suite's definition. Such entry helps to locate a given test. (cherry picked from commit 4e4b743fe12266135b9e808215bb415a059b06d9) Signed-off-by: Maciej Perkowski --- scripts/pylib/twister/twisterlib/reports.py | 1 + scripts/pylib/twister/twisterlib/testsuite.py | 2 ++ 2 files changed, 3 insertions(+) diff --git a/scripts/pylib/twister/twisterlib/reports.py b/scripts/pylib/twister/twisterlib/reports.py index bd005d4319a..0b34a5d309b 100644 --- a/scripts/pylib/twister/twisterlib/reports.py +++ b/scripts/pylib/twister/twisterlib/reports.py @@ -258,6 +258,7 @@ def json_report(self, filename, version="NA"): "name": instance.testsuite.name, "arch": instance.platform.arch, "platform": instance.platform.name, + "path": instance.testsuite.source_dir_rel } if instance.run_id: suite['run_id'] = instance.run_id diff --git a/scripts/pylib/twister/twisterlib/testsuite.py b/scripts/pylib/twister/twisterlib/testsuite.py index 3f4a71e4a8c..faacf669c1d 100644 --- a/scripts/pylib/twister/twisterlib/testsuite.py +++ b/scripts/pylib/twister/twisterlib/testsuite.py @@ -373,6 +373,8 @@ def __init__(self, suite_root, suite_path, name, data=None): self.id = name self.source_dir = suite_path + self.source_dir_rel = os.path.relpath(os.path.realpath(suite_path), + start=canonical_zephyr_base) self.yamlfile = suite_path self.testcases = [] From b19ec69bf9ef2c7ac5d7fa37b6f4d934de6e567d Mon Sep 17 00:00:00 2001 From: Maciej Perkowski Date: Fri, 21 Jul 2023 16:09:39 +0200 Subject: [PATCH 370/421] [nrf fromtree] twister: Add options deciding if paths be included in tests' names Test suites names are not being handled uniformly for tests not in zephyr tree. Their names depend on -T arg used in twister's CLI. The newly added options allow to select if twister should add paths to suite names. This is needed if test plans are to be used for tests outside of zephyr tree. (cherry picked from commit 066cc2c9d2ee86c35cb10e38bc7ba152c1560602) Signed-off-by: Maciej Perkowski --- .../pylib/twister/twisterlib/environment.py | 15 +++++++ scripts/pylib/twister/twisterlib/reports.py | 10 +++-- .../pylib/twister/twisterlib/testinstance.py | 7 +++- scripts/pylib/twister/twisterlib/testplan.py | 2 +- scripts/pylib/twister/twisterlib/testsuite.py | 16 +++++--- scripts/tests/twister/test_harness.py | 1 + scripts/tests/twister/test_testsuite.py | 40 +++++++++++++++++++ 7 files changed, 81 insertions(+), 10 deletions(-) diff --git a/scripts/pylib/twister/twisterlib/environment.py b/scripts/pylib/twister/twisterlib/environment.py index 160233a66fe..b5018bc1f01 100644 --- a/scripts/pylib/twister/twisterlib/environment.py +++ b/scripts/pylib/twister/twisterlib/environment.py @@ -437,6 +437,21 @@ def add_parse_arguments(parser = None): help="Re-use the outdir before building. Will result in " "faster compilation since builds will be incremental.") + parser.add_argument( + '--detailed-test-id', action='store_true', + help="Include paths to tests' locations in tests' names. Names will follow " + "PATH_TO_TEST/SCENARIO_NAME schema " + "e.g. samples/hello_world/sample.basic.helloworld") + + parser.add_argument( + "--no-detailed-test-id", dest='detailed_test_id', action="store_false", + help="Don't put paths into tests' names. " + "With this arg a test name will be a scenario name " + "e.g. sample.basic.helloworld.") + + # Include paths in names by default. + parser.set_defaults(detailed_test_id=True) + # To be removed in favor of --detailed-skipped-report parser.add_argument( "--no-skipped-report", action="store_true", diff --git a/scripts/pylib/twister/twisterlib/reports.py b/scripts/pylib/twister/twisterlib/reports.py index 0b34a5d309b..c1f160caad9 100644 --- a/scripts/pylib/twister/twisterlib/reports.py +++ b/scripts/pylib/twister/twisterlib/reports.py @@ -420,6 +420,7 @@ def footprint_reports(self, report, show_footprint, all_deltas, def synopsis(self): cnt = 0 example_instance = None + detailed_test_id = self.env.options.detailed_test_id for instance in self.instances.values(): if instance.status not in ["passed", "filtered", "skipped"]: cnt = cnt + 1 @@ -435,11 +436,14 @@ def synopsis(self): if cnt and example_instance: logger.info("") logger.info("To rerun the tests, call twister using the following commandline:") - logger.info("west twister -p -s , for example:") + extra_parameters = '' if detailed_test_id else ' --no-detailed-test-id' + logger.info(f"west twister -p -s {extra_parameters}, for example:") logger.info("") - logger.info(f"west twister -p {example_instance.platform.name} -s {example_instance.testsuite.name}") + logger.info(f"west twister -p {example_instance.platform.name} -s {example_instance.testsuite.name}" + f"{extra_parameters}") logger.info(f"or with west:") - logger.info(f"west build -p -b {example_instance.platform.name} -T {example_instance.testsuite.name}") + logger.info(f"west build -p -b {example_instance.platform.name} " + f"{example_instance.testsuite.source_dir_rel} -T {example_instance.testsuite.id}") logger.info("-+" * 40) def summary(self, results, unrecognized_sections, duration): diff --git a/scripts/pylib/twister/twisterlib/testinstance.py b/scripts/pylib/twister/twisterlib/testinstance.py index ccfc3cd06d4..b9e7d411cb5 100644 --- a/scripts/pylib/twister/twisterlib/testinstance.py +++ b/scripts/pylib/twister/twisterlib/testinstance.py @@ -55,7 +55,12 @@ def __init__(self, testsuite, platform, outdir): self.name = os.path.join(platform.name, testsuite.name) self.run_id = self._get_run_id() self.dut = None - self.build_dir = os.path.join(outdir, platform.name, testsuite.name) + if testsuite.detailed_test_id: + self.build_dir = os.path.join(outdir, platform.name, testsuite.name) + else: + # if suite is not in zephyr, keep only the part after ".." in reconstructed dir structure + source_dir_rel = testsuite.source_dir_rel.rsplit(os.pardir+os.path.sep, 1)[-1] + self.build_dir = os.path.join(outdir, platform.name, source_dir_rel, testsuite.name) self.domains = None diff --git a/scripts/pylib/twister/twisterlib/testplan.py b/scripts/pylib/twister/twisterlib/testplan.py index 1d9c625b28a..209b76c65d2 100755 --- a/scripts/pylib/twister/twisterlib/testplan.py +++ b/scripts/pylib/twister/twisterlib/testplan.py @@ -524,7 +524,7 @@ def add_testsuites(self, testsuite_filter=[]): for name in parsed_data.scenarios.keys(): suite_dict = parsed_data.get_scenario(name) - suite = TestSuite(root, suite_path, name, data=suite_dict) + suite = TestSuite(root, suite_path, name, data=suite_dict, detailed_test_id=self.options.detailed_test_id) suite.add_subcases(suite_dict, subcases, ztest_suite_names) if testsuite_filter: if suite.name and suite.name in testsuite_filter: diff --git a/scripts/pylib/twister/twisterlib/testsuite.py b/scripts/pylib/twister/twisterlib/testsuite.py index faacf669c1d..39c21098718 100644 --- a/scripts/pylib/twister/twisterlib/testsuite.py +++ b/scripts/pylib/twister/twisterlib/testsuite.py @@ -348,7 +348,7 @@ class TestSuite(DisablePyTestCollectionMixin): """Class representing a test application """ - def __init__(self, suite_root, suite_path, name, data=None): + def __init__(self, suite_root, suite_path, name, data=None, detailed_test_id=True): """TestSuite constructor. This gets called by TestPlan as it finds and reads test yaml files. @@ -369,12 +369,14 @@ def __init__(self, suite_root, suite_path, name, data=None): """ workdir = os.path.relpath(suite_path, suite_root) - self.name = self.get_unique(suite_root, workdir, name) + + assert self.check_suite_name(name, suite_root, workdir) + self.detailed_test_id = detailed_test_id + self.name = self.get_unique(suite_root, workdir, name) if self.detailed_test_id else name self.id = name self.source_dir = suite_path - self.source_dir_rel = os.path.relpath(os.path.realpath(suite_path), - start=canonical_zephyr_base) + self.source_dir_rel = os.path.relpath(os.path.realpath(suite_path), start=canonical_zephyr_base) self.yamlfile = suite_path self.testcases = [] @@ -427,10 +429,14 @@ def get_unique(testsuite_root, workdir, name): # workdir can be "." unique = os.path.normpath(os.path.join(relative_ts_root, workdir, name)) + return unique + + @staticmethod + def check_suite_name(name, testsuite_root, workdir): check = name.split(".") if len(check) < 2: raise TwisterException(f"""bad test name '{name}' in {testsuite_root}/{workdir}. \ Tests should reference the category and subsystem with a dot as a separator. """ ) - return unique + return True diff --git a/scripts/tests/twister/test_harness.py b/scripts/tests/twister/test_harness.py index a33d6431ab4..1da2aed3f46 100644 --- a/scripts/tests/twister/test_harness.py +++ b/scripts/tests/twister/test_harness.py @@ -40,6 +40,7 @@ def gtest(): mock_platform.name = "mock_platform" mock_testsuite = mock.Mock() mock_testsuite.name = "mock_testsuite" + mock_testsuite.detailed_test_id = True mock_testsuite.id = "id" mock_testsuite.testcases = [] instance = TestInstance(testsuite=mock_testsuite, platform=mock_platform, outdir="") diff --git a/scripts/tests/twister/test_testsuite.py b/scripts/tests/twister/test_testsuite.py index 49f19d0d0f8..23e4f8ed034 100644 --- a/scripts/tests/twister/test_testsuite.py +++ b/scripts/tests/twister/test_testsuite.py @@ -749,3 +749,43 @@ def test_testcase_dunders(): assert case_lesser < case_greater assert str(case_greater) == 'a greater name' assert repr(case_greater) == '' + + +TESTDATA_11 = [ + ( + ZEPHYR_BASE + '/scripts/tests/twister/test_data/testsuites', + ZEPHYR_BASE + '/scripts/tests/twister/test_data/testsuites/tests/test_a', + 'test_a.check_1', + 'test_a.check_1' + ), + ( + ZEPHYR_BASE, + ZEPHYR_BASE, + 'test_a.check_1', + 'test_a.check_1' + ), + ( + ZEPHYR_BASE, + ZEPHYR_BASE + '/scripts/tests/twister/test_data/testsuites/test_b', + 'test_b.check_1', + 'test_b.check_1' + ), + ( + os.path.join(ZEPHYR_BASE, 'scripts/tests'), + os.path.join(ZEPHYR_BASE, 'scripts/tests'), + 'test_b.check_1', + 'test_b.check_1' + ), + ( + ZEPHYR_BASE, + ZEPHYR_BASE, + 'test_a.check_1.check_2', + 'test_a.check_1.check_2' + ), +] +@pytest.mark.parametrize("testsuite_root, suite_path, name, expected", TESTDATA_11) +def test_get_no_detailed_test_id(testsuite_root, suite_path, name, expected): + '''Test to check if the name without path is given for each testsuite''' + suite = TestSuite(testsuite_root, suite_path, name, detailed_test_id=False) + print(suite.name) + assert suite.name == expected From e4052b3643de84d69f5d6fb5656295298d4aac62 Mon Sep 17 00:00:00 2001 From: Maciej Perkowski Date: Thu, 12 Oct 2023 13:15:00 +0200 Subject: [PATCH 371/421] [nrf fromtree] twister: Fix error for --device-testing with not runnable integration An urforseen error was introduce with #62713. When "--device-testing" or "--filter runnable" is used in CLI, twister will skip tests which cannot be executed (not just built) on a given platform. If a given platform is among integration platforms it will cause an error. However, it shouldn't be the case. Such skip is intentional and shouldn't be an error. Fixed by assigning an existing Filter.CMD_LINE, which is exempted from being turned to error. fixes: #63844 (cherry picked from commit 4cd7df2eec31969e84cae74cb49b0bb5710c200d) Signed-off-by: Maciej Perkowski --- scripts/pylib/twister/twisterlib/testplan.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/pylib/twister/twisterlib/testplan.py b/scripts/pylib/twister/twisterlib/testplan.py index 209b76c65d2..ae122862d1e 100755 --- a/scripts/pylib/twister/twisterlib/testplan.py +++ b/scripts/pylib/twister/twisterlib/testplan.py @@ -740,7 +740,7 @@ def apply_filters(self, **kwargs): instance.add_filter("Not part of requested test plan", Filters.TESTSUITE) if runnable and not instance.run: - instance.add_filter("Not runnable on device", Filters.PLATFORM) + instance.add_filter("Not runnable on device", Filters.CMD_LINE) if self.options.integration and ts.integration_platforms and plat.name not in ts.integration_platforms: instance.add_filter("Not part of integration platforms", Filters.TESTSUITE) From 55257c34d335471c33fc2469f1c562e412efb4ed Mon Sep 17 00:00:00 2001 From: Maciej Perkowski Date: Mon, 24 Jul 2023 13:24:51 +0200 Subject: [PATCH 372/421] [nrf fromtree] scripts: Add --no-detailed-test-id arg to test_plan.py script An option --no-detailed-test-id was added to twister to help align names for test outside of zephyr tree. This commit add this arg to test_plan.py script which is then propagated to twister. (cherry picked from commit f9178926a983acd507c183910721138456e3794b) Signed-off-by: Maciej Perkowski --- scripts/ci/test_plan.py | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/scripts/ci/test_plan.py b/scripts/ci/test_plan.py index 8f2f24b0825..6251104c32e 100755 --- a/scripts/ci/test_plan.py +++ b/scripts/ci/test_plan.py @@ -86,7 +86,7 @@ def __repr__(self): return "".format(self.name) class Filters: - def __init__(self, modified_files, pull_request=False, platforms=[]): + def __init__(self, modified_files, pull_request=False, platforms=[], detailed_test_id=True): self.modified_files = modified_files self.twister_options = [] self.full_twister = False @@ -95,6 +95,7 @@ def __init__(self, modified_files, pull_request=False, platforms=[]): self.pull_request = pull_request self.platforms = platforms self.default_run = False + self.detailed_test_id = detailed_test_id def process(self): self.find_modules() @@ -112,6 +113,8 @@ def process(self): def get_plan(self, options, integration=False): fname = "_test_plan_partial.json" cmd = ["scripts/twister", "-c"] + options + ["--save-tests", fname ] + if not self.detailed_test_id: + cmd += ["--no-detailed-test-id"] if integration: cmd.append("--integration") @@ -353,6 +356,13 @@ def parse_args(): help="Number of tests per builder") parser.add_argument('-n', '--default-matrix', default=10, type=int, help="Number of tests per builder") + parser.add_argument('--detailed-test-id', action='store_true', + help="Include paths to tests' locations in tests' names.") + parser.add_argument("--no-detailed-test-id", dest='detailed_test_id', action="store_false", + help="Don't put paths into tests' names.") + + # Include paths in names by default. + parser.set_defaults(detailed_test_id=True) return parser.parse_args() @@ -375,8 +385,7 @@ def parse_args(): print("\n".join(files)) print("=========") - - f = Filters(files, args.pull_request, args.platform) + f = Filters(files, args.pull_request, args.platform, args.detailed_test_id) f.process() # remove dupes and filtered cases From 26dfd71e944b74eb2ec73e41689cd26c128f3566 Mon Sep 17 00:00:00 2001 From: Maciej Perkowski Date: Mon, 31 Jul 2023 13:05:35 +0200 Subject: [PATCH 373/421] [nrf fromtree] scripts: Allow test_plan.py to work with other than zephyr repos The test_plan.py script has a path to repository to be scanned for changes hard coded to zephyr. This patch separates zephyr path from such repository's path and adds an arg to pass repo to scan (cherry picked from commit f7c4d5f9d44b7cec85427235cb508a77bdbd898a) Signed-off-by: Maciej Perkowski --- scripts/ci/test_plan.py | 33 ++++++++++++++++++++++++--------- 1 file changed, 24 insertions(+), 9 deletions(-) diff --git a/scripts/ci/test_plan.py b/scripts/ci/test_plan.py index 6251104c32e..9a6f50f57d0 100755 --- a/scripts/ci/test_plan.py +++ b/scripts/ci/test_plan.py @@ -19,10 +19,17 @@ if "ZEPHYR_BASE" not in os.environ: exit("$ZEPHYR_BASE environment variable undefined.") -repository_path = Path(os.environ['ZEPHYR_BASE']) +# These are globaly used variables. They are assigned in __main__ and are visible in further methods +# however, pylint complains that it doesn't recognized them when used (used-before-assignment). +zephyr_base = Path(os.environ['ZEPHYR_BASE']) +repository_path = zephyr_base +repo_to_scan = zephyr_base +args = None + + logging.basicConfig(format='%(levelname)s: %(message)s', level=logging.INFO) -sys.path.append(os.path.join(repository_path, 'scripts')) +sys.path.append(os.path.join(zephyr_base, 'scripts')) import list_boards def _get_match_fn(globs, regexes): @@ -112,7 +119,7 @@ def process(self): def get_plan(self, options, integration=False): fname = "_test_plan_partial.json" - cmd = ["scripts/twister", "-c"] + options + ["--save-tests", fname ] + cmd = [f"{zephyr_base}/scripts/twister", "-c"] + options + ["--save-tests", fname ] if not self.detailed_test_id: cmd += ["--no-detailed-test-id"] if integration: @@ -131,7 +138,7 @@ def find_modules(self): if 'west.yml' in self.modified_files: print(f"Manifest file 'west.yml' changed") print("=========") - old_manifest_content = repo.git.show(f"{args.commits[:-2]}:west.yml") + old_manifest_content = repo_to_scan.git.show(f"{args.commits[:-2]}:west.yml") with open("west_old.yml", "w") as manifest: manifest.write(old_manifest_content) old_manifest = Manifest.from_file("west_old.yml") @@ -212,8 +219,12 @@ def find_boards(self): if p and p.groups(): boards.add(p.group(1)) - # Limit search to $ZEPHYR_BASE since this is where the changed files are - lb_args = argparse.Namespace(**{ 'arch_roots': [repository_path], 'board_roots': [repository_path] }) + roots = [zephyr_base] + if repository_path != zephyr_base: + roots.append(repository_path) + + # Look for boards in monitored repositories + lb_args = argparse.Namespace(**{ 'arch_roots': roots, 'board_roots': roots}) known_boards = list_boards.find_boards(lb_args) for b in boards: name_re = re.compile(b) @@ -268,7 +279,7 @@ def find_tests(self): def find_tags(self): - tag_cfg_file = os.path.join(repository_path, 'scripts', 'ci', 'tags.yaml') + tag_cfg_file = os.path.join(zephyr_base, 'scripts', 'ci', 'tags.yaml') with open(tag_cfg_file, 'r') as ymlfile: tags_config = yaml.safe_load(ymlfile) @@ -360,6 +371,8 @@ def parse_args(): help="Include paths to tests' locations in tests' names.") parser.add_argument("--no-detailed-test-id", dest='detailed_test_id', action="store_false", help="Don't put paths into tests' names.") + parser.add_argument('-r', '--repo-to-scan', default=None, + help="Repo to scan") # Include paths in names by default. parser.set_defaults(detailed_test_id=True) @@ -372,9 +385,11 @@ def parse_args(): args = parse_args() files = [] errors = 0 + if args.repo_to_scan: + repository_path = Path(args.repo_to_scan) if args.commits: - repo = Repo(repository_path) - commit = repo.git.diff("--name-only", args.commits) + repo_to_scan = Repo(repository_path) + commit = repo_to_scan.git.diff("--name-only", args.commits) files = commit.split("\n") elif args.modified_files: with open(args.modified_files, "r") as fp: From bd2c89e4a589eb0ad43c9a617d3308417b4ddda6 Mon Sep 17 00:00:00 2001 From: Maciej Perkowski Date: Tue, 25 Jul 2023 16:45:55 +0200 Subject: [PATCH 374/421] [nrf fromtree] scripts: Allow using alternative ignore-patters in test_plan.py Expand test_plan.py args with --ignore-path. This allows to provide an alternative lists of patterns for the script. Signed-off-by: Maciej Perkowski (cherry picked from commit 47405a114ad676abde2ac2e0d987aba916686576) Signed-off-by: Maciej Perkowski --- scripts/ci/test_plan.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/scripts/ci/test_plan.py b/scripts/ci/test_plan.py index 9a6f50f57d0..6ebcfc744bc 100755 --- a/scripts/ci/test_plan.py +++ b/scripts/ci/test_plan.py @@ -93,7 +93,7 @@ def __repr__(self): return "".format(self.name) class Filters: - def __init__(self, modified_files, pull_request=False, platforms=[], detailed_test_id=True): + def __init__(self, modified_files, ignore_path, pull_request=False, platforms=[], detailed_test_id=True): self.modified_files = modified_files self.twister_options = [] self.full_twister = False @@ -103,6 +103,7 @@ def __init__(self, modified_files, pull_request=False, platforms=[], detailed_te self.platforms = platforms self.default_run = False self.detailed_test_id = detailed_test_id + self.ignore_path = ignore_path def process(self): self.find_modules() @@ -317,7 +318,7 @@ def find_tags(self): logging.info(f'Potential tag based filters: {exclude_tags}') def find_excludes(self, skip=[]): - with open("scripts/ci/twister_ignore.txt", "r") as twister_ignore: + with open(self.ignore_path, "r") as twister_ignore: ignores = twister_ignore.read().splitlines() ignores = filter(lambda x: not x.startswith("#"), ignores) @@ -373,6 +374,9 @@ def parse_args(): help="Don't put paths into tests' names.") parser.add_argument('-r', '--repo-to-scan', default=None, help="Repo to scan") + parser.add_argument('--ignore-path', + default=os.path.join(zephyr_base, 'scripts', 'ci', 'twister_ignore.txt'), + help="Path to a text file with patterns of files to be matched against changed files") # Include paths in names by default. parser.set_defaults(detailed_test_id=True) @@ -400,7 +404,7 @@ def parse_args(): print("\n".join(files)) print("=========") - f = Filters(files, args.pull_request, args.platform, args.detailed_test_id) + f = Filters(files, args.ignore_path, args.pull_request, args.platform, args.detailed_test_id) f.process() # remove dupes and filtered cases From bff52954a69905e162abbbb49045b81cf8e7bee1 Mon Sep 17 00:00:00 2001 From: Maciej Perkowski Date: Wed, 2 Aug 2023 14:36:03 +0200 Subject: [PATCH 375/421] [nrf fromtree] scripts: Add arg to set_plan.py for alternative tag relation list Add --alt-tag arg for test_plan.py script. User can use it and point to an alternative file with tag-directories relations. If so, such file will be used instead of the default one. (cherry picked from commit 76926100048082cc559c85114f89dde2faa3ec3e) Signed-off-by: Maciej Perkowski --- scripts/ci/test_plan.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/scripts/ci/test_plan.py b/scripts/ci/test_plan.py index 6ebcfc744bc..6ee76b74aae 100755 --- a/scripts/ci/test_plan.py +++ b/scripts/ci/test_plan.py @@ -93,7 +93,7 @@ def __repr__(self): return "".format(self.name) class Filters: - def __init__(self, modified_files, ignore_path, pull_request=False, platforms=[], detailed_test_id=True): + def __init__(self, modified_files, ignore_path, alt_tags, pull_request=False, platforms=[], detailed_test_id=True): self.modified_files = modified_files self.twister_options = [] self.full_twister = False @@ -104,6 +104,7 @@ def __init__(self, modified_files, ignore_path, pull_request=False, platforms=[] self.default_run = False self.detailed_test_id = detailed_test_id self.ignore_path = ignore_path + self.tag_cfg_file = alt_tags def process(self): self.find_modules() @@ -280,8 +281,7 @@ def find_tests(self): def find_tags(self): - tag_cfg_file = os.path.join(zephyr_base, 'scripts', 'ci', 'tags.yaml') - with open(tag_cfg_file, 'r') as ymlfile: + with open(self.tag_cfg_file, 'r') as ymlfile: tags_config = yaml.safe_load(ymlfile) tags = {} @@ -377,6 +377,9 @@ def parse_args(): parser.add_argument('--ignore-path', default=os.path.join(zephyr_base, 'scripts', 'ci', 'twister_ignore.txt'), help="Path to a text file with patterns of files to be matched against changed files") + parser.add_argument('--alt-tags', + default=os.path.join(zephyr_base, 'scripts', 'ci', 'tags.yaml'), + help="Path to a file describing relations between directories and tags") # Include paths in names by default. parser.set_defaults(detailed_test_id=True) @@ -404,7 +407,7 @@ def parse_args(): print("\n".join(files)) print("=========") - f = Filters(files, args.ignore_path, args.pull_request, args.platform, args.detailed_test_id) + f = Filters(files, args.ignore_path, args.alt_tags, args.pull_request, args.platform, args.detailed_test_id) f.process() # remove dupes and filtered cases From dfbb9972f240c1e55d4e84dcdb941f91af552ea0 Mon Sep 17 00:00:00 2001 From: Maciej Perkowski Date: Wed, 2 Aug 2023 16:43:54 +0200 Subject: [PATCH 376/421] [nrf fromtree] scripts: Add arg to test_plan.py for alternative test locations The arg --testsuite-root was copied from twister. When it is used for test_plan.py it will be propagated to twister calls. This allows to make alternative test locations (e.g. from another repo) to work with test_plan.py (cherry picked from commit 0752d604430b2c77b535a51ad30735fb9f61ccbc) Signed-off-by: Maciej Perkowski --- scripts/ci/test_plan.py | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/scripts/ci/test_plan.py b/scripts/ci/test_plan.py index 6ee76b74aae..1388250716f 100755 --- a/scripts/ci/test_plan.py +++ b/scripts/ci/test_plan.py @@ -93,8 +93,10 @@ def __repr__(self): return "".format(self.name) class Filters: - def __init__(self, modified_files, ignore_path, alt_tags, pull_request=False, platforms=[], detailed_test_id=True): + def __init__(self, modified_files, ignore_path, alt_tags, testsuite_root, + pull_request=False, platforms=[], detailed_test_id=True): self.modified_files = modified_files + self.testsuite_root = testsuite_root self.twister_options = [] self.full_twister = False self.all_tests = [] @@ -119,11 +121,14 @@ def process(self): else: self.find_excludes() - def get_plan(self, options, integration=False): + def get_plan(self, options, integration=False, use_testsuite_root=True): fname = "_test_plan_partial.json" cmd = [f"{zephyr_base}/scripts/twister", "-c"] + options + ["--save-tests", fname ] if not self.detailed_test_id: cmd += ["--no-detailed-test-id"] + if self.testsuite_root and use_testsuite_root: + for root in self.testsuite_root: + cmd+=["-T", root] if integration: cmd.append("--integration") @@ -277,7 +282,7 @@ def find_tests(self): _options.extend(["-p", platform]) else: _options.append("--all") - self.get_plan(_options) + self.get_plan(_options, use_testsuite_root=False) def find_tags(self): @@ -380,6 +385,12 @@ def parse_args(): parser.add_argument('--alt-tags', default=os.path.join(zephyr_base, 'scripts', 'ci', 'tags.yaml'), help="Path to a file describing relations between directories and tags") + parser.add_argument( + "-T", "--testsuite-root", action="append", default=[], + help="Base directory to recursively search for test cases. All " + "testcase.yaml files under here will be processed. May be " + "called multiple times. Defaults to the 'samples/' and " + "'tests/' directories at the base of the Zephyr tree.") # Include paths in names by default. parser.set_defaults(detailed_test_id=True) @@ -407,7 +418,8 @@ def parse_args(): print("\n".join(files)) print("=========") - f = Filters(files, args.ignore_path, args.alt_tags, args.pull_request, args.platform, args.detailed_test_id) + f = Filters(files, args.ignore_path, args.alt_tags, args.testsuite_root, + args.pull_request, args.platform, args.detailed_test_id) f.process() # remove dupes and filtered cases From 158f0db91c3ab5455fb79e8fa3f07cb482c43b56 Mon Sep 17 00:00:00 2001 From: Maciej Perkowski Date: Thu, 17 Aug 2023 14:34:31 +0200 Subject: [PATCH 377/421] [nrf fromtree] scripts: Make workflow of test_plan.py script more robust The script was not resolving all detected changes uniformly: find_excludes() could skip or not certain patterns based on required testing scope. The idea was to not include files that were already handled by find_test() and find_boards() workflows. However, only boards and tests folders could be removed but not samples. This also led to blind spots: changes in some files were not triggering any tests. E.g. change in a test/common, where no corresponding yaml can be found by find_tests() which is also ignored by find_excludes(). In the new workflow a list of resolved files (for which find_arch(), find_tests() or find_boards() found scope) is created. Instead of using skip in find_excludes, files are excluded only if they were resolved. (cherry picked from commit 9f850010612f18925ea09fad3d99cadbd7c4b33f) Signed-off-by: Maciej Perkowski --- scripts/ci/test_plan.py | 39 +++++++++++++++++++++-------------- scripts/ci/twister_ignore.txt | 19 ----------------- 2 files changed, 24 insertions(+), 34 deletions(-) diff --git a/scripts/ci/test_plan.py b/scripts/ci/test_plan.py index 1388250716f..234d1302731 100755 --- a/scripts/ci/test_plan.py +++ b/scripts/ci/test_plan.py @@ -97,13 +97,13 @@ def __init__(self, modified_files, ignore_path, alt_tags, testsuite_root, pull_request=False, platforms=[], detailed_test_id=True): self.modified_files = modified_files self.testsuite_root = testsuite_root + self.resolved_files = [] self.twister_options = [] self.full_twister = False self.all_tests = [] self.tag_options = [] self.pull_request = pull_request self.platforms = platforms - self.default_run = False self.detailed_test_id = detailed_test_id self.ignore_path = ignore_path self.tag_cfg_file = alt_tags @@ -115,11 +115,7 @@ def process(self): if not self.platforms: self.find_archs() self.find_boards() - - if self.default_run: - self.find_excludes(skip=["tests/*", "boards/*/*/*"]) - else: - self.find_excludes() + self.find_excludes() def get_plan(self, options, integration=False, use_testsuite_root=True): fname = "_test_plan_partial.json" @@ -200,6 +196,8 @@ def find_archs(self): archs.add('riscv64') else: archs.add(p.group(1)) + # Modified file is treated as resolved, since a matching scope was found + self.resolved_files.append(f) _options = [] for arch in archs: @@ -218,6 +216,7 @@ def find_archs(self): def find_boards(self): boards = set() all_boards = set() + resolved = [] for f in self.modified_files: if f.endswith(".rst") or f.endswith(".png") or f.endswith(".jpg"): @@ -225,6 +224,7 @@ def find_boards(self): p = re.match(r"^boards\/[^/]+\/([^/]+)\/", f) if p and p.groups(): boards.add(p.group(1)) + resolved.append(f) roots = [zephyr_base] if repository_path != zephyr_base: @@ -239,10 +239,16 @@ def find_boards(self): if name_re.search(kb.name): all_boards.add(kb.name) + # If modified file is catched by "find_boards" workflow (change in "boards" dir AND board recognized) + # it means a proper testing scope for this file was found and this file can be removed + # from further consideration + for board in all_boards: + self.resolved_files.extend(list(filter(lambda f: board in f, resolved))) + _options = [] if len(all_boards) > 20: logging.warning(f"{len(boards)} boards changed, this looks like a global change, skipping test handling, revert to default.") - self.default_run = True + self.full_twister = True return for board in all_boards: @@ -262,6 +268,8 @@ def find_tests(self): if os.path.exists(os.path.join(d, "testcase.yaml")) or \ os.path.exists(os.path.join(d, "sample.yaml")): tests.add(d) + # Modified file is treated as resolved, since a matching scope was found + self.resolved_files.append(f) break else: d = os.path.dirname(d) @@ -272,7 +280,7 @@ def find_tests(self): if len(tests) > 20: logging.warning(f"{len(tests)} tests changed, this looks like a global change, skipping test handling, revert to default") - self.default_run = True + self.full_twister = True return if _options: @@ -328,21 +336,22 @@ def find_excludes(self, skip=[]): ignores = filter(lambda x: not x.startswith("#"), ignores) found = set() - files = list(filter(lambda x: x, self.modified_files)) + files_not_resolved = list(filter(lambda x: x not in self.resolved_files, self.modified_files)) for pattern in ignores: - if pattern in skip: - continue if pattern: - found.update(fnmatch.filter(files, pattern)) + found.update(fnmatch.filter(files_not_resolved, pattern)) logging.debug(found) - logging.debug(files) + logging.debug(files_not_resolved) - if sorted(files) != sorted(found): + # Full twister run can be ordered by detecting great number of tests/boards changed + # or if not all modified files were resolved (corresponding scope found) + self.full_twister = self.full_twister or sorted(files_not_resolved) != sorted(found) + + if self.full_twister: _options = [] logging.info(f'Need to run full or partial twister...') - self.full_twister = True if self.platforms: for platform in self.platforms: _options.extend(["-p", platform]) diff --git a/scripts/ci/twister_ignore.txt b/scripts/ci/twister_ignore.txt index 59f735495ca..4a0589f291c 100644 --- a/scripts/ci/twister_ignore.txt +++ b/scripts/ci/twister_ignore.txt @@ -17,25 +17,6 @@ CODEOWNERS MAINTAINERS.yml LICENSE Makefile -tests/* -samples/* -boards/*/*/* -arch/xtensa/* -arch/x86/* -arch/posix/* -arch/arc/* -arch/sparc/* -arch/arm/* -arch/nios2/* -arch/riscv/* -include/arch/xtensa/* -include/arch/x86/* -include/arch/posix/* -include/arch/arc/* -include/arch/sparc/* -include/arch/arm/* -include/arch/nios2/* -include/arch/riscv/* doc/* # GH action have no impact on code .github/* From 10ef01ba7924b88c6f3dc9d75409f679486eb4ba Mon Sep 17 00:00:00 2001 From: Maciej Perkowski Date: Fri, 18 Aug 2023 16:02:12 +0200 Subject: [PATCH 378/421] [nrf fromtree] scripts: Add workflow for "common" directories in find_tests() Some tests use a "common" directory to store pieces of code which are reused by different scenarios. In those cases, no test yaml is found within such director nor within its parents. If no test yaml is found in a directory, and the directory is called common, also look in collocated directories if they have test yamls. If so, add all those locations to the scope. E.g. tests/bluetooth/controller/common (cherry picked from commit 72f416f382f061199900096f50315608b75aae8b) Signed-off-by: Maciej Perkowski --- scripts/ci/test_plan.py | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/scripts/ci/test_plan.py b/scripts/ci/test_plan.py index 234d1302731..a308abe63ab 100755 --- a/scripts/ci/test_plan.py +++ b/scripts/ci/test_plan.py @@ -12,6 +12,7 @@ import json import logging import sys +import glob from pathlib import Path from git import Repo from west.manifest import Manifest @@ -264,13 +265,25 @@ def find_tests(self): if f.endswith(".rst"): continue d = os.path.dirname(f) - while d: + scope_found = False + while not scope_found and d: + head, tail = os.path.split(d) if os.path.exists(os.path.join(d, "testcase.yaml")) or \ os.path.exists(os.path.join(d, "sample.yaml")): tests.add(d) # Modified file is treated as resolved, since a matching scope was found self.resolved_files.append(f) - break + scope_found = True + elif tail == "common": + # Look for yamls in directories collocated with common + + yamls_found = [yaml for yaml in glob.iglob(head + '/**/testcase.yaml', recursive=True)] + yamls_found.extend([yaml for yaml in glob.iglob(head + '/**/sample.yaml', recursive=True)]) + if yamls_found: + for yaml in yamls_found: + tests.add(os.path.dirname(yaml)) + self.resolved_files.append(f) + scope_found = True else: d = os.path.dirname(d) From d8af055fc8c45815beaae06947d1625011451c88 Mon Sep 17 00:00:00 2001 From: Maciej Perkowski Date: Mon, 30 Oct 2023 15:24:09 +0100 Subject: [PATCH 379/421] [nrf fromtree] twister: bugfix: Fix infinite loop in test_plan.py script Commit 72f416f382f061199900096f50315608b75aae8b added a horizontal scan for .yaml files when a modification was made in "common" folder. If yamls were found in such way, the loop ended. However, the implementation didn't address what happens if such yamls are not found. This made the script going into an infinite loop. If yamls are not found next to "common", the script should proceed as before, i.e. go to the directory above an start looking there. (cherry picked from commit 3314b8e0c3fd8c8d717b5b718fb86acc7d1c9022) Signed-off-by: Maciej Perkowski --- scripts/ci/test_plan.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/ci/test_plan.py b/scripts/ci/test_plan.py index a308abe63ab..21cac8e4914 100755 --- a/scripts/ci/test_plan.py +++ b/scripts/ci/test_plan.py @@ -284,6 +284,8 @@ def find_tests(self): tests.add(os.path.dirname(yaml)) self.resolved_files.append(f) scope_found = True + else: + d = os.path.dirname(d) else: d = os.path.dirname(d) From ac573c04413a1f16faf2a3b63936b0e91720820a Mon Sep 17 00:00:00 2001 From: Maciej Perkowski Date: Mon, 30 Oct 2023 16:03:52 +0100 Subject: [PATCH 380/421] [nrf fromtree] scripts: Add test_plan.py to twister_ignore.txt There is no point in running full twister scope when test_plan.py script is modified. (cherry picked from commit aa3e79a88ac635492c2baccf0f74dc26597dadf8) Signed-off-by: Maciej Perkowski --- scripts/ci/twister_ignore.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/ci/twister_ignore.txt b/scripts/ci/twister_ignore.txt index 4a0589f291c..fb267ed81f7 100644 --- a/scripts/ci/twister_ignore.txt +++ b/scripts/ci/twister_ignore.txt @@ -24,6 +24,7 @@ doc/* *.md # if we change this file or associated script, it should not trigger a full # twister. +scripts/ci/test_plan.py scripts/ci/twister_ignore.txt scripts/ci/what_changed.py scripts/ci/version_mgr.py From 2b912a70f905022a1ef891161b5f6c977980c87a Mon Sep 17 00:00:00 2001 From: Rubin Gerritsen Date: Mon, 6 Nov 2023 14:49:08 +0100 Subject: [PATCH 381/421] [nrf fromtree] Bluetooth: HCI: Add bt_hci_get_ver_str() This new API returns the version string corresponding to a given HCI version. The API can be used by applications to print out human-readable information about the controller being used. Adding this API removes possible code duplication. Signed-off-by: Rubin Gerritsen (cherry picked from commit 8b2dd61ebab8af6a1c17abee4b565f1d1c8222b6) --- include/zephyr/bluetooth/hci.h | 13 +++++++++++++ subsys/bluetooth/host/hci_core.c | 10 +++++----- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/include/zephyr/bluetooth/hci.h b/include/zephyr/bluetooth/hci.h index 8dd7434e445..258f86519b6 100644 --- a/include/zephyr/bluetooth/hci.h +++ b/include/zephyr/bluetooth/hci.h @@ -97,6 +97,19 @@ int bt_hci_get_conn_handle(const struct bt_conn *conn, uint16_t *conn_handle); */ int bt_hci_get_adv_handle(const struct bt_le_ext_adv *adv, uint8_t *adv_handle); +/** @brief Obtain the version string given a core version number. + * + * The core version of a controller can be obtained by issuing + * the HCI Read Local Version Information command. + * + * See also the defines prefixed with BT_HCI_VERSION_. + * + * @param core_version The core version. + * + * @return Version string corresponding to the core version number. + */ +const char *bt_hci_get_ver_str(uint8_t core_version); + /** @typedef bt_hci_vnd_evt_cb_t * @brief Callback type for vendor handling of HCI Vendor-Specific Events. * diff --git a/subsys/bluetooth/host/hci_core.c b/subsys/bluetooth/host/hci_core.c index 8e1227c0bf5..eb1d7195d5c 100644 --- a/subsys/bluetooth/host/hci_core.c +++ b/subsys/bluetooth/host/hci_core.c @@ -3425,15 +3425,15 @@ static int set_event_mask(void) return bt_hci_cmd_send_sync(BT_HCI_OP_SET_EVENT_MASK, buf, NULL); } -static const char *ver_str(uint8_t ver) +const char *bt_hci_get_ver_str(uint8_t core_version) { const char * const str[] = { "1.0b", "1.1", "1.2", "2.0", "2.1", "3.0", "4.0", "4.1", "4.2", "5.0", "5.1", "5.2", "5.3", "5.4" }; - if (ver < ARRAY_SIZE(str)) { - return str[ver]; + if (core_version < ARRAY_SIZE(str)) { + return str[core_version]; } return "unknown"; @@ -3474,9 +3474,9 @@ static void bt_dev_show_info(void) } LOG_INF("HCI: version %s (0x%02x) revision 0x%04x, manufacturer 0x%04x", - ver_str(bt_dev.hci_version), bt_dev.hci_version, bt_dev.hci_revision, + bt_hci_get_ver_str(bt_dev.hci_version), bt_dev.hci_version, bt_dev.hci_revision, bt_dev.manufacturer); - LOG_INF("LMP: version %s (0x%02x) subver 0x%04x", ver_str(bt_dev.lmp_version), + LOG_INF("LMP: version %s (0x%02x) subver 0x%04x", bt_hci_get_ver_str(bt_dev.lmp_version), bt_dev.lmp_version, bt_dev.lmp_subversion); } From ede86123951b7f824f91f6ebd1ea15f307f9a208 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ga=C5=82da?= Date: Mon, 6 Nov 2023 18:44:48 +0100 Subject: [PATCH 382/421] [nrf noup] ci: Add CI-run-zephyr-twister test spec MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CI-run-zephyr-twister is used to determine if twister tests from sdk-zephyr should be run on PR to sdk-nrf repository. Signed-off-by: Jan Gałda --- .github/test-spec.yml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/.github/test-spec.yml b/.github/test-spec.yml index 007f4307aa9..789f1a4e235 100644 --- a/.github/test-spec.yml +++ b/.github/test-spec.yml @@ -1,4 +1,19 @@ # This is the Jenkins ci variant of the .github/labler.yaml + +"CI-run-zephyr-twister": + - any: + - "!.github/**/*" + - "!doc/**/*" + - "!CODEOWNERS" + - "!LICENSE" + - "!**/*.rst" + - "!VERSION" + - "!submanifests/**/*" + - "!MAINTAINERS.yml" + - "!version.h.in" + - "!Jenkinsfile" + - "!**/*.md" + "CI-iot-zephyr-lwm2m-test": - "drivers/console/**/*" - "drivers/flash/**/*" From 4a05f790ba8345cc348c2ca2f7fcf84dfa983e8d Mon Sep 17 00:00:00 2001 From: Grzegorz Chwierut Date: Fri, 8 Sep 2023 17:50:24 +0200 Subject: [PATCH 383/421] [nrf fromtree] twister: pytest: Move fixtures to one file Fixtures in pytest-twister-harness plugin are moved to one file to simplify adding new fixtures in the future - no need to add pytest_plugins entry and register asserts. Moved also shell fixture from sample dir, because that fixture can be reused in new tests. Signed-off-by: Grzegorz Chwierut (cherry picked from commit f6185221440b7fe9f0c1b17702c8231105edc06b) --- .../pytest/shell/pytest/test_shell.py | 12 +--------- .../src/twister_harness/__init__.py | 2 +- .../{fixtures/dut.py => fixtures.py} | 22 +++++++++++++++++++ .../src/twister_harness/fixtures/__init__.py | 8 ------- .../{fixtures => helpers}/mcumgr.py | 16 -------------- .../src/twister_harness/plugin.py | 3 +-- .../tests/fixtures/mcumgr_fixture_test.py | 4 ++-- 7 files changed, 27 insertions(+), 40 deletions(-) rename scripts/pylib/pytest-twister-harness/src/twister_harness/{fixtures/dut.py => fixtures.py} (72%) delete mode 100644 scripts/pylib/pytest-twister-harness/src/twister_harness/fixtures/__init__.py rename scripts/pylib/pytest-twister-harness/src/twister_harness/{fixtures => helpers}/mcumgr.py (88%) diff --git a/samples/subsys/testsuite/pytest/shell/pytest/test_shell.py b/samples/subsys/testsuite/pytest/shell/pytest/test_shell.py index 37efa74795b..84d16ec1e5a 100755 --- a/samples/subsys/testsuite/pytest/shell/pytest/test_shell.py +++ b/samples/subsys/testsuite/pytest/shell/pytest/test_shell.py @@ -4,21 +4,11 @@ import logging -import pytest -from twister_harness import DeviceAdapter, Shell +from twister_harness import Shell logger = logging.getLogger(__name__) -@pytest.fixture(scope='function') -def shell(dut: DeviceAdapter) -> Shell: - """Return ready to use shell interface""" - shell = Shell(dut, timeout=20.0) - logger.info('wait for prompt') - assert shell.wait_for_prompt() - return shell - - def test_shell_print_help(shell: Shell): logger.info('send "help" command') lines = shell.exec_command('help') diff --git a/scripts/pylib/pytest-twister-harness/src/twister_harness/__init__.py b/scripts/pylib/pytest-twister-harness/src/twister_harness/__init__.py index 251c5deb672..4897e2cf391 100644 --- a/scripts/pylib/pytest-twister-harness/src/twister_harness/__init__.py +++ b/scripts/pylib/pytest-twister-harness/src/twister_harness/__init__.py @@ -5,7 +5,7 @@ # flake8: noqa from twister_harness.device.device_adapter import DeviceAdapter -from twister_harness.fixtures.mcumgr import MCUmgr +from twister_harness.helpers.mcumgr import MCUmgr from twister_harness.helpers.shell import Shell __all__ = ['DeviceAdapter', 'MCUmgr', 'Shell'] diff --git a/scripts/pylib/pytest-twister-harness/src/twister_harness/fixtures/dut.py b/scripts/pylib/pytest-twister-harness/src/twister_harness/fixtures.py similarity index 72% rename from scripts/pylib/pytest-twister-harness/src/twister_harness/fixtures/dut.py rename to scripts/pylib/pytest-twister-harness/src/twister_harness/fixtures.py index 0f34c05b252..e2e82674ada 100644 --- a/scripts/pylib/pytest-twister-harness/src/twister_harness/fixtures/dut.py +++ b/scripts/pylib/pytest-twister-harness/src/twister_harness/fixtures.py @@ -10,6 +10,8 @@ from twister_harness.device.device_adapter import DeviceAdapter from twister_harness.device.factory import DeviceFactory from twister_harness.twister_harness_config import DeviceConfig, TwisterHarnessConfig +from twister_harness.helpers.shell import Shell +from twister_harness.helpers.mcumgr import MCUmgr logger = logging.getLogger(__name__) @@ -44,3 +46,23 @@ def dut(request: pytest.FixtureRequest, device_object: DeviceAdapter) -> Generat yield device_object finally: # to make sure we close all running processes execution device_object.close() + + +@pytest.fixture(scope='function') +def shell(dut: DeviceAdapter) -> Shell: + """Return ready to use shell interface""" + shell = Shell(dut, timeout=20.0) + logger.info('Wait for prompt') + assert shell.wait_for_prompt() + return shell + + +@pytest.fixture(scope='session') +def is_mcumgr_available() -> None: + if not MCUmgr.is_available(): + pytest.skip('mcumgr not available') + + +@pytest.fixture() +def mcumgr(is_mcumgr_available: None, dut: DeviceAdapter) -> Generator[MCUmgr, None, None]: + yield MCUmgr.create_for_serial(dut.device_config.serial) diff --git a/scripts/pylib/pytest-twister-harness/src/twister_harness/fixtures/__init__.py b/scripts/pylib/pytest-twister-harness/src/twister_harness/fixtures/__init__.py deleted file mode 100644 index ed61bf17b1c..00000000000 --- a/scripts/pylib/pytest-twister-harness/src/twister_harness/fixtures/__init__.py +++ /dev/null @@ -1,8 +0,0 @@ -# Copyright (c) 2023 Nordic Semiconductor ASA -# -# SPDX-License-Identifier: Apache-2.0 - -import pytest - -pytest.register_assert_rewrite('twister_harness.fixtures.dut') -pytest.register_assert_rewrite('twister_harness.fixtures.mcumgr') diff --git a/scripts/pylib/pytest-twister-harness/src/twister_harness/fixtures/mcumgr.py b/scripts/pylib/pytest-twister-harness/src/twister_harness/helpers/mcumgr.py similarity index 88% rename from scripts/pylib/pytest-twister-harness/src/twister_harness/fixtures/mcumgr.py rename to scripts/pylib/pytest-twister-harness/src/twister_harness/helpers/mcumgr.py index e0d85893792..b6cab6475c1 100755 --- a/scripts/pylib/pytest-twister-harness/src/twister_harness/fixtures/mcumgr.py +++ b/scripts/pylib/pytest-twister-harness/src/twister_harness/helpers/mcumgr.py @@ -3,19 +3,14 @@ # SPDX-License-Identifier: Apache-2.0 from __future__ import annotations -import pytest import logging import re import shlex -from typing import Generator from subprocess import check_output, getstatusoutput from pathlib import Path from dataclasses import dataclass -from twister_harness.device.device_adapter import DeviceAdapter - - logger = logging.getLogger(__name__) @@ -108,14 +103,3 @@ def image_confirm(self, hash: str | None = None): image_list = self.get_image_list() hash = image_list[0].hash self.run_command(f'image confirm {hash}') - - -@pytest.fixture(scope='session') -def is_mcumgr_available() -> None: - if not MCUmgr.is_available(): - pytest.skip('mcumgr not available') - - -@pytest.fixture() -def mcumgr(is_mcumgr_available: None, dut: DeviceAdapter) -> Generator[MCUmgr, None, None]: - yield MCUmgr.create_for_serial(dut.device_config.serial) diff --git a/scripts/pylib/pytest-twister-harness/src/twister_harness/plugin.py b/scripts/pylib/pytest-twister-harness/src/twister_harness/plugin.py index 59bec12955d..076d36d4cc9 100644 --- a/scripts/pylib/pytest-twister-harness/src/twister_harness/plugin.py +++ b/scripts/pylib/pytest-twister-harness/src/twister_harness/plugin.py @@ -14,8 +14,7 @@ logger = logging.getLogger(__name__) pytest_plugins = ( - 'twister_harness.fixtures.dut', - 'twister_harness.fixtures.mcumgr' + 'twister_harness.fixtures' ) diff --git a/scripts/pylib/pytest-twister-harness/tests/fixtures/mcumgr_fixture_test.py b/scripts/pylib/pytest-twister-harness/tests/fixtures/mcumgr_fixture_test.py index f294adba30a..f336311143a 100644 --- a/scripts/pylib/pytest-twister-harness/tests/fixtures/mcumgr_fixture_test.py +++ b/scripts/pylib/pytest-twister-harness/tests/fixtures/mcumgr_fixture_test.py @@ -6,7 +6,7 @@ import textwrap from unittest import mock -from twister_harness.fixtures.mcumgr import MCUmgr, MCUmgrException +from twister_harness.helpers.mcumgr import MCUmgr, MCUmgrException @pytest.fixture(name='mcumgr') @@ -14,7 +14,7 @@ def fixture_mcumgr() -> MCUmgr: return MCUmgr.create_for_serial('SERIAL_PORT') -@mock.patch('twister_harness.fixtures.mcumgr.MCUmgr.run_command', return_value='') +@mock.patch('twister_harness.helpers.mcumgr.MCUmgr.run_command', return_value='') def test_if_mcumgr_fixture_generate_proper_command( patched_run_command: mock.Mock, mcumgr: MCUmgr ) -> None: From 8186e5cf7cf25d3586896060730eddd6145589c5 Mon Sep 17 00:00:00 2001 From: Grzegorz Chwierut Date: Wed, 25 Oct 2023 12:33:23 +0200 Subject: [PATCH 384/421] [nrf fromtree] twister: pytest: Parametrize scope of the dut fixture Added pytest_dut_scope keyword under harness_config section. New keyword is used to determine the scope of dut and shell fixtures in pytest-twister-harness plugin. Signed-off-by: Grzegorz Chwierut (cherry picked from commit fffe0b9fadd6271b932fd8e382eff7be3c9b3c13) --- doc/develop/test/pytest.rst | 9 +++++++-- doc/develop/test/twister.rst | 5 +++++ .../src/twister_harness/fixtures.py | 13 +++++++++---- .../src/twister_harness/plugin.py | 5 +++++ scripts/pylib/twister/twisterlib/harness.py | 5 ++++- scripts/schemas/twister/testsuite-schema.yaml | 8 ++++++++ .../pytest_integration/test_harness_pytest.py | 19 +++++++++++++++++++ 7 files changed, 57 insertions(+), 7 deletions(-) diff --git a/doc/develop/test/pytest.rst b/doc/develop/test/pytest.rst index d0fad4d6be6..087c45bcce8 100644 --- a/doc/develop/test/pytest.rst +++ b/doc/develop/test/pytest.rst @@ -69,6 +69,9 @@ DUT (initialize logging, flash device, connect serial etc). This fixture yields a device prepared according to the requested type (native posix, qemu, hardware, etc.). All types of devices share the same API. This allows for writing tests which are device-type-agnostic. +Scope of this fixture is determined by the ``pytest_dut_scope`` +keyword placed under ``harness_config`` section. + .. code-block:: python @@ -81,8 +84,10 @@ shell ----- Provide an object with methods used to interact with shell application. -It calls `wait_for_promt` method, to not start scenario until DUT is ready. -Note that it uses `dut` fixture, so `dut` can be skipped when `shell` is used. +It calls ``wait_for_promt`` method, to not start scenario until DUT is ready. +Note that it uses ``dut`` fixture, so ``dut`` can be skipped when ``shell`` is used. +Scope of this fixture is determined by the ``pytest_dut_scope`` +keyword placed under ``harness_config`` section. .. code-block:: python diff --git a/doc/develop/test/twister.rst b/doc/develop/test/twister.rst index 4456386b77c..a61744eec6d 100644 --- a/doc/develop/test/twister.rst +++ b/doc/develop/test/twister.rst @@ -501,6 +501,11 @@ harness_config: pytest_args: (default empty) Specify a list of additional arguments to pass to ``pytest``. + pytest_dut_scope: (default function) + The scope for which ``dut`` and ``shell`` pytest fixtures are shared. + If the scope is set to ``function``, DUT is launched for every test case + in python script. For ``session`` scope, DUT is launched only once. + robot_test_path: (default empty) Specify a path to a file containing a Robot Framework test suite to be run. diff --git a/scripts/pylib/pytest-twister-harness/src/twister_harness/fixtures.py b/scripts/pylib/pytest-twister-harness/src/twister_harness/fixtures.py index e2e82674ada..f2b1b53706c 100644 --- a/scripts/pylib/pytest-twister-harness/src/twister_harness/fixtures.py +++ b/scripts/pylib/pytest-twister-harness/src/twister_harness/fixtures.py @@ -36,11 +36,16 @@ def device_object(twister_harness_config: TwisterHarnessConfig) -> Generator[Dev device_object.close() -@pytest.fixture(scope='function') +def determine_scope(fixture_name, config): + if dut_scope := config.getoption("--dut-scope", None): + return dut_scope + return 'function' + + +@pytest.fixture(scope=determine_scope) def dut(request: pytest.FixtureRequest, device_object: DeviceAdapter) -> Generator[DeviceAdapter, None, None]: """Return launched device - with run application.""" - test_name = request.node.name - device_object.initialize_log_files(test_name) + device_object.initialize_log_files(request.node.name) try: device_object.launch() yield device_object @@ -48,7 +53,7 @@ def dut(request: pytest.FixtureRequest, device_object: DeviceAdapter) -> Generat device_object.close() -@pytest.fixture(scope='function') +@pytest.fixture(scope=determine_scope) def shell(dut: DeviceAdapter) -> Shell: """Return ready to use shell interface""" shell = Shell(dut, timeout=20.0) diff --git a/scripts/pylib/pytest-twister-harness/src/twister_harness/plugin.py b/scripts/pylib/pytest-twister-harness/src/twister_harness/plugin.py index 076d36d4cc9..dbd3465aba1 100644 --- a/scripts/pylib/pytest-twister-harness/src/twister_harness/plugin.py +++ b/scripts/pylib/pytest-twister-harness/src/twister_harness/plugin.py @@ -100,6 +100,11 @@ def pytest_addoption(parser: pytest.Parser): metavar='PATH', help='Script executed after closing serial connection.' ) + twister_harness_group.addoption( + '--dut-scope', + choices=('function', 'class', 'module', 'package', 'session'), + help='The scope for which `dut` and `shell` fixtures are shared.' + ) def pytest_configure(config: pytest.Config): diff --git a/scripts/pylib/twister/twisterlib/harness.py b/scripts/pylib/twister/twisterlib/harness.py index 6ae2622c810..951a8c40010 100644 --- a/scripts/pylib/twister/twisterlib/harness.py +++ b/scripts/pylib/twister/twisterlib/harness.py @@ -247,6 +247,7 @@ def generate_command(self): config = self.instance.testsuite.harness_config pytest_root = config.get('pytest_root', ['pytest']) if config else ['pytest'] pytest_args = config.get('pytest_args', []) if config else [] + pytest_dut_scope = config.get('pytest_dut_scope', None) if config else None command = [ 'pytest', '--twister-harness', @@ -260,6 +261,8 @@ def generate_command(self): command.extend([os.path.normpath(os.path.join( self.source_dir, os.path.expanduser(os.path.expandvars(src)))) for src in pytest_root]) command.extend(pytest_args) + if pytest_dut_scope: + command.append(f'--dut-scope={pytest_dut_scope}') handler: Handler = self.instance.handler @@ -406,7 +409,7 @@ def _parse_report_file(self, report): self.instance.execution_time = float(elem_ts.get('time')) for elem_tc in elem_ts.findall('testcase'): - tc = self.instance.get_case_or_create(f"{self.id}.{elem_tc.get('name')}") + tc = self.instance.add_testcase(f"{self.id}.{elem_tc.get('name')}") tc.duration = float(elem_tc.get('time')) elem = elem_tc.find('*') if elem is None: diff --git a/scripts/schemas/twister/testsuite-schema.yaml b/scripts/schemas/twister/testsuite-schema.yaml index 96a121767a5..1e198173c72 100644 --- a/scripts/schemas/twister/testsuite-schema.yaml +++ b/scripts/schemas/twister/testsuite-schema.yaml @@ -104,6 +104,10 @@ mapping: required: false sequence: - type: str + "pytest_dut_scope": + type: str + enum: ["function", "class", "module", "package", "session"] + required: false "regex": type: seq required: false @@ -304,6 +308,10 @@ mapping: required: false sequence: - type: str + "pytest_dut_scope": + type: str + enum: ["function", "class", "module", "package", "session"] + required: false "regex": type: seq required: false diff --git a/scripts/tests/twister/pytest_integration/test_harness_pytest.py b/scripts/tests/twister/pytest_integration/test_harness_pytest.py index e1b27a0cf02..ab4baf88656 100644 --- a/scripts/tests/twister/pytest_integration/test_harness_pytest.py +++ b/scripts/tests/twister/pytest_integration/test_harness_pytest.py @@ -48,6 +48,25 @@ def test_pytest_command(testinstance: TestInstance, device_type): assert c in command +def test_pytest_command_dut_scope(testinstance: TestInstance): + pytest_harness = Pytest() + dut_scope = 'session' + testinstance.testsuite.harness_config['pytest_dut_scope'] = dut_scope + pytest_harness.configure(testinstance) + command = pytest_harness.generate_command() + assert f'--dut-scope={dut_scope}' in command + + +def test_pytest_command_extra_args(testinstance: TestInstance): + pytest_harness = Pytest() + pytest_args = ['-k test1', '-m mark1'] + testinstance.testsuite.harness_config['pytest_args'] = pytest_args + pytest_harness.configure(testinstance) + command = pytest_harness.generate_command() + for c in pytest_args: + assert c in command + + @pytest.mark.parametrize( ('pytest_root', 'expected'), [ From ac5a9860b73bdbde2e8ba936fdc35a5e7654189c Mon Sep 17 00:00:00 2001 From: Grzegorz Chwierut Date: Thu, 26 Oct 2023 09:08:54 +0200 Subject: [PATCH 385/421] [nrf fromtree] twister: pytest: Improve reporting failed pytest scenarios When pytest scenario fails, then 'handler.log' is printed. Changed to print 'twister_harness.log' that is a log from pytest execution. That file tells much more when test fails. Signed-off-by: Grzegorz Chwierut (cherry picked from commit e466b7ac266b24fe4e1c27b01fef3a722e18ddd3) --- .../device/hardware_adapter.py | 1 - scripts/pylib/twister/twisterlib/harness.py | 2 ++ scripts/pylib/twister/twisterlib/reports.py | 5 +++- scripts/pylib/twister/twisterlib/runner.py | 26 +++++++++++++++---- .../pytest_integration/test_harness_pytest.py | 2 ++ 5 files changed, 29 insertions(+), 7 deletions(-) diff --git a/scripts/pylib/pytest-twister-harness/src/twister_harness/device/hardware_adapter.py b/scripts/pylib/pytest-twister-harness/src/twister_harness/device/hardware_adapter.py index 403978eed9a..3b7bf5d8214 100644 --- a/scripts/pylib/pytest-twister-harness/src/twister_harness/device/hardware_adapter.py +++ b/scripts/pylib/pytest-twister-harness/src/twister_harness/device/hardware_adapter.py @@ -116,7 +116,6 @@ def _flash_and_run(self) -> None: stdout_decoded = stdout.decode(errors='ignore') with open(self.device_log_path, 'a+') as log_file: log_file.write(stdout_decoded) - logger.debug(f'Flashing output:\n{stdout_decoded}') if self.device_config.post_flash_script: self._run_custom_script(self.device_config.post_flash_script, self.base_timeout) if process is not None and process.returncode == 0: diff --git a/scripts/pylib/twister/twisterlib/harness.py b/scripts/pylib/twister/twisterlib/harness.py index 951a8c40010..bd86df1b4df 100644 --- a/scripts/pylib/twister/twisterlib/harness.py +++ b/scripts/pylib/twister/twisterlib/harness.py @@ -400,8 +400,10 @@ def _parse_report_file(self, report): if elem_ts := root.find('testsuite'): if elem_ts.get('failures') != '0': self.state = 'failed' + self.instance.reason = f"{elem_ts.get('failures')}/{elem_ts.get('tests')} pytest scenario(s) failed" elif elem_ts.get('errors') != '0': self.state = 'error' + self.instance.reason = 'Error during pytest execution' elif elem_ts.get('skipped') == elem_ts.get('tests'): self.state = 'skipped' else: diff --git a/scripts/pylib/twister/twisterlib/reports.py b/scripts/pylib/twister/twisterlib/reports.py index c1f160caad9..be1bbb4dbd7 100644 --- a/scripts/pylib/twister/twisterlib/reports.py +++ b/scripts/pylib/twister/twisterlib/reports.py @@ -246,6 +246,7 @@ def json_report(self, filename, version="NA"): for instance in self.instances.values(): suite = {} handler_log = os.path.join(instance.build_dir, "handler.log") + pytest_log = os.path.join(instance.build_dir, "twister_harness.log") build_log = os.path.join(instance.build_dir, "build.log") device_log = os.path.join(instance.build_dir, "device.log") @@ -284,7 +285,9 @@ def json_report(self, filename, version="NA"): suite['status'] = instance.status suite["reason"] = instance.reason # FIXME - if os.path.exists(handler_log): + if os.path.exists(pytest_log): + suite["log"] = self.process_log(pytest_log) + elif os.path.exists(handler_log): suite["log"] = self.process_log(handler_log) elif os.path.exists(device_log): suite["log"] = self.process_log(device_log) diff --git a/scripts/pylib/twister/twisterlib/runner.py b/scripts/pylib/twister/twisterlib/runner.py index ef41084cdd4..4dbdb21f882 100644 --- a/scripts/pylib/twister/twisterlib/runner.py +++ b/scripts/pylib/twister/twisterlib/runner.py @@ -40,6 +40,9 @@ from twisterlib.log_helper import log_command from twisterlib.testinstance import TestInstance +from twisterlib.environment import TwisterEnv +from twisterlib.testsuite import TestSuite +from twisterlib.platform import Platform from twisterlib.testplan import change_skip_to_error_if_integration from twisterlib.harness import HarnessImporter, Pytest @@ -220,7 +223,7 @@ class CMake: config_re = re.compile('(CONFIG_[A-Za-z0-9_]+)[=]\"?([^\"]*)\"?$') dt_re = re.compile('([A-Za-z0-9_]+)[=]\"?([^\"]*)\"?$') - def __init__(self, testsuite, platform, source_dir, build_dir, jobserver): + def __init__(self, testsuite: TestSuite, platform: Platform, source_dir, build_dir, jobserver): self.cwd = None self.capture_output = True @@ -414,7 +417,7 @@ def run_cmake(self, args="", filter_stages=[]): class FilterBuilder(CMake): - def __init__(self, testsuite, platform, source_dir, build_dir, jobserver): + def __init__(self, testsuite: TestSuite, platform: Platform, source_dir, build_dir, jobserver): super().__init__(testsuite, platform, source_dir, build_dir, jobserver) self.log = "config-twister.log" @@ -517,7 +520,7 @@ def parse_generated(self, filter_stages=[]): class ProjectBuilder(FilterBuilder): - def __init__(self, instance, env, jobserver, **kwargs): + def __init__(self, instance: TestInstance, env: TwisterEnv, jobserver, **kwargs): super().__init__(instance.testsuite, instance.platform, instance.testsuite.source_dir, instance.build_dir, jobserver) self.log = "build.log" @@ -527,8 +530,7 @@ def __init__(self, instance, env, jobserver, **kwargs): self.env = env self.duts = None - @staticmethod - def log_info(filename, inline_logs): + def log_info(self, filename, inline_logs, log_testcases=False): filename = os.path.abspath(os.path.realpath(filename)) if inline_logs: logger.info("{:-^100}".format(filename)) @@ -542,6 +544,17 @@ def log_info(filename, inline_logs): logger.error(data) logger.info("{:-^100}".format(filename)) + + if log_testcases: + for tc in self.instance.testcases: + if not tc.reason: + continue + logger.info( + f"\n{str(tc.name).center(100, '_')}\n" + f"{tc.reason}\n" + f"{100*'_'}\n" + f"{tc.output}" + ) else: logger.error("see: " + Fore.YELLOW + filename + Fore.RESET) @@ -551,9 +564,12 @@ def log_info_file(self, inline_logs): b_log = "{}/build.log".format(build_dir) v_log = "{}/valgrind.log".format(build_dir) d_log = "{}/device.log".format(build_dir) + pytest_log = "{}/twister_harness.log".format(build_dir) if os.path.exists(v_log) and "Valgrind" in self.instance.reason: self.log_info("{}".format(v_log), inline_logs) + elif os.path.exists(pytest_log) and os.path.getsize(pytest_log) > 0: + self.log_info("{}".format(pytest_log), inline_logs, log_testcases=True) elif os.path.exists(h_log) and os.path.getsize(h_log) > 0: self.log_info("{}".format(h_log), inline_logs) elif os.path.exists(d_log) and os.path.getsize(d_log) > 0: diff --git a/scripts/tests/twister/pytest_integration/test_harness_pytest.py b/scripts/tests/twister/pytest_integration/test_harness_pytest.py index ab4baf88656..150980059b3 100644 --- a/scripts/tests/twister/pytest_integration/test_harness_pytest.py +++ b/scripts/tests/twister/pytest_integration/test_harness_pytest.py @@ -188,6 +188,8 @@ def test_err(): assert tc.status == "failed" assert tc.output assert tc.reason + assert testinstance.reason + assert '2/2' in testinstance.reason def test_if_report_with_skip(pytester, testinstance: TestInstance): From 196bab5029e3217952429c58f38a2be656dfee94 Mon Sep 17 00:00:00 2001 From: Carles Cufi Date: Thu, 9 Nov 2023 18:15:32 +0100 Subject: [PATCH 386/421] [nrf fromtree] doc: gsg: macOS: Include instructions to add homebrew to the path Multiple users have failed to read the output from the Homebrew installation script, which instructs the user how to add it to the path. Include the instructions in the guide. Also add a step to include the Homebrew Python executable to the path, which allows then for invocation of python and pip as well as python3 and pip3. Signed-off-by: Carles Cufi (cherry picked from commit 318836af23aa1607342a019c01580fd87442f32b) --- doc/develop/getting_started/index.rst | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/doc/develop/getting_started/index.rst b/doc/develop/getting_started/index.rst index 4a1b345ee62..f7a76a71585 100644 --- a/doc/develop/getting_started/index.rst +++ b/doc/develop/getting_started/index.rst @@ -118,12 +118,32 @@ The current minimum required version for the main dependencies are: /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" + #. After the Homebrew installation script completes, follow the on-screen + instructions to add the Homebrew installation to the path. + + * On macOS running on Apple Silicon, this is achieved with: + + .. code-block:: bash + + (echo; echo 'eval "$(/opt/homebrew/bin/brew shellenv)"') >> ~/.zprofile + source ~/.zprofile + + * On macOS running on Intel, use the command for Apple Silicon, but replace ``/opt/homebrew/`` with ``/usr/local/``. + #. Use ``brew`` to install the required dependencies: .. code-block:: bash brew install cmake ninja gperf python3 ccache qemu dtc wget libmagic + #. Add the Homebrew Python folder to the path, in order to be able to + execute ``python`` and ``pip`` as well ``python3`` and ``pip3``. + + .. code-block:: bash + + (echo; echo 'export PATH="'$(brew --prefix)'/opt/python/libexec/bin:$PATH"') >> ~/.zprofile + source ~/.zprofile + .. group-tab:: Windows .. note:: From 2a8c218f530fcc80ef3209ca49d36dc7a68d2b59 Mon Sep 17 00:00:00 2001 From: Chaitanya Tata Date: Wed, 8 Nov 2023 20:23:37 +0530 Subject: [PATCH 387/421] [nrf fromtree] net: Remove unnecessary lock The main action in this function it queueing the packet for transmission which doesn't need a lock and interface flags use atomic operations. So, remove the unnecessary lock. Signed-off-by: Chaitanya Tata (cherry picked from commit ed17320c3d2e43c76b09dc359d3b371e9d23732d) --- subsys/net/ip/net_if.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/subsys/net/ip/net_if.c b/subsys/net/ip/net_if.c index 828e48ecf78..035e18da74f 100644 --- a/subsys/net/ip/net_if.c +++ b/subsys/net/ip/net_if.c @@ -448,8 +448,6 @@ enum net_verdict net_if_send_data(struct net_if *iface, struct net_pkt *pkt) enum net_verdict verdict = NET_OK; int status = -EIO; - net_if_lock(iface); - if (!net_if_flag_is_set(iface, NET_IF_LOWER_UP) || net_if_flag_is_set(iface, NET_IF_SUSPENDED)) { /* Drop packet if interface is not up */ @@ -532,8 +530,6 @@ enum net_verdict net_if_send_data(struct net_if *iface, struct net_pkt *pkt) net_if_queue_tx(iface, pkt); } - net_if_unlock(iface); - return verdict; } From a707fc77ef2d80ce5f4bed6e5c9bdd6bc0cc3912 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Mon, 11 Sep 2023 17:54:13 +0300 Subject: [PATCH 388/421] [nrf fromtree] net: arp: Directly send the queued pkt We must send the packet without queueing it. The pkt has already been queued for sending, once by net_if and second time in the ARP queue. We must not queue it twice in net_if so that the statistics of the pkt are not counted twice and the packet filter callbacks are only called once. Fixes #62483 Signed-off-by: Jukka Rissanen (cherry picked from commit 0e5016e5026fb1f83bd32c1255a9edb2bdf53127) --- subsys/net/l2/ethernet/arp.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/subsys/net/l2/ethernet/arp.c b/subsys/net/l2/ethernet/arp.c index f26c2f7ba96..35a2ec63a64 100644 --- a/subsys/net/l2/ethernet/arp.c +++ b/subsys/net/l2/ethernet/arp.c @@ -514,6 +514,8 @@ static void arp_update(struct net_if *iface, sys_slist_prepend(&arp_table, &entry->node); while (!k_fifo_is_empty(&entry->pending_queue)) { + int ret; + pkt = k_fifo_get(&entry->pending_queue, K_FOREVER); /* Set the dst in the pending packet */ @@ -525,7 +527,17 @@ static void arp_update(struct net_if *iface, net_sprint_ipv4_addr(&entry->ip), pkt, pkt->frags); - net_if_queue_tx(iface, pkt); + /* We directly send the packet without first queueing it. + * The pkt has already been queued for sending, once by + * net_if and second time in the ARP queue. We must not + * queue it twice in net_if so that the statistics of + * the pkt are not counted twice and the packet filter + * callbacks are only called once. + */ + ret = net_if_l2(iface)->send(iface, pkt); + if (ret < 0) { + net_pkt_unref(pkt); + } } k_mutex_unlock(&arp_mutex); From 9ed7de1afad3ebc08a3ce379bee0bbbbd9702414 Mon Sep 17 00:00:00 2001 From: Robert Lubos Date: Fri, 10 Nov 2023 10:23:34 +0100 Subject: [PATCH 389/421] [nrf fromlist] net: iface: Introduce TX mutex locking A recent iface lock removal in ed17320c3d2e43c76b09dc359d3b371e9d23732d exposed issues with concurrent access on TX to drivers that are not re-entrant. Reverting that commit does not really solve the problem, as it would still exist if multiple Traffic Class queues are in use. Therefore, introduce a separate mutex for TX data path, protecting the L2/driver from concurrent transfers from several threads. Upstream PR: https://github.com/zephyrproject-rtos/zephyr/pull/65049 Signed-off-by: Robert Lubos --- include/zephyr/net/net_if.h | 29 +++++++++++++++++++++++++++++ subsys/net/ip/net_if.c | 3 +++ subsys/net/l2/ethernet/arp.c | 2 ++ 3 files changed, 34 insertions(+) diff --git a/include/zephyr/net/net_if.h b/include/zephyr/net/net_if.h index b06bf74de03..92a59ad3b73 100644 --- a/include/zephyr/net/net_if.h +++ b/include/zephyr/net/net_if.h @@ -212,6 +212,9 @@ enum net_if_flag { /** IPv6 Multicast Listener Discovery disabled. */ NET_IF_IPV6_NO_MLD, + /** Mutex locking on TX data path disabled on the interface. */ + NET_IF_NO_TX_LOCK, + /** @cond INTERNAL_HIDDEN */ /* Total number of flags - must be at the end of the enum */ NET_IF_NUM_FLAGS @@ -613,6 +616,7 @@ struct net_if { #endif struct k_mutex lock; + struct k_mutex tx_lock; }; static inline void net_if_lock(struct net_if *iface) @@ -629,6 +633,31 @@ static inline void net_if_unlock(struct net_if *iface) k_mutex_unlock(&iface->lock); } +static inline bool net_if_flag_is_set(struct net_if *iface, + enum net_if_flag value); + +static inline void net_if_tx_lock(struct net_if *iface) +{ + NET_ASSERT(iface); + + if (net_if_flag_is_set(iface, NET_IF_NO_TX_LOCK)) { + return; + } + + (void)k_mutex_lock(&iface->tx_lock, K_FOREVER); +} + +static inline void net_if_tx_unlock(struct net_if *iface) +{ + NET_ASSERT(iface); + + if (net_if_flag_is_set(iface, NET_IF_NO_TX_LOCK)) { + return; + } + + k_mutex_unlock(&iface->tx_lock); +} + /** * @brief Set a value in network interface flags * diff --git a/subsys/net/ip/net_if.c b/subsys/net/ip/net_if.c index 035e18da74f..026eaa88b48 100644 --- a/subsys/net/ip/net_if.c +++ b/subsys/net/ip/net_if.c @@ -265,7 +265,9 @@ static bool net_if_tx(struct net_if *iface, struct net_pkt *pkt) } } + net_if_tx_lock(iface); status = net_if_l2(iface)->send(iface, pkt); + net_if_tx_unlock(iface); if (IS_ENABLED(CONFIG_NET_PKT_TXTIME_STATS)) { uint32_t end_tick = k_cycle_get_32(); @@ -437,6 +439,7 @@ static inline void init_iface(struct net_if *iface) #endif k_mutex_init(&iface->lock); + k_mutex_init(&iface->tx_lock); api->init(iface); } diff --git a/subsys/net/l2/ethernet/arp.c b/subsys/net/l2/ethernet/arp.c index 35a2ec63a64..39a06ed64a0 100644 --- a/subsys/net/l2/ethernet/arp.c +++ b/subsys/net/l2/ethernet/arp.c @@ -534,7 +534,9 @@ static void arp_update(struct net_if *iface, * the pkt are not counted twice and the packet filter * callbacks are only called once. */ + net_if_tx_lock(iface); ret = net_if_l2(iface)->send(iface, pkt); + net_if_tx_unlock(iface); if (ret < 0) { net_pkt_unref(pkt); } From 2c3b9c4f763085faa0c4654bc4cce8baaf32b89c Mon Sep 17 00:00:00 2001 From: Lingao Meng Date: Wed, 6 Sep 2023 16:11:20 +0800 Subject: [PATCH 390/421] [nrf fromlist] Bluetooth: Mesh: Remove bits for adv tag since tag for buf single only, no need for bit, also for save some memory for rfu. Upstream PR: https://github.com/zephyrproject-rtos/zephyr/pull/62331 Signed-off-by: Lingao Meng (cherry picked from commit b14d235c31e5e79c857e0e46a1a632f35e2ca77e) --- subsys/bluetooth/mesh/adv.c | 14 +++++------ subsys/bluetooth/mesh/adv.h | 17 +++++++++---- subsys/bluetooth/mesh/adv_ext.c | 42 +++++++++++++++---------------- subsys/bluetooth/mesh/statistic.c | 12 ++++----- 4 files changed, 46 insertions(+), 39 deletions(-) diff --git a/subsys/bluetooth/mesh/adv.c b/subsys/bluetooth/mesh/adv.c index 2132c14e151..e67d96414e7 100644 --- a/subsys/bluetooth/mesh/adv.c +++ b/subsys/bluetooth/mesh/adv.c @@ -138,7 +138,7 @@ struct net_buf *bt_mesh_adv_create(enum bt_mesh_adv_type type, uint8_t xmit, k_timeout_t timeout) { #if defined(CONFIG_BT_MESH_RELAY) - if (tag & BT_MESH_RELAY_ADV) { + if (tag == BT_MESH_RELAY_ADV) { return bt_mesh_adv_create_from_pool(&relay_buf_pool, adv_relay_pool, type, tag, xmit, timeout); @@ -146,7 +146,7 @@ struct net_buf *bt_mesh_adv_create(enum bt_mesh_adv_type type, #endif #if defined(CONFIG_BT_MESH_ADV_EXT_FRIEND_SEPARATE) - if (tag & BT_MESH_FRIEND_ADV) { + if (tag == BT_MESH_FRIEND_ADV) { return bt_mesh_adv_create_from_pool(&friend_buf_pool, adv_friend_pool, type, tag, xmit, timeout); @@ -202,14 +202,14 @@ struct net_buf *bt_mesh_adv_buf_get(k_timeout_t timeout) return process_events(events, ARRAY_SIZE(events)); } -struct net_buf *bt_mesh_adv_buf_get_by_tag(uint8_t tag, k_timeout_t timeout) +struct net_buf *bt_mesh_adv_buf_get_by_tag(enum bt_mesh_adv_tags tags, k_timeout_t timeout) { - if (IS_ENABLED(CONFIG_BT_MESH_ADV_EXT_FRIEND_SEPARATE) && tag & BT_MESH_FRIEND_ADV) { + if (IS_ENABLED(CONFIG_BT_MESH_ADV_EXT_FRIEND_SEPARATE) && tags & BT_MESH_FRIEND_ADV_BIT) { return net_buf_get(&bt_mesh_friend_queue, timeout); } #if CONFIG_BT_MESH_RELAY_ADV_SETS - if (tag & BT_MESH_RELAY_ADV) { + if (tags & BT_MESH_RELAY_ADV_BIT) { return net_buf_get(&bt_mesh_relay_queue, timeout); } #endif @@ -222,9 +222,9 @@ struct net_buf *bt_mesh_adv_buf_get(k_timeout_t timeout) return net_buf_get(&bt_mesh_adv_queue, timeout); } -struct net_buf *bt_mesh_adv_buf_get_by_tag(uint8_t tag, k_timeout_t timeout) +struct net_buf *bt_mesh_adv_buf_get_by_tag(enum bt_mesh_adv_tags tags, k_timeout_t timeout) { - ARG_UNUSED(tag); + ARG_UNUSED(tags); return bt_mesh_adv_buf_get(timeout); } diff --git a/subsys/bluetooth/mesh/adv.h b/subsys/bluetooth/mesh/adv.h index 3d0acf8a7ac..22a8e0645e1 100644 --- a/subsys/bluetooth/mesh/adv.h +++ b/subsys/bluetooth/mesh/adv.h @@ -26,10 +26,17 @@ enum bt_mesh_adv_type { }; enum bt_mesh_adv_tag { - BT_MESH_LOCAL_ADV = BIT(0), - BT_MESH_RELAY_ADV = BIT(1), - BT_MESH_PROXY_ADV = BIT(2), - BT_MESH_FRIEND_ADV = BIT(3), + BT_MESH_LOCAL_ADV, + BT_MESH_RELAY_ADV, + BT_MESH_PROXY_ADV, + BT_MESH_FRIEND_ADV, +}; + +enum bt_mesh_adv_tags { + BT_MESH_LOCAL_ADV_BIT = BIT(BT_MESH_LOCAL_ADV), + BT_MESH_RELAY_ADV_BIT = BIT(BT_MESH_RELAY_ADV), + BT_MESH_PROXY_ADV_BIT = BIT(BT_MESH_PROXY_ADV), + BT_MESH_FRIEND_ADV_BIT = BIT(BT_MESH_FRIEND_ADV), }; struct bt_mesh_adv { @@ -57,7 +64,7 @@ void bt_mesh_adv_send(struct net_buf *buf, const struct bt_mesh_send_cb *cb, struct net_buf *bt_mesh_adv_buf_get(k_timeout_t timeout); -struct net_buf *bt_mesh_adv_buf_get_by_tag(uint8_t tag, k_timeout_t timeout); +struct net_buf *bt_mesh_adv_buf_get_by_tag(enum bt_mesh_adv_tags tags, k_timeout_t timeout); void bt_mesh_adv_gatt_update(void); diff --git a/subsys/bluetooth/mesh/adv_ext.c b/subsys/bluetooth/mesh/adv_ext.c index 5c1a2bc3c32..d347602ac09 100644 --- a/subsys/bluetooth/mesh/adv_ext.c +++ b/subsys/bluetooth/mesh/adv_ext.c @@ -60,7 +60,7 @@ enum { }; struct bt_mesh_ext_adv { - uint8_t tag; + enum bt_mesh_adv_tags tags; ATOMIC_DEFINE(flags, ADV_FLAGS_NUM); struct bt_le_ext_adv *instance; struct net_buf *buf; @@ -73,17 +73,17 @@ static void send_pending_adv(struct k_work *work); static bool schedule_send(struct bt_mesh_ext_adv *adv); static STRUCT_SECTION_ITERABLE(bt_mesh_ext_adv, adv_main) = { - .tag = ( + .tags = ( #if !defined(CONFIG_BT_MESH_ADV_EXT_FRIEND_SEPARATE) - BT_MESH_FRIEND_ADV | + BT_MESH_FRIEND_ADV_BIT | #endif #if !defined(CONFIG_BT_MESH_ADV_EXT_GATT_SEPARATE) - BT_MESH_PROXY_ADV | + BT_MESH_PROXY_ADV_BIT | #endif /* !CONFIG_BT_MESH_ADV_EXT_GATT_SEPARATE */ #if defined(CONFIG_BT_MESH_ADV_EXT_RELAY_USING_MAIN_ADV_SET) - BT_MESH_RELAY_ADV | + BT_MESH_RELAY_ADV_BIT | #endif /* CONFIG_BT_MESH_ADV_EXT_RELAY_USING_MAIN_ADV_SET */ - BT_MESH_LOCAL_ADV), + BT_MESH_LOCAL_ADV_BIT), .work = Z_WORK_DELAYABLE_INITIALIZER(send_pending_adv), }; @@ -91,7 +91,7 @@ static STRUCT_SECTION_ITERABLE(bt_mesh_ext_adv, adv_main) = { #if CONFIG_BT_MESH_RELAY_ADV_SETS static STRUCT_SECTION_ITERABLE_ARRAY(bt_mesh_ext_adv, adv_relay, CONFIG_BT_MESH_RELAY_ADV_SETS) = { [0 ... CONFIG_BT_MESH_RELAY_ADV_SETS - 1] = { - .tag = BT_MESH_RELAY_ADV, + .tags = BT_MESH_RELAY_ADV_BIT, .work = Z_WORK_DELAYABLE_INITIALIZER(send_pending_adv), } }; @@ -100,7 +100,7 @@ static STRUCT_SECTION_ITERABLE_ARRAY(bt_mesh_ext_adv, adv_relay, CONFIG_BT_MESH_ #if defined(CONFIG_BT_MESH_ADV_EXT_FRIEND_SEPARATE) #define ADV_EXT_FRIEND 1 static STRUCT_SECTION_ITERABLE(bt_mesh_ext_adv, adv_friend) = { - .tag = BT_MESH_FRIEND_ADV, + .tags = BT_MESH_FRIEND_ADV_BIT, .work = Z_WORK_DELAYABLE_INITIALIZER(send_pending_adv), }; #else /* CONFIG_BT_MESH_ADV_EXT_FRIEND_SEPARATE */ @@ -110,7 +110,7 @@ static STRUCT_SECTION_ITERABLE(bt_mesh_ext_adv, adv_friend) = { #if defined(CONFIG_BT_MESH_ADV_EXT_GATT_SEPARATE) #define ADV_EXT_GATT 1 static STRUCT_SECTION_ITERABLE(bt_mesh_ext_adv, adv_gatt) = { - .tag = BT_MESH_PROXY_ADV, + .tags = BT_MESH_PROXY_ADV_BIT, .work = Z_WORK_DELAYABLE_INITIALIZER(send_pending_adv), }; #else /* CONFIG_BT_MESH_ADV_EXT_GATT_SEPARATE */ @@ -259,18 +259,18 @@ static int buf_send(struct bt_mesh_ext_adv *adv, struct net_buf *buf) return err; } -static const char *adv_tag_to_str(enum bt_mesh_adv_tag tag) +static const char *adv_tag_to_str(enum bt_mesh_adv_tags tags) { - if (tag & BT_MESH_LOCAL_ADV) { + if (tags & BT_MESH_LOCAL_ADV_BIT) { return "local adv"; - } else if (tag & BT_MESH_PROXY_ADV) { + } else if (tags & BT_MESH_PROXY_ADV_BIT) { return "proxy adv"; - } else if (tag & BT_MESH_RELAY_ADV) { + } else if (tags & BT_MESH_RELAY_ADV_BIT) { return "relay adv"; - } else if (tag & BT_MESH_FRIEND_ADV) { + } else if (tags & BT_MESH_FRIEND_ADV_BIT) { return "friend adv"; } else { - return "(unknown tag)"; + return "(unknown tags)"; } } @@ -289,8 +289,8 @@ static void send_pending_adv(struct k_work *work) */ int64_t duration = k_uptime_delta(&adv->timestamp); - LOG_DBG("Advertising stopped after %u ms for (%u) %s", (uint32_t)duration, adv->tag, - adv_tag_to_str(adv->tag)); + LOG_DBG("Advertising stopped after %u ms for (%u) %s", (uint32_t)duration, adv->tags, + adv_tag_to_str(adv->tags)); atomic_clear_bit(adv->flags, ADV_FLAG_ACTIVE); atomic_clear_bit(adv->flags, ADV_FLAG_PROXY); @@ -308,7 +308,7 @@ static void send_pending_adv(struct k_work *work) atomic_clear_bit(adv->flags, ADV_FLAG_SCHEDULED); - while ((buf = bt_mesh_adv_buf_get_by_tag(adv->tag, K_NO_WAIT))) { + while ((buf = bt_mesh_adv_buf_get_by_tag(adv->tags, K_NO_WAIT))) { /* busy == 0 means this was canceled */ if (!BT_MESH_ADV(buf)->busy) { net_buf_unref(buf); @@ -326,7 +326,7 @@ static void send_pending_adv(struct k_work *work) } if (!IS_ENABLED(CONFIG_BT_MESH_GATT_SERVER) || - !(adv->tag & BT_MESH_PROXY_ADV)) { + !(adv->tags & BT_MESH_RELAY_ADV_BIT)) { return; } @@ -369,8 +369,8 @@ static bool schedule_send(struct bt_mesh_ext_adv *adv) atomic_clear_bit(adv->flags, ADV_FLAG_SCHEDULE_PENDING); - if ((IS_ENABLED(CONFIG_BT_MESH_ADV_EXT_FRIEND_SEPARATE) && adv->tag & BT_MESH_FRIEND_ADV) || - (CONFIG_BT_MESH_RELAY_ADV_SETS > 0 && adv->tag == BT_MESH_RELAY_ADV)) { + if ((IS_ENABLED(CONFIG_BT_MESH_ADV_EXT_FRIEND_SEPARATE) && adv->tags & BT_MESH_FRIEND_ADV_BIT) || + (CONFIG_BT_MESH_RELAY_ADV_SETS > 0 && adv->tags & BT_MESH_RELAY_ADV_BIT)) { k_work_reschedule(&adv->work, K_NO_WAIT); } else { /* The controller will send the next advertisement immediately. diff --git a/subsys/bluetooth/mesh/statistic.c b/subsys/bluetooth/mesh/statistic.c index 5b1ffe7e0f5..046fa3c0eeb 100644 --- a/subsys/bluetooth/mesh/statistic.c +++ b/subsys/bluetooth/mesh/statistic.c @@ -24,22 +24,22 @@ void bt_mesh_stat_reset(void) void bt_mesh_stat_planned_count(struct bt_mesh_adv *adv) { - if (adv->tag & BT_MESH_LOCAL_ADV) { + if (adv->tag == BT_MESH_LOCAL_ADV) { stat.tx_local_planned++; - } else if (adv->tag & BT_MESH_RELAY_ADV) { + } else if (adv->tag == BT_MESH_RELAY_ADV) { stat.tx_adv_relay_planned++; - } else if (adv->tag & BT_MESH_FRIEND_ADV) { + } else if (adv->tag == BT_MESH_FRIEND_ADV) { stat.tx_friend_planned++; } } void bt_mesh_stat_succeeded_count(struct bt_mesh_adv *adv) { - if (adv->tag & BT_MESH_LOCAL_ADV) { + if (adv->tag == BT_MESH_LOCAL_ADV) { stat.tx_local_succeeded++; - } else if (adv->tag & BT_MESH_RELAY_ADV) { + } else if (adv->tag == BT_MESH_RELAY_ADV) { stat.tx_adv_relay_succeeded++; - } else if (adv->tag & BT_MESH_FRIEND_ADV) { + } else if (adv->tag == BT_MESH_FRIEND_ADV) { stat.tx_friend_succeeded++; } } From 4d33c79aca6fab97c81dfc03228b997028989562 Mon Sep 17 00:00:00 2001 From: Lingao Meng Date: Wed, 6 Sep 2023 16:47:20 +0800 Subject: [PATCH 391/421] [nrf fromlist] Bluetooth: Mesh: Rename adv relay to adv simultaneous Since notice that simultaneous advertising is not only used by relay message, provision over pb-adv can also be used. so it was changed to a more general name. refs:https://github.com/zephyrproject-rtos/zephyr/pull/48903 Upstream PR: https://github.com/zephyrproject-rtos/zephyr/pull/62331 Signed-off-by: Lingao Meng (cherry picked from commit 141467a2611bde904cacc7d3f6b89ac282c617ac) --- subsys/bluetooth/mesh/Kconfig | 40 +++++-- subsys/bluetooth/mesh/adv.c | 44 +++---- subsys/bluetooth/mesh/adv.h | 22 ++-- subsys/bluetooth/mesh/adv_ext.c | 109 ++++++++++++------ subsys/bluetooth/mesh/adv_legacy.c | 8 +- subsys/bluetooth/mesh/beacon.c | 6 +- subsys/bluetooth/mesh/friend.c | 2 +- subsys/bluetooth/mesh/net.c | 2 +- subsys/bluetooth/mesh/pb_adv.c | 19 ++- subsys/bluetooth/mesh/statistic.c | 12 +- subsys/bluetooth/mesh/transport.c | 4 +- subsys/bluetooth/mesh/transport_legacy.c | 4 +- tests/bluetooth/mesh/basic/multi_ext_adv.conf | 2 +- .../bsim/bluetooth/mesh/src/test_advertiser.c | 18 +-- 14 files changed, 185 insertions(+), 107 deletions(-) diff --git a/subsys/bluetooth/mesh/Kconfig b/subsys/bluetooth/mesh/Kconfig index 605e4608be7..a05d3917c1d 100644 --- a/subsys/bluetooth/mesh/Kconfig +++ b/subsys/bluetooth/mesh/Kconfig @@ -103,22 +103,22 @@ menuconfig BT_MESH_ADV_EXT if BT_MESH_ADV_EXT -config BT_MESH_RELAY_ADV_SETS - int "Maximum of simultaneous relay message support" +config BT_MESH_SIMULT_ADV_SETS + int "Maximum number of parallel advertising sets that can be used by the Bluetooth Mesh stack" default 0 range 0 BT_EXT_ADV_MAX_ADV_SET - depends on BT_MESH_RELAY + depends on BT_MESH_RELAY || BT_MESH_PB_ADV help - Maximum of simultaneous relay message support. Requires controller support + Maximum of simultaneous message support. Requires controller support multiple advertising sets. config BT_MESH_ADV_EXT_RELAY_USING_MAIN_ADV_SET bool "Use the main advertising set to relay messages" - depends on BT_MESH_RELAY_ADV_SETS > 0 + depends on BT_MESH_SIMULT_ADV_SETS > 0 help When this option is enabled, there is a message that needs to be relayed, all relay advertising sets defined by - CONFIG_BT_MESH_RELAY_ADV_SETS are busy with relaying messages + CONFIG_BT_MESH_SIMULT_ADV_SETS are busy with relaying messages and the main advertising set is not busy with sending local messages, the stack will use the main advertising set to relay the message. This maximizes the utilization efficiency of @@ -199,6 +199,32 @@ config BT_MESH_PB_ADV_RETRANS_TIMEOUT help Timeout value of retransmit provisioning PDUs. +config BT_MESH_PB_ADV_TRANS_PDU_RETRANSMIT_COUNT + int "Link Open and Transaction PDU retransmit count" + default 7 if BT_MESH_SIMULT_ADV_SETS > 0 + default 0 + range 0 7 + help + Controls the number of retransmissions of original Link Open and Transaction PDU, + in addition to the first transmission. + +config BT_MESH_PB_ADV_TRANS_ACK_RETRANSMIT_COUNT + int "Link Ack and Transaction Ack retransmit count" + default 2 + range 0 7 + help + Controls the number of retransmissions of original Link Open and Transaction Acknowledgment PDU, + in addition to the first transmission. + +config BT_MESH_PB_ADV_LINK_CLOSE_RETRANSMIT_COUNT + int "Link Close retransmit count" + default 7 if BT_MESH_SIMULT_ADV_SETS > 0 + default 2 + range 0 7 + help + Controls the number of retransmissions of original Link Close, + in addition to the first transmission. + endif # BT_MESH_PB_ADV if BT_CONN @@ -375,7 +401,7 @@ config BT_MESH_RELAY_BUF_COUNT of packet drops. When considering the message latency, also consider the values of BT_MESH_RELAY_RETRANSMIT_COUNT and BT_MESH_RELAY_RETRANSMIT_INTERVAL. A higher number of - BT_MESH_RELAY_ADV_SETS allows the increase in the number of buffers + BT_MESH_SIMULT_ADV_SETS allows the increase in the number of buffers while maintaining the latency. endif # BT_MESH_RELAY diff --git a/subsys/bluetooth/mesh/adv.c b/subsys/bluetooth/mesh/adv.c index e67d96414e7..c7abcd53d70 100644 --- a/subsys/bluetooth/mesh/adv.c +++ b/subsys/bluetooth/mesh/adv.c @@ -44,7 +44,7 @@ const uint8_t bt_mesh_adv_type[BT_MESH_ADV_TYPES] = { static bool active_scanning; static K_FIFO_DEFINE(bt_mesh_adv_queue); -static K_FIFO_DEFINE(bt_mesh_relay_queue); +static K_FIFO_DEFINE(bt_mesh_simult_queue); static K_FIFO_DEFINE(bt_mesh_friend_queue); void bt_mesh_adv_send_start(uint16_t duration, int err, struct bt_mesh_adv *adv) @@ -138,7 +138,7 @@ struct net_buf *bt_mesh_adv_create(enum bt_mesh_adv_type type, uint8_t xmit, k_timeout_t timeout) { #if defined(CONFIG_BT_MESH_RELAY) - if (tag == BT_MESH_RELAY_ADV) { + if (tag == BT_MESH_ADV_TAG_RELAY) { return bt_mesh_adv_create_from_pool(&relay_buf_pool, adv_relay_pool, type, tag, xmit, timeout); @@ -146,7 +146,7 @@ struct net_buf *bt_mesh_adv_create(enum bt_mesh_adv_type type, #endif #if defined(CONFIG_BT_MESH_ADV_EXT_FRIEND_SEPARATE) - if (tag == BT_MESH_FRIEND_ADV) { + if (tag == BT_MESH_ADV_TAG_FRIEND) { return bt_mesh_adv_create_from_pool(&friend_buf_pool, adv_friend_pool, type, tag, xmit, timeout); @@ -157,7 +157,7 @@ struct net_buf *bt_mesh_adv_create(enum bt_mesh_adv_type type, tag, xmit, timeout); } -#if CONFIG_BT_MESH_RELAY_ADV_SETS || CONFIG_BT_MESH_ADV_EXT_FRIEND_SEPARATE +#if CONFIG_BT_MESH_SIMULT_ADV_SETS || CONFIG_BT_MESH_ADV_EXT_FRIEND_SEPARATE static struct net_buf *process_events(struct k_poll_event *ev, int count) { for (; count; ev++, count--) { @@ -189,7 +189,7 @@ struct net_buf *bt_mesh_adv_buf_get(k_timeout_t timeout) #if defined(CONFIG_BT_MESH_ADV_EXT_RELAY_USING_MAIN_ADV_SET) K_POLL_EVENT_STATIC_INITIALIZER(K_POLL_TYPE_FIFO_DATA_AVAILABLE, K_POLL_MODE_NOTIFY_ONLY, - &bt_mesh_relay_queue, + &bt_mesh_simult_queue, 0), #endif /* CONFIG_BT_MESH_ADV_EXT_RELAY_USING_MAIN_ADV_SET */ }; @@ -204,19 +204,20 @@ struct net_buf *bt_mesh_adv_buf_get(k_timeout_t timeout) struct net_buf *bt_mesh_adv_buf_get_by_tag(enum bt_mesh_adv_tags tags, k_timeout_t timeout) { - if (IS_ENABLED(CONFIG_BT_MESH_ADV_EXT_FRIEND_SEPARATE) && tags & BT_MESH_FRIEND_ADV_BIT) { + if (IS_ENABLED(CONFIG_BT_MESH_ADV_EXT_FRIEND_SEPARATE) && + tags & BT_MESH_ADV_TAG_FRIEND_BIT) { return net_buf_get(&bt_mesh_friend_queue, timeout); } -#if CONFIG_BT_MESH_RELAY_ADV_SETS - if (tags & BT_MESH_RELAY_ADV_BIT) { - return net_buf_get(&bt_mesh_relay_queue, timeout); + if (tags & BT_MESH_ADV_TAG_LOCAL_BIT) { + return bt_mesh_adv_buf_get(timeout); } -#endif - return bt_mesh_adv_buf_get(timeout); +#if CONFIG_BT_MESH_SIMULT_ADV_SETS + return net_buf_get(&bt_mesh_simult_queue, timeout); +#endif } -#else /* !(CONFIG_BT_MESH_RELAY_ADV_SETS || CONFIG_BT_MESH_ADV_EXT_FRIEND_SEPARATE) */ +#else /* !(CONFIG_BT_MESH_SIMULT_ADV_SETS || CONFIG_BT_MESH_ADV_EXT_FRIEND_SEPARATE) */ struct net_buf *bt_mesh_adv_buf_get(k_timeout_t timeout) { return net_buf_get(&bt_mesh_adv_queue, timeout); @@ -228,7 +229,7 @@ struct net_buf *bt_mesh_adv_buf_get_by_tag(enum bt_mesh_adv_tags tags, k_timeout return bt_mesh_adv_buf_get(timeout); } -#endif /* CONFIG_BT_MESH_RELAY_ADV_SETS || CONFIG_BT_MESH_ADV_EXT_FRIEND_SEPARATE */ +#endif /* CONFIG_BT_MESH_SIMULT_ADV_SETS || CONFIG_BT_MESH_ADV_EXT_FRIEND_SEPARATE */ void bt_mesh_adv_buf_get_cancel(void) { @@ -236,9 +237,9 @@ void bt_mesh_adv_buf_get_cancel(void) k_fifo_cancel_wait(&bt_mesh_adv_queue); -#if CONFIG_BT_MESH_RELAY_ADV_SETS - k_fifo_cancel_wait(&bt_mesh_relay_queue); -#endif /* CONFIG_BT_MESH_RELAY_ADV_SETS */ +#if CONFIG_BT_MESH_SIMULT_ADV_SETS + k_fifo_cancel_wait(&bt_mesh_simult_queue); +#endif /* CONFIG_BT_MESH_SIMULT_ADV_SETS */ if (IS_ENABLED(CONFIG_BT_MESH_ADV_EXT_FRIEND_SEPARATE)) { k_fifo_cancel_wait(&bt_mesh_friend_queue); @@ -260,16 +261,17 @@ void bt_mesh_adv_send(struct net_buf *buf, const struct bt_mesh_send_cb *cb, } if (IS_ENABLED(CONFIG_BT_MESH_ADV_EXT_FRIEND_SEPARATE) && - BT_MESH_ADV(buf)->tag == BT_MESH_FRIEND_ADV) { + BT_MESH_ADV(buf)->tag == BT_MESH_ADV_TAG_FRIEND) { net_buf_put(&bt_mesh_friend_queue, net_buf_ref(buf)); bt_mesh_adv_buf_friend_ready(); return; } -#if CONFIG_BT_MESH_RELAY_ADV_SETS - if (BT_MESH_ADV(buf)->tag == BT_MESH_RELAY_ADV) { - net_buf_put(&bt_mesh_relay_queue, net_buf_ref(buf)); - bt_mesh_adv_buf_relay_ready(); +#if CONFIG_BT_MESH_SIMULT_ADV_SETS + if (BT_MESH_ADV(buf)->tag == BT_MESH_ADV_TAG_RELAY || + BT_MESH_ADV(buf)->tag == BT_MESH_ADV_TAG_PROV) { + net_buf_put(&bt_mesh_simult_queue, net_buf_ref(buf)); + bt_mesh_adv_buf_simult_ready(); return; } #endif diff --git a/subsys/bluetooth/mesh/adv.h b/subsys/bluetooth/mesh/adv.h index 22a8e0645e1..50c5b47604c 100644 --- a/subsys/bluetooth/mesh/adv.h +++ b/subsys/bluetooth/mesh/adv.h @@ -26,17 +26,19 @@ enum bt_mesh_adv_type { }; enum bt_mesh_adv_tag { - BT_MESH_LOCAL_ADV, - BT_MESH_RELAY_ADV, - BT_MESH_PROXY_ADV, - BT_MESH_FRIEND_ADV, + BT_MESH_ADV_TAG_LOCAL, + BT_MESH_ADV_TAG_RELAY, + BT_MESH_ADV_TAG_PROXY, + BT_MESH_ADV_TAG_FRIEND, + BT_MESH_ADV_TAG_PROV, }; enum bt_mesh_adv_tags { - BT_MESH_LOCAL_ADV_BIT = BIT(BT_MESH_LOCAL_ADV), - BT_MESH_RELAY_ADV_BIT = BIT(BT_MESH_RELAY_ADV), - BT_MESH_PROXY_ADV_BIT = BIT(BT_MESH_PROXY_ADV), - BT_MESH_FRIEND_ADV_BIT = BIT(BT_MESH_FRIEND_ADV), + BT_MESH_ADV_TAG_LOCAL_BIT = BIT(BT_MESH_ADV_TAG_LOCAL), + BT_MESH_ADV_TAG_RELAY_BIT = BIT(BT_MESH_ADV_TAG_RELAY), + BT_MESH_ADV_TAG_PROXY_BIT = BIT(BT_MESH_ADV_TAG_PROXY), + BT_MESH_ADV_TAG_FRIEND_BIT = BIT(BT_MESH_ADV_TAG_FRIEND), + BT_MESH_ADV_TAG_PROV_BIT = BIT(BT_MESH_ADV_TAG_PROV), }; struct bt_mesh_adv { @@ -80,7 +82,9 @@ int bt_mesh_adv_enable(void); void bt_mesh_adv_buf_local_ready(void); -void bt_mesh_adv_buf_relay_ready(void); +void bt_mesh_adv_buf_simult_ready(void); + +void bt_mesh_adv_buf_terminate(struct net_buf *buf); void bt_mesh_adv_buf_friend_ready(void); diff --git a/subsys/bluetooth/mesh/adv_ext.c b/subsys/bluetooth/mesh/adv_ext.c index d347602ac09..2065de372a4 100644 --- a/subsys/bluetooth/mesh/adv_ext.c +++ b/subsys/bluetooth/mesh/adv_ext.c @@ -33,8 +33,8 @@ LOG_MODULE_REGISTER(bt_mesh_adv_ext); /* Convert from ms to 0.625ms units */ #define ADV_INT_FAST_MS 20 -#ifndef CONFIG_BT_MESH_RELAY_ADV_SETS -#define CONFIG_BT_MESH_RELAY_ADV_SETS 0 +#ifndef CONFIG_BT_MESH_SIMULT_ADV_SETS +#define CONFIG_BT_MESH_SIMULT_ADV_SETS 0 #endif enum { @@ -75,32 +75,40 @@ static bool schedule_send(struct bt_mesh_ext_adv *adv); static STRUCT_SECTION_ITERABLE(bt_mesh_ext_adv, adv_main) = { .tags = ( #if !defined(CONFIG_BT_MESH_ADV_EXT_FRIEND_SEPARATE) - BT_MESH_FRIEND_ADV_BIT | + BT_MESH_ADV_TAG_FRIEND_BIT | #endif #if !defined(CONFIG_BT_MESH_ADV_EXT_GATT_SEPARATE) - BT_MESH_PROXY_ADV_BIT | + BT_MESH_ADV_TAG_PROXY_BIT | #endif /* !CONFIG_BT_MESH_ADV_EXT_GATT_SEPARATE */ #if defined(CONFIG_BT_MESH_ADV_EXT_RELAY_USING_MAIN_ADV_SET) - BT_MESH_RELAY_ADV_BIT | + BT_MESH_ADV_TAG_RELAY_BIT | #endif /* CONFIG_BT_MESH_ADV_EXT_RELAY_USING_MAIN_ADV_SET */ - BT_MESH_LOCAL_ADV_BIT), + BT_MESH_ADV_TAG_LOCAL_BIT), .work = Z_WORK_DELAYABLE_INITIALIZER(send_pending_adv), }; -#if CONFIG_BT_MESH_RELAY_ADV_SETS -static STRUCT_SECTION_ITERABLE_ARRAY(bt_mesh_ext_adv, adv_relay, CONFIG_BT_MESH_RELAY_ADV_SETS) = { - [0 ... CONFIG_BT_MESH_RELAY_ADV_SETS - 1] = { - .tags = BT_MESH_RELAY_ADV_BIT, +#if CONFIG_BT_MESH_SIMULT_ADV_SETS +static STRUCT_SECTION_ITERABLE_ARRAY(bt_mesh_ext_adv, adv_relay, CONFIG_BT_MESH_SIMULT_ADV_SETS) = { + [0 ... CONFIG_BT_MESH_SIMULT_ADV_SETS - 1] = { + .tags = ( +#if defined(CONFIG_BT_MESH_RELAY) + BT_MESH_ADV_TAG_RELAY_BIT | +#endif /* CONFIG_BT_MESH_RELAY */ +#if defined(CONFIG_BT_MESH_PB_ADV) + BT_MESH_ADV_TAG_PROV_BIT | +#endif /* CONFIG_BT_MESH_PB_ADV */ + 0), + .work = Z_WORK_DELAYABLE_INITIALIZER(send_pending_adv), } }; -#endif /* CONFIG_BT_MESH_RELAY_ADV_SETS */ +#endif /* CONFIG_BT_MESH_SIMULT_ADV_SETS */ #if defined(CONFIG_BT_MESH_ADV_EXT_FRIEND_SEPARATE) #define ADV_EXT_FRIEND 1 static STRUCT_SECTION_ITERABLE(bt_mesh_ext_adv, adv_friend) = { - .tags = BT_MESH_FRIEND_ADV_BIT, + .tags = BT_MESH_ADV_TAG_FRIEND_BIT, .work = Z_WORK_DELAYABLE_INITIALIZER(send_pending_adv), }; #else /* CONFIG_BT_MESH_ADV_EXT_FRIEND_SEPARATE */ @@ -110,25 +118,25 @@ static STRUCT_SECTION_ITERABLE(bt_mesh_ext_adv, adv_friend) = { #if defined(CONFIG_BT_MESH_ADV_EXT_GATT_SEPARATE) #define ADV_EXT_GATT 1 static STRUCT_SECTION_ITERABLE(bt_mesh_ext_adv, adv_gatt) = { - .tags = BT_MESH_PROXY_ADV_BIT, + .tags = BT_MESH_ADV_TAG_PROXY_BIT, .work = Z_WORK_DELAYABLE_INITIALIZER(send_pending_adv), }; #else /* CONFIG_BT_MESH_ADV_EXT_GATT_SEPARATE */ #define ADV_EXT_GATT 0 #endif /* CONFIG_BT_MESH_ADV_EXT_GATT_SEPARATE */ -#define BT_MESH_ADV_COUNT (1 + CONFIG_BT_MESH_RELAY_ADV_SETS + ADV_EXT_FRIEND + ADV_EXT_GATT) +#define BT_MESH_ADV_COUNT (1 + CONFIG_BT_MESH_SIMULT_ADV_SETS + ADV_EXT_FRIEND + ADV_EXT_GATT) BUILD_ASSERT(CONFIG_BT_EXT_ADV_MAX_ADV_SET >= BT_MESH_ADV_COUNT, "Insufficient adv instances"); static inline struct bt_mesh_ext_adv *relay_adv_get(void) { -#if CONFIG_BT_MESH_RELAY_ADV_SETS +#if CONFIG_BT_MESH_SIMULT_ADV_SETS return adv_relay; -#else /* !CONFIG_BT_MESH_RELAY_ADV_SETS */ +#else /* !CONFIG_BT_MESH_SIMULT_ADV_SETS */ return &adv_main; -#endif /* CONFIG_BT_MESH_RELAY_ADV_SETS */ +#endif /* CONFIG_BT_MESH_SIMULT_ADV_SETS */ } static inline struct bt_mesh_ext_adv *gatt_adv_get(void) @@ -259,20 +267,13 @@ static int buf_send(struct bt_mesh_ext_adv *adv, struct net_buf *buf) return err; } -static const char *adv_tag_to_str(enum bt_mesh_adv_tags tags) -{ - if (tags & BT_MESH_LOCAL_ADV_BIT) { - return "local adv"; - } else if (tags & BT_MESH_PROXY_ADV_BIT) { - return "proxy adv"; - } else if (tags & BT_MESH_RELAY_ADV_BIT) { - return "relay adv"; - } else if (tags & BT_MESH_FRIEND_ADV_BIT) { - return "friend adv"; - } else { - return "(unknown tags)"; - } -} +static const char * const adv_tag_to_str[] = { + [BT_MESH_ADV_TAG_LOCAL] = "local adv", + [BT_MESH_ADV_TAG_RELAY] = "relay adv", + [BT_MESH_ADV_TAG_PROXY] = "proxy adv", + [BT_MESH_ADV_TAG_FRIEND] = "friend adv", + [BT_MESH_ADV_TAG_PROV] = "prov adv", +}; static void send_pending_adv(struct k_work *work) { @@ -289,8 +290,9 @@ static void send_pending_adv(struct k_work *work) */ int64_t duration = k_uptime_delta(&adv->timestamp); - LOG_DBG("Advertising stopped after %u ms for (%u) %s", (uint32_t)duration, adv->tags, - adv_tag_to_str(adv->tags)); + LOG_DBG("Advertising stopped after %u ms for %s", (uint32_t)duration, + adv->buf ? adv_tag_to_str[BT_MESH_ADV(adv->buf)->tag] : + adv_tag_to_str[BT_MESH_ADV_TAG_PROXY]); atomic_clear_bit(adv->flags, ADV_FLAG_ACTIVE); atomic_clear_bit(adv->flags, ADV_FLAG_PROXY); @@ -326,7 +328,7 @@ static void send_pending_adv(struct k_work *work) } if (!IS_ENABLED(CONFIG_BT_MESH_GATT_SERVER) || - !(adv->tags & BT_MESH_RELAY_ADV_BIT)) { + !(adv->tags & BT_MESH_ADV_TAG_PROXY_BIT)) { return; } @@ -369,8 +371,9 @@ static bool schedule_send(struct bt_mesh_ext_adv *adv) atomic_clear_bit(adv->flags, ADV_FLAG_SCHEDULE_PENDING); - if ((IS_ENABLED(CONFIG_BT_MESH_ADV_EXT_FRIEND_SEPARATE) && adv->tags & BT_MESH_FRIEND_ADV_BIT) || - (CONFIG_BT_MESH_RELAY_ADV_SETS > 0 && adv->tags & BT_MESH_RELAY_ADV_BIT)) { + if ((IS_ENABLED(CONFIG_BT_MESH_ADV_EXT_FRIEND_SEPARATE) && + adv->tags & BT_MESH_ADV_TAG_FRIEND_BIT) || + (CONFIG_BT_MESH_SIMULT_ADV_SETS > 0 && adv->tags & BT_MESH_ADV_TAG_RELAY_BIT)) { k_work_reschedule(&adv->work, K_NO_WAIT); } else { /* The controller will send the next advertisement immediately. @@ -394,11 +397,11 @@ void bt_mesh_adv_buf_local_ready(void) (void)schedule_send(&adv_main); } -void bt_mesh_adv_buf_relay_ready(void) +void bt_mesh_adv_buf_simult_ready(void) { struct bt_mesh_ext_adv *adv = relay_adv_get(); - for (int i = 0; i < CONFIG_BT_MESH_RELAY_ADV_SETS; i++) { + for (int i = 0; i < CONFIG_BT_MESH_SIMULT_ADV_SETS; i++) { if (schedule_send(&adv[i])) { return; } @@ -417,6 +420,36 @@ void bt_mesh_adv_buf_friend_ready(void) #endif } +void bt_mesh_adv_buf_terminate(struct net_buf *buf) +{ + int err; + + STRUCT_SECTION_FOREACH(bt_mesh_ext_adv, adv) { + if (adv->buf != buf) { + continue; + } + + if (!atomic_test_bit(adv->flags, ADV_FLAG_ACTIVE)) { + return; + } + + err = bt_le_ext_adv_stop(adv->instance); + if (err) { + LOG_ERR("Failed to stop adv %d", err); + return; + } + + /* Do not call `cb:end`, since this user action */ + BT_MESH_ADV(adv->buf)->cb = NULL; + + atomic_set_bit(adv->flags, ADV_FLAG_SENT); + + k_work_submit(&adv->work.work); + + break; + } +} + void bt_mesh_adv_init(void) { struct bt_le_adv_param adv_param = { diff --git a/subsys/bluetooth/mesh/adv_legacy.c b/subsys/bluetooth/mesh/adv_legacy.c index 8136aef9f22..cb4028662f9 100644 --- a/subsys/bluetooth/mesh/adv_legacy.c +++ b/subsys/bluetooth/mesh/adv_legacy.c @@ -195,7 +195,7 @@ void bt_mesh_adv_buf_local_ready(void) /* Will be handled automatically */ } -void bt_mesh_adv_buf_relay_ready(void) +void bt_mesh_adv_buf_simult_ready(void) { /* Will be handled automatically */ } @@ -205,6 +205,12 @@ void bt_mesh_adv_gatt_update(void) bt_mesh_adv_buf_get_cancel(); } +void bt_mesh_adv_buf_terminate(struct net_buf *buf) +{ + /* todo */ + ARG_UNUSED(buf); +} + void bt_mesh_adv_init(void) { k_thread_create(&adv_thread_data, adv_thread_stack, diff --git a/subsys/bluetooth/mesh/beacon.c b/subsys/bluetooth/mesh/beacon.c index 8c0ac3b54e9..afdea5b4c6a 100644 --- a/subsys/bluetooth/mesh/beacon.c +++ b/subsys/bluetooth/mesh/beacon.c @@ -271,7 +271,7 @@ static bool net_beacon_send(struct bt_mesh_subnet *sub, struct bt_mesh_beacon *b return false; } - buf = bt_mesh_adv_create(BT_MESH_ADV_BEACON, BT_MESH_LOCAL_ADV, + buf = bt_mesh_adv_create(BT_MESH_ADV_BEACON, BT_MESH_ADV_TAG_LOCAL, PROV_XMIT, K_NO_WAIT); if (!buf) { LOG_ERR("Unable to allocate beacon buffer"); @@ -335,7 +335,7 @@ static int unprovisioned_beacon_send(void) LOG_DBG(""); - buf = bt_mesh_adv_create(BT_MESH_ADV_BEACON, BT_MESH_LOCAL_ADV, + buf = bt_mesh_adv_create(BT_MESH_ADV_BEACON, BT_MESH_ADV_TAG_LOCAL, UNPROV_XMIT, K_NO_WAIT); if (!buf) { LOG_ERR("Unable to allocate beacon buffer"); @@ -362,7 +362,7 @@ static int unprovisioned_beacon_send(void) if (prov->uri) { size_t len; - buf = bt_mesh_adv_create(BT_MESH_ADV_URI, BT_MESH_LOCAL_ADV, + buf = bt_mesh_adv_create(BT_MESH_ADV_URI, BT_MESH_ADV_TAG_LOCAL, UNPROV_XMIT, K_NO_WAIT); if (!buf) { LOG_ERR("Unable to allocate URI buffer"); diff --git a/subsys/bluetooth/mesh/friend.c b/subsys/bluetooth/mesh/friend.c index 179755d9706..73b75eadf4f 100644 --- a/subsys/bluetooth/mesh/friend.c +++ b/subsys/bluetooth/mesh/friend.c @@ -1281,7 +1281,7 @@ static void friend_timeout(struct k_work *work) frnd->queue_size--; send_last: - buf = bt_mesh_adv_create(BT_MESH_ADV_DATA, BT_MESH_FRIEND_ADV, + buf = bt_mesh_adv_create(BT_MESH_ADV_DATA, BT_MESH_ADV_TAG_FRIEND, FRIEND_XMIT, K_NO_WAIT); if (!buf) { LOG_ERR("Unable to allocate friend adv buffer"); diff --git a/subsys/bluetooth/mesh/net.c b/subsys/bluetooth/mesh/net.c index 2cfc709c648..61efaeb2c81 100644 --- a/subsys/bluetooth/mesh/net.c +++ b/subsys/bluetooth/mesh/net.c @@ -712,7 +712,7 @@ static void bt_mesh_net_relay(struct net_buf_simple *sbuf, transmit = bt_mesh_net_transmit_get(); } - buf = bt_mesh_adv_create(BT_MESH_ADV_DATA, BT_MESH_RELAY_ADV, + buf = bt_mesh_adv_create(BT_MESH_ADV_DATA, BT_MESH_ADV_TAG_RELAY, transmit, K_NO_WAIT); if (!buf) { LOG_DBG("Out of relay buffers"); diff --git a/subsys/bluetooth/mesh/pb_adv.c b/subsys/bluetooth/mesh/pb_adv.c index 27d55763298..cb5f53f32b7 100644 --- a/subsys/bluetooth/mesh/pb_adv.c +++ b/subsys/bluetooth/mesh/pb_adv.c @@ -55,11 +55,11 @@ LOG_MODULE_REGISTER(bt_mesh_pb_adv); /* Acked messages, will do retransmissions manually, taking acks into account: */ -#define RETRANSMITS_RELIABLE 0 +#define RETRANSMITS_RELIABLE CONFIG_BT_MESH_PB_ADV_TRANS_PDU_RETRANSMIT_COUNT /* PDU acks: */ -#define RETRANSMITS_ACK 2 +#define RETRANSMITS_ACK CONFIG_BT_MESH_PB_ADV_TRANS_ACK_RETRANSMIT_COUNT /* Link close retransmits: */ -#define RETRANSMITS_LINK_CLOSE 2 +#define RETRANSMITS_LINK_CLOSE CONFIG_BT_MESH_PB_ADV_LINK_CLOSE_RETRANSMIT_COUNT enum { ADV_LINK_ACTIVE, /* Link has been opened */ @@ -178,8 +178,15 @@ static void free_segments(void) } link.tx.buf[i] = NULL; - /* Mark as canceled */ - BT_MESH_ADV(buf)->busy = 0U; + + /* Terminate active adv */ + if (BT_MESH_ADV(buf)->busy == 0U) { + bt_mesh_adv_buf_terminate(buf); + } else { + /* Mark as canceled */ + BT_MESH_ADV(buf)->busy = 0U; + } + net_buf_unref(buf); } } @@ -251,7 +258,7 @@ static struct net_buf *adv_buf_create(uint8_t retransmits) { struct net_buf *buf; - buf = bt_mesh_adv_create(BT_MESH_ADV_PROV, BT_MESH_LOCAL_ADV, + buf = bt_mesh_adv_create(BT_MESH_ADV_PROV, BT_MESH_ADV_TAG_PROV, BT_MESH_TRANSMIT(retransmits, 20), BUF_TIMEOUT); if (!buf) { diff --git a/subsys/bluetooth/mesh/statistic.c b/subsys/bluetooth/mesh/statistic.c index 046fa3c0eeb..21c451bee73 100644 --- a/subsys/bluetooth/mesh/statistic.c +++ b/subsys/bluetooth/mesh/statistic.c @@ -24,22 +24,22 @@ void bt_mesh_stat_reset(void) void bt_mesh_stat_planned_count(struct bt_mesh_adv *adv) { - if (adv->tag == BT_MESH_LOCAL_ADV) { + if (adv->tag == BT_MESH_ADV_TAG_LOCAL) { stat.tx_local_planned++; - } else if (adv->tag == BT_MESH_RELAY_ADV) { + } else if (adv->tag == BT_MESH_ADV_TAG_RELAY) { stat.tx_adv_relay_planned++; - } else if (adv->tag == BT_MESH_FRIEND_ADV) { + } else if (adv->tag == BT_MESH_ADV_TAG_FRIEND) { stat.tx_friend_planned++; } } void bt_mesh_stat_succeeded_count(struct bt_mesh_adv *adv) { - if (adv->tag == BT_MESH_LOCAL_ADV) { + if (adv->tag == BT_MESH_ADV_TAG_LOCAL) { stat.tx_local_succeeded++; - } else if (adv->tag == BT_MESH_RELAY_ADV) { + } else if (adv->tag == BT_MESH_ADV_TAG_RELAY) { stat.tx_adv_relay_succeeded++; - } else if (adv->tag == BT_MESH_FRIEND_ADV) { + } else if (adv->tag == BT_MESH_ADV_TAG_FRIEND) { stat.tx_friend_succeeded++; } } diff --git a/subsys/bluetooth/mesh/transport.c b/subsys/bluetooth/mesh/transport.c index 0343993e348..f4c49aa6856 100644 --- a/subsys/bluetooth/mesh/transport.c +++ b/subsys/bluetooth/mesh/transport.c @@ -124,7 +124,7 @@ static int send_unseg(struct bt_mesh_net_tx *tx, struct net_buf_simple *sdu, { struct net_buf *buf; - buf = bt_mesh_adv_create(BT_MESH_ADV_DATA, BT_MESH_LOCAL_ADV, + buf = bt_mesh_adv_create(BT_MESH_ADV_DATA, BT_MESH_ADV_TAG_LOCAL, tx->xmit, BUF_TIMEOUT); if (!buf) { LOG_ERR("Out of network buffers"); @@ -414,7 +414,7 @@ static void seg_tx_send_unacked(struct seg_tx *tx) continue; } - seg = bt_mesh_adv_create(BT_MESH_ADV_DATA, BT_MESH_LOCAL_ADV, + seg = bt_mesh_adv_create(BT_MESH_ADV_DATA, BT_MESH_ADV_TAG_LOCAL, tx->xmit, BUF_TIMEOUT); if (!seg) { LOG_DBG("Allocating segment failed"); diff --git a/subsys/bluetooth/mesh/transport_legacy.c b/subsys/bluetooth/mesh/transport_legacy.c index 475a0429f75..23e103b4370 100644 --- a/subsys/bluetooth/mesh/transport_legacy.c +++ b/subsys/bluetooth/mesh/transport_legacy.c @@ -131,7 +131,7 @@ static int send_unseg(struct bt_mesh_net_tx *tx, struct net_buf_simple *sdu, { struct net_buf *buf; - buf = bt_mesh_adv_create(BT_MESH_ADV_DATA, BT_MESH_LOCAL_ADV, + buf = bt_mesh_adv_create(BT_MESH_ADV_DATA, BT_MESH_ADV_TAG_LOCAL, tx->xmit, BUF_TIMEOUT); if (!buf) { LOG_ERR("Out of network buffers"); @@ -401,7 +401,7 @@ static void seg_tx_send_unacked(struct seg_tx *tx) continue; } - seg = bt_mesh_adv_create(BT_MESH_ADV_DATA, BT_MESH_LOCAL_ADV, + seg = bt_mesh_adv_create(BT_MESH_ADV_DATA, BT_MESH_ADV_TAG_LOCAL, tx->xmit, BUF_TIMEOUT); if (!seg) { LOG_DBG("Allocating segment failed"); diff --git a/tests/bluetooth/mesh/basic/multi_ext_adv.conf b/tests/bluetooth/mesh/basic/multi_ext_adv.conf index 610318f847b..0278bd557bd 100644 --- a/tests/bluetooth/mesh/basic/multi_ext_adv.conf +++ b/tests/bluetooth/mesh/basic/multi_ext_adv.conf @@ -51,5 +51,5 @@ CONFIG_BT_MESH_CRYPTO_LOG_LEVEL_DBG=y CONFIG_BT_MESH_ADV_LOG_LEVEL_DBG=y CONFIG_BT_EXT_ADV_MAX_ADV_SET=3 -CONFIG_BT_MESH_RELAY_ADV_SETS=1 +CONFIG_BT_MESH_SIMULT_ADV_SETS=1 CONFIG_BT_MESH_ADV_EXT=y diff --git a/tests/bsim/bluetooth/mesh/src/test_advertiser.c b/tests/bsim/bluetooth/mesh/src/test_advertiser.c index 590eed8eebc..911c5772f8b 100644 --- a/tests/bsim/bluetooth/mesh/src/test_advertiser.c +++ b/tests/bsim/bluetooth/mesh/src/test_advertiser.c @@ -81,7 +81,7 @@ static void adv_init(void) static void allocate_all_array(struct net_buf **buf, size_t num_buf, uint8_t xmit) { for (int i = 0; i < num_buf; i++) { - *buf = bt_mesh_adv_create(BT_MESH_ADV_DATA, BT_MESH_LOCAL_ADV, + *buf = bt_mesh_adv_create(BT_MESH_ADV_DATA, BT_MESH_ADV_TAG_LOCAL, xmit, K_NO_WAIT); ASSERT_FALSE(!*buf, "Out of buffers"); @@ -94,7 +94,7 @@ static void verify_adv_queue_overflow(void) struct net_buf *dummy_buf; /* Verity Queue overflow */ - dummy_buf = bt_mesh_adv_create(BT_MESH_ADV_DATA, BT_MESH_LOCAL_ADV, + dummy_buf = bt_mesh_adv_create(BT_MESH_ADV_DATA, BT_MESH_ADV_TAG_LOCAL, BT_MESH_TRANSMIT(2, 20), K_NO_WAIT); ASSERT_TRUE(!dummy_buf, "Unexpected extra buffer"); } @@ -160,7 +160,7 @@ static void realloc_end_cb(int err, void *cb_data) struct net_buf *buf = (struct net_buf *)cb_data; ASSERT_EQUAL(0, err); - buf = bt_mesh_adv_create(BT_MESH_ADV_DATA, BT_MESH_LOCAL_ADV, + buf = bt_mesh_adv_create(BT_MESH_ADV_DATA, BT_MESH_ADV_TAG_LOCAL, BT_MESH_TRANSMIT(2, 20), K_NO_WAIT); ASSERT_FALSE(!buf, "Out of buffers"); @@ -425,7 +425,7 @@ static void test_tx_cb_single(void) bt_init(); adv_init(); - buf = bt_mesh_adv_create(BT_MESH_ADV_DATA, BT_MESH_LOCAL_ADV, + buf = bt_mesh_adv_create(BT_MESH_ADV_DATA, BT_MESH_ADV_TAG_LOCAL, BT_MESH_TRANSMIT(2, 20), K_NO_WAIT); ASSERT_FALSE(!buf, "Out of buffers"); @@ -530,7 +530,7 @@ static void test_tx_proxy_mixin(void) * Advertising the proxy service should be resumed after * finishing advertising the message. */ - struct net_buf *buf = bt_mesh_adv_create(BT_MESH_ADV_DATA, BT_MESH_LOCAL_ADV, + struct net_buf *buf = bt_mesh_adv_create(BT_MESH_ADV_DATA, BT_MESH_ADV_TAG_LOCAL, BT_MESH_TRANSMIT(5, 20), K_NO_WAIT); net_buf_add_mem(buf, txt_msg, sizeof(txt_msg)); bt_mesh_adv_send(buf, NULL, NULL); @@ -636,16 +636,16 @@ static void test_tx_random_order(void) /* Verify random order calls */ num_adv_sent = ARRAY_SIZE(buf); previous_checker = 0xff; - buf[0] = bt_mesh_adv_create(BT_MESH_ADV_DATA, BT_MESH_LOCAL_ADV, + buf[0] = bt_mesh_adv_create(BT_MESH_ADV_DATA, BT_MESH_ADV_TAG_LOCAL, xmit, K_NO_WAIT); - ASSERT_FALSE(!buf[0], "Out of buffers"); - buf[1] = bt_mesh_adv_create(BT_MESH_ADV_DATA, BT_MESH_LOCAL_ADV, + ASSERT_FALSE(!buf[0], "Out of buffers\n"); + buf[1] = bt_mesh_adv_create(BT_MESH_ADV_DATA, BT_MESH_ADV_TAG_LOCAL, xmit, K_NO_WAIT); ASSERT_FALSE(!buf[1], "Out of buffers"); send_adv_buf(buf[0], 0, 0xff); - buf[2] = bt_mesh_adv_create(BT_MESH_ADV_DATA, BT_MESH_LOCAL_ADV, + buf[2] = bt_mesh_adv_create(BT_MESH_ADV_DATA, BT_MESH_ADV_TAG_LOCAL, xmit, K_NO_WAIT); ASSERT_FALSE(!buf[2], "Out of buffers"); From d5bb75fa25114593f868352f0b6cfcc5af996a86 Mon Sep 17 00:00:00 2001 From: Lingao Meng Date: Thu, 7 Sep 2023 16:04:00 +0800 Subject: [PATCH 392/421] [nrf fromlist] Bluetooth: Mesh: Use system workqueue for dhkey gen Since the default process dhkey gen in bt rx, will block send Trans Ack, cause peer device send more package. Upstream PR: https://github.com/zephyrproject-rtos/zephyr/pull/62331 Signed-off-by: Lingao Meng (cherry picked from commit 1b22324317ceafc4fc3d1243eba0be371af22e2d) --- subsys/bluetooth/mesh/Kconfig | 2 +- subsys/bluetooth/mesh/prov_device.c | 9 ++++++++- subsys/bluetooth/mesh/provisioner.c | 11 ++++++++++- 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/subsys/bluetooth/mesh/Kconfig b/subsys/bluetooth/mesh/Kconfig index a05d3917c1d..cb04b4dedfb 100644 --- a/subsys/bluetooth/mesh/Kconfig +++ b/subsys/bluetooth/mesh/Kconfig @@ -210,7 +210,7 @@ config BT_MESH_PB_ADV_TRANS_PDU_RETRANSMIT_COUNT config BT_MESH_PB_ADV_TRANS_ACK_RETRANSMIT_COUNT int "Link Ack and Transaction Ack retransmit count" - default 2 + default 0 range 0 7 help Controls the number of retransmissions of original Link Open and Transaction Acknowledgment PDU, diff --git a/subsys/bluetooth/mesh/prov_device.c b/subsys/bluetooth/mesh/prov_device.c index 992bf656202..6e56519eefb 100644 --- a/subsys/bluetooth/mesh/prov_device.c +++ b/subsys/bluetooth/mesh/prov_device.c @@ -358,6 +358,13 @@ static void prov_dh_key_gen(void) } } +static void prov_dh_key_gen_handler(struct k_work *work) +{ + prov_dh_key_gen(); +} + +static K_WORK_DEFINE(dh_gen_work, prov_dh_key_gen_handler); + static void prov_pub_key(const uint8_t *data) { LOG_DBG("Remote Public Key: %s", bt_hex(data, PUB_KEY_SIZE)); @@ -385,7 +392,7 @@ static void prov_pub_key(const uint8_t *data) PDU_LEN_PUB_KEY); } - prov_dh_key_gen(); + k_work_submit(&dh_gen_work); } static void notify_input_complete(void) diff --git a/subsys/bluetooth/mesh/provisioner.c b/subsys/bluetooth/mesh/provisioner.c index 717cdbee610..6bf759272dd 100644 --- a/subsys/bluetooth/mesh/provisioner.c +++ b/subsys/bluetooth/mesh/provisioner.c @@ -20,6 +20,8 @@ #include "common/bt_str.h" +#include "host/long_wq.h" + #include "crypto.h" #include "adv.h" #include "mesh.h" @@ -450,6 +452,13 @@ static void prov_dh_key_gen(void) send_confirm(); } +static void prov_dh_key_gen_handler(struct k_work *work) +{ + prov_dh_key_gen(); +} + +static K_WORK_DEFINE(dh_gen_work, prov_dh_key_gen_handler); + static void prov_pub_key(const uint8_t *data) { LOG_DBG("Remote Public Key: %s", bt_hex(data, PUB_KEY_SIZE)); @@ -460,7 +469,7 @@ static void prov_pub_key(const uint8_t *data) memcpy(bt_mesh_prov_link.conf_inputs.pub_key_device, data, PUB_KEY_SIZE); bt_mesh_prov_link.bearer->clear_tx(); - prov_dh_key_gen(); + k_work_submit(&dh_gen_work); } static void notify_input_complete(void) From 9c6d0f8a0bdca74bee70bea3746db945ac9d314a Mon Sep 17 00:00:00 2001 From: Lingao Meng Date: Fri, 8 Sep 2023 13:56:10 +0800 Subject: [PATCH 393/421] [nrf fromlist] Bluetooth: Mesh: Move ext adv sector to vector Obviously, it looks obscure by putting it in a sector, so, let's move to vector. refs: https://github.com/zephyrproject-rtos/zephyr/pull/57883 Upstream PR: https://github.com/zephyrproject-rtos/zephyr/pull/62331 Signed-off-by: Lingao Meng (cherry picked from commit c2b2641fc18233df68e7cec3f0665aa1dbf29f5f) --- cmake/linker_script/common/common-ram.cmake | 3 - include/zephyr/linker/common-ram.ld | 4 - subsys/bluetooth/mesh/Kconfig | 38 +++-- subsys/bluetooth/mesh/adv.c | 41 ++--- subsys/bluetooth/mesh/adv.h | 18 +-- subsys/bluetooth/mesh/adv_ext.c | 151 +++++++++--------- subsys/bluetooth/mesh/adv_legacy.c | 5 +- subsys/bluetooth/mesh/provisioner.c | 2 - tests/bluetooth/mesh/basic/multi_ext_adv.conf | 2 +- .../bsim/bluetooth/mesh/src/test_advertiser.c | 2 +- 10 files changed, 129 insertions(+), 137 deletions(-) diff --git a/cmake/linker_script/common/common-ram.cmake b/cmake/linker_script/common/common-ram.cmake index e6ef59eaf29..9c051477d10 100644 --- a/cmake/linker_script/common/common-ram.cmake +++ b/cmake/linker_script/common/common-ram.cmake @@ -111,9 +111,6 @@ if(CONFIG_UVB) zephyr_iterable_section(NAME uvb_node GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN 4) endif() -if(CONFIG_BT_MESH_ADV_EXT) - zephyr_iterable_section(NAME bt_mesh_ext_adv GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN 4) -endif() if(CONFIG_LOG) zephyr_iterable_section(NAME log_mpsc_pbuf GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN 4) diff --git a/include/zephyr/linker/common-ram.ld b/include/zephyr/linker/common-ram.ld index bfaa26ed400..8ae67c73257 100644 --- a/include/zephyr/linker/common-ram.ld +++ b/include/zephyr/linker/common-ram.ld @@ -12,10 +12,6 @@ #endif #endif /* NETWORKING */ -#if defined(CONFIG_BT_MESH) - ITERABLE_SECTION_RAM(bt_mesh_ext_adv, 4) -#endif - #if defined(CONFIG_GEN_SW_ISR_TABLE) && defined(CONFIG_DYNAMIC_INTERRUPTS) SECTION_DATA_PROLOGUE(sw_isr_table,,) { diff --git a/subsys/bluetooth/mesh/Kconfig b/subsys/bluetooth/mesh/Kconfig index cb04b4dedfb..63749a69d56 100644 --- a/subsys/bluetooth/mesh/Kconfig +++ b/subsys/bluetooth/mesh/Kconfig @@ -103,22 +103,22 @@ menuconfig BT_MESH_ADV_EXT if BT_MESH_ADV_EXT -config BT_MESH_SIMULT_ADV_SETS - int "Maximum number of parallel advertising sets that can be used by the Bluetooth Mesh stack" +config BT_MESH_RELAY_ADV_SETS + int "Maximum of simultaneous relay message support" default 0 range 0 BT_EXT_ADV_MAX_ADV_SET - depends on BT_MESH_RELAY || BT_MESH_PB_ADV + depends on BT_MESH_RELAY help - Maximum of simultaneous message support. Requires controller support + Maximum of simultaneous relay message support. Requires controller support multiple advertising sets. config BT_MESH_ADV_EXT_RELAY_USING_MAIN_ADV_SET bool "Use the main advertising set to relay messages" - depends on BT_MESH_SIMULT_ADV_SETS > 0 + depends on BT_MESH_RELAY_ADV_SETS > 0 help When this option is enabled, there is a message that needs to be relayed, all relay advertising sets defined by - CONFIG_BT_MESH_SIMULT_ADV_SETS are busy with relaying messages + CONFIG_BT_MESH_RELAY_ADV_SETS are busy with relaying messages and the main advertising set is not busy with sending local messages, the stack will use the main advertising set to relay the message. This maximizes the utilization efficiency of @@ -192,16 +192,15 @@ config BT_MESH_UNPROV_BEACON_INT if BT_MESH_PB_ADV -config BT_MESH_PB_ADV_RETRANS_TIMEOUT - int "Timeout value of retransmit provisioning PDUs" - default 500 - range 100 800 +config BT_MESH_PB_ADV_USE_RELAY_SETS + bool "Use relay advertising sets to send provisioning PDUs" + depends on BT_MESH_RELAY_ADV_SETS > 0 help - Timeout value of retransmit provisioning PDUs. + Use relay advertising sets to send provisioning PDUs config BT_MESH_PB_ADV_TRANS_PDU_RETRANSMIT_COUNT int "Link Open and Transaction PDU retransmit count" - default 7 if BT_MESH_SIMULT_ADV_SETS > 0 + default 7 if BT_MESH_PB_ADV_USE_RELAY_SETS default 0 range 0 7 help @@ -210,21 +209,28 @@ config BT_MESH_PB_ADV_TRANS_PDU_RETRANSMIT_COUNT config BT_MESH_PB_ADV_TRANS_ACK_RETRANSMIT_COUNT int "Link Ack and Transaction Ack retransmit count" - default 0 + default 2 range 0 7 help - Controls the number of retransmissions of original Link Open and Transaction Acknowledgment PDU, + Controls the number of retransmissions of original Link Ack and Transaction Acknowledgment PDU, in addition to the first transmission. config BT_MESH_PB_ADV_LINK_CLOSE_RETRANSMIT_COUNT int "Link Close retransmit count" - default 7 if BT_MESH_SIMULT_ADV_SETS > 0 + default 7 if BT_MESH_PB_ADV_USE_RELAY_SETS default 2 range 0 7 help Controls the number of retransmissions of original Link Close, in addition to the first transmission. +config BT_MESH_PB_ADV_RETRANS_TIMEOUT + int "Timeout value of retransmit provisioning PDUs" + default 500 + range 100 800 + help + Timeout value of retransmit provisioning PDUs. + endif # BT_MESH_PB_ADV if BT_CONN @@ -401,7 +407,7 @@ config BT_MESH_RELAY_BUF_COUNT of packet drops. When considering the message latency, also consider the values of BT_MESH_RELAY_RETRANSMIT_COUNT and BT_MESH_RELAY_RETRANSMIT_INTERVAL. A higher number of - BT_MESH_SIMULT_ADV_SETS allows the increase in the number of buffers + BT_MESH_RELAY_ADV_SETS allows the increase in the number of buffers while maintaining the latency. endif # BT_MESH_RELAY diff --git a/subsys/bluetooth/mesh/adv.c b/subsys/bluetooth/mesh/adv.c index c7abcd53d70..b24523aacf3 100644 --- a/subsys/bluetooth/mesh/adv.c +++ b/subsys/bluetooth/mesh/adv.c @@ -44,7 +44,7 @@ const uint8_t bt_mesh_adv_type[BT_MESH_ADV_TYPES] = { static bool active_scanning; static K_FIFO_DEFINE(bt_mesh_adv_queue); -static K_FIFO_DEFINE(bt_mesh_simult_queue); +static K_FIFO_DEFINE(bt_mesh_relay_queue); static K_FIFO_DEFINE(bt_mesh_friend_queue); void bt_mesh_adv_send_start(uint16_t duration, int err, struct bt_mesh_adv *adv) @@ -157,7 +157,7 @@ struct net_buf *bt_mesh_adv_create(enum bt_mesh_adv_type type, tag, xmit, timeout); } -#if CONFIG_BT_MESH_SIMULT_ADV_SETS || CONFIG_BT_MESH_ADV_EXT_FRIEND_SEPARATE +#if CONFIG_BT_MESH_RELAY_ADV_SETS || CONFIG_BT_MESH_ADV_EXT_FRIEND_SEPARATE static struct net_buf *process_events(struct k_poll_event *ev, int count) { for (; count; ev++, count--) { @@ -189,7 +189,7 @@ struct net_buf *bt_mesh_adv_buf_get(k_timeout_t timeout) #if defined(CONFIG_BT_MESH_ADV_EXT_RELAY_USING_MAIN_ADV_SET) K_POLL_EVENT_STATIC_INITIALIZER(K_POLL_TYPE_FIFO_DATA_AVAILABLE, K_POLL_MODE_NOTIFY_ONLY, - &bt_mesh_simult_queue, + &bt_mesh_relay_queue, 0), #endif /* CONFIG_BT_MESH_ADV_EXT_RELAY_USING_MAIN_ADV_SET */ }; @@ -202,34 +202,34 @@ struct net_buf *bt_mesh_adv_buf_get(k_timeout_t timeout) return process_events(events, ARRAY_SIZE(events)); } -struct net_buf *bt_mesh_adv_buf_get_by_tag(enum bt_mesh_adv_tags tags, k_timeout_t timeout) +struct net_buf *bt_mesh_adv_buf_get_by_tag(enum bt_mesh_adv_tag_bit tags, k_timeout_t timeout) { if (IS_ENABLED(CONFIG_BT_MESH_ADV_EXT_FRIEND_SEPARATE) && - tags & BT_MESH_ADV_TAG_FRIEND_BIT) { + tags & BT_MESH_ADV_TAG_BIT_FRIEND) { return net_buf_get(&bt_mesh_friend_queue, timeout); } - if (tags & BT_MESH_ADV_TAG_LOCAL_BIT) { - return bt_mesh_adv_buf_get(timeout); +#if CONFIG_BT_MESH_RELAY_ADV_SETS + if (!(tags & BT_MESH_ADV_TAG_BIT_LOCAL)) { + return net_buf_get(&bt_mesh_relay_queue, timeout); } - -#if CONFIG_BT_MESH_SIMULT_ADV_SETS - return net_buf_get(&bt_mesh_simult_queue, timeout); #endif + + return bt_mesh_adv_buf_get(timeout); } -#else /* !(CONFIG_BT_MESH_SIMULT_ADV_SETS || CONFIG_BT_MESH_ADV_EXT_FRIEND_SEPARATE) */ +#else /* !(CONFIG_BT_MESH_RELAY_ADV_SETS || CONFIG_BT_MESH_ADV_EXT_FRIEND_SEPARATE) */ struct net_buf *bt_mesh_adv_buf_get(k_timeout_t timeout) { return net_buf_get(&bt_mesh_adv_queue, timeout); } -struct net_buf *bt_mesh_adv_buf_get_by_tag(enum bt_mesh_adv_tags tags, k_timeout_t timeout) +struct net_buf *bt_mesh_adv_buf_get_by_tag(enum bt_mesh_adv_tag_bit tags, k_timeout_t timeout) { ARG_UNUSED(tags); return bt_mesh_adv_buf_get(timeout); } -#endif /* CONFIG_BT_MESH_SIMULT_ADV_SETS || CONFIG_BT_MESH_ADV_EXT_FRIEND_SEPARATE */ +#endif /* CONFIG_BT_MESH_RELAY_ADV_SETS || CONFIG_BT_MESH_ADV_EXT_FRIEND_SEPARATE */ void bt_mesh_adv_buf_get_cancel(void) { @@ -237,9 +237,9 @@ void bt_mesh_adv_buf_get_cancel(void) k_fifo_cancel_wait(&bt_mesh_adv_queue); -#if CONFIG_BT_MESH_SIMULT_ADV_SETS - k_fifo_cancel_wait(&bt_mesh_simult_queue); -#endif /* CONFIG_BT_MESH_SIMULT_ADV_SETS */ +#if CONFIG_BT_MESH_RELAY_ADV_SETS + k_fifo_cancel_wait(&bt_mesh_relay_queue); +#endif /* CONFIG_BT_MESH_RELAY_ADV_SETS */ if (IS_ENABLED(CONFIG_BT_MESH_ADV_EXT_FRIEND_SEPARATE)) { k_fifo_cancel_wait(&bt_mesh_friend_queue); @@ -267,11 +267,12 @@ void bt_mesh_adv_send(struct net_buf *buf, const struct bt_mesh_send_cb *cb, return; } -#if CONFIG_BT_MESH_SIMULT_ADV_SETS +#if CONFIG_BT_MESH_RELAY_ADV_SETS if (BT_MESH_ADV(buf)->tag == BT_MESH_ADV_TAG_RELAY || - BT_MESH_ADV(buf)->tag == BT_MESH_ADV_TAG_PROV) { - net_buf_put(&bt_mesh_simult_queue, net_buf_ref(buf)); - bt_mesh_adv_buf_simult_ready(); + (IS_ENABLED(CONFIG_BT_MESH_PB_ADV_USE_RELAY_SETS) && + BT_MESH_ADV(buf)->tag == BT_MESH_ADV_TAG_PROV)) { + net_buf_put(&bt_mesh_relay_queue, net_buf_ref(buf)); + bt_mesh_adv_buf_relay_ready(); return; } #endif diff --git a/subsys/bluetooth/mesh/adv.h b/subsys/bluetooth/mesh/adv.h index 50c5b47604c..a80ff7e8d4b 100644 --- a/subsys/bluetooth/mesh/adv.h +++ b/subsys/bluetooth/mesh/adv.h @@ -33,12 +33,12 @@ enum bt_mesh_adv_tag { BT_MESH_ADV_TAG_PROV, }; -enum bt_mesh_adv_tags { - BT_MESH_ADV_TAG_LOCAL_BIT = BIT(BT_MESH_ADV_TAG_LOCAL), - BT_MESH_ADV_TAG_RELAY_BIT = BIT(BT_MESH_ADV_TAG_RELAY), - BT_MESH_ADV_TAG_PROXY_BIT = BIT(BT_MESH_ADV_TAG_PROXY), - BT_MESH_ADV_TAG_FRIEND_BIT = BIT(BT_MESH_ADV_TAG_FRIEND), - BT_MESH_ADV_TAG_PROV_BIT = BIT(BT_MESH_ADV_TAG_PROV), +enum bt_mesh_adv_tag_bit { + BT_MESH_ADV_TAG_BIT_LOCAL = BIT(BT_MESH_ADV_TAG_LOCAL), + BT_MESH_ADV_TAG_BIT_RELAY = BIT(BT_MESH_ADV_TAG_RELAY), + BT_MESH_ADV_TAG_BIT_PROXY = BIT(BT_MESH_ADV_TAG_PROXY), + BT_MESH_ADV_TAG_BIT_FRIEND = BIT(BT_MESH_ADV_TAG_FRIEND), + BT_MESH_ADV_TAG_BIT_PROV = BIT(BT_MESH_ADV_TAG_PROV), }; struct bt_mesh_adv { @@ -66,7 +66,7 @@ void bt_mesh_adv_send(struct net_buf *buf, const struct bt_mesh_send_cb *cb, struct net_buf *bt_mesh_adv_buf_get(k_timeout_t timeout); -struct net_buf *bt_mesh_adv_buf_get_by_tag(enum bt_mesh_adv_tags tags, k_timeout_t timeout); +struct net_buf *bt_mesh_adv_buf_get_by_tag(enum bt_mesh_adv_tag_bit tags, k_timeout_t timeout); void bt_mesh_adv_gatt_update(void); @@ -82,9 +82,9 @@ int bt_mesh_adv_enable(void); void bt_mesh_adv_buf_local_ready(void); -void bt_mesh_adv_buf_simult_ready(void); +void bt_mesh_adv_buf_relay_ready(void); -void bt_mesh_adv_buf_terminate(struct net_buf *buf); +void bt_mesh_adv_buf_terminate(const struct net_buf *buf); void bt_mesh_adv_buf_friend_ready(void); diff --git a/subsys/bluetooth/mesh/adv_ext.c b/subsys/bluetooth/mesh/adv_ext.c index 2065de372a4..525e5ee5066 100644 --- a/subsys/bluetooth/mesh/adv_ext.c +++ b/subsys/bluetooth/mesh/adv_ext.c @@ -33,8 +33,8 @@ LOG_MODULE_REGISTER(bt_mesh_adv_ext); /* Convert from ms to 0.625ms units */ #define ADV_INT_FAST_MS 20 -#ifndef CONFIG_BT_MESH_SIMULT_ADV_SETS -#define CONFIG_BT_MESH_SIMULT_ADV_SETS 0 +#ifndef CONFIG_BT_MESH_RELAY_ADV_SETS +#define CONFIG_BT_MESH_RELAY_ADV_SETS 0 #endif enum { @@ -60,7 +60,7 @@ enum { }; struct bt_mesh_ext_adv { - enum bt_mesh_adv_tags tags; + const enum bt_mesh_adv_tag_bit tags; ATOMIC_DEFINE(flags, ADV_FLAGS_NUM); struct bt_le_ext_adv *instance; struct net_buf *buf; @@ -72,80 +72,71 @@ struct bt_mesh_ext_adv { static void send_pending_adv(struct k_work *work); static bool schedule_send(struct bt_mesh_ext_adv *adv); -static STRUCT_SECTION_ITERABLE(bt_mesh_ext_adv, adv_main) = { - .tags = ( +static struct bt_mesh_ext_adv advs[] = { + [0] = { + .tags = ( #if !defined(CONFIG_BT_MESH_ADV_EXT_FRIEND_SEPARATE) - BT_MESH_ADV_TAG_FRIEND_BIT | + BT_MESH_ADV_TAG_BIT_FRIEND | #endif #if !defined(CONFIG_BT_MESH_ADV_EXT_GATT_SEPARATE) - BT_MESH_ADV_TAG_PROXY_BIT | + BT_MESH_ADV_TAG_BIT_PROXY | #endif /* !CONFIG_BT_MESH_ADV_EXT_GATT_SEPARATE */ #if defined(CONFIG_BT_MESH_ADV_EXT_RELAY_USING_MAIN_ADV_SET) - BT_MESH_ADV_TAG_RELAY_BIT | + BT_MESH_ADV_TAG_BIT_RELAY | #endif /* CONFIG_BT_MESH_ADV_EXT_RELAY_USING_MAIN_ADV_SET */ - BT_MESH_ADV_TAG_LOCAL_BIT), - - .work = Z_WORK_DELAYABLE_INITIALIZER(send_pending_adv), -}; - -#if CONFIG_BT_MESH_SIMULT_ADV_SETS -static STRUCT_SECTION_ITERABLE_ARRAY(bt_mesh_ext_adv, adv_relay, CONFIG_BT_MESH_SIMULT_ADV_SETS) = { - [0 ... CONFIG_BT_MESH_SIMULT_ADV_SETS - 1] = { +#if defined(CONFIG_BT_MESH_PB_ADV) + BT_MESH_ADV_TAG_BIT_PROV | +#endif /* CONFIG_BT_MESH_PB_ADV */ + BT_MESH_ADV_TAG_BIT_LOCAL + ), + .work = Z_WORK_DELAYABLE_INITIALIZER(send_pending_adv), + }, +#if CONFIG_BT_MESH_RELAY_ADV_SETS + [1 ... CONFIG_BT_MESH_RELAY_ADV_SETS] = { .tags = ( #if defined(CONFIG_BT_MESH_RELAY) - BT_MESH_ADV_TAG_RELAY_BIT | + BT_MESH_ADV_TAG_BIT_RELAY | #endif /* CONFIG_BT_MESH_RELAY */ -#if defined(CONFIG_BT_MESH_PB_ADV) - BT_MESH_ADV_TAG_PROV_BIT | -#endif /* CONFIG_BT_MESH_PB_ADV */ +#if defined(CONFIG_BT_MESH_PB_ADV_USE_RELAY_SETS) + BT_MESH_ADV_TAG_BIT_PROV | +#endif /* CONFIG_BT_MESH_PB_ADV_USE_RELAY_SETS */ 0), - .work = Z_WORK_DELAYABLE_INITIALIZER(send_pending_adv), - } -}; -#endif /* CONFIG_BT_MESH_SIMULT_ADV_SETS */ - + }, +#endif /* CONFIG_BT_MESH_RELAY_ADV_SETS */ #if defined(CONFIG_BT_MESH_ADV_EXT_FRIEND_SEPARATE) -#define ADV_EXT_FRIEND 1 -static STRUCT_SECTION_ITERABLE(bt_mesh_ext_adv, adv_friend) = { - .tags = BT_MESH_ADV_TAG_FRIEND_BIT, - .work = Z_WORK_DELAYABLE_INITIALIZER(send_pending_adv), -}; -#else /* CONFIG_BT_MESH_ADV_EXT_FRIEND_SEPARATE */ -#define ADV_EXT_FRIEND 0 + { + .tags = BT_MESH_ADV_TAG_BIT_FRIEND, + .work = Z_WORK_DELAYABLE_INITIALIZER(send_pending_adv), + }, #endif /* CONFIG_BT_MESH_ADV_EXT_FRIEND_SEPARATE */ - #if defined(CONFIG_BT_MESH_ADV_EXT_GATT_SEPARATE) -#define ADV_EXT_GATT 1 -static STRUCT_SECTION_ITERABLE(bt_mesh_ext_adv, adv_gatt) = { - .tags = BT_MESH_ADV_TAG_PROXY_BIT, - .work = Z_WORK_DELAYABLE_INITIALIZER(send_pending_adv), -}; -#else /* CONFIG_BT_MESH_ADV_EXT_GATT_SEPARATE */ -#define ADV_EXT_GATT 0 + { + .tags = BT_MESH_ADV_TAG_BIT_PROXY, + .work = Z_WORK_DELAYABLE_INITIALIZER(send_pending_adv), + }, #endif /* CONFIG_BT_MESH_ADV_EXT_GATT_SEPARATE */ +}; -#define BT_MESH_ADV_COUNT (1 + CONFIG_BT_MESH_SIMULT_ADV_SETS + ADV_EXT_FRIEND + ADV_EXT_GATT) - -BUILD_ASSERT(CONFIG_BT_EXT_ADV_MAX_ADV_SET >= BT_MESH_ADV_COUNT, +BUILD_ASSERT(ARRAY_SIZE(advs) <= CONFIG_BT_EXT_ADV_MAX_ADV_SET, "Insufficient adv instances"); static inline struct bt_mesh_ext_adv *relay_adv_get(void) { -#if CONFIG_BT_MESH_SIMULT_ADV_SETS - return adv_relay; -#else /* !CONFIG_BT_MESH_SIMULT_ADV_SETS */ - return &adv_main; -#endif /* CONFIG_BT_MESH_SIMULT_ADV_SETS */ + if (!!(CONFIG_BT_MESH_RELAY_ADV_SETS)) { + return &advs[1]; + } else { + return &advs[0]; + } } static inline struct bt_mesh_ext_adv *gatt_adv_get(void) { -#if defined(CONFIG_BT_MESH_ADV_EXT_GATT_SEPARATE) - return &adv_gatt; -#else /* !CONFIG_BT_MESH_ADV_EXT_GATT_SEPARATE */ - return &adv_main; -#endif /* CONFIG_BT_MESH_ADV_EXT_GATT_SEPARATE */ + if (IS_ENABLED(CONFIG_BT_MESH_ADV_EXT_GATT_SEPARATE)) { + return &advs[ARRAY_SIZE(advs) - 1]; + } else { + return &advs[0]; + } } static int set_adv_randomness(uint8_t handle, int rand_us) @@ -328,7 +319,7 @@ static void send_pending_adv(struct k_work *work) } if (!IS_ENABLED(CONFIG_BT_MESH_GATT_SERVER) || - !(adv->tags & BT_MESH_ADV_TAG_PROXY_BIT)) { + !(adv->tags & BT_MESH_ADV_TAG_BIT_PROXY)) { return; } @@ -372,8 +363,8 @@ static bool schedule_send(struct bt_mesh_ext_adv *adv) atomic_clear_bit(adv->flags, ADV_FLAG_SCHEDULE_PENDING); if ((IS_ENABLED(CONFIG_BT_MESH_ADV_EXT_FRIEND_SEPARATE) && - adv->tags & BT_MESH_ADV_TAG_FRIEND_BIT) || - (CONFIG_BT_MESH_SIMULT_ADV_SETS > 0 && adv->tags & BT_MESH_ADV_TAG_RELAY_BIT)) { + adv->tags & BT_MESH_ADV_TAG_BIT_FRIEND) || + (CONFIG_BT_MESH_RELAY_ADV_SETS > 0 && adv->tags & BT_MESH_ADV_TAG_BIT_RELAY)) { k_work_reschedule(&adv->work, K_NO_WAIT); } else { /* The controller will send the next advertisement immediately. @@ -394,14 +385,14 @@ void bt_mesh_adv_gatt_update(void) void bt_mesh_adv_buf_local_ready(void) { - (void)schedule_send(&adv_main); + (void)schedule_send(advs); } -void bt_mesh_adv_buf_simult_ready(void) +void bt_mesh_adv_buf_relay_ready(void) { struct bt_mesh_ext_adv *adv = relay_adv_get(); - for (int i = 0; i < CONFIG_BT_MESH_SIMULT_ADV_SETS; i++) { + for (int i = 0; i < CONFIG_BT_MESH_RELAY_ADV_SETS; i++) { if (schedule_send(&adv[i])) { return; } @@ -409,22 +400,26 @@ void bt_mesh_adv_buf_simult_ready(void) /* Attempt to use the main adv set for the sending of relay messages. */ if (IS_ENABLED(CONFIG_BT_MESH_ADV_EXT_RELAY_USING_MAIN_ADV_SET)) { - (void)schedule_send(&adv_main); + (void)schedule_send(advs); } } void bt_mesh_adv_buf_friend_ready(void) { -#if defined(CONFIG_BT_MESH_ADV_EXT_FRIEND_SEPARATE) - (void)schedule_send(&adv_friend); -#endif + if (IS_ENABLED(CONFIG_BT_MESH_ADV_EXT_FRIEND_SEPARATE)) { + schedule_send(&advs[1 + CONFIG_BT_MESH_RELAY_ADV_SETS]); + } else { + schedule_send(&advs[0]); + } } -void bt_mesh_adv_buf_terminate(struct net_buf *buf) +void bt_mesh_adv_buf_terminate(const struct net_buf *buf) { int err; - STRUCT_SECTION_FOREACH(bt_mesh_ext_adv, adv) { + for (int i = 0; i < ARRAY_SIZE(advs); i++) { + struct bt_mesh_ext_adv *adv = &advs[i]; + if (adv->buf != buf) { continue; } @@ -446,7 +441,7 @@ void bt_mesh_adv_buf_terminate(struct net_buf *buf) k_work_submit(&adv->work.work); - break; + return; } } @@ -459,17 +454,18 @@ void bt_mesh_adv_init(void) #if defined(CONFIG_BT_MESH_DEBUG_USE_ID_ADDR) .options = BT_LE_ADV_OPT_USE_IDENTITY, #endif -}; - STRUCT_SECTION_FOREACH(bt_mesh_ext_adv, adv) { - (void)memcpy(&adv->adv_param, &adv_param, sizeof(adv_param)); + }; + + for (int i = 0; i < ARRAY_SIZE(advs); i++) { + (void)memcpy(&advs[i].adv_param, &adv_param, sizeof(adv_param)); } } static struct bt_mesh_ext_adv *adv_instance_find(struct bt_le_ext_adv *instance) { - STRUCT_SECTION_FOREACH(bt_mesh_ext_adv, adv) { - if (adv->instance == instance) { - return adv; + for (int i = 0; i < ARRAY_SIZE(advs); i++) { + if (advs[i].instance == instance) { + return &advs[i]; } } @@ -519,15 +515,14 @@ int bt_mesh_adv_enable(void) #endif /* CONFIG_BT_MESH_GATT_SERVER */ }; - if (adv_main.instance) { + if (advs[0].instance) { /* Already initialized */ return 0; } - - STRUCT_SECTION_FOREACH(bt_mesh_ext_adv, adv) { - err = bt_le_ext_adv_create(&adv->adv_param, &adv_cb, - &adv->instance); + for (int i = 0; i < ARRAY_SIZE(advs); i++) { + err = bt_le_ext_adv_create(&advs[i].adv_param, &adv_cb, + &advs[i].instance); if (err) { return err; } @@ -566,5 +561,5 @@ int bt_mesh_adv_gatt_start(const struct bt_le_adv_param *param, int bt_mesh_adv_bt_data_send(uint8_t num_events, uint16_t adv_interval, const struct bt_data *ad, size_t ad_len) { - return bt_data_send(&adv_main, num_events, adv_interval, ad, ad_len); + return bt_data_send(advs, num_events, adv_interval, ad, ad_len); } diff --git a/subsys/bluetooth/mesh/adv_legacy.c b/subsys/bluetooth/mesh/adv_legacy.c index cb4028662f9..a7d7dd1a320 100644 --- a/subsys/bluetooth/mesh/adv_legacy.c +++ b/subsys/bluetooth/mesh/adv_legacy.c @@ -195,7 +195,7 @@ void bt_mesh_adv_buf_local_ready(void) /* Will be handled automatically */ } -void bt_mesh_adv_buf_simult_ready(void) +void bt_mesh_adv_buf_relay_ready(void) { /* Will be handled automatically */ } @@ -205,9 +205,8 @@ void bt_mesh_adv_gatt_update(void) bt_mesh_adv_buf_get_cancel(); } -void bt_mesh_adv_buf_terminate(struct net_buf *buf) +void bt_mesh_adv_buf_terminate(const struct net_buf *buf) { - /* todo */ ARG_UNUSED(buf); } diff --git a/subsys/bluetooth/mesh/provisioner.c b/subsys/bluetooth/mesh/provisioner.c index 6bf759272dd..a65bd25ab53 100644 --- a/subsys/bluetooth/mesh/provisioner.c +++ b/subsys/bluetooth/mesh/provisioner.c @@ -20,8 +20,6 @@ #include "common/bt_str.h" -#include "host/long_wq.h" - #include "crypto.h" #include "adv.h" #include "mesh.h" diff --git a/tests/bluetooth/mesh/basic/multi_ext_adv.conf b/tests/bluetooth/mesh/basic/multi_ext_adv.conf index 0278bd557bd..610318f847b 100644 --- a/tests/bluetooth/mesh/basic/multi_ext_adv.conf +++ b/tests/bluetooth/mesh/basic/multi_ext_adv.conf @@ -51,5 +51,5 @@ CONFIG_BT_MESH_CRYPTO_LOG_LEVEL_DBG=y CONFIG_BT_MESH_ADV_LOG_LEVEL_DBG=y CONFIG_BT_EXT_ADV_MAX_ADV_SET=3 -CONFIG_BT_MESH_SIMULT_ADV_SETS=1 +CONFIG_BT_MESH_RELAY_ADV_SETS=1 CONFIG_BT_MESH_ADV_EXT=y diff --git a/tests/bsim/bluetooth/mesh/src/test_advertiser.c b/tests/bsim/bluetooth/mesh/src/test_advertiser.c index 911c5772f8b..6a171b499bf 100644 --- a/tests/bsim/bluetooth/mesh/src/test_advertiser.c +++ b/tests/bsim/bluetooth/mesh/src/test_advertiser.c @@ -638,7 +638,7 @@ static void test_tx_random_order(void) previous_checker = 0xff; buf[0] = bt_mesh_adv_create(BT_MESH_ADV_DATA, BT_MESH_ADV_TAG_LOCAL, xmit, K_NO_WAIT); - ASSERT_FALSE(!buf[0], "Out of buffers\n"); + ASSERT_FALSE_MSG(!buf[0], "Out of buffers\n"); buf[1] = bt_mesh_adv_create(BT_MESH_ADV_DATA, BT_MESH_ADV_TAG_LOCAL, xmit, K_NO_WAIT); ASSERT_FALSE(!buf[1], "Out of buffers"); From 6dde66941e658d5a73420e49ac96113c457ce072 Mon Sep 17 00:00:00 2001 From: Pavel Vasilyev Date: Tue, 17 Oct 2023 14:07:52 +0200 Subject: [PATCH 394/421] [nrf fromlist] bsim: bluetooth: mesh: Increase Net Transmit Count value on the node This is to increase probability of reception of responses (Config Status messages) from the node when the provisioner sends a Set message and the node response with a Status message at the same time so that the message collide. Upstream PR: https://github.com/zephyrproject-rtos/zephyr/pull/62331 Signed-off-by: Pavel Vasilyev (cherry picked from commit 7c7ea3847196c57dab9f85ed196cf02dad0c3747) --- tests/bsim/bluetooth/mesh/src/test_persistence.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/tests/bsim/bluetooth/mesh/src/test_persistence.c b/tests/bsim/bluetooth/mesh/src/test_persistence.c index 6c510922330..90bf41f73a6 100644 --- a/tests/bsim/bluetooth/mesh/src/test_persistence.c +++ b/tests/bsim/bluetooth/mesh/src/test_persistence.c @@ -520,6 +520,17 @@ static void node_configure(void) uint16_t va; struct bt_mesh_cfg_cli_mod_pub pub_params; + /* Set Network Transmit Count state on the device greater than on provisioner to increase + * probability of reception responses. + */ + uint8_t net_transmit; + + net_transmit = BT_MESH_TRANSMIT(3, 20); + err = bt_mesh_cfg_cli_net_transmit_set(test_netkey_idx, TEST_ADDR, net_transmit, &status); + if (err || status != net_transmit) { + FAIL("Net transmit set failed (err %d, transmit %x)", err, status); + } + struct test_appkey_t test_appkeys[] = { { .idx = TEST_APPKEY_0_IDX, .key = TEST_APPKEY_0_KEY }, { .idx = TEST_APPKEY_1_IDX, .key = TEST_APPKEY_1_KEY }, From d466b521fbbdf602a32d92c8ff9f9371e624fa51 Mon Sep 17 00:00:00 2001 From: Aleksandr Khromykh Date: Wed, 1 Nov 2023 15:44:23 +0100 Subject: [PATCH 395/421] [nrf fromlist] Bluetooth: Mesh: no more tinycrypt in ble mesh tfm image PR allows to get rid of tinycrypt objects from the final binary of the ble mesh apps based on PSA TFM crypto. Upstream PR: https://github.com/zephyrproject-rtos/zephyr/pull/64696 Signed-off-by: Aleksandr Khromykh (cherry picked from commit c5ee143d773e713901896319a4d116082ca0771d) --- .../boards/nrf5340dk_nrf5340_cpuapp_ns.conf | 5 +++ .../boards/nrf5340dk_nrf5340_cpuapp_ns.conf | 5 +++ .../boards/nrf5340dk_nrf5340_cpuapp_ns.conf | 3 ++ subsys/bluetooth/host/Kconfig | 7 ++-- subsys/bluetooth/mesh/crypto_psa.c | 10 ++++++ tests/bsim/bluetooth/mesh/overlay_psa.conf | 5 +++ tests/bsim/bluetooth/mesh/src/test_dfu.c | 35 ++++++++++--------- .../bluetooth/mesh/src/test_persistence.c | 2 +- .../bluetooth/mesh/src/test_replay_cache.c | 8 +++++ 9 files changed, 59 insertions(+), 21 deletions(-) diff --git a/samples/bluetooth/mesh/boards/nrf5340dk_nrf5340_cpuapp_ns.conf b/samples/bluetooth/mesh/boards/nrf5340dk_nrf5340_cpuapp_ns.conf index c638a292c91..4693e4d1f78 100644 --- a/samples/bluetooth/mesh/boards/nrf5340dk_nrf5340_cpuapp_ns.conf +++ b/samples/bluetooth/mesh/boards/nrf5340dk_nrf5340_cpuapp_ns.conf @@ -1,3 +1,8 @@ +# The option adds TinyCrypt based bt_rand. +CONFIG_BT_HOST_CRYPTO=n +# The option adds GATT caching feature that is based on TinyCrypt. +CONFIG_BT_GATT_CACHING=n + # Known issue: non secure platforms do not work with settings subsystem. CONFIG_SETTINGS=n CONFIG_BT_SETTINGS=n diff --git a/samples/bluetooth/mesh_demo/boards/nrf5340dk_nrf5340_cpuapp_ns.conf b/samples/bluetooth/mesh_demo/boards/nrf5340dk_nrf5340_cpuapp_ns.conf index c638a292c91..4693e4d1f78 100644 --- a/samples/bluetooth/mesh_demo/boards/nrf5340dk_nrf5340_cpuapp_ns.conf +++ b/samples/bluetooth/mesh_demo/boards/nrf5340dk_nrf5340_cpuapp_ns.conf @@ -1,3 +1,8 @@ +# The option adds TinyCrypt based bt_rand. +CONFIG_BT_HOST_CRYPTO=n +# The option adds GATT caching feature that is based on TinyCrypt. +CONFIG_BT_GATT_CACHING=n + # Known issue: non secure platforms do not work with settings subsystem. CONFIG_SETTINGS=n CONFIG_BT_SETTINGS=n diff --git a/samples/bluetooth/mesh_provisioner/boards/nrf5340dk_nrf5340_cpuapp_ns.conf b/samples/bluetooth/mesh_provisioner/boards/nrf5340dk_nrf5340_cpuapp_ns.conf index c638a292c91..c3d134592fc 100644 --- a/samples/bluetooth/mesh_provisioner/boards/nrf5340dk_nrf5340_cpuapp_ns.conf +++ b/samples/bluetooth/mesh_provisioner/boards/nrf5340dk_nrf5340_cpuapp_ns.conf @@ -1,3 +1,6 @@ +# The option adds TinyCrypt based bt_rand. +CONFIG_BT_HOST_CRYPTO=n + # Known issue: non secure platforms do not work with settings subsystem. CONFIG_SETTINGS=n CONFIG_BT_SETTINGS=n diff --git a/subsys/bluetooth/host/Kconfig b/subsys/bluetooth/host/Kconfig index a4cf2e0959b..2e740686b69 100644 --- a/subsys/bluetooth/host/Kconfig +++ b/subsys/bluetooth/host/Kconfig @@ -163,12 +163,13 @@ rsource "../mesh/Kconfig" rsource "../audio/Kconfig" config BT_HOST_CRYPTO - # Hidden option that compiles in AES encryption support using TinyCrypt - # library if this is not provided by the controller implementation. - bool + bool "Use crypto functionality implemented in the Bluetooth host" default y if !BT_CTLR_CRYPTO select TINYCRYPT select TINYCRYPT_AES + help + The option adds the AES encryption support using TinyCrypt + library if this is not provided by the controller implementation. config BT_HOST_CRYPTO_PRNG bool "Use Tinycrypt library for random number generation" diff --git a/subsys/bluetooth/mesh/crypto_psa.c b/subsys/bluetooth/mesh/crypto_psa.c index 450cde679a8..587c367a6bd 100644 --- a/subsys/bluetooth/mesh/crypto_psa.c +++ b/subsys/bluetooth/mesh/crypto_psa.c @@ -7,6 +7,7 @@ #include #include +#include #define LOG_LEVEL CONFIG_BT_MESH_CRYPTO_LOG_LEVEL #include @@ -510,3 +511,12 @@ int bt_mesh_key_compare(const uint8_t raw_key[16], const struct bt_mesh_key *key return memcmp(out, raw_key, 16); } + +__weak int bt_rand(void *buf, size_t len) +{ + CHECKIF(buf == NULL || len == 0) { + return -EINVAL; + } + + return psa_generate_random(buf, len) == PSA_SUCCESS ? 0 : -EIO; +} diff --git a/tests/bsim/bluetooth/mesh/overlay_psa.conf b/tests/bsim/bluetooth/mesh/overlay_psa.conf index ba81c1e0213..1957085b7e4 100644 --- a/tests/bsim/bluetooth/mesh/overlay_psa.conf +++ b/tests/bsim/bluetooth/mesh/overlay_psa.conf @@ -1,2 +1,7 @@ +# The option adds TinyCrypt based bt_rand. +CONFIG_BT_HOST_CRYPTO=n +# The option adds GATT caching feature that is based on TinyCrypt. +CONFIG_BT_GATT_CACHING=n + # Enable mbedTLS PSA as a crypto backend CONFIG_BT_MESH_USES_MBEDTLS_PSA=y diff --git a/tests/bsim/bluetooth/mesh/src/test_dfu.c b/tests/bsim/bluetooth/mesh/src/test_dfu.c index a235e86eeec..46ad4cecb41 100644 --- a/tests/bsim/bluetooth/mesh/src/test_dfu.c +++ b/tests/bsim/bluetooth/mesh/src/test_dfu.c @@ -23,6 +23,7 @@ LOG_MODULE_REGISTER(LOG_MODULE_NAME, LOG_LEVEL_INF); #define TARGET_ADDR 0x0100 #define IMPOSTER_MODEL_ID 0xe000 #define TEST_BLOB_ID 0xaabbccdd +#define SEMAPHORE_TIMEOUT 250 /* seconds */ struct bind_params { uint16_t model_id; @@ -1016,7 +1017,7 @@ static void test_cli_fail_on_persistency(void) FAIL("DFU Client send failed (err: %d)", err); } - if (k_sem_take(&dfu_ended, K_SECONDS(200))) { + if (k_sem_take(&dfu_ended, K_SECONDS(SEMAPHORE_TIMEOUT))) { FAIL("Firmware transfer failed"); } @@ -1050,7 +1051,7 @@ static void test_cli_fail_on_persistency(void) FAIL("DFU Client apply failed (err: %d)", err); } - if (k_sem_take(&dfu_cli_applied_sem, K_SECONDS(200))) { + if (k_sem_take(&dfu_cli_applied_sem, K_SECONDS(SEMAPHORE_TIMEOUT))) { FAIL("Failed to apply firmware"); } @@ -1063,7 +1064,7 @@ static void test_cli_fail_on_persistency(void) FAIL("DFU Client confirm failed (err: %d)", err); } - if (k_sem_take(&dfu_cli_confirmed_sem, K_SECONDS(200))) { + if (k_sem_take(&dfu_cli_confirmed_sem, K_SECONDS(SEMAPHORE_TIMEOUT))) { FAIL("Failed to confirm firmware"); } @@ -1096,7 +1097,7 @@ static void test_cli_all_targets_lost_common(void) FAIL("DFU Client send failed (err: %d)", err); } - if (k_sem_take(&dfu_ended, K_SECONDS(200))) { + if (k_sem_take(&dfu_ended, K_SECONDS(SEMAPHORE_TIMEOUT))) { FAIL("Firmware transfer failed"); } } @@ -1187,7 +1188,7 @@ static void test_cli_all_targets_lost_on_apply(void) FAIL("DFU Client apply failed (err: %d)", err); } - if (!k_sem_take(&dfu_cli_applied_sem, K_SECONDS(200))) { + if (!k_sem_take(&dfu_cli_applied_sem, K_SECONDS(SEMAPHORE_TIMEOUT))) { FAIL("Apply should not be successful on any target"); } @@ -1218,7 +1219,7 @@ static void test_cli_stop(void) FAIL("DFU Client send failed (err: %d)", err); } - if (k_sem_take(&dfu_started, K_SECONDS(200))) { + if (k_sem_take(&dfu_started, K_SECONDS(SEMAPHORE_TIMEOUT))) { FAIL("Firmware transfer failed"); } @@ -1234,7 +1235,7 @@ static void test_cli_stop(void) FAIL("DFU Client resume failed (err: %d)", err); } - if (k_sem_take(&dfu_verifying, K_SECONDS(200))) { + if (k_sem_take(&dfu_verifying, K_SECONDS(SEMAPHORE_TIMEOUT))) { FAIL("Firmware transfer failed"); } ASSERT_EQUAL(BT_MESH_DFU_ERR_INTERNAL, dfu_cli_xfer.targets[0].status); @@ -1253,7 +1254,7 @@ static void test_cli_stop(void) FAIL("DFU Client send failed (err: %d)", err); } - if (k_sem_take(&dfu_verify_failed, K_SECONDS(200))) { + if (k_sem_take(&dfu_verify_failed, K_SECONDS(SEMAPHORE_TIMEOUT))) { FAIL("Firmware transfer failed"); } @@ -1269,12 +1270,12 @@ static void test_cli_stop(void) if (err) { FAIL("DFU Client send failed (err: %d)", err); } - if (k_sem_take(&dfu_ended, K_SECONDS(200))) { + if (k_sem_take(&dfu_ended, K_SECONDS(SEMAPHORE_TIMEOUT))) { FAIL("Firmware transfer failed"); } bt_mesh_dfu_cli_apply(&dfu_cli); - if (k_sem_take(&dfu_cli_applied_sem, K_SECONDS(200))) { + if (k_sem_take(&dfu_cli_applied_sem, K_SECONDS(SEMAPHORE_TIMEOUT))) { /* This will time out as target will reboot before applying */ } ASSERT_EQUAL(BT_MESH_DFU_ERR_INTERNAL, dfu_cli_xfer.targets[0].status); @@ -1464,7 +1465,7 @@ static void test_target_fail_on_metadata(void) common_fail_on_target_init(&target_comp); target_prov_and_conf_default(); - if (k_sem_take(&dfu_metadata_check_sem, K_SECONDS(200))) { + if (k_sem_take(&dfu_metadata_check_sem, K_SECONDS(SEMAPHORE_TIMEOUT))) { FAIL("Metadata check CB wasn't called"); } @@ -1478,7 +1479,7 @@ static void test_target_fail_on_caps_get(void) common_fail_on_target_init(&srv_caps_broken_comp); target_prov_and_conf_with_imposer(); - if (k_sem_take(&caps_get_sem, K_SECONDS(200))) { + if (k_sem_take(&caps_get_sem, K_SECONDS(SEMAPHORE_TIMEOUT))) { FAIL("BLOB Info Get msg handler wasn't called"); } @@ -1492,11 +1493,11 @@ static void test_target_fail_on_update_get(void) common_fail_on_target_init(&srv_update_get_broken_comp); target_prov_and_conf_with_imposer(); - if (k_sem_take(&dfu_verify_sem, K_SECONDS(200))) { + if (k_sem_take(&dfu_verify_sem, K_SECONDS(SEMAPHORE_TIMEOUT))) { FAIL("Transfer end CB wasn't triggered"); } - if (k_sem_take(&update_get_sem, K_SECONDS(200))) { + if (k_sem_take(&update_get_sem, K_SECONDS(SEMAPHORE_TIMEOUT))) { FAIL("Firmware Update Get msg handler wasn't called"); } @@ -1511,7 +1512,7 @@ static void test_target_fail_on_verify(void) common_fail_on_target_init(&target_comp); target_prov_and_conf_default(); - if (k_sem_take(&dfu_verify_sem, K_SECONDS(200))) { + if (k_sem_take(&dfu_verify_sem, K_SECONDS(SEMAPHORE_TIMEOUT))) { FAIL("Transfer end CB wasn't triggered"); } @@ -1525,7 +1526,7 @@ static void test_target_fail_on_apply(void) common_fail_on_target_init(&srv_update_apply_broken_comp); target_prov_and_conf_with_imposer(); - if (k_sem_take(&update_apply_sem, K_SECONDS(200))) { + if (k_sem_take(&update_apply_sem, K_SECONDS(SEMAPHORE_TIMEOUT))) { FAIL("Firmware Update Apply msg handler wasn't called"); } @@ -1537,7 +1538,7 @@ static void test_target_fail_on_nothing(void) common_fail_on_target_init(&target_comp); target_prov_and_conf_default(); - if (k_sem_take(&dfu_ended, K_SECONDS(200))) { + if (k_sem_take(&dfu_ended, K_SECONDS(SEMAPHORE_TIMEOUT))) { FAIL("DFU failed"); } diff --git a/tests/bsim/bluetooth/mesh/src/test_persistence.c b/tests/bsim/bluetooth/mesh/src/test_persistence.c index 90bf41f73a6..aab9c6dd185 100644 --- a/tests/bsim/bluetooth/mesh/src/test_persistence.c +++ b/tests/bsim/bluetooth/mesh/src/test_persistence.c @@ -525,7 +525,7 @@ static void node_configure(void) */ uint8_t net_transmit; - net_transmit = BT_MESH_TRANSMIT(3, 20); + net_transmit = BT_MESH_TRANSMIT(3, 50); err = bt_mesh_cfg_cli_net_transmit_set(test_netkey_idx, TEST_ADDR, net_transmit, &status); if (err || status != net_transmit) { FAIL("Net transmit set failed (err %d, transmit %x)", err, status); diff --git a/tests/bsim/bluetooth/mesh/src/test_replay_cache.c b/tests/bsim/bluetooth/mesh/src/test_replay_cache.c index dbab05661cb..d7c140ab3ed 100644 --- a/tests/bsim/bluetooth/mesh/src/test_replay_cache.c +++ b/tests/bsim/bluetooth/mesh/src/test_replay_cache.c @@ -149,6 +149,8 @@ static void test_tx_immediate_replay_attack(void) } ASSERT_TRUE(is_tx_succeeded); + /* Let complete advertising of the previous transaction to prevent collisions. */ + k_sleep(K_SECONDS(1)); } bt_mesh.seq = seq; @@ -165,6 +167,8 @@ static void test_tx_immediate_replay_attack(void) } ASSERT_TRUE(!is_tx_succeeded); + /* Let complete advertising of the previous transaction to prevent collisions. */ + k_sleep(K_SECONDS(1)); } PASS(); @@ -208,6 +212,8 @@ static void test_tx_power_replay_attack(void) } ASSERT_TRUE(!is_tx_succeeded); + /* Let complete advertising of the previous transaction to prevent collisions. */ + k_sleep(K_SECONDS(1)); } for (int i = 0; i < 3; i++) { @@ -222,6 +228,8 @@ static void test_tx_power_replay_attack(void) } ASSERT_TRUE(is_tx_succeeded); + /* Let complete advertising of the previous transaction to prevent collisions. */ + k_sleep(K_SECONDS(1)); } PASS(); From 533baa16b5a6750cf59a7ce7257bc09bcac09637 Mon Sep 17 00:00:00 2001 From: Aleksandr Khromykh Date: Thu, 9 Nov 2023 13:30:15 +0100 Subject: [PATCH 396/421] [nrf noup] Bluetooth: Mesh: adapt SDC specific api usage Usage of the Softdevice specific api has been adapted to upstream adv changes. Signed-off-by: Aleksandr Khromykh --- subsys/bluetooth/mesh/adv_ext.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/subsys/bluetooth/mesh/adv_ext.c b/subsys/bluetooth/mesh/adv_ext.c index 525e5ee5066..fe9fc4fd403 100644 --- a/subsys/bluetooth/mesh/adv_ext.c +++ b/subsys/bluetooth/mesh/adv_ext.c @@ -529,8 +529,8 @@ int bt_mesh_adv_enable(void) if (IS_ENABLED(CONFIG_BT_LL_SOFTDEVICE) && IS_ENABLED(CONFIG_BT_MESH_ADV_EXT_FRIEND_SEPARATE) && - adv->tag == BT_MESH_FRIEND_ADV) { - err = set_adv_randomness(adv->instance->handle, 0); + advs[i].tags == BT_MESH_ADV_TAG_BIT_FRIEND) { + err = set_adv_randomness(advs[i].instance->handle, 0); if (err) { LOG_ERR("Failed to set zero randomness: %d", err); } From f6a5a29a18823fb2bfce70344bf8ba5bcb070388 Mon Sep 17 00:00:00 2001 From: Joakim Andersson Date: Tue, 7 Nov 2023 14:26:26 +0100 Subject: [PATCH 397/421] Revert "[nrf noup] modules: mbedtls: Add PSA symbols for Oberon PSA extension" This reverts commit 07385636ee190aefce8405776eb76d836c791808. Reverting to add !fixup line to the commit message Signed-off-by: Joakim Andersson --- modules/mbedtls/Kconfig.psa | 24 ++++-------------------- 1 file changed, 4 insertions(+), 20 deletions(-) diff --git a/modules/mbedtls/Kconfig.psa b/modules/mbedtls/Kconfig.psa index 0d43f112aeb..1bd37cedb0b 100644 --- a/modules/mbedtls/Kconfig.psa +++ b/modules/mbedtls/Kconfig.psa @@ -301,8 +301,7 @@ config PSA_HAS_KEY_DERIVATION PSA_WANT_ALG_PBKDF2_HMAC || \ PSA_WANT_ALG_PBKDF2_AES_CMAC_PRF_128 || \ PSA_WANT_ALG_TLS12_PRF || \ - PSA_WANT_ALG_TLS12_PSK_TO_MS || \ - PSA_WANT_ALG_TLS12_ECJPAKE_TO_PMS + PSA_WANT_ALG_TLS12_PSK_TO_MS help Prompt-less configuration that states that key derivation is supported. @@ -337,10 +336,6 @@ config PSA_WANT_ALG_TLS12_PSK_TO_MS bool prompt "PSA TLS 1.2 PSK to MS support" if !PSA_PROMPTLESS -config PSA_WANT_ALG_TLS12_ECJPAKE_TO_PMS - bool - prompt "PSA TLS 1.2 EC J-PAKE to PMS support" if !PSA_PROMPTLESS - endmenu # PSA Key derivation support @@ -487,19 +482,8 @@ config PSA_WANT_ALG_SPAKE2P prompt "PSA SPAKE2+ support" if !PSA_PROMPTLESS select EXPERIMENTAL -config PSA_WANT_ALG_SRP_6 +config PSA_WANT_ALG_SRP bool - prompt "PSA SRP-6 support" if !PSA_PROMPTLESS + prompt "PSA SRP support" if !PSA_PROMPTLESS + default n select EXPERIMENTAL - -config PSA_WANT_ALG_PURE_EDDSA - bool - prompt "PSA PURE_EDDSA support" if !PSA_PROMPTLESS - -config PSA_WANT_ALG_ED25519PH - bool - prompt "PSA ED25519PH support" if !PSA_PROMPTLESS - -config PSA_WANT_ALG_ED448PH - bool - prompt "PSA ED448PH support" if !PSA_PROMPTLESS From dc4c71ff44f1c67a52a8b786900c832e480b99e6 Mon Sep 17 00:00:00 2001 From: Joakim Andersson Date: Tue, 7 Nov 2023 14:27:16 +0100 Subject: [PATCH 398/421] Revert "[nrf noup] mbedtls: Add config support for PBKDF2_HMAC" This reverts commit 51bef37071aad3301b4223a59991af71614a13ed. Reverting to add !fixup line to the commit message Signed-off-by: Joakim Andersson --- modules/mbedtls/Kconfig.psa | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/mbedtls/Kconfig.psa b/modules/mbedtls/Kconfig.psa index 1bd37cedb0b..0e321df6598 100644 --- a/modules/mbedtls/Kconfig.psa +++ b/modules/mbedtls/Kconfig.psa @@ -320,8 +320,9 @@ config PSA_WANT_ALG_HKDF_EXPAND config PSA_WANT_ALG_PBKDF2_HMAC bool - prompt "PSA PBKDF2 HMAC support" if !PSA_PROMPTLESS depends on PSA_WANT_ALG_HMAC + help + PBKDF2-HMAC is not yet supported via the PSA APIs in Mbed TLS. config PSA_WANT_ALG_PBKDF2_AES_CMAC_PRF_128 bool From bcd9dbacb4eaffedc22fbe53403528a36c056897 Mon Sep 17 00:00:00 2001 From: Joakim Andersson Date: Tue, 7 Nov 2023 14:28:00 +0100 Subject: [PATCH 399/421] Revert "[nrf noup] mbedtls: Add config support for PBKDF2_AES_CMAC_PRF_128" This reverts commit 192697c16cc5908a88d0b75440ec319e2c5d211a. Reverting to add !fixup line to commit message Signed-off-by: Joakim Andersson --- modules/mbedtls/Kconfig.psa | 6 ------ 1 file changed, 6 deletions(-) diff --git a/modules/mbedtls/Kconfig.psa b/modules/mbedtls/Kconfig.psa index 0e321df6598..c0c34aa0cce 100644 --- a/modules/mbedtls/Kconfig.psa +++ b/modules/mbedtls/Kconfig.psa @@ -299,7 +299,6 @@ config PSA_HAS_KEY_DERIVATION PSA_WANT_ALG_HKDF_EXPAND || \ PSA_WANT_ALG_HKDF_EXTRACT || \ PSA_WANT_ALG_PBKDF2_HMAC || \ - PSA_WANT_ALG_PBKDF2_AES_CMAC_PRF_128 || \ PSA_WANT_ALG_TLS12_PRF || \ PSA_WANT_ALG_TLS12_PSK_TO_MS help @@ -324,11 +323,6 @@ config PSA_WANT_ALG_PBKDF2_HMAC help PBKDF2-HMAC is not yet supported via the PSA APIs in Mbed TLS. -config PSA_WANT_ALG_PBKDF2_AES_CMAC_PRF_128 - bool - prompt "PSA PBKDF2-AES-CMAC-PRF-128 support" if !PSA_PROMPTLESS - depends on PSA_WANT_ALG_CMAC - config PSA_WANT_ALG_TLS12_PRF bool prompt "PSA PRF support (TLS1.2)" if !PSA_PROMPTLESS From c490eb32ce3d568f4a29112ebd04658bfcd962d6 Mon Sep 17 00:00:00 2001 From: Joakim Andersson Date: Tue, 7 Nov 2023 14:28:49 +0100 Subject: [PATCH 400/421] Revert "[nrf noup] modules: mbedtls: Fix key support Kconfig" This reverts commit 132cee61e6ce404b25dbc626b57b5df149c136a8. Reverting to add !fixup line to commit message Signed-off-by: Joakim Andersson --- modules/mbedtls/Kconfig.psa | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/mbedtls/Kconfig.psa b/modules/mbedtls/Kconfig.psa index c0c34aa0cce..399d18a3797 100644 --- a/modules/mbedtls/Kconfig.psa +++ b/modules/mbedtls/Kconfig.psa @@ -47,7 +47,7 @@ config PSA_HAS_KEY_SUPPORT PSA_WANT_KEY_TYPE_RSA_KEY_PAIR || \ PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY || \ PSA_WANT_KEY_TYPE_DH_KEY_PAIR || \ - PSA_WANT_KEY_TYPE_DH_PUBLIC_KEY + PSA_WANT_KEY_TYPE_DH_KEY_PAIR config PSA_WANT_KEY_TYPE_DERIVE bool "PSA derive key type support" From 0a78b665e502695a7855178595c3c077ff2ce71c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vidar=20Lilleb=C3=B8?= Date: Tue, 9 May 2023 16:21:35 +0200 Subject: [PATCH 401/421] [nrf noup] modules: mbedtls: Add PSA symbols for Oberon PSA extension MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fixup! [nrf noup] modules: mbedtls: add PSA configurations Add PSA symbols for Oberon extension to the PSA specification. Mbed TLS has adopted the same naming, so while this is not part of the PSA specification it is fine to add it to the generic configuration for both implementations. Signed-off-by: Joakim Andersson Signed-off-by: Vidar Lillebø (cherry picked from commit 0b32fd2743f574aaa293122545caeadd3b01fd41) --- modules/mbedtls/Kconfig.psa | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/modules/mbedtls/Kconfig.psa b/modules/mbedtls/Kconfig.psa index 399d18a3797..9f93771584c 100644 --- a/modules/mbedtls/Kconfig.psa +++ b/modules/mbedtls/Kconfig.psa @@ -300,7 +300,8 @@ config PSA_HAS_KEY_DERIVATION PSA_WANT_ALG_HKDF_EXTRACT || \ PSA_WANT_ALG_PBKDF2_HMAC || \ PSA_WANT_ALG_TLS12_PRF || \ - PSA_WANT_ALG_TLS12_PSK_TO_MS + PSA_WANT_ALG_TLS12_PSK_TO_MS || \ + PSA_WANT_ALG_TLS12_ECJPAKE_TO_PMS help Prompt-less configuration that states that key derivation is supported. @@ -331,6 +332,10 @@ config PSA_WANT_ALG_TLS12_PSK_TO_MS bool prompt "PSA TLS 1.2 PSK to MS support" if !PSA_PROMPTLESS +config PSA_WANT_ALG_TLS12_ECJPAKE_TO_PMS + bool + prompt "PSA TLS 1.2 EC J-PAKE to PMS support" if !PSA_PROMPTLESS + endmenu # PSA Key derivation support @@ -477,8 +482,19 @@ config PSA_WANT_ALG_SPAKE2P prompt "PSA SPAKE2+ support" if !PSA_PROMPTLESS select EXPERIMENTAL -config PSA_WANT_ALG_SRP +config PSA_WANT_ALG_SRP_6 bool - prompt "PSA SRP support" if !PSA_PROMPTLESS - default n + prompt "PSA SRP-6 support" if !PSA_PROMPTLESS select EXPERIMENTAL + +config PSA_WANT_ALG_PURE_EDDSA + bool + prompt "PSA PURE_EDDSA support" if !PSA_PROMPTLESS + +config PSA_WANT_ALG_ED25519PH + bool + prompt "PSA ED25519PH support" if !PSA_PROMPTLESS + +config PSA_WANT_ALG_ED448PH + bool + prompt "PSA ED448PH support" if !PSA_PROMPTLESS From b850ab7cfc8161ba37194f9c7e1935051e3d206f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20B=C3=B8e?= Date: Tue, 20 Jun 2023 13:27:15 +0200 Subject: [PATCH 402/421] [nrf noup] mbedtls: Add config support for PBKDF2_HMAC MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fixup! [nrf noup] modules: mbedtls: add PSA configurations Add config support for PBKDF2_HMAC. This patches an existing noup commit and is therefore also noup. Signed-off-by: Sebastian Bøe (cherry picked from commit 1ff52962ebce37d536949bcc1804fcf502011af6) Signed-off-by: Joakim Andersson --- modules/mbedtls/Kconfig.psa | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/modules/mbedtls/Kconfig.psa b/modules/mbedtls/Kconfig.psa index 9f93771584c..5e8e9a8ead0 100644 --- a/modules/mbedtls/Kconfig.psa +++ b/modules/mbedtls/Kconfig.psa @@ -320,9 +320,8 @@ config PSA_WANT_ALG_HKDF_EXPAND config PSA_WANT_ALG_PBKDF2_HMAC bool + prompt "PSA PBKDF2 HMAC support" if !PSA_PROMPTLESS depends on PSA_WANT_ALG_HMAC - help - PBKDF2-HMAC is not yet supported via the PSA APIs in Mbed TLS. config PSA_WANT_ALG_TLS12_PRF bool From 33121ff883e93385eb12dddbed7077e8dcbb968d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20B=C3=B8e?= Date: Tue, 20 Jun 2023 15:04:46 +0200 Subject: [PATCH 403/421] [nrf noup] mbedtls: Add config support for PBKDF2_AES_CMAC_PRF_128 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fixup! [nrf noup] modules: mbedtls: add PSA configurations Add config support for PBKDF2_AES_CMAC_PRF_128 Signed-off-by: Sebastian Bøe (cherry picked from commit 743f99947369088ecba6820a720ede8054893866) Signed-off-by: Joakim Andersson --- modules/mbedtls/Kconfig.psa | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/modules/mbedtls/Kconfig.psa b/modules/mbedtls/Kconfig.psa index 5e8e9a8ead0..b0d21685f70 100644 --- a/modules/mbedtls/Kconfig.psa +++ b/modules/mbedtls/Kconfig.psa @@ -299,6 +299,7 @@ config PSA_HAS_KEY_DERIVATION PSA_WANT_ALG_HKDF_EXPAND || \ PSA_WANT_ALG_HKDF_EXTRACT || \ PSA_WANT_ALG_PBKDF2_HMAC || \ + PSA_WANT_ALG_PBKDF2_AES_CMAC_PRF_128 || \ PSA_WANT_ALG_TLS12_PRF || \ PSA_WANT_ALG_TLS12_PSK_TO_MS || \ PSA_WANT_ALG_TLS12_ECJPAKE_TO_PMS @@ -323,6 +324,11 @@ config PSA_WANT_ALG_PBKDF2_HMAC prompt "PSA PBKDF2 HMAC support" if !PSA_PROMPTLESS depends on PSA_WANT_ALG_HMAC +config PSA_WANT_ALG_PBKDF2_AES_CMAC_PRF_128 + bool + prompt "PSA PBKDF2-AES-CMAC-PRF-128 support" if !PSA_PROMPTLESS + depends on PSA_WANT_ALG_CMAC + config PSA_WANT_ALG_TLS12_PRF bool prompt "PSA PRF support (TLS1.2)" if !PSA_PROMPTLESS From 1fab667892451f21114f87cf48863c0dbdfb9507 Mon Sep 17 00:00:00 2001 From: Markus Swarowsky Date: Fri, 18 Aug 2023 10:20:45 +0200 Subject: [PATCH 404/421] [nrf noup] modules: mbedtls: Fix key support Kconfig fixup! [nrf noup] modules: mbedtls: add PSA configurations PSA_HAS_KEY_SUPPORT was missing the DH_PUBLIC_KEY only Kconfig as the KEY_PAIR was double in there Signed-off-by: Markus Swarowsky (cherry picked from commit 53c4b20c15611a9d13b91e5dc025733d6dd65adb) Signed-off-by: Joakim Andersson --- modules/mbedtls/Kconfig.psa | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/mbedtls/Kconfig.psa b/modules/mbedtls/Kconfig.psa index b0d21685f70..0d43f112aeb 100644 --- a/modules/mbedtls/Kconfig.psa +++ b/modules/mbedtls/Kconfig.psa @@ -47,7 +47,7 @@ config PSA_HAS_KEY_SUPPORT PSA_WANT_KEY_TYPE_RSA_KEY_PAIR || \ PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY || \ PSA_WANT_KEY_TYPE_DH_KEY_PAIR || \ - PSA_WANT_KEY_TYPE_DH_KEY_PAIR + PSA_WANT_KEY_TYPE_DH_PUBLIC_KEY config PSA_WANT_KEY_TYPE_DERIVE bool "PSA derive key type support" From 0708dc8e65603cca2abe7799bffe765f97d00bb4 Mon Sep 17 00:00:00 2001 From: Joakim Andersson Date: Tue, 7 Nov 2023 11:01:52 +0100 Subject: [PATCH 405/421] [nrf noup] modules: mbedtls: Add all PSA spec algorithms and key types fixup! [nrf noup] modules: mbedtls: add PSA configurations Add all of the PSA specification defined algorithms and key types. This makes the configurations independent of what is supported by the specific implementation. Fix CCM star no tag wrongly listed as an AEAD instead of Cipher algorithm. Remove the HAS_ECC and HAS_RSA support. They don't provide much information. ECC and RSA are both assymetric signing algorithms, while RSA is also an assymetric encryption algorithm. Signed-off-by: Joakim Andersson --- modules/mbedtls/Kconfig.psa | 296 ++++++++++++++---- .../Kconfig.tfm.crypto_modules | 3 +- 2 files changed, 244 insertions(+), 55 deletions(-) diff --git a/modules/mbedtls/Kconfig.psa b/modules/mbedtls/Kconfig.psa index 0d43f112aeb..42d2a48825b 100644 --- a/modules/mbedtls/Kconfig.psa +++ b/modules/mbedtls/Kconfig.psa @@ -41,6 +41,11 @@ config PSA_HAS_KEY_SUPPORT PSA_WANT_KEY_TYPE_PASSWORD_HASH || \ PSA_WANT_KEY_TYPE_PEPPER || \ PSA_WANT_KEY_TYPE_AES || \ + PSA_WANT_KEY_TYPE_ARIA || \ + PSA_WANT_KEY_TYPE_DES || \ + PSA_WANT_KEY_TYPE_CAMELLIA || \ + PSA_WANT_KEY_TYPE_SM4 || \ + PSA_WANT_KEY_TYPE_ARC4 || \ PSA_WANT_KEY_TYPE_CHACHA20 || \ PSA_WANT_KEY_TYPE_ECC_KEY_PAIR || \ PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY || \ @@ -86,6 +91,29 @@ config PSA_WANT_KEY_TYPE_AES help Key for cipher, AEAD or MAC algorithm based on the AES block cipher. +config PSA_WANT_KEY_TYPE_ARIA + bool "PSA ARIA key type support" + +config PSA_WANT_KEY_TYPE_DES + bool "PSA DES key type support (weak)" + help + Warning: Single DES and 2-key 3DES are weak and strongly deprecated + and are only recommended for decrypting legacy data. + 3-key 3DES is weak and deprecated and is only recommended for use in + legacy protocols. + +config PSA_WANT_KEY_TYPE_CAMELLIA + bool "PSA CAMELLIA key type support" + +config PSA_WANT_KEY_TYPE_SM4 + bool "PSA SM4 key type support" + +config PSA_WANT_KEY_TYPE_ARC4 + bool "PSA ARC4 key type support (weak)" + help + Warning: The ARC4 cipher is weak and deprecated and is only + recommended for use in legacy protocols. + config PSA_WANT_KEY_TYPE_CHACHA20 bool "PSA ChaCha20 key type support" default y @@ -135,7 +163,6 @@ config PSA_HAS_AEAD_SUPPORT bool default y depends on PSA_WANT_ALG_CCM || \ - PSA_WANT_ALG_CCM_STAR_NO_TAG || \ PSA_WANT_ALG_GCM || \ PSA_WANT_ALG_CHACHA20_POLY1305 help @@ -145,10 +172,6 @@ config PSA_WANT_ALG_CCM bool prompt "PSA CCM support" if !PSA_PROMPTLESS -config PSA_WANT_ALG_CCM_STAR_NO_TAG - bool - prompt "PSA AES CCM star with no tag support" if !PSA_PROMPTLESS - config PSA_WANT_ALG_GCM bool prompt "PSA GCM support" if !PSA_PROMPTLESS @@ -173,8 +196,7 @@ config PSA_HAS_MAC_SUPPORT config PSA_WANT_ALG_CBC_MAC bool - help - CBC-MAC is not yet supported via the PSA API in Mbed TLS. + prompt "PSA CBC-MAC support" if !PSA_PROMPTLESS config PSA_WANT_ALG_CMAC bool @@ -197,7 +219,17 @@ config PSA_HAS_HASH_SUPPORT PSA_WANT_ALG_SHA_256 || \ PSA_WANT_ALG_SHA_384 || \ PSA_WANT_ALG_SHA_512 || \ + PSA_WANT_ALG_SHA_512_224 || \ + PSA_WANT_ALG_SHA_512_256 || \ + PSA_WANT_ALG_SHA3_224 || \ + PSA_WANT_ALG_SHA3_256 || \ + PSA_WANT_ALG_SHA3_384 || \ + PSA_WANT_ALG_SHA3_512 || \ + PSA_WANT_ALG_SM3 || \ + PSA_WANT_ALG_SHAKE256_512 || \ PSA_WANT_ALG_RIPEMD160 || \ + PSA_WANT_ALG_MD2 || \ + PSA_WANT_ALG_MD4 || \ PSA_WANT_ALG_MD5 help Prompt-less configuration that states that hash is supported. @@ -225,10 +257,56 @@ config PSA_WANT_ALG_SHA_512 bool prompt "PSA SHA-512 support" if !PSA_PROMPTLESS +config PSA_WANT_ALG_SHA_512_224 + bool + prompt "PSA SHA-512/224 support" if !PSA_PROMPTLESS + +config PSA_WANT_ALG_SHA_512_256 + bool + prompt "PSA SHA-512/256 support" if !PSA_PROMPTLESS + +config PSA_WANT_ALG_SHA3_224 + bool + prompt "PSA SHA3-224 support" if !PSA_PROMPTLESS + +config PSA_WANT_ALG_SHA3_256 + bool + prompt "PSA SHA3-256 support" if !PSA_PROMPTLESS + +config PSA_WANT_ALG_SHA3_384 + bool + prompt "PSA SHA3-384 support" if !PSA_PROMPTLESS + +config PSA_WANT_ALG_SHA3_512 + bool + prompt "PSA SHA3-512 support" if !PSA_PROMPTLESS + +config PSA_WANT_ALG_SM3 + bool + prompt "PSA SM3 support" if !PSA_PROMPTLESS + +config PSA_WANT_ALG_SHAKE256_512 + bool + prompt "PSA SHAKE256 512 bits support" if !PSA_PROMPTLESS + config PSA_WANT_ALG_RIPEMD160 bool prompt "PSA RIPEMD-160 support" if !PSA_PROMPTLESS +config PSA_WANT_ALG_MD2 + bool + prompt "PSA MD2 support (weak)" if !PSA_PROMPTLESS + help + Warning: The MD2 hash is weak and deprecated and is only recommended + for use in legacy protocols. + +config PSA_WANT_ALG_MD4 + bool + prompt "PSA MD4 support (weak)" if !PSA_PROMPTLESS + help + Warning: The MD4 hash is weak and deprecated and is only recommended + for use in legacy protocols. + config PSA_WANT_ALG_MD5 bool prompt "PSA MD5 support (weak)" if !PSA_PROMPTLESS @@ -246,10 +324,10 @@ config PSA_HAS_CIPHER_SUPPORT depends on PSA_WANT_ALG_ECB_NO_PADDING || \ PSA_WANT_ALG_CBC_NO_PADDING || \ PSA_WANT_ALG_CBC_PKCS7 || \ + PSA_WANT_ALG_CCM_STAR_NO_TAG || \ PSA_WANT_ALG_CFB || \ PSA_WANT_ALG_CTR || \ PSA_WANT_ALG_OFB || \ - PSA_WANT_ALG_CTR || \ PSA_WANT_ALG_XTS || \ PSA_WANT_ALG_STREAM_CIPHER help @@ -283,12 +361,38 @@ config PSA_WANT_ALG_XTS bool prompt "PSA XTS block cipher mode support" if !PSA_PROMPTLESS +config PSA_WANT_ALG_CCM_STAR_NO_TAG + bool + prompt "PSA CCM* with no tag support" if !PSA_PROMPTLESS + help + Unauthenticated version of CCM. Uses the cipher API instead of the AEAD API. + config PSA_WANT_ALG_STREAM_CIPHER bool prompt "PSA stream cipher support" if !PSA_PROMPTLESS endmenu # PSA Cipher Support +menu "PSA Key agreement support" + +config PSA_HAS_KEY_AGREEMENT + bool + default y + depends on PSA_WANT_ALG_ECDH + depends on PSA_WANT_ALG_FFDH + help + Promt-less configuration that states that key agreement is supported. + +config PSA_WANT_ALG_ECDH + bool + prompt "PSA ECDH support" if !PSA_PROMPTLESS + + +config PSA_WANT_ALG_FFDH + bool + prompt "PSA FFDH support" if !PSA_PROMPTLESS + +endmenu # PSA Key agreement support menu "PSA Key derivation support" @@ -361,65 +465,86 @@ config PSA_HAS_ASYM_SIGN_SUPPORT default y depends on PSA_WANT_ALG_DETERMINISTIC_ECDSA || \ PSA_WANT_ALG_ECDSA || \ + PSA_WANT_ALG_ECDSA_ANY || \ + PSA_WANT_ALG_PURE_EDDSA || \ + PSA_WANT_ALG_ED25519PH || \ + PSA_WANT_ALG_ED448PH || \ PSA_WANT_ALG_RSA_PKCS1V15_SIGN || \ - PSA_WANT_ALG_RSA_PSS + PSA_WANT_ALG_RSA_PKCS1V15_SIGN_RAW || \ + PSA_WANT_ALG_RSA_PSS || \ + PSA_WANT_ALG_RSA_PSS_ANY_SALT help Prompt-less configuration that states that asymmetric signing is supported. -config PSA_HAS_ECC_SUPPORT - bool - depends on PSA_WANT_ALG_ECDH || \ - PSA_WANT_ALG_ECDSA || \ - PSA_WANT_ALG_DETERMINISTIC_ECDSA || \ - PSA_WANT_KEY_TYPE_ECC_KEY_PAIR || \ - PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY - default y - help - Prompt-less configuration that states that ECC is supported. - -config PSA_WANT_ALG_ECDH - bool - prompt "PSA ECDH support" if !PSA_PROMPTLESS - config PSA_WANT_ALG_ECDSA bool prompt "PSA ECDSA support" if !PSA_PROMPTLESS +config PSA_WANT_ALG_ECDSA_ANY + bool + prompt "PSA ECDSA support, without hashing" if !PSA_PROMPTLESS + config PSA_WANT_ALG_DETERMINISTIC_ECDSA bool prompt "PSA ECDSA support (deterministic mode)" if !PSA_PROMPTLESS menu "Elliptic Curve type support" - depends on PSA_HAS_ECC_SUPPORT + +config PSA_WANT_ECC_BRAINPOOL_P_R1_160 + bool + prompt "PSA ECC BrainpoolP160r1 support (weak)" if !PSA_PROMPTLESS + help + Warning: The 160-bit curve brainpoolP160r1 is weak and deprecated and + is only recommended for use in legacy protocols. + +config PSA_WANT_ECC_BRAINPOOL_P_R1_192 + bool + prompt "PSA ECC BrainpoolP192r1 support" if !PSA_PROMPTLESS + +config PSA_WANT_ECC_BRAINPOOL_P_R1_224 + bool + prompt "PSA ECC BrainpoolP224r1 support" if !PSA_PROMPTLESS config PSA_WANT_ECC_BRAINPOOL_P_R1_256 bool - prompt "PSA ECC Brainpool256r1 support" + prompt "PSA ECC BrainpoolP256r1 support" if !PSA_PROMPTLESS + +config PSA_WANT_ECC_BRAINPOOL_P_R1_320 + bool + prompt "PSA ECC BrainpoolP320r1 support" if !PSA_PROMPTLESS config PSA_WANT_ECC_BRAINPOOL_P_R1_384 - bool "PSA ECC Brainpool384r1 support" + bool + prompt "PSA ECC BrainpoolP384r1 support" if !PSA_PROMPTLESS config PSA_WANT_ECC_BRAINPOOL_P_R1_512 - bool "PSA ECC Brainpool512r1 support" + bool + prompt "PSA ECC BrainpoolP512r1 support" if !PSA_PROMPTLESS config PSA_WANT_ECC_MONTGOMERY_255 - bool "PSA ECC Curve25519 (X25519) support" + bool + prompt "PSA ECC Curve25519 (X25519) support" if !PSA_PROMPTLESS config PSA_WANT_ECC_MONTGOMERY_448 - bool "PSA ECC Curve448 (X448) support" + bool + prompt "PSA ECC Curve448 (X448) support" if !PSA_PROMPTLESS config PSA_WANT_ECC_TWISTED_EDWARDS_255 - bool "PSA ECC Edwards25519 (Ed25519) support" + bool + prompt "PSA ECC Edwards25519 (Ed25519) support" if !PSA_PROMPTLESS + +config PSA_WANT_ECC_TWISTED_EDWARDS_448 + bool + prompt "PSA ECC Edwards448 (Ed448) support" if !PSA_PROMPTLESS config PSA_WANT_ECC_SECP_K1_192 - bool "PSA ECC secp192k1 support" + bool + prompt "PSA ECC secp192k1 support" if !PSA_PROMPTLESS config PSA_WANT_ECC_SECP_K1_224 bool - help - SECP224K1 is buggy via the PSA API in Mbed TLS - See https://github.com/ARMmbed/mbedtls/issues/3541 + prompt "PSA ECC secp224k1 support" if !PSA_PROMPTLESS config PSA_WANT_ECC_SECP_K1_256 bool @@ -427,53 +552,116 @@ config PSA_WANT_ECC_SECP_K1_256 config PSA_WANT_ECC_SECP_R1_192 bool - prompt "PSA ECC secp192r1" if !PSA_PROMPTLESS + prompt "PSA ECC secp192r1 support" if !PSA_PROMPTLESS config PSA_WANT_ECC_SECP_R1_224 bool - prompt "PSA ECC secp224r1" if !PSA_PROMPTLESS + prompt "PSA ECC secp224r1 support" if !PSA_PROMPTLESS config PSA_WANT_ECC_SECP_R1_256 bool - prompt "PSA ECC secp256r1" if !PSA_PROMPTLESS + prompt "PSA ECC secp256r1 support" if !PSA_PROMPTLESS config PSA_WANT_ECC_SECP_R1_384 bool - prompt "PSA ECC secp384r1" if !PSA_PROMPTLESS + prompt "PSA ECC secp384r1 support" if !PSA_PROMPTLESS config PSA_WANT_ECC_SECP_R1_521 bool - prompt "PSA ECC secp521r1" if !PSA_PROMPTLESS + prompt "PSA ECC secp521r1 support" if !PSA_PROMPTLESS -endmenu # Elliptic Curve type support +config PSA_WANT_ECC_SECP_R2_160 + bool + prompt "PSA ECC secp160r2 support (weak)" if !PSA_PROMPTLESS + help + Warning: his family of curves is weak and deprecated. -config PSA_HAS_RSA_SUPPORT +config PSA_WANT_ECC_SECT_K1_163 bool - depends on PSA_WANT_ALG_RSA_OAEP || \ - PSA_WANT_ALG_RSA_PKCS1V15_CRYPT || \ - PSA_WANT_ALG_RSA_PKCS1V15_SIGN || \ - PSA_WANT_ALG_RSA_PSS || \ - PSA_WANT_KEY_TYPE_RSA_KEY_PAIR || \ - PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY - default y + prompt "PSA ECC sect163k1 support (weak)" if !PSA_PROMPTLESS + help + Warning: The 163-bit curve sect163k1 is weak and deprecated and is + only recommended for use in legacy protocols. + +config PSA_WANT_ECC_SECT_K1_233 + bool + prompt "PSA ECC sect233k1 support" if !PSA_PROMPTLESS + +config PSA_WANT_ECC_SECT_K1_239 + bool + prompt "PSA ECC sect239k1 support" if !PSA_PROMPTLESS + +config PSA_WANT_ECC_SECT_K1_283 + bool + prompt "PSA ECC sect283k1 support" if !PSA_PROMPTLESS + +config PSA_WANT_ECC_SECT_K1_409 + bool + prompt "PSA ECC sect409k1 support" if !PSA_PROMPTLESS + +config PSA_WANT_ECC_SECT_K1_571 + bool + prompt "PSA ECC sect571k1 support" if !PSA_PROMPTLESS + +config PSA_WANT_ECC_SECT_R1_163 + bool + prompt "PSA ECC sect163r1 support (weak)" if !PSA_PROMPTLESS + help + Warning: The 163-bit curve sect163r1 is weak and deprecated and is + only recommended for use in legacy protocols. + +config PSA_WANT_ECC_SECT_R1_233 + bool + prompt "PSA ECC sect233r1 support" if !PSA_PROMPTLESS + +config PSA_WANT_ECC_SECT_R1_283 + bool + prompt "PSA ECC sect283r1 support" if !PSA_PROMPTLESS + +config PSA_WANT_ECC_SECT_R1_409 + bool + prompt "PSA ECC sect409r1 support" if !PSA_PROMPTLESS + +config PSA_WANT_ECC_SECT_R1_571 + bool + prompt "PSA ECC sect571r1 support" if !PSA_PROMPTLESS + +config PSA_WANT_ECC_SECT_R2_163 + bool + prompt "PSA ECC sect163r2 support (weak)" if !PSA_PROMPTLESS help - Prompt-less configuration that states that RSA is supported. + Warning: The 163-bit curve sect163r2 is weak and deprecated and is + only recommended for use in legacy protocols. + +config PSA_WANT_ECC_FRP_V1_256 + bool + prompt "PSA ECC FRP256v1 support" if !PSA_PROMPTLESS + +endmenu # Elliptic Curve type support config PSA_WANT_ALG_RSA_OAEP bool - prompt "PSA RSA OAEP support" if !PSA_PROMPTLESS + prompt "PSA RSA OAEP asymmetric encryption support" if !PSA_PROMPTLESS config PSA_WANT_ALG_RSA_PKCS1V15_CRYPT bool - prompt "PSA RSA crypt support (PKCS#1 v1.5 mode)" if !PSA_PROMPTLESS + prompt "PSA RSA PKCS#1 v1.5 asymmetric encryption support" if !PSA_PROMPTLESS config PSA_WANT_ALG_RSA_PKCS1V15_SIGN bool - prompt "PSA RSA signature support (PKCS#1 v1.5 mode)" if !PSA_PROMPTLESS + prompt "PSA RSA PKCS#1 v1.5 message signature support, with hashing" if !PSA_PROMPTLESS + +config PSA_WANT_ALG_RSA_PKCS1V15_SIGN_RAW + bool + prompt "PSA RSA raw PKCS#1 v1.5 message signature support, without hashing)" if !PSA_PROMPTLESS config PSA_WANT_ALG_RSA_PSS bool - prompt "PSA RSA (PSS mode)" if !PSA_PROMPTLESS + prompt "PSA RSA PSS message signature support" if !PSA_PROMPTLESS + +config PSA_WANT_ALG_RSA_PSS_ANY_SALT + bool + prompt "PSA RSA PSS message signature support, any salt length" if !PSA_PROMPTLESS endmenu # PSA Asymmetric support diff --git a/modules/trusted-firmware-m/Kconfig.tfm.crypto_modules b/modules/trusted-firmware-m/Kconfig.tfm.crypto_modules index 89893686143..1f0ec52aed3 100644 --- a/modules/trusted-firmware-m/Kconfig.tfm.crypto_modules +++ b/modules/trusted-firmware-m/Kconfig.tfm.crypto_modules @@ -80,11 +80,12 @@ config TFM_CRYPTO_ASYM_SIGN_MODULE_ENABLED config TFM_CRYPTO_KEY_DERIVATION_MODULE_ENABLED bool "KEY DERIVATION crypto module" default y - depends on PSA_HAS_KEY_DERIVATION && NRF_SECURITY + depends on (PSA_HAS_KEY_DERIVATION || PSA_HAS_KEY_AGREEMENT) && NRF_SECURITY help Enables the KEY_DERIVATION crypto module within the crypto partition. Unset this option if the functionality provided by 'crypto_key_derivation.c' is not used. + Note that key agreement is under key derivation in the current implementation. endif # TFM_PARTITION_CRYPTO From f8e27684ca11e884c1e8ae6e1903c815277137a6 Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Tue, 31 Oct 2023 11:56:24 +0000 Subject: [PATCH 406/421] [nrf fromlist] cmake: Add support for sysbuild-set signing script Allows a sysbuild project to specify a signing script file to use instead of the default zephyr one Upstream PR: https://github.com/zephyrproject-rtos/zephyr/pull/63912 Signed-off-by: Jamie McCrae --- CMakeLists.txt | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8fc047610fc..e23650f262f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1824,8 +1824,15 @@ endif() # Generate and use MCUboot related artifacts as needed. if(CONFIG_BOOTLOADER_MCUBOOT) get_target_property(signing_script zephyr_property_target SIGNING_SCRIPT) + if(NOT signing_script) - set_target_properties(zephyr_property_target PROPERTIES SIGNING_SCRIPT ${CMAKE_CURRENT_LIST_DIR}/cmake/mcuboot.cmake) + zephyr_get(signing_script VAR SIGNING_SCRIPT SYSBUILD) + + if(signing_script) + set_target_properties(zephyr_property_target PROPERTIES SIGNING_SCRIPT ${signing_script}) + else() + set_target_properties(zephyr_property_target PROPERTIES SIGNING_SCRIPT ${CMAKE_CURRENT_LIST_DIR}/cmake/mcuboot.cmake) + endif() endif() endif() From c441a8dc1291faf8972964f2f944dfe2129a5ede Mon Sep 17 00:00:00 2001 From: Torsten Rasmussen Date: Mon, 13 Nov 2023 13:36:44 +0100 Subject: [PATCH 407/421] [nrf fromlist] sysbuild: create sysbuild_cache function Create dedicated function, sysbuild_cache(), for handling sysbuild's image specific cache file. This provides a cleaner handling of said cache file, and provides a mechanism for updating the cache file at later sysbuild CMake stages. Upstream PR: https://github.com/zephyrproject-rtos/zephyr/pull/65124 Signed-off-by: Torsten Rasmussen --- .../cmake/modules/sysbuild_extensions.cmake | 124 ++++++++++++------ 1 file changed, 82 insertions(+), 42 deletions(-) diff --git a/share/sysbuild/cmake/modules/sysbuild_extensions.cmake b/share/sysbuild/cmake/modules/sysbuild_extensions.cmake index a3838415eee..ac8bac25f8c 100644 --- a/share/sysbuild/cmake/modules/sysbuild_extensions.cmake +++ b/share/sysbuild/cmake/modules/sysbuild_extensions.cmake @@ -107,6 +107,87 @@ function(sysbuild_get variable) endif() endfunction() +# Usage: +# sysbuild_cache(CREATE APPLICATION [CMAKE_RERUN]) +# +# This function works on the sysbuild cache for sysbuild managed applications. +# +# Arguments: +# CREATE : Create or update existing sysbuild cache file for the application. +# The sysbuild cache is only updated if it contain changes. +# APPLICATION : Name of the application. +# CMAKE_RERUN : Force a CMake rerun for the application during next build +# invocation if the sysbuild cache has changed. It is +# advised to always use this flag. Not using this flag can +# reduce build time, but only do so if application is +# guranteed to be up-to-date. +# +function(sysbuild_cache) + cmake_parse_arguments(SB_CACHE "CREATE;CMAKE_RERUN" "APPLICATION" "" ${ARGN}) + zephyr_check_arguments_required(sysbuild_cache SB_CACHE APPLICATION) + zephyr_check_flags_required(sysbuild_cache SB_CACHE CREATE) + + get_target_property(${SB_CACHE_APPLICATION}_MAIN_APP ${SB_CACHE_APPLICATION} MAIN_APP) + get_cmake_property(sysbuild_cache CACHE_VARIABLES) + + foreach(var_name ${sysbuild_cache}) + if(NOT "${var_name}" MATCHES "^(CMAKE_.*|BOARD)$") + # Perform a dummy read to prevent a false warning about unused variables + # being emitted due to a cmake bug: https://gitlab.kitware.com/cmake/cmake/-/issues/24555 + set(unused_tmp_var ${${var_name}}) + + # We don't want to pass internal CMake variables. + # Required CMake variable to be passed, like CMAKE_BUILD_TYPE must be + # passed using `-D` on command invocation. + get_property(var_type CACHE ${var_name} PROPERTY TYPE) + set(cache_entry "${var_name}:${var_type}=$CACHE{${var_name}}") + string(REPLACE ";" "\;" cache_entry "${cache_entry}") + list(APPEND sysbuild_cache_strings "${cache_entry}\n") + endif() + endforeach() + if(DEFINED BOARD_REVISION) + list(APPEND sysbuild_cache_strings "BOARD:STRING=${BOARD}@${BOARD_REVISION}\n") + else() + list(APPEND sysbuild_cache_strings "BOARD:STRING=${BOARD}\n") + endif() + list(APPEND sysbuild_cache_strings "SYSBUILD_NAME:STRING=${SB_CACHE_APPLICATION}\n") + + if(${SB_CACHE_APPLICATION}_MAIN_APP) + list(APPEND sysbuild_cache_strings "SYSBUILD_MAIN_APP:BOOL=True\n") + endif() + + if(${SB_CACHE_APPLICATION}_BOARD AND NOT DEFINED CACHE{${SB_CACHE_APPLICATION}_BOARD}) + # Only set image specific board if provided. + # The sysbuild BOARD is exported through sysbuild cache, and will be used + # unless _BOARD is defined. + list(APPEND sysbuild_cache_strings + "${SB_CACHE_APPLICATION}_BOARD:STRING=${${SB_CACHE_APPLICATION}_BOARD}\n" + ) + endif() + + get_target_property(${SB_CACHE_APPLICATION}_CACHE_FILE ${SB_CACHE_APPLICATION} CACHE_FILE) + file(WRITE ${${SB_CACHE_APPLICATION}_CACHE_FILE}.tmp ${sysbuild_cache_strings}) + if(SB_CACHE_CMAKE_RERUN) + execute_process(COMMAND ${CMAKE_COMMAND} -E compare_files + ${${SB_CACHE_APPLICATION}_CACHE_FILE}.tmp + ${${SB_CACHE_APPLICATION}_CACHE_FILE} + RESULT_VARIABLE compare_res + ) + if(NOT compare_res EQUAL 0) + file(COPY_FILE ${${SB_CACHE_APPLICATION}_CACHE_FILE}.tmp + ${${SB_CACHE_APPLICATION}_CACHE_FILE} + ) + ExternalProject_Get_Property(${SB_CACHE_APPLICATION} BINARY_DIR) + file(TOUCH_NOCREATE ${BINARY_DIR}/CMakeCache.txt) + endif() + else() + zephyr_file_copy(${${SB_CACHE_APPLICATION}_CACHE_FILE}.tmp + ${${SB_CACHE_APPLICATION}_CACHE_FILE} ONLY_IF_DIFFERENT + ) + endif() + +endfunction() + # Usage: # ExternalZephyrProject_Add(APPLICATION # SOURCE_DIR @@ -372,9 +453,7 @@ function(ExternalZephyrProject_Cmake) ) ExternalProject_Get_Property(${ZCMAKE_APPLICATION} SOURCE_DIR BINARY_DIR CMAKE_ARGS) - get_target_property(${ZCMAKE_APPLICATION}_CACHE_FILE ${ZCMAKE_APPLICATION} CACHE_FILE) get_target_property(${ZCMAKE_APPLICATION}_BOARD ${ZCMAKE_APPLICATION} BOARD) - get_target_property(${ZCMAKE_APPLICATION}_MAIN_APP ${ZCMAKE_APPLICATION} MAIN_APP) get_property(${ZCMAKE_APPLICATION}_CONF_SCRIPT TARGET ${ZCMAKE_APPLICATION} PROPERTY IMAGE_CONF_SCRIPT @@ -390,46 +469,7 @@ function(ExternalZephyrProject_Cmake) endif() endforeach() - get_cmake_property(sysbuild_cache CACHE_VARIABLES) - foreach(var_name ${sysbuild_cache}) - if(NOT "${var_name}" MATCHES "^(CMAKE_.*|BOARD)$") - # Perform a dummy read to prevent a false warning about unused variables - # being emitted due to a cmake bug: https://gitlab.kitware.com/cmake/cmake/-/issues/24555 - set(unused_tmp_var ${${var_name}}) - - # We don't want to pass internal CMake variables. - # Required CMake variable to be passed, like CMAKE_BUILD_TYPE must be - # passed using `-D` on command invocation. - get_property(var_type CACHE ${var_name} PROPERTY TYPE) - set(cache_entry "${var_name}:${var_type}=$CACHE{${var_name}}") - string(REPLACE ";" "\;" cache_entry "${cache_entry}") - list(APPEND sysbuild_cache_strings "${cache_entry}\n") - endif() - endforeach() - if(DEFINED BOARD_REVISION) - list(APPEND sysbuild_cache_strings "BOARD:STRING=${BOARD}@${BOARD_REVISION}\n") - else() - list(APPEND sysbuild_cache_strings "BOARD:STRING=${BOARD}\n") - endif() - list(APPEND sysbuild_cache_strings "SYSBUILD_NAME:STRING=${ZCMAKE_APPLICATION}\n") - - if(${ZCMAKE_APPLICATION}_MAIN_APP) - list(APPEND sysbuild_cache_strings "SYSBUILD_MAIN_APP:BOOL=True\n") - endif() - - if(${ZCMAKE_APPLICATION}_BOARD AND NOT DEFINED CACHE{${ZCMAKE_APPLICATION}_BOARD}) - # Only set image specific board if provided. - # The sysbuild BOARD is exported through sysbuild cache, and will be used - # unless _BOARD is defined. - list(APPEND sysbuild_cache_strings - "${ZCMAKE_APPLICATION}_BOARD:STRING=${${ZCMAKE_APPLICATION}_BOARD}\n" - ) - endif() - - file(WRITE ${${ZCMAKE_APPLICATION}_CACHE_FILE}.tmp ${sysbuild_cache_strings}) - zephyr_file_copy(${${ZCMAKE_APPLICATION}_CACHE_FILE}.tmp - ${${ZCMAKE_APPLICATION}_CACHE_FILE} ONLY_IF_DIFFERENT - ) + sysbuild_cache(CREATE APPLICATION ${ZCMAKE_APPLICATION}) foreach(script ${${ZCMAKE_APPLICATION}_CONF_SCRIPT}) include(${script}) From fda9e48e5d953cf436fa0d0d50f0df9ca0127632 Mon Sep 17 00:00:00 2001 From: Jacob Preston Date: Wed, 18 Oct 2023 09:21:16 -0700 Subject: [PATCH 408/421] [nrf fromtree] drivers: uart: nrf: rx_timeout_slab incorrectly set When rx_timeout is set to a sufficiently small value, rx_timeout_slab could potentially get set to a greater than necessary value that causes spurious UART_RX_RDY events. Fixes #62828 Signed-off-by: Jacob Preston (cherry picked from commit 52c55177ba71af328c6069ea56c007e6eb5cdf1d) --- drivers/serial/uart_nrfx_uarte.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/drivers/serial/uart_nrfx_uarte.c b/drivers/serial/uart_nrfx_uarte.c index 017efa6a2e5..b70af538abf 100644 --- a/drivers/serial/uart_nrfx_uarte.c +++ b/drivers/serial/uart_nrfx_uarte.c @@ -844,15 +844,7 @@ static int uarte_nrfx_rx_enable(const struct device *dev, uint8_t *buf, } data->async->rx_timeout = timeout; - /* Set minimum interval to 3 RTC ticks. 3 is used due to RTC limitation - * which cannot set timeout for next tick. Assuming delay in processing - * 3 instead of 2 is used. Note that lower value would work in a similar - * way but timeouts would always occur later than expected, most likely - * after ~3 ticks. - */ - data->async->rx_timeout_slab = - MAX(timeout / RX_TIMEOUT_DIV, - NRFX_CEIL_DIV(3 * 1000000, CONFIG_SYS_CLOCK_TICKS_PER_SEC)); + data->async->rx_timeout_slab = timeout / RX_TIMEOUT_DIV; data->async->rx_buf = buf; data->async->rx_buf_len = len; From e40ab3aeae65a78c7371113cfcb3bcf2d68d1845 Mon Sep 17 00:00:00 2001 From: Maximilian Deubel Date: Fri, 1 Sep 2023 11:20:03 +0200 Subject: [PATCH 409/421] [nrf fromtree] boards: arm: add nrf9131ek_nrf9131 This patch adds the nRF9131-EK board. (cherry picked from commit 386b65800896262779336e83552c8a44ba96f7a2) Signed-off-by: Maximilian Deubel --- boards/arm/nrf9131ek_nrf9131/Kconfig.board | 14 ++ .../arm/nrf9131ek_nrf9131/Kconfig.defconfig | 38 +++ boards/arm/nrf9131ek_nrf9131/board.cmake | 14 ++ .../nrf9131ek_nrf9131/nrf9131ek_nrf9131.dts | 19 ++ .../nrf9131ek_nrf9131/nrf9131ek_nrf9131.yaml | 17 ++ .../nrf9131ek_nrf9131_common-pinctrl.dtsi | 100 ++++++++ .../nrf9131ek_nrf9131_common.dtsi | 227 ++++++++++++++++++ .../nrf9131ek_nrf9131_defconfig | 26 ++ .../nrf9131ek_nrf9131_ns.dts | 22 ++ .../nrf9131ek_nrf9131_ns.yaml | 15 ++ .../nrf9131ek_nrf9131_ns_defconfig | 35 +++ .../nrf9131ek_nrf9131_partition_conf.dtsi | 60 +++++ .../arm/nrf9131ek_nrf9131/pre_dt_board.cmake | 7 + tests/lib/devicetree/devices/testcase.yaml | 2 + 14 files changed, 596 insertions(+) create mode 100644 boards/arm/nrf9131ek_nrf9131/Kconfig.board create mode 100644 boards/arm/nrf9131ek_nrf9131/Kconfig.defconfig create mode 100644 boards/arm/nrf9131ek_nrf9131/board.cmake create mode 100644 boards/arm/nrf9131ek_nrf9131/nrf9131ek_nrf9131.dts create mode 100644 boards/arm/nrf9131ek_nrf9131/nrf9131ek_nrf9131.yaml create mode 100644 boards/arm/nrf9131ek_nrf9131/nrf9131ek_nrf9131_common-pinctrl.dtsi create mode 100644 boards/arm/nrf9131ek_nrf9131/nrf9131ek_nrf9131_common.dtsi create mode 100644 boards/arm/nrf9131ek_nrf9131/nrf9131ek_nrf9131_defconfig create mode 100644 boards/arm/nrf9131ek_nrf9131/nrf9131ek_nrf9131_ns.dts create mode 100644 boards/arm/nrf9131ek_nrf9131/nrf9131ek_nrf9131_ns.yaml create mode 100644 boards/arm/nrf9131ek_nrf9131/nrf9131ek_nrf9131_ns_defconfig create mode 100644 boards/arm/nrf9131ek_nrf9131/nrf9131ek_nrf9131_partition_conf.dtsi create mode 100644 boards/arm/nrf9131ek_nrf9131/pre_dt_board.cmake diff --git a/boards/arm/nrf9131ek_nrf9131/Kconfig.board b/boards/arm/nrf9131ek_nrf9131/Kconfig.board new file mode 100644 index 00000000000..4a237e3fb61 --- /dev/null +++ b/boards/arm/nrf9131ek_nrf9131/Kconfig.board @@ -0,0 +1,14 @@ +# nRF9131-EK board configuration + +# Copyright (c) 2023 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +if SOC_NRF9131_LACA + +config BOARD_NRF9131EK_NRF9131 + bool "nRF9131 EK NRF9131" + +config BOARD_NRF9131EK_NRF9131_NS + bool "nRF9131 EK NRF9131 non-secure" + +endif # SOC_NRF9131_LACA diff --git a/boards/arm/nrf9131ek_nrf9131/Kconfig.defconfig b/boards/arm/nrf9131ek_nrf9131/Kconfig.defconfig new file mode 100644 index 00000000000..0ece4f9a2ac --- /dev/null +++ b/boards/arm/nrf9131ek_nrf9131/Kconfig.defconfig @@ -0,0 +1,38 @@ +# nRF9131 EK NRF9131 board configuration + +# Copyright (c) 2023 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +if BOARD_NRF9131EK_NRF9131 || BOARD_NRF9131EK_NRF9131_NS + +config BOARD + default "nrf9131ek_nrf9131" + +# For the secure version of the board the firmware is linked at the beginning +# of the flash, or into the code-partition defined in DT if it is intended to +# be loaded by MCUboot. If the secure firmware is to be combined with a non- +# secure image (TRUSTED_EXECUTION_SECURE=y), the secure FW image shall always +# be restricted to the size of its code partition. +# For the non-secure version of the board, the firmware +# must be linked into the code-partition (non-secure) defined in DT, regardless. +# Apply this configuration below by setting the Kconfig symbols used by +# the linker according to the information extracted from DT partitions. + +# Workaround for not being able to have commas in macro arguments +DT_CHOSEN_Z_CODE_PARTITION := zephyr,code-partition + +config FLASH_LOAD_SIZE + default $(dt_chosen_reg_size_hex,$(DT_CHOSEN_Z_CODE_PARTITION)) + depends on BOARD_NRF9131EK_NRF9131 && TRUSTED_EXECUTION_SECURE + +if BOARD_NRF9131EK_NRF9131_NS + +config FLASH_LOAD_OFFSET + default $(dt_chosen_reg_addr_hex,$(DT_CHOSEN_Z_CODE_PARTITION)) + +config FLASH_LOAD_SIZE + default $(dt_chosen_reg_size_hex,$(DT_CHOSEN_Z_CODE_PARTITION)) + +endif # BOARD_NRF9131EK_NRF9131_NS + +endif # BOARD_NRF9131EK_NRF9131 || BOARD_NRF9131EK_NRF9131_NS diff --git a/boards/arm/nrf9131ek_nrf9131/board.cmake b/boards/arm/nrf9131ek_nrf9131/board.cmake new file mode 100644 index 00000000000..8293a428b40 --- /dev/null +++ b/boards/arm/nrf9131ek_nrf9131/board.cmake @@ -0,0 +1,14 @@ +# SPDX-License-Identifier: Apache-2.0 + +if(CONFIG_BOARD_NRF9131EK_NRF9131_NS) + set(TFM_PUBLIC_KEY_FORMAT "full") +endif() + +if(CONFIG_TFM_FLASH_MERGED_BINARY) + set_property(TARGET runners_yaml_props_target PROPERTY hex_file tfm_merged.hex) +endif() + +# TODO: change to nRF9131_xxAA when such device is available in JLink +board_runner_args(jlink "--device=nRF9160_xxAA" "--speed=4000") +include(${ZEPHYR_BASE}/boards/common/nrfjprog.board.cmake) +include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake) diff --git a/boards/arm/nrf9131ek_nrf9131/nrf9131ek_nrf9131.dts b/boards/arm/nrf9131ek_nrf9131/nrf9131ek_nrf9131.dts new file mode 100644 index 00000000000..4b66e5348a0 --- /dev/null +++ b/boards/arm/nrf9131ek_nrf9131/nrf9131ek_nrf9131.dts @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; +#include +#include "nrf9131ek_nrf9131_common.dtsi" + +/ { + chosen { + zephyr,sram = &sram0_s; + zephyr,flash = &flash0; + zephyr,code-partition = &slot0_partition; + zephyr,sram-secure-partition = &sram0_s; + zephyr,sram-non-secure-partition = &sram0_ns; + }; +}; diff --git a/boards/arm/nrf9131ek_nrf9131/nrf9131ek_nrf9131.yaml b/boards/arm/nrf9131ek_nrf9131/nrf9131ek_nrf9131.yaml new file mode 100644 index 00000000000..d1b04054ce8 --- /dev/null +++ b/boards/arm/nrf9131ek_nrf9131/nrf9131ek_nrf9131.yaml @@ -0,0 +1,17 @@ +identifier: nrf9131ek_nrf9131 +name: nRF9131-EK-NRF9131 +type: mcu +arch: arm +toolchain: + - gnuarmemb + - xtools + - zephyr +ram: 88 +flash: 1024 +supported: + - gpio + - i2c + - pwm + - spi + - watchdog + - counter diff --git a/boards/arm/nrf9131ek_nrf9131/nrf9131ek_nrf9131_common-pinctrl.dtsi b/boards/arm/nrf9131ek_nrf9131/nrf9131ek_nrf9131_common-pinctrl.dtsi new file mode 100644 index 00000000000..419e7c8d70c --- /dev/null +++ b/boards/arm/nrf9131ek_nrf9131/nrf9131ek_nrf9131_common-pinctrl.dtsi @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor + * SPDX-License-Identifier: Apache-2.0 + */ + +&pinctrl { + uart0_default: uart0_default { + group1 { + psels = , + ; + }; + group2 { + psels = , + ; + bias-pull-up; + }; + }; + + uart0_sleep: uart0_sleep { + group1 { + psels = , + , + , + ; + low-power-enable; + }; + }; + + uart1_default: uart1_default { + group1 { + psels = , + ; + }; + group2 { + psels = , + ; + bias-pull-up; + }; + }; + + uart1_sleep: uart1_sleep { + group1 { + psels = , + , + , + ; + low-power-enable; + }; + }; + + i2c2_default: i2c2_default { + group1 { + psels = , + ; + }; + }; + + i2c2_sleep: i2c2_sleep { + group1 { + psels = , + ; + low-power-enable; + }; + }; + + pwm0_default: pwm0_default { + group1 { + psels = , + , + ; + }; + }; + + pwm0_sleep: pwm0_sleep { + group1 { + psels = , + , + ; + low-power-enable; + }; + }; + + spi3_default: spi3_default { + group1 { + psels = , + , + ; + nordic,drive-mode = ; + }; + }; + + spi3_sleep: spi3_sleep { + group1 { + psels = , + , + ; + low-power-enable; + }; + }; +}; diff --git a/boards/arm/nrf9131ek_nrf9131/nrf9131ek_nrf9131_common.dtsi b/boards/arm/nrf9131ek_nrf9131/nrf9131ek_nrf9131_common.dtsi new file mode 100644 index 00000000000..35314cd0784 --- /dev/null +++ b/boards/arm/nrf9131ek_nrf9131/nrf9131ek_nrf9131_common.dtsi @@ -0,0 +1,227 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include "nrf9131ek_nrf9131_common-pinctrl.dtsi" +#include + +/ { + model = "Nordic nRF9131 EK NRF9131"; + compatible = "nordic,nrf9131-ek-nrf9131"; + + chosen { + zephyr,console = &uart0; + zephyr,shell-uart = &uart0; + zephyr,uart-mcumgr = &uart0; + }; + + leds { + compatible = "gpio-leds"; + led0: led_0 { + gpios = <&gpio0 29 GPIO_ACTIVE_HIGH>; + label = "Green LED 1"; + }; + led1: led_1 { + gpios = <&gpio0 30 GPIO_ACTIVE_HIGH>; + label = "Green LED 2"; + }; + led2: led_2 { + gpios = <&gpio0 31 GPIO_ACTIVE_HIGH>; + label = "Green LED 3"; + }; + }; + + pwmleds { + compatible = "pwm-leds"; + pwm_led0: pwm_led_0 { + pwms = <&pwm0 0 PWM_MSEC(8) PWM_POLARITY_NORMAL>; + }; + pwm_led1: pwm_led_1 { + pwms = <&pwm0 1 PWM_MSEC(8) PWM_POLARITY_NORMAL>; + }; + pwm_led2: pwm_led_2 { + pwms = <&pwm0 2 PWM_MSEC(8) PWM_POLARITY_NORMAL>; + }; + }; + + buttons { + compatible = "gpio-keys"; + button0: button_0 { + gpios = <&gpio0 28 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; + label = "Push button 1"; + zephyr,code = ; + }; + }; + + /* These aliases are provided for compatibility with samples */ + aliases { + led0 = &led0; + led1 = &led1; + led2 = &led2; + pwm-led0 = &pwm_led0; + pwm-led1 = &pwm_led1; + pwm-led2 = &pwm_led2; + sw0 = &button0; + bootloader-led0 = &led0; + mcuboot-button0 = &button0; + mcuboot-led0 = &led0; + watchdog0 = &wdt0; + spi-flash0 = &gd25wb256; + }; +}; + +&adc { + status = "okay"; +}; + +&gpiote { + status = "okay"; +}; + +&gpio0 { + status = "okay"; +}; + +&uart0 { + status = "okay"; + current-speed = <115200>; + pinctrl-0 = <&uart0_default>; + pinctrl-1 = <&uart0_sleep>; + pinctrl-names = "default", "sleep"; +}; + +&uart1 { + status = "okay"; + current-speed = <115200>; + pinctrl-0 = <&uart1_default>; + pinctrl-1 = <&uart1_sleep>; + pinctrl-names = "default", "sleep"; +}; + +&i2c2 { + compatible = "nordic,nrf-twim"; + status = "okay"; + pinctrl-0 = <&i2c2_default>; + pinctrl-1 = <&i2c2_sleep>; + pinctrl-names = "default", "sleep"; + clock-frequency = ; + + pmic_main: npm1300@6b { + compatible = "nordic,npm1300"; + reg = <0x6b>; + pmic_charger: charger { + compatible = "nordic,npm1300-charger"; + term-microvolt = <4150000>; + term-warm-microvolt = <4000000>; + current-microamp = <150000>; + dischg-limit-microamp = <1000000>; + vbus-limit-microamp = <500000>; + thermistor-ohms = <10000>; + thermistor-beta = <3380>; + charging-enable; + }; + regulators { + compatible = "nordic,npm1300-regulator"; + BUCK1 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-boot-on; + }; + BUCK2 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-boot-on; + }; + }; + }; +}; + +&pwm0 { + status = "okay"; + pinctrl-0 = <&pwm0_default>; + pinctrl-1 = <&pwm0_sleep>; + pinctrl-names = "default", "sleep"; +}; + +&spi3 { + compatible = "nordic,nrf-spim"; + status = "okay"; + cs-gpios = <&gpio0 26 GPIO_ACTIVE_LOW>; + pinctrl-0 = <&spi3_default>; + pinctrl-1 = <&spi3_sleep>; + pinctrl-names = "default", "sleep"; + + gd25wb256: gd25wb256e3ir@0 { + compatible = "jedec,spi-nor"; + status = "disabled"; + reg = <0>; + spi-max-frequency = <8000000>; + size = <268435456>; + has-dpd; + t-enter-dpd = <3000>; + t-exit-dpd = <40000>; + sfdp-bfp = [ + e5 20 f3 ff ff ff ff 0f 44 eb 08 6b 08 3b 42 bb + ee ff ff ff ff ff 00 ff ff ff 00 ff 0c 20 0f 52 + 10 d8 00 ff 44 7a c9 fe 83 67 26 62 ec 82 18 44 + 7a 75 7a 75 04 c4 d5 5c 00 06 74 00 08 50 00 01 + ]; + jedec-id = [c8 65 19]; + }; +}; + +&flash0 { + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + boot_partition: partition@0 { + label = "mcuboot"; + reg = <0x00000000 0x10000>; + }; + slot0_partition: partition@10000 { + label = "image-0"; + }; + slot0_ns_partition: partition@50000 { + label = "image-0-nonsecure"; + }; + slot1_partition: partition@85000 { + label = "image-1"; + }; + slot1_ns_partition: partition@c5000 { + label = "image-1-nonsecure"; + }; + storage_partition: partition@fa000 { + label = "storage"; + reg = <0x000fa000 0x00006000>; + }; + }; +}; + + + +/ { + + reserved-memory { + #address-cells = <1>; + #size-cells = <1>; + ranges; + + sram0_s: image_s@20000000 { + /* Secure image memory */ + }; + + sram0_modem: image_modem@20016000 { + /* Modem (shared) memory */ + }; + + sram0_ns: image_ns@20020000 { + /* Non-Secure image memory */ + }; + }; +}; + +/* Include partition configuration file */ +#include "nrf9131ek_nrf9131_partition_conf.dtsi" diff --git a/boards/arm/nrf9131ek_nrf9131/nrf9131ek_nrf9131_defconfig b/boards/arm/nrf9131ek_nrf9131/nrf9131ek_nrf9131_defconfig new file mode 100644 index 00000000000..fc77ffe0d13 --- /dev/null +++ b/boards/arm/nrf9131ek_nrf9131/nrf9131ek_nrf9131_defconfig @@ -0,0 +1,26 @@ +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_SOC_SERIES_NRF91X=y +CONFIG_SOC_NRF9131_LACA=y +CONFIG_BOARD_NRF9131EK_NRF9131=y + +# Enable MPU +CONFIG_ARM_MPU=y + +# Enable hardware stack protection +CONFIG_HW_STACK_PROTECTION=y + +# Enable TrustZone-M +CONFIG_ARM_TRUSTZONE_M=y + +# enable GPIO +CONFIG_GPIO=y + +# Enable uart driver +CONFIG_SERIAL=y + +# enable console +CONFIG_CONSOLE=y +CONFIG_UART_CONSOLE=y + +CONFIG_PINCTRL=y diff --git a/boards/arm/nrf9131ek_nrf9131/nrf9131ek_nrf9131_ns.dts b/boards/arm/nrf9131ek_nrf9131/nrf9131ek_nrf9131_ns.dts new file mode 100644 index 00000000000..9a652cd0aed --- /dev/null +++ b/boards/arm/nrf9131ek_nrf9131/nrf9131ek_nrf9131_ns.dts @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; +#include +#include "nrf9131ek_nrf9131_common.dtsi" + +/ { + chosen { + zephyr,flash = &flash0; + zephyr,sram = &sram0_ns; + zephyr,code-partition = &slot0_ns_partition; + }; +}; + +/* Disable UART1, because it is used by default in TF-M */ +&uart1 { + status = "disabled"; +}; diff --git a/boards/arm/nrf9131ek_nrf9131/nrf9131ek_nrf9131_ns.yaml b/boards/arm/nrf9131ek_nrf9131/nrf9131ek_nrf9131_ns.yaml new file mode 100644 index 00000000000..cf33abd55da --- /dev/null +++ b/boards/arm/nrf9131ek_nrf9131/nrf9131ek_nrf9131_ns.yaml @@ -0,0 +1,15 @@ +identifier: nrf9131ek_nrf9131_ns +name: nRF9131-EK-NRF9131-Non-Secure +type: mcu +arch: arm +toolchain: + - gnuarmemb + - xtools + - zephyr +ram: 128 +flash: 212 +supported: + - i2c + - pwm + - watchdog + - netif:modem diff --git a/boards/arm/nrf9131ek_nrf9131/nrf9131ek_nrf9131_ns_defconfig b/boards/arm/nrf9131ek_nrf9131/nrf9131ek_nrf9131_ns_defconfig new file mode 100644 index 00000000000..83af1cf6b74 --- /dev/null +++ b/boards/arm/nrf9131ek_nrf9131/nrf9131ek_nrf9131_ns_defconfig @@ -0,0 +1,35 @@ +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_SOC_SERIES_NRF91X=y +CONFIG_SOC_NRF9131_LACA=y +CONFIG_BOARD_NRF9131EK_NRF9131_NS=y + +# Enable MPU +CONFIG_ARM_MPU=y + +# Enable hardware stack protection +CONFIG_HW_STACK_PROTECTION=y + +# Enable TrustZone-M +CONFIG_ARM_TRUSTZONE_M=y + +# This Board implies building Non-Secure firmware +CONFIG_TRUSTED_EXECUTION_NONSECURE=y + +# enable GPIO +CONFIG_GPIO=y + +# Enable uart driver +CONFIG_SERIAL=y + +# enable console +CONFIG_CONSOLE=y +CONFIG_UART_CONSOLE=y + +CONFIG_PINCTRL=y + +# enable PMIC +CONFIG_I2C=y +CONFIG_REGULATOR=y +CONFIG_SENSOR=y +CONFIG_NPM1300_CHARGER=y diff --git a/boards/arm/nrf9131ek_nrf9131/nrf9131ek_nrf9131_partition_conf.dtsi b/boards/arm/nrf9131ek_nrf9131/nrf9131ek_nrf9131_partition_conf.dtsi new file mode 100644 index 00000000000..d14d8d95f75 --- /dev/null +++ b/boards/arm/nrf9131ek_nrf9131/nrf9131ek_nrf9131_partition_conf.dtsi @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * Default Flash planning for nRF9131ek_nrf9131. + * + * Zephyr build for nRF9131 with ARM TrustZone-M support, + * implies building Secure and Non-Secure Zephyr images. + * + * Secure image will be placed, by default, in flash0 + * (or in slot0, if MCUboot is present). + * Secure image will use sram0 for system memory. + * + * Non-Secure image will be placed in slot0_ns, and use + * sram0_ns for system memory. + * + * Note that the Secure image only requires knowledge of + * the beginning of the Non-Secure image (not its size). + */ + +&slot0_partition { + reg = <0x00010000 0x40000>; +}; + +&slot0_ns_partition { + reg = <0x00050000 0x35000>; +}; + +&slot1_partition { + reg = <0x00085000 0x40000>; +}; + +&slot1_ns_partition { + reg = <0x000c5000 0x35000>; +}; + +/* Default SRAM planning when building for nRF9131 with + * ARM TrustZone-M support + * - Lowest 88 kB SRAM allocated to Secure image (sram0_s). + * - 40 kB SRAM reserved for and used by the modem library + * (sram0_modem). This memory is Non-Secure. + * - Upper 128 kB allocated to Non-Secure image (sram0_ns). + * When building with TF-M, both sram0_modem and sram0_ns + * are allocated to the Non-Secure image. + */ + +&sram0_s { + reg = <0x20000000 DT_SIZE_K(88)>; +}; + +&sram0_modem { + reg = <0x20016000 DT_SIZE_K(40)>; +}; + +&sram0_ns { + reg = <0x20020000 DT_SIZE_K(128)>; +}; diff --git a/boards/arm/nrf9131ek_nrf9131/pre_dt_board.cmake b/boards/arm/nrf9131ek_nrf9131/pre_dt_board.cmake new file mode 100644 index 00000000000..c8267afd1b4 --- /dev/null +++ b/boards/arm/nrf9131ek_nrf9131/pre_dt_board.cmake @@ -0,0 +1,7 @@ +# Copyright (c) 2021 Linaro Limited +# SPDX-License-Identifier: Apache-2.0 + +# Suppress "unique_unit_address_if_enabled" to handle the following overlaps: +# - flash-controller@39000 & kmu@39000 +# - power@5000 & clock@5000 +list(APPEND EXTRA_DTC_FLAGS "-Wno-unique_unit_address_if_enabled") diff --git a/tests/lib/devicetree/devices/testcase.yaml b/tests/lib/devicetree/devices/testcase.yaml index b57489b9a11..673e2319702 100644 --- a/tests/lib/devicetree/devices/testcase.yaml +++ b/tests/lib/devicetree/devices/testcase.yaml @@ -15,3 +15,5 @@ tests: - bl5340_dvk_cpuapp - bl5340_dvk_cpuapp_ns - mimxrt595_evk_cm33 + - nrf9131ek_nrf9131 + - nrf9131ek_nrf9131_ns From 6755c4785640afb19f4973563f9737eece9f57c4 Mon Sep 17 00:00:00 2001 From: Maximilian Deubel Date: Wed, 15 Nov 2023 12:55:40 +0100 Subject: [PATCH 410/421] [nrf noup] boards: arm: nrf9131ek: enable tfm This patch backports the nrf9131ek to a time before tfm was refactored. To be reverted when TF-M is updated. Signed-off-by: Maximilian Deubel --- boards/arm/nrf9131ek_nrf9131/Kconfig.defconfig | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/boards/arm/nrf9131ek_nrf9131/Kconfig.defconfig b/boards/arm/nrf9131ek_nrf9131/Kconfig.defconfig index 0ece4f9a2ac..378a58fb6e3 100644 --- a/boards/arm/nrf9131ek_nrf9131/Kconfig.defconfig +++ b/boards/arm/nrf9131ek_nrf9131/Kconfig.defconfig @@ -8,6 +8,22 @@ if BOARD_NRF9131EK_NRF9131 || BOARD_NRF9131EK_NRF9131_NS config BOARD default "nrf9131ek_nrf9131" + +# By default, if we build for a Non-Secure version of the board, +# enable building with TF-M as the Secure Execution Environment. +config BUILD_WITH_TFM + default y if BOARD_NRF9131EK_NRF9131_NS + +if BUILD_WITH_TFM + +# By default, if we build with TF-M, instruct build system to +# flash the combined TF-M (Secure) & Zephyr (Non Secure) image +config TFM_FLASH_MERGED_BINARY + bool + default y + +endif # BUILD_WITH_TFM + # For the secure version of the board the firmware is linked at the beginning # of the flash, or into the code-partition defined in DT if it is intended to # be loaded by MCUboot. If the secure firmware is to be combined with a non- From b0177d6df95deb539e3ddc95048faa8d0c4b69bd Mon Sep 17 00:00:00 2001 From: Maximilian Deubel Date: Wed, 15 Nov 2023 12:41:16 +0100 Subject: [PATCH 411/421] [nrf fromlist] boards: arm: nrf9131ek: add docs This patch adds a readme file for the nRF9131-EK. Upstream PR: https://github.com/zephyrproject-rtos/zephyr/pull/65224 Signed-off-by: Maximilian Deubel (cherry picked from commit f4297253a79867a94ddd97d9877cc5ed094a5040) --- .../doc/img/nrf9131ek_nrf9131.webp | Bin 0 -> 75800 bytes boards/arm/nrf9131ek_nrf9131/doc/index.rst | 228 ++++++++++++++++++ .../nrf9131ek_nrf9131_common.dtsi | 4 +- 3 files changed, 230 insertions(+), 2 deletions(-) create mode 100644 boards/arm/nrf9131ek_nrf9131/doc/img/nrf9131ek_nrf9131.webp create mode 100644 boards/arm/nrf9131ek_nrf9131/doc/index.rst diff --git a/boards/arm/nrf9131ek_nrf9131/doc/img/nrf9131ek_nrf9131.webp b/boards/arm/nrf9131ek_nrf9131/doc/img/nrf9131ek_nrf9131.webp new file mode 100644 index 0000000000000000000000000000000000000000..056296ebbbcab5b514be7a6f30771f3b12167bc3 GIT binary patch literal 75800 zcmaI6V~{36w>A2-d)l_AZTGZo+t##g+qP}np0;iGv~53k-g9o;^ZoeF-4R*2YHeiZ zu8OLR9jPQKCWb@_0#FwfQczR)r2zu~0BHX;LNEXs2tZO;SRo(u-z@+%-`d#537ioC zu(5S^R1y~=($Lf*f;s`f0uTZ402%;}p|O*_pn`(Tf2{xS^1K27`HyCi?mw~q?>7G{ z3vXiTWDEd+5dE_dFt&Ge{)Y|zVRkoX`~Tqde;Cd9x1q^DT>THzI{usBKfLxI-sr#a z<$tjGf8qaH6q=)olJLK^q5b2D%>NH;^nYOE-;Or_Y*_!fYLv` z(Es9(^I!f7|GbR;d07CA|9OZ2>;N_Z!~gOJ{O1|`v-v0glUpY<7Uut=K;VP`0EitR z@PP~ffJy=YzT$zvj{+d@s}KMH+X4XkZU4vLE*}8+_4JRA{~wMt4*)<61^`7ya7)+4_8Gf2DovKjq#03pn-x{~h&p_MbzqJMU}qGwr$Va`%yc!8-=nc4W8w zZy@z=tLNFRz9T|S--@rK&#*VdEB?>EC7-FUx)1eN#I?MO-B-VrkG$L6SB5+NX2QL` zYrm5Zh)=uM(IzIwuqz7M~m_tf-YS&-MkUF=CBv`$h6mpE7U1}MMS@U;n1`^lhVO)O1 zMf{kS6i=~4K^vR|Q2F^?k2fS;2K$8DL&^Kks3BYARb*F1+ zUz@4ujr{Ffg>5-IG;XBt7KJzVbcHTfF(2VpwUCm~217(>?su zT}Y}m&@(}vkb&WHwNHv4kB$qgF8+?+27a!n0LarnE#Ss+23ZTfR^RFL;71ERyHT84 z{;R_|E#-_TkNWiUFv=NP!~(Z7`|i8O&1o;H2;_8&e>JOo%AtM51S$KyeE#&siXYxj zTSM2zkW-^t`ueib6YADfoyrnvZ~x4--``5ML&dCF{>NR00(O^39Vr<*464!DLedjP zGq%b|b{2q+o*jB0Yo1m>;iDs<%G!W=)2q%s2g##c`}~B4segW%@Xy-bW|ok4Tt{7s zU^}#f)2^t@(~B^bm9s&Tz+cNkp}A4UUx9qA6T9gol0V~9F6Oasj42*Iz}4+6Q|#)* zXR~P)tCwEN3SNT$iq$@(W=hT|#WwGHAB(ntKN=j;e&4T|K0MCyr3c{=Fl)cFL6@bMITf@!@UYD37d(14! zI3Ic>ra=`?asp#7Q>c#YI|d^KC5`!{yB#EamLoMNf^MYZ>$G`KcFKmrseA)|lf zgSQ=f{NGmylRDMX z(tprBS2OGi%x1*NC}Yz^l&wmj;FHl8G#3(E07t?(kiDxG_SaY%St`hxCoM;sDB8vx&UpT;1A8e`(8JkgT zLDl*lI~g{GQD+>B^_VaWRKu{3mrQ!@7q_&T-jYu0pWBbEMKt^;K51%1z{ig+G3oVO zmu*tdN9b8GfLk8@4~&?rg2U{4K^JxFpM#R^8-r%1qq&PigHU0h4;H|>`$U)p`_VRC zB$oa>`45IhhDH}dxUHh(k@3am6DHN@mmncqT#oUA8o%U^SFZ7a0R-jl0b1xBGo0+7 z8{gg-_1cXGB$ubbx!(PsU0%8VYjUTw5*qbwT~12wSjGu0Gn5fEWSw)FqKsZT?cjgV zjg@Bsg}U8(MC{c-tS67V7{fWBstH6L-ly0{1>rke_0VF*c?rWN4Vwg zEk_D(;Ca&^jh-pA#Z+liisC`WC?qLkB?tVcW$q_aHroTvtM*SnwI6Tp z6jizLq*WHYF4_Ddvab>olyOEdN#;6^cxh0#4l*)F!YqM*0#70lVO_l}GZ}vx z?R||78^<*hUX7D+Oy8us=FS==)>Oe0=G2`22PNr`t_p`Tm1?Vor}uRmYZA=yHx_4V zCfO^2Lle>h548c?B%xF^qC^{Wvu;FpoyJ)$H`E*@V;51~>ATx$Rg0_sh?YWCE%34} zIINp4HhlOXge%eXcdq``;tGIV=Srg9+Y=G+~+Lnk$vO<#qV zAaw_vh$GT`KZG=_$<&A|#ly}hm1lMrbgSmtp@G*R%Ee@ifXX=c2BiTL%_xs5P$b4q zGz6(}KOk9r1@u$&@;8-J3^z2%`e^!LSy^LE(VZ4yFQuuzibwFWzN=-K`S=xt6B>L= zYrD*VVvrH*=JY+zQ+c4>ozx93$BcCl zbWgLz@H0$apZ5OwZ8urEhkg&57E?u!I7*+80a_im7X1mQFHM7&w18s$2DdR0=#-Sr zv?A56v+yp<$nR{Yw{XJz=xo0{#uhxC&@}}&} z5O(9QirJ{qyM@M)HmWhUoj8kFHwt2S25BI48IH*P?6JTvr7(lD(KuIFoP}j=w~5lO+TJ<~B&S`bGkiFJ-~?Do09a(k%Nw z3s}j2hnRnQK6wvJ{|IaQ2!`6lEF0-~7H_(D{p#+>%qN&6KqhgXbq*vEL4K7GiY(|s z1A;;C^GXUrEdB-SMWtmHPPCv5nX#$tas9J5O{2p5tR{c=Hw8H&s`i7?bQzA67|4PFp2)PihNS8l{Kh;&NAT=LQid#lq;vW}Hg<6MgGy?Vg4 z-l(O;+%!bq>J&9%8^7GoNv;0KYU`Dn8Z#zgj5hiei0;BHo3GPg0-^xhAF3cJ{9PfDG5 zoACvimvP8ws=9e}x6ZKZrkP8l?O!rj{uCVHkpNf^p2HK;S&E-q;dgJ$*_+8M`pk4i z7IlScRdZ$4zBT4$MRcgXGhkFsvuMW6u8Aw?zEZw+FQ;TS8$Pie@7^v(c(U5dH%M&L z{FASFl3`sUgcy+)H8#oY)nN6z)NH}BnJpvFQ$nY&FHKc&jOtH<7iFSeXS2gV+YSuQ zPN*9=jD@NlRCE-74F&QBsDl9GM0UC5qIU@YV4Rn1HnNuDNe5P-F1>So4 za@4;-U6DVQr^x<5q`ij3`Iv~F1?7HcFRoa9aTL%&*>(K2-#rt3#5GHMu-wy0BGyLP z40;zf6Mx41aF9)bKDCtH+y=1*L?sA3nIeC=DdS!*E~b3s7f&HXH9|08cv8sK?wM#r z(j`oJpvtB^V)YmeU#r0$0pse}9LJv@3{c?@7F}1{g`K|YQ_z?n)9OjT8d)8}(8T`w zl${wuM%Ig7eCf0&_|e!ltp!O5SL@ofMuN=4h1GET~+H_ZtSwf<-&XrlFu->vuFeHjuB#77} zJp3AdbUXAEsVS3iKrgAJA6I@lMLIUB@9)q&LgTXXz;Zp!Pn$$7yM63D!li6u%Ar@M zE{UT>Lo(RI?L20u5=+VZ1F+K?lbXFhi2rq}{r8eNzJZDzR0}73#6HCpaIHoeb=~KW`Y>v>2?~rz+);qlN*gbCawbD+~pc zL*||;ZbT5*I=9Cq=e(&LnL_}VT>kfxM==+=;AQom^Y&jN!AL$V0uL03aHGRkA*qF0 znopL~f378(F8%nY7v?P?b=0vk3fEJORj+{JKK$nl6k!zC`IS{x8!;vFID0lfsOYwVO^GjDs)ev5NhzgrNsq(weimQ8Ksl zM5FL1H0{S4DsOBE4^?+I_(!UGn*Czby?z66YMtapJ}tX8#b5u`WWIsD|EVbb zx6qqSg?J6*XL+LD{Xsq@o;&Il_$j;mi}!Q0ympW(mu8=cLIDK|J~^BZ9_Np_;Y3PD z%7$sGIbqHuRS_3+Jn_RUC*8->_1lPsj_NO}u2)(lck6QCU|Z;hww~@h+SRM)c45Ie zP2a|QZwrrl(hKzx~?oJ2)7$vyj>L~yW#h5O~>YS zqIZrNGwGe;qu{}4+$IQkb_l{#+eNKmNQY%U70jk*;Wm$WgxjRPJpMDi>Lo0uDx{cj zfj`Mc6Lm8e-!Or(es!d_yE#iRzb^#&9ev9JTXjwA+NX@K-mSG*7P>;U)6nf3AHzN= zOMFQ|x!oMRd@D6Om=Ukjx6z^S*62HU%j*R96cDl_gL87M=Ui>yppAMHDC-Kt-$L%D zq1MRGAX>}kKXPtBH9W-J?p}A`JLJzrPk;RIV23&+7Tw;3pjAbrK@1Q_eo#^3N)MtJ zmP?(vM!3)S?Jc5BN3lQf$?>t5z!rZwFss_7$hrK&jMX2QymuRZj?uE^f+;r`%0lW> zZ)~JefoI}>NJ-Uba=nWA+nzI5m0}-`X(#31qL!uTL{&&Z@~JPq#9)Y+ylE?$%ul?KuM$OfnWL+Pth^j7wWwIc|E! z4HZzX1YTEL_;bSClhxpsEV{icKAGTfT=M5eX;zf;FR2o2;Klnu(h%~tL}*H#WCtXZ zWZ0fatJ~0_H&EbJJ^`QHlBh-5MjfuxD?6ne3^D)m>w@*4+IC51XR;b z%F}x4CF$>l77+6AhjC(cMxNGK>Soeum-DAyusVz~KW|-$VFCGMNQ%?F(q-5{F3}j} zN|g+(hJuTc{BCr4z($m|AMyTc>7#g&Z-pQW`DrSiUw27$81hTY`gXQ`REEhXU$$Zz zi09d>lhlg0>~Rr}Y>_F3KpSLTk*|!i=!>^<5#(#y*ISp|Od+$RUFdgbwV5Pa6p}4) zIhZN}@ue|Vv-BsIS-#V^O4m(Aov0}}>ZFCQ?6p?D1pnK>l^6IXl4cr?t*X}t*x$47 z$*uN}jYCp}kK?>)oZ)P3@E@&lJ#K5zulD08n~jfRo*ROs=eN7iK}hcUsNt_}IyhUr z+tr3aEejj|wlEm!KwMF$4J9dzeH`Dj4=YoHEGfsILeVZOu+pcy&`naE~rk#JF_q;dpSeZYXaf`>5jDqjALRrd$27%H_ri=U# z*xhmGLZof`JADH4y9-(O(b4ovk`F|vFTC}9!K_kSayBe|F9^0++JE*EQl8sVLeOp6 z)X(tK&N>>VqU_5MnjMXg&4EzuQ{z&1L?e)PQZnUAm;@gDa%PYL zR92oAoP6&YuJ@%0i4dQfiMEjOevkUvf>*=JW{`3P{)hTmt`ik(WBSItkcvo8j(X(Wy}d3|*kJQ4=R z>?BsOb&(iaShzO6CEt<neRr1tm#_daE{KpF zyf4&lYui#jndHgswr)Kplqc-f{`=kQW>?QW?$-EMeJ7^kM$>FvBPtUA>MGO7-uYo` z2I(v}sRKlLh1fMy=TAQY9V|)}Ib(7x_umJx({mBKK-=0L`?Rz{kA?$hCLnHZIbK!p0;?id)Ue9@iyqGR5gw96wB%RsNhjVY0XGM7i6{Z}2}SG9{{9%&pG&vK=y9Zu zdoZ2E(ru7^F_xvXgxoRJb?gf`gW}AG33p6P6YKy%8JDRb)8=BGPffNFVC3+d0kUgE z0cPVS!PR5x(JZ@Bk*um8IcW z2?r1b5k9VI!8$l+I)i@hgWr!I$8)`FDyf8p8V6p3ZxwgcV)G;&(Ag^q6+R4TeLO$h z?)O*_gdT{Gx}PCtK#>i3aog|(9tH-zNKYpdM`00bJ$*YcUJZ_@;2l^QzF3REC{9EmR$yZIc5b=idg$&ybj;ZSx_oCQ;3?)yL`)WbbO<{j$rtPKX4SFAt}e9A|(Y@0G>w=6&6ekt9~ z*-TALmCZBGY@>`=^@2xdnl=gE^C-1dd!Qu8AX3E{q31*54r0;*!QnT< zZ&kc)j5~hXNIT-i&ulgTdm{Ks%s?i6iFn$bYZ)qLj04le4$zxgZmGjh7o;^H6--ZS z1mAYr=8*!0Q_kcNOPMhHpp6$M!{W=PgovsYGgDW6oO0ClP(y= zO%6f7gT7z-)3$jR@nuG$n`una$5@Ro_jlbBg05%w9(EvM< zl1n<3pQWs2Bz+O258}nboT5rTo7EN#w{DU$xe&80L;Vvd9z-=9=IXWL<|TNs6V^A_ zh&?o~m_HQyhn2CKjW8g%$IfHKaCM|mYqD58 zR18F5L1cy^P(K3Tn#Cx)S5_1C(Q!RG35StcZpV5=-~8pCD;LPBF3P@wL@ZbZof1dI zbXB9bWVWjKSBIpsL`lEN1nu;z`%g*a%d-e)I+`*^wtpa!E#KQk@~@Zb-}Kd^JFL3O%pX1fbMg(Lgkn`!_9&rl+g9YuSds&#O#D7gwkFs^*84l}l0QW^DOAvl zltRv`&kl7m-CxuV)?pal)ASU`$sEHHY z{-)5{A};E3)!5CsIfw~iqv{bW}AEr&OM~5LsL(e zW-NNvLsST}zQ%@!-rJOuH(T=ufiC~o6!4{}x z*5FGwitRAe3a!sNxlzFs%AaZ-cIAa^*DjM81*8jXj>p`3G zU+p8e2cu*aTC{Ysq^q8KhJpYr*q%s{jz#f!C;m;tZPY9b_vv>gUm5enr{y*UpGPR+{(y2}>;Oho2h77~L3Ubv$M3AKpwzj=f6F`MifV6V!fU zvln7uM>;*`d^`JtCd`EX1vXuL1VN$<{sNF<9gG4 zSdMT8zoIvm7_AohOM-N;lS1iX&9zCrCLW8ysr+;Zn4SSBm{dmoHf{ZkYR`VClY;e9u8z{-- zX&D?W6?z<#FVpJX=Ia5KGkNJT3`4aSLB{7FQu;glKHQz}(Z?*Z>NHPghiYOIa*^tI zDnbKWFmMMmE`nyft1gsE)ySaaM)ji(PkTW5C`$XF)|aK@q-edq4{qehkayy}5)Fy; zbG!p%S@JHvcz@RKrTew}*i=oMmg4Fc7oxFEl)(&X|2t|q70%YuGg91O-c@jR7hFU5AhL)MGuIQRzFElik_|P!qw5AD?Xf#|k^JBMOZ7RzNMD zO+@K1lwo131*;4wQN~O^{`vkTACp)zRx}hZ=+8?Rx>FFg#2t>m15X4MB<2%SDAN{e zknan&3^jK0%?fWl@`0z-am&;r$-)&r@ASX6-@pb8Q&gH)vfXZ#&INxntd!IQRy*Im z1S&EohQp7)0(d}W6`^Z`MHXDS9 zA@=;PqP_>KzYY<7BA!}H-rUk;(P#ViDomQP7wZeUov(xiM-1!f)iw_D1`n5F1PTr= znHW%t4Jid-U4{2$t&irlX4lSp=t2F@4Io1ewVo_yj?|X!puIatb>`Gy;P99?xnyQA z#R^h=66URg_P-LRh zk%#w2|2)_tESg@5SgWL;;V3=!;&WZP`?5|E@iIRr1objfmg&&4~=#A4* zJMD)2DT>doDTF{KbYK&jq3#ekMFx8^(p`OwAjSe0g@z~XNSw0qvTJgr@-j!1YAckH%rJ8EDES-*P)(K6K2WCJbD@fFWb=rudOAL$TG zCeou2*{S3y{TFpo{lqH{-LO$U0a0cKD5b&9<>V@!{9WtuH;#uq(2$?`k59z)(Hxo3 z?DSE#=(m3PAkqRvv{nIuTmY9!m$ar`0j>2`bz~d|DP4egmU@BgVzaGB!wKm#4SrGY=GazBj1;IS*+AXafmUacjy{Yz6)b_2y>m-L__!hRx zH$8Wl2#gv_0ikcH1QQ^ZDfJxyUb-PuMx^edU^1r+D>*CpS_yr)eWnAsFo*AICXujc zcS`5grQAhneKDdni`*R3$SltAlL!D5|K0UH{L@0V%v8!}S_x&&UvK92az%I>q6X`! zHMNNr0$b9m!TD-wXHRwkmr!u`=^3?qj#-!U;a}NTdI(caS#dHIt~TA@?>CR%A>kNO z1!BXnk*o@yadT>Hlwg$iQK`VGLn`{oiZ#9S3(uk+h3Y0Ap?SmUkX-^K+ka0$Gnrw1l?lm=we%iV0T+@bs&zvGVI(PC*q)v;)3p7B%Hw4s4r zQ2JXJ&kTL$;zSwctVQ#&lO!Z&1lGTO7`8kwosanFA-V6U;xSW?W_itoq{(-vVU8$j zc*=ArL>WtH{LEsnqPdh9zpEEsP3yy1J=(mbQiNj5RODUmcbjHje zX+x zK(JUlz66E#bcz1@DIoyA*(reNmIlvWl0F~zyz_*pf&~!p>GtP<@_&9j z9Ox4B5F_|<>qVNh?x1I+pPtd+7N^yg{!B}FQT|p(fuqw!XZr!NnR#97g{@`W8&g>c z-(E1p1DckIvaAS-`umDGL&Kw_cl$`IqBOMj5-`S2LBHC4qE}*8Dg(v*N{oTBJvQlP z4U74SK+mp&W2@Vz%wo6(ty53tjuI{rjY$Mw78!8nqvhB=Xm(kx8k_E)_UJYNadx!{ z_j#WSr^>U^^9htmZ&|s$!zk2MF*UtGyx2TKjzMv5NDeOA?EVftz268`UJ@vHl2HNm zwc0UnOeh&B?4lT{o*z{pPSO-XWR++l4`|1X40(5*GHBSlE;zASNVbXP{f*Pd(#jk5 zoUWxYU3%r|UTv8WP&4>!Gc~b}Xy(kSU8^5YUKLa*1A=CSdb#)z9dnSOi{%OF+f5pd z?vOJkO7@nvMO+`eAp0*ZQ-bWPefSsb+rQ}l+%c-;UUq#qfUB;>_6>i4U`7XOdBzTq zW@e;P#=PqKqp9>$PrW!2Q(Yod)aN8)FJj5AUAQjU(xR%xe_BK%Y z6I&As1TcLzW?I!?a63`qB<1R=f@ek8@`WwCDY8wl!3DWT0Y&1P$$SmO^LVK1edk_a_46kDcCn&2%5#baEL5P(VD}PtDCeu9?_@-7$75e}V2+Q; zLCSNINh0i7k{(poz>h-DVwv&k>xYH!c@}cz!u0W&6%`QG6YB#F93bsLB>rf~=y4sX zkz*nKX@T7|WQ^Umo)Dp|me{wTiZA+bKQXPu9Y)tYrHJR)PYu|byXoI5aBpH%4a65z zLe0*~_RV3)9v;hUEv7seNNfC8>vmv+B=q>~qx<5IWoc7lwLQMY8p|u$z6q-uc({Cc zUJt3vGY56ut~E{a?N;}MKldmG(~I-|Q%87GJ5-* zkHS6Avr4tnTc&*+-qJ!}xrZ<=s+KGr)XqD&rMaLDFP4a}VNS^jW7?x+ZiOU%m^gSY zK~KsCL=J*))U<%YXbp95O;RZTgecs1C_C%yn*A9;)KpRWiC;l9=3ju!1fR@dtq|>s zEZt5GO=Z})s@Wy6Cyk(1u#iVOF5rKH~WTC zSiTk0de3Rkb1&mfT=6lYMAu=v?v=hDTqcmQV0Ug6=SK5d;zj+qQ z&)=O!!nBXLLUk=^c11f>ZYn&WnYuFOu^L=_;Xn3klc#RueX@jvGI7k0608*G{@ zqn}O94dXR(uS{FNkAuuu{bDv`vXs!ji%4=x@QHpa<>z7}BDYoc>ddbVbjhtF+&6(Y z&$pxL1L-UK2oMRPRj@91e`ruz8IJ9N_IJXY{-F^X#-)1hKIshY9tAgusK9Go2w(bb zw+yk+TXTNz;E5d;Pvu(D2}^m+RqpTy`RVMu}F-EI~ylet(42w3? zgE~P+O4u{Ir{W>eg47LzAx;GD3ZCN>1F=X}H-b$t4Lk+Nm7{_fK>3MiZ!CzcxMG0| zJ8{YJ&t+a`^2*jSs~>uN6N@_*#Cl9 z;Ea6C)oj;XxaJoeZs6s8q(P+}7_jrFzGTquaw3s-?dw`BKCeGg!_=yP?G}-3f6)lW zxk>DnnA0ixLFO2)Pq#w1eB?sDQrDc0ouJDLaVF2ZU8vY@2*jHs#h_h!a5aX_1fzgo zxGJK&lvfj6tYuzI2(429m`Gu7b?>;0Ohz`i?K`N2*?_=st#zk4#xSuowBY)N`>K?X z5fap_#|+nAzJE6);%T^5@F7l>RgBkL$yu9XwXxQt@bk|@qASo5I7Wq=a?iShZd(<- z0ajg_KRP|4lZRodlAchEe1J7`g@hJc9U~UvlGzhO6m@_K@q<%`SH<`1^FZX0{;6#1e zk^p=_^X443)zQnFI5`<@=1#)P4dgdD-8gVee066=)ka1+cc#e|U=TLpAosM0Mq6NO z^uAWF^5rUeA-0LxS=TVYb4~fRVikTwjGGn*UY@q$O2g+bv$m>&v>Tx5F|m%ZHU!7w zgYo2Vy~jp(3XMpWB0|49=8}awD}aLD=&-SEwL(@Kx*4+4jC>(-GyR&$C_KYVQ~3CN z9NfwvNQ3tyFjM!apUfcyrnJBbwG}#FWRzkTZYV+%CLGts%T&doU*S9UN|chNDDmLX z3zM++8Pzx@^)~N=bH1Y6W=j}Bk~}SA5FpEBPcqr>0&Bae{o!EP z_4N=v)~K&OeMBIWr2mI_r4dxSVbmcq4m`UNw$In!6shOc#{F%OmqCJg?57}n`QjO- z7?~%yE+%I8Vjbvc+OC2&H@)jcvIwjAsmO#iUb0Gvehlb2?!boNEpi0Y>^+kq(WdVo zzF(qwLi{lWeEPcjY^090kvkWyIM%s$x9ggnUWNk{>5U_ca?&*W;cB^7n2e02Zr&(< zNz-kRkAZXa9dVo19eBX^aZ6z&orEXJ#il14-^U8b#Ie2VK?t|nVX-s4y^ODVbnf3X z31sA-vZG9xi*__L4Lw(uY{WA&!>yc!DjuMCZsr&6zyQj-ALEJmGb6X{r_UXt?rOJR zgZ4xWmJm!-^OyXwSk-tu(rM@Alpas127~!*`xpz3c((E{WLuAtG4fI)E3X%bgg?P; zK&a>7FEEquz+{jhHqr<`tMou!3%0goZqMU(BLM?Pa!6~%(4?zbPoYXiV2C=L%UJRe z6r8Y*Wh*BOrjkRg#y?X?qJLTbE?s}^6E+1@KDw8<)Ov@~NXL-FlW%}(bX!T)T(S&3 zG~3IpPDZ&V-m&4eZ(u1>5-m~K@AXU-t|9H!keF=d*SYRyG+_ws>o z*90m+*uGz{Kk{R9B+(76B2oz(HA3Y(!+0?H$QM9p?2gA?2?>tTNnSlkHFffJXJ(rCY{EeBl=CBSv+O&mK3|5Wc{wx zw)pfmZ(Y49p*=;^6@%Sam{R}huE@i`612?ozd$(2HnB}VD|I5}B2)WaN|J4XB>O(E-J zl|bX*n^T{yhmLXV?D*u3!Kfix_8??Ixk<;Ftf6T3*qM2*yKt0dBhTH=BTzg9a~;o7 zp{k4M8g|U<0wxSZlvf8A>cSw8G50Y;=YSfZOMO}&sfg}U_xg8v2LW}nVq%&=r3c2TZzz2KxRtg$^*yG#+sH!;8~Sb zD)Fj^U4O{8w#DcX6vB>#YKksHrr4U1)Pgu`xFELqa~@jahx@`$V%5rE(N^O&Jd_0! zS`<#h9GrR;n2O>rs3+WzsoufAt>zm;Z6&>^k;*N&>sG?7C$%jowl;X!Pkf<9Dmo&E zcw1MEdm#c@*X2#Y+I4=Lm4iM|5>?f_k?TM`P^9;x_SedY5;a8w1wR+zUv#AgL|T_~ z4}1Pp>-Rm5dGxv`V~>(T4f8W77*osl7Oj9d%%VaKry>8gHL*O&$4+`#te=jbztn66 z8R&R+0)ewlkg`>gZAJZzDMI9GEp+aG$Gy9%!L%15>a{GrM!DHV2w6SL;76prsZPau zM&3<(rC~-G?14$HIs~$;&D|!1*Q7Fpw9i>N>}$455+e(k8tuY>OnQGb*fxLX+L>=7 zB#jJp%s?U#In0ogYwHTOCJE-Kk5-2Jr=(^XzUKNzYk$)B=`Jp}oM@W9w=dBU2&%++xs9OEMr|&;Fotnm=z#>fjs>J$Z+(bx z#pto~#Xn{)Uhp)`)e@XU#D$`GDAOGyZovM{8OL9FQz^P{FYr$LhismLF#2`LtxDgC z-C94|Lm9VXmm0*p4(fzI%D&&8cYc9N@ux`IW--6auDf#f;~M!Pkdv|w2imHAnej$a zz+^I(wP*$2RA*%}W@M0Ri*G&TdO{E}%kqT#Ex~`Fx2z0qcqByLztk80@qxYW|1mD3 zIKK8YFGrY@;7WCsX}kRfd&)76YTU$CnNDgKQX!NgvWGB)L%k13Tiqy1>0NsE@mNCG zzmYzR?i(qN&LgXoDO!d-C}C{{slx_%;D~T)KsjD`OV(!O$kRzGiz7~I;Im7k$A!r;24N4)yK5yD z1^8-JlOg;>bk76SOZ`F5_Gkkkt$r4L*RTs{m-Xt2A~G`OYb?pU`5_fh263)}ZRs7* z?%0TdIPhw6tf4+U&xizfa1wir15?~+2^v$Y52&l5|2d`9tIXyqq+sKiAQR|QWSUE% zkfk}Is!u)sE7kqb9#5=%DHdsJKqs46-&L1EM31Z^*9Sj0AnpTtx;pp{4hP9GVMe=8 zovn9wV*W`2p?~%J>22L8e<{-fj&GkM^t+!iY39hU(hi;lmF6#}FK`!F(rpvXN{8?6 z-XdMKO8TWf%FWrwo5?~$dG3t~{nwy%IJHc^@#mf7)zAG*j*e>nqgx{_(V5Z=srOzN z8rk=csFt;b5%h`5JejPXN1i`r^IECvIagjea(KOMtF@D%Jg`J*sCYay#0O%rWF{Fk z`Z9`nUAvPikvQ{GF`T16k1a{03_29`&hX&il4=zU%2NtyS1%M1P}Mb3tIS1k?M*r3 z3A})Pp#JG(FdTydSHLvP!^T3X#xTLR{UkKzGzhXEmR>A7+bTC9&lwCi8hM(GDr~*E zgbw+GQG(K35BB!TEr^r`K>NF08YNFZ##r#hO4ZZ+S|?Pj$Jtn=3e9v2^?6oNZXQXm7^l>q@0-50ASh8}(MHRpGjZJ4;D zR*r#>rqz_oZO!wGN-&rVHrHxPsoXdZ$rC%?6#LFLpx-xt?3?DS$64BAj`< z;=xD2Rb(eqV=cEo4B#&QTAhq?>-O|<*BOI@sKJXd=1^#LGJ?fQVg4w@)l6%8^tfgl zKYkzBn0xqa1oB|hk|KMeT#CIcvZJ*e>f}}0NYmzlzhx7?iXrvEzWA3FCHdF3J_#c} zeltG{$cCGb%h@J%PoYl@v94SJM7WD9y12KhaBb1aJ#E{IPnI@P1|`(hcMY*#8epY_ z3*@&bD8F^RagGxj#jyXkDQn1D&S96HN3*JO+uW1bib*Jj-i3wVO+&F$$iRDmQ^~>e zoz$DQ9s6%e??dZQ4IV~=J8jRui*A)#?jTJ54vz{4KGRSaX%uj&5E?wRxz1mEb_4WR z`SZ?XJ_t^W3V*X&su-gDIa8Jq-htX~H|2zNHo0Q5$&5iL?#G!PaqM8--a7$SMsvMR zHc&^}xdc=x8?(9df0t2Qg(-{B!l^!c6O0Fgdj?MLvC~Xz!k2=uz3P=als9@rDrl?x zApO2xEwYB1bsQ*y6ucz9vkf=D#bNQkp6hoApt^vd%6L!-v z>x$E-t@r{QTGQOooX1a`H^$w%rLH%*2DM_+O8R@=ah|}4c(yRQa?nKh<8Nwd45YZs z>zx@aD$0FxHaB?cCCPN)VVzwPp8heu)JrXU_}vWe&{h2|zxmwBQK*n^GY3n5P^NY% zt0Zk*ChcCBCv&sm<~)I*5-yLrnhvQB?5P(Cgo1STi`fn9y#YbKac$=u4gP-qK@R8TA-d$O_U0Z%Dl+Njp!={-*7 zD98xmLu)T$hP)ucK5dU-sQi$zcr_E|ARyxc2RZrKnUe2VJQ6ybE z2VJqZuC|CeIixFc|KRFHOWmu8wsMX!5YR+BGI>d#lwaG7xyuZ_z8_fm&6M;&0rC~Z zfaH17R{-D8sn}g)b>;@d4_YN5VLaGGdYd>EWKscaIWuU+&ujr_-w+N+<%(%KwRRW2 zq4F4PGWl9G0awc}2uKq!k9+V1#&*t_1p#&qt%JI3p-9}=;FgQN?5#O4{_018 za=T`Nn}N&9ZX%8#@4z05Sz#Jsq}G4g^~W&AwmkdTjho%?2T@sz zx|%5W*fF)Ht|j0-?EI=horsi~l_T!FG@#>nSb?Rc0S==+qu*Q|8r)}@6q>COYDLOP zQOywa3w~4nM-$xOZO1J{(29zQZEU`p34rv*8^LBy>Kg7CP?13KTNi>dV*Af%Nzb<@ zwch&y`L@*yjCko%ZF$ZVnGCE9BrWny*Zq0gpOK(_P+GoRI^IvJTdpBt8Au1_3WvuS z4%qK9CkGE)9f^Iu0aOHRZ@$|g4M?2D93AmBskh!;gY)KNU!{K$FKbc~?9-vtBe`pl z>)0A-A-guUCYH-0y7iG3Z$K70ugNk}?Kb)Y+yaeq%6PU5fsB&is2(1bY1P$<2CI3Z z;tqW-Ns5E0^CYp-k)#JxcqPAxa!lh<63Y9RI{H#Kcb1)2v z^%!Oi^ToTk<(oK;UykjA7r=ape17WYlRK(+$O$_I4(r25zLBEjD|jMZjj~sy1bkk| zs>aqK-nIY`b0E{X&^XSI_Q~3tf&o1lAz2P^>AuLAzccH+bPlSwzzH239tb<6Q(#J~ zNS}vkZ+meIGYv)Mllbr=eCq7KS8lQUKM8v4d~=5ZD;9C$z-?`C@ey&bufHj%d#@PR{z9U%R$h0}zpq;3S_9zikuaM+sdJ!o(j2p-!eAewbxr?U zlt8D@uo10?D}zVn2sXv36?8yElYq`L1c)#HtWUAb%L`uAZ)X#9lnP;Qd$hBbEII60 zbJ(!wnstHK4JTQ;dsgV>*KJ(bVocd^6_a4Hh)}(GID{6i^jee~AEht8n9N~rG^hBu zyJ-4Pe7|YnoIoi!&pZ#Uf8k0Qk#bGd{y^cbgIQyDVJi?@B3T#Ksv7)kMqdA~!nh~# zD5X$!k51iD`AA2AK#L#*qEQ3VZe$$+-L?;CeYO0puk2tNkIun-C0-Mftxtt4f9%Z- z?29G4xVspQY%h0j<9p1nqBXmtDXTT0#+VT}Me}Dp)BxFgIndFTb#nFa2i(9tx91uU}i}03IR$To~;EMbVI9e z+BpR6?wVur9(&@cUV!sUZ@DbYym(bg>!>O&p{~{Gh(9nUL9{)O}?@a4`)giu@m-U!F}oJWI@i2g70?{ zhs;MV%V%W?5#OY24<7Wcs+4!ejo~*Vgzs9Hk?XR_{FOMLZzGdALW?K%7Vi#JFWHnz z4<1~8C3etXlc^d=cT~`EQG_WhG#ctD?tw}(OVfG)_&5@?*a-l8Bx_~=>%|Q^ACZy~ zvt<+hQJ?(Jdi^O0H(V7%(%UD)77Yh0v8kbq?m6|v9IrG_aY10|GC0R}k*Y$D=GPP8 z0Y7Vrtn*NLRjF6DnWQ@$F@v z!a5X{{wb0V^tX`yZeQY`^xQBd<_I|_KAmkHm5B%7LA`V|vfUlh54ke$9F)OmGNaa(`#C_ER_`XLYc6%(ctZkhUYYh(EIP3k4k2 zZ*hwZBKc`qz1r|@IpSWv8*(b#5J|pG)p^_cx44ZRi^=Z4X;)v+j1(8$vTf zsg-)@*(jLo0+A6|i$HAz0F;93$fcDajab007`Nhx-|J5sYT?<2N$}4TQ$)TYfzzk8 zYEy?`{DoT~I?-AXLF9&pp>3mIx(JLu;`68OBA$=Q(mWbWyx!D{zNBax0vjWctXlzN zD@`PCgu>oGv_v}=%7SqwWmxQFg7Livd7F6t-Z>inigg1_zc>me`x3=%j5giD=Ccye zqGwmg7u|`pMOAB;l00$_eieR9|Eg z)Pz1O-ms?w2~P32&lEWC__pHL?@0lWDkVxz*d#z9UWU;D?V&g(4mUvtqg8+s1q0WF zD*&n4BV2|i@pH99%i7|*y)hK{i=5<+;0vb% zJz)36@!PTULVlHWw3}|ph$X!#3!o}=i$bA_f3fmRCA$^C1_|dXA?!2xKCHHIhW%6~li_AejY`mdJC#X-s!Mcb1 z0RQZ@niPlO(MnB@qWdJn;qZe`zlJ{Flfw;z?i4rKV@=B^n2*VK<@umiB>+tD{q;2+ zKer!wdwnxS+R6F9g^q*G&fzElc^{X~4!)V3X8N&|NNWd#sl_64tK=M91bnJ_dr4^g z5t&$Yc6HIWG*Kot`ZPK}1CFLoR|y-sAE?N7opsIDXo24tv?t?`MiyA0#clieDwI=R z1Bjj-4ztGj^4JESRc!%JXVaC?p}v0M!Pfq+wiVuy?jX_K4HVDYrNz)G{V_pJpGd=N3db+sWlx@V^e1+#1nM?8)uu?Qd$DZ>TB?JWlI zmqIaEK;?HrKGyKlfF0X;CtfVd}dNl(oQfWZUHz z+|Z;^`C9jrog!rK(ZHWolId7Ov{4*(D zp9kadlVKaSF7wXOwGuLaqDOj{tOF%#MU#2w;w^!hg zj)vz?FisG@H&R98&!w03*nciR1tA8praGRHB}+uWIF64a+RmMORiWNa7)S5&CSn-m zCCJ6Jxir}%)O#sZoYESc%k(Wha^j_XOmu6C;tXthb1Na)*81b&zo{msZ?L1@b>LQ- z{Gg~|oI?_pNe4FQB_b#y5X8W5-`=5ihM2~|?G*Bsobr1twB%9SyfYKs5N60HzHu?k zUv1oWy;|yCAXVxtEHc!fRGU#|nkJkB;-TSfJWGj6b*~)OkLBq|sh`5ug@+{vWy^~4 z#!#bD#-(yZ=-2C2u!gL9?gidw;|ka9TYXz} zN7gWib|F+Yz<|3SFfX1U`rv^dS>^_On#qM`Mp76pEN;xt)h5xsogHq!kI?%)reTUl z8oRL3*YwIsa4Td#w;=7VTsG2?xp9h;))JYyGUW%|RjjT_WD}5GFnjqdj z?dKVwqi+o^?1-g^)|GINqA)nRO-h{0lYf)1UdMbSigWc#Vhz)hlR2Kr$44d4xU;0W z+g=ucw6ffxGEwWDY-|jqV6Q}~JpsuRXGXmP%Iy8NpylIO&^D}F{~_0{OrD0qj6OTd z^luI(p(s;IEd3FarhoR7ind@uO?GdS}NEo&Fa2ezp;p_I7v44ku@j|xR~vr4%fHNoYmxFkr#HPNzN&PVc$sA+k1_MZp?;isN%cB}yFrFLxLKlr6wb-wAPeFV`32`Sf(*sj*5$*){9SrB$}^X#>FPZT%sKWMQ^az| zvpE^$EZ-+_Y#P2ACN*DrXDmCgf5M-XeUaBAdv&5k$Yv zL7p-x@;27_P9dnrihZ$el=uvLd0qA2MasPE$AcJ#y)i>jzF=UMMvUy z0^-tH>FIG^2gu^Refg}}0NOEgWl~Fa%IA%CHUweqHB70S7KylMJAyY>wQ6$6cDz&#JQ!W71z zrv?Fv>asEa*9Go+QK=3%ljNTVIi6>2C-|DgddIX3A|Q;C=>v{~Lp%Snl(6Rr}>-Q~b9X z-~vyhN;VgmuH&!B^`kRAnCQE^mU`Dq@-2~f{m}l?xgvK{U~vMpapEhA$)OLRdFH0) z4feRMbH5=;AYk|F0#1*oYw`nH*HmT622uJLJ44^N}* zONhzy3lCb!y2bqmN2n1GSiPVn5)KLPxxd`ZhdCoBw%a4MODr3I<$5d10Jv~hGvog8 z=TCeUP1YL=Qq_}m{J%fRWmpAKmZ1rlI#vMT>y8I!U+hsx19n0STTGik{c4`o4ZI9#K`asg6jv!b z2#z~IJ#y`F=%4!y_&U+eA#=w8VQ@LzFWm5!Ek$Y(h?vCI77IZMJ-GmxktiV_ zsIzAI3iYy3{Yv?xTo%@0#`;i2GU3ZX~ac~8IUWXFcg3N%$UdAK`)Q;alDl;Q|-nBGm}^zY0)3M!owOZz{ocog@Ibj6w0+LB|a=ACqGYOnX`W_2T50ps9Do zEFv8D!t?Iskr*xlv30MRiTzG+&3cQiY$!-Ph1nMZL${USIu!y~UhH2lyyBJ;Znk)t z)}L#{gxsMqdZ2ez%?KkvA;+A>phPq=doBeMG^v=d37vpeRutUx6L)Wp8#M3KPvw5hu@y=HPO^Nvz>qf zEo|$uRHxP9>Gspf|9baA5V&|Y>XKQ;gJohdUQ1;edOLp@2~OA^E4?&LRxwffM!z4D ziu~@7QAUT~0!Kz{fgH_?Mc{3`C9sEw%aeAz;e`8z**t1(|0p&+S8miarPJL%*vy{> zB(6N8+X%EPiSkq3t&I+?XB_F8R{BbA=FnDg^_DoCfpC#{Z}(OQrc9nS(}Gf%hMI>A z^ZGQNEgg1cxD8;F!s9cY7HW@QpILUmNB;M;!?tq+x^j}QJaI8O-e!eX|3%gOj0DMa zHiQ;t&QZ1Z*r0SdCGf(gfHXPjbOga}o{`}?_Ndl^b^PJS8O}SU^}J@4Bv#v9gDmPg zOLlU_*BYzG!!~b(xfKphb>GeaX1v^6aib;t*lDNWcXOa%hj0nML$-7)=@DAKJHtx4*K7HX=r1OkKLhYIe`$8f5!Ac@=q$508KmERca44*Mb zfq@RvmA161aUEGsE_dq%V*`BZBQUJ(!{WR{-k$tfM90Vw|@TltA zPi67s%{adB_=M@{R4_um`lMXQr1p7D7AtBLw`lw?Udn{x?6&zrLpL0jt3@iyyN+|_ ztS9{7hC+B6Sno_Q2!}GZY=UM9!Zp2kuszHBG*T@|o{U*RHZq}xVd;56JF6vk9pu9~ zeiwN6d2PyuJt440wgHPa@(PDpH!9rw^A&u&Rd2D)y+gHw0l#j4W70=aa@6~>#X>m+ zY@3{D-?l4j8Q9f+<`iJeGMvyvJerHXK+^+X;i)vuuH57VYn> zT~M9*4K!MAfC+Rs{Vg5D?dU||GpRi&nkSY!On;F>uk5TP%QRQjCj~;3p{9PsCuNe> zSv|)5BoA?wdg_$g=Ria$S<9DMY~oS*Yr>ixY9YH(?t(-#(35v#HKH(~04pta2CV}m z20*YcN9h2l+^F6c9{ldeca_hHMc#7LN!MHi?~J9W1qtsVMv^YTQR(1B^5E@CrU&_U zXE$PJsq+Sxp3r^jF^L|(r%@bI+*9|I&@6r%i&fKW5Bl!Ji!-A=eQNWSAf=)NlQF0k z9W>f+<%}Ge9LY(~ugc*JeTB5ZS%)r|{6K;_70Ov~*?r?*nF*Mp4t*){fQj`S%?$P| zO}Jj^N9zhw;@d@8ATq6&mpJ{X7XiC&4=Lo$K!f*Ae+SN_n(78Z0XW3Au-ed#!oLJV z;yXgKAe!rj$3r`}Q*75vLy!NzMh3z=5XuI>k+w9z_h8zLpF?XyJ)+tFSQG(#pus_Q z<9>`HgIIqZ2(BZ`YV!(H#vm;#13Y&$3J7{+DcAcdA4EFJ6xP6AWX5?QY-K8FEL{jK z^tG*YQl#SJn=F80m?{bJS3D>wFcG12B)qu5OfF^>%H3(hv5A5homNpyl76TH9nM3y z4roBZAWH6Ke+Z6`0#r$vJCa6QA@1*>9kXhPaeOKBUw6FgpP zxA3YS93Lz7cV2W&y{`Mr5HD)N(ELL~eve_k&3WljewV9p?6mdv?hCNG7o7gz1UMng zts(O;V+!>O!HB5c@+NoW2oCU%Nat-sKlMxo*^mylaAIOXqxUZJ?sVRnQ`*l*NKeOg zz3(s{$z+d@QF66La zDFBc2%<`9s&ka|EmaGn5w?kq~S3sKC(zt4>=}e{lnfLFy$QklKQp9Cj_0Z${_i!{z zcQp%*Xe@Li&Ig1R#VneTCyU&A^Hw1hu9+PSmG>{;$|Ng~>1;8-Wofpv44@SUqjKO! z;&u;YslGApQ=VFGG&&f?p1y4LFA*$z7K!htQu=ledGT-J9mU8$rny>JZixB|Xm)>} z{hKd0vv;(s51tz4K4Al|$Xj8o(wD?oTW?AmCwZH_9=dkq@Bd|`t)w5(d?V&b1s2;v zDYC*+gS(n`-<+O&09IeK&?WtP zdI2Nd&OYLe*4XLN-rtx+K0#X-a-cw1@uni)#Jrf}{ZfK94F%n5Q{RM=Do@q(O6+?$ zo;3S2F6>JG8WgIhBe(-twiaI|)X4>DxP`^i%G@8r5qMb&C}Glk&51ubtnKTj+?ykm z?U1R}VW%UvJkGx7U>Q1OXk-k^r`((J^2!=ymdU;=h*=O33~aC! zWnHDwH5S#m$8zo6|G5fNpyaVj1X1GvyeuMFD=MvIO&?0E3*MYgo5xIm`yqU6 zd?I(sG?r}y!ItHAvz><+tU4X7C;>pgSWulOyeu(H>8)pI;X5cN5-|Rdu_}K|U}M3L zT0I(@?zBq%1zkMsJ0HY*sp(7jDr~Mkg$h@Q2b0uW5c*26jjh)j?em(rY#A;aA=|^p zNe+a#8vt&y_<}oS7Q4)K(xGBShxtX^LMWbtG)ER?bwaa#Z-4~MmMuEpYcH@BR*X$ zjQ0A;?GQedIVW5(37hjfQ>39GH5Zus$@2~_2>IQp+?59OQrhg!nR5jrFZBRx<32g% zrR#tfNcGQ~z;&wKkD^7d@J?WreW2W424GZ?gm><;F?Pf=ShmI0SK;c6n+#R@?+GZM zX7xlgy4c3Q7bpSxaI)_6iJWo=8JIxQFdlz1y`aq}SWFm0HS0}JUHNLW@xa{y{*3H?(PQdzK)&tjVt{9@5s%?28u`Q8jnMmrtyWXmz*V?iC ztl=Wc{x67iA^Rxf;IpfXa_OIAW?0l*K`2U*8+?pZu~GVLWN#L0?5_BwX@yyX=AIB*W0#hB0PqEo)j$Viu=n9TqAy}u~jYp(T<}T&QbGyn= zw9tfExu*2e0yWGzR~4soHe1EDDKX>B{u^v5=!zD6oR z@TQa_WrJ9`d67DO(-D!RZZzh_#DDrvY^jXofo0O+Q?powF$e*r;dGXecqcmV<$?tF zR`9*GY0mzh)YJZ0oX^Yrro11ywH&O$kGIsiQQp{Eu%^XSAebPM2d?Q5_{*t%>i>O2 zhjP>;m?9XJ^#L{af_pxB8M~x`hYp1eP5&9DN6?gbOv4X7dw&Gi;wW;mxce{gu>vY$A>g0ylH?b%LY6In4e#)ts0#i@wECL#)1iyz^ce>FLgsg5EWXArD zyffD9k(o!q&pZ`dFA)#4Lar4unXF;s->Pi)CR-(xEJE8@otmH8>hC?UydM2$+f8da zMl&$W_^{e@b9$okYxh~L0n_5Gq%6v_#ga#|jiuu-&+cmh(EGwKi8J(xT+XWYks?$* z$Uz)aiuyulWQ=}9To75?zzLhMNpoep_C3zc?E$ZWm^IX*cm0vf;^tIv@>NxJy187y zozrRIT*H@ikF2p_OX|;xZN;wG_FM>}k-QP7`O{%Y{Gk0%o}nwvY;S_3a|r=g8jj{ z6%KqXKYDN9!75Gz)-su)4^@F7G!2}TFJZR$!q&La>ixi}i;gPoFezPF-0ReQ$7SFg zwlb-bu<++ECol&pylg;(2Y=^4stI_au{*x64|jtt2$bZx?1on{>;kqX{_1NJ8T=$j zw4Aq~2vxX?5NayPT$Fi@CM=y^qPF|nX^R26vCe&^8(&x&~)f8u{d5M;1@V zHnw`;hu7|;=%%=wLLt#VaCjwX@L7)eg@7*DwW56BHA0oBxmxoTJ@Q7iU?U#aCZyLJMJq=Uk+1In`oN@iCYW-x)*jN^60e37oWOkEW4Y?(8 z&N32}=@liI0t7r6!8 zVEHcD5^Vf$&Uoj-2$nlFUN#3C(9oiu7L?L+v?>`}wkvvR;%3OB%!K1iHjC>?W^;cx zEu)?Wh~h5Gi~I=bsdg2i;2NaGLsw1jE)r^VbK`k~^ zMPK-Bz8hbkZr;n&h~Sq`1xYvgsPN%!gS!*=>a3=QtE!GB8?woQ`3 z$N(piCwtwsTX20a;~`ICXXaQ-qPD;?+hYcoxMOS^JbrYnRjkNBVy{;m6<3VJJZ{{- z=|V|DYu2o7gGC<06k|%;A$1}g zeEMN$Kh6OL=I8}G=$)1wIRm`=NIRdxgESUs|3r#_$1G}u;_f!kyu_WRY;)@0#;{=3 zo9$QFDU;7e3e~xU(w-2L)}swNW)xmD+dtnE%b>KEMF)h-W-OIX)C!?g6!KI$n64Ix zCF*YO(-$5e1uXz;Uj|nLU%LPC1Rr9u)Va9i74gARp{AI1$fGq65V0q)d*snLQDe3J z%AFH`t--MS3F4t}uk?6p>^p8Lqe5Hzl{8QHa67Aklm^(DIi2`NXuKI($5@DC zMA~x)`|;z&*edOL;1-lWJD6qk-PF|}<~fNOs+#tM6r+!bmiYP0WP7Q^Tgx;zjXg7R z53e*OZt1PpB}9S3{5FZl$;aI)$vZK74gf&Sgy=5r6{v!+`Df2j>*!f{^63yg`Ch-xodGcsQc9Yyj9sRnb& z%(2_i-7g*Q+!*;}OJl}7V;kv)U-;|gCvf2`0a!Z?Qp6q(%LTxz2XdMvMr9fWHG`#nLIBO54|QQR?Af?{X|Me-Xl z{|Dca$eg`RtCvXHT@-|XLdC_30T#Ws_5dryZOFyUj8<MWx}j3o0`ubK!?L@p8w5EEZW=rR19cJbTLtB-pw zvw^8UF{}OjmWLFBY;1r^iE+i9YXh!I^|D2!*});y`h#)Cx0S;Q3Bs?YSNVbvMA|^{ zW{l}HtjV)%Z!UGTPbK zG-ofIB9>BS6AJhkce^k6K&I+TccIsQ0c50dav0(KN+x8g1Yap+A-JIyLd<6SM(ymC z4qwNRouOGMt|+!6cD0!3AY6)#3j;{Kp`|W(kJZt(T8q&8@v$pBE7~s`Wv|h8jitsh z=fmBgpEi@rLe1?9OQZlG(3~C*6_{z)vW7u3zUG%K z@0|-U{wOWDd>erwN=6cFF=FC7;gK+!L(ltqHS!@LKieWMYkC%u=sNn429WITbR6Vq z|A=KcZO|JX!t-^nsg$iNvIBdJeowT_d3yV!S@RREOw$t&MlOtDZicC?{ z*iE&Fh^Y~e@rxQ};6-gu87ws+bvoO@tJ~CLK2rH`;Qh=#fE^>%+=EUYXlM!*&O2P` z4KbZ{yJ+!nT5@hgbxyx$druw|D|+-1AXQBBUdq_hJrTJ+2fc3p(d&B#0^_m-L-+@(u-DL zR~w~&lz?_#CLstW36X?pU_~biRJ8G#R1bS(v6L)ZH-I@{IoTwTpHM-7i@EVtz_K zK~&4sR$RLbE-{(6b5*0R3@s$&@uXA(Ll#{_u@hC%iAVT*sv5;rg^Yu1ax&e_40y}o zi!PnB%0ZC8(MS5$E`0r(mxS3NZ;lWj-1oOK%^?JjHetM=phdzyPeV~;M5vB=Efslu z>VfnSEQovW_d7s2zB);;)^3)%mEN!%07+3jMRU8AGM9kpF0LYPbk}agee@@}?yI?C zY3RDAMSZlGtkck|gI;$4qgd(SS+9Y8B)vy5@)mBhd74kRbBj{QHhn2I{7D5K@XV8% z*;SNEq(;nYr~j^Y$~b$mjrI4^M(_3tge?gm(GMx>EO0Ub-`)X6cqVjOwzp4+EBGN< zW@aIVi$A0yEpe!~qGb#yLg6QoBS%9kG30yh5$yaHElNu5c3<=Nv4!0sx71l;6kvPx zLx4RY`1>cfc*z+`ML?#2zjE=fBd~G_20dqteKz>VY%8q&&(_=u1!QqZj-u`&y=+}+ zV^4q@8y&fccwcX+a#7d7=vgUJ5I%<1*v?lC{mKON(n4f0*_I(vaBY{Rv_%(v2lOyF z6zuFwW1P6*M#3!A@n0pXC^|(O3gbn=PFkJE$#@`qIBlH99XVdjt$ULy;#p?903NGQ zV^3IAZ?^ki+J28)!gm6ouk{Bv_^}0}6DcjrLLn?D>-8wrR!rJdUQcK;e-6 z#kA-pOA`BMLEn??-eL4&2(73&#rFMU!|Y7IC&;nX4RkGV^=?rVgIE&rG=40dTOdr{ ziLumMpl*Lrf`2Lf0VK=8k-&WmKtw+7U_oD^d}{<@q4<+PdpR`vUxZdhK@U#TJeO5R zv!Sw4a>t2VMqX5DBC}kY$o#YjDDZJNHd?JXgu#N7k3sgE9y55#AfGQO4VXKJFlnoq zRA@(P-r`lO8Ie}V>F=4zk-X-|I#L*Y24rKr7#A|s>iP)zDb;1Jo*nljc^wQZrgzUo znz%HyJoZFytOGQ=@7~G4#$Y^GWevG;ng^vxgmAU00}wsse5@+KW-mA=T_9>@GEwdb z8QDk&;IeJxH>6IzU6P5XCha1fii@sr8y>JP=MJPSyqYeufzeA>k5NeDDDGl7 z533(>@`dtlzgt-@wl>e{-As$$VHjr60gS8hXSoGXjrjIAwVZb@iR(PtpzaNR8k4Ib^?+_3|iM29!v7?sPCfJTxLVi0l+ZF2|uBJxGXYk~Z(Mpet^5NtJv zsJiIgeQ87Hzb#8$Piqn)omKSurIsWvvO8 zx{=-)I)Y+kutTVhDpt1>MqidhIDmfqcN% zaljF{0fHmSsLk_CWVgbdrtLQ92*bBd$jz4{XdQWs*pn}2tDwffQDjINjDu#)0|Ulu zB3CuSN5}sDD$^#j8n||-M-;ki^lNC8?)Y^RTd&3x=B)Z+h3k@385~VK;#5wY;Q3z(8C*xYT}CMaO9OgLxE;Efczf$Y z{LzH|a8&=-?<|i~UP&T<&B(Cq1M0ZRg>Grlr&x@wi|E? zdBF1IZjAl=cle8R#*K>{7dy!!d=5cTi_8vqYtFqg2dpDq9aE#CRO%;h1&22t=_toX(?Z!Wc~k82@5#szP+XI^PUp+Ji`* zevWA5$pAhId8deQ2_Kyri;SHR7iXZuO%<@W`G3_w-$^g)Kifjl62j&1?imQNU|@%* z(aGXZB$|z(_aI?XUXMY@FJ*GP?^kV%($}EKuhC1Rr8O5QV+_JmVi2ibn!-LW|d zp6rqLFyOVeXs)Yl0L1bW3ys-`q8YIuNtHlwTzT2%D+$pGq;BeRE%EllCdP7_6#a6P zrt6jRwS4fzLcmDijZ`1^c!GwFQX4|+mW#`Jx%ez6_u4SFXf!mI&&bJTp1uQ z92N#XaLw1@Uu_n-b1!>@%#qdWS2(eVpf<&}ib5thmge`-oi{2=X8P8*LEzU0W?3NP zuNM3ZyAysvc16{W9ljjPAlbAcs(XokBK57x5?|?fj>K?s;dalrGsA1$f}b$meCE_6 zqlWxZ=ij%bI_Sx4H#U?Blqds1+W7KWEIxIZ->-Ll;K$8MH)*QZ-A4 zPt#@n)l*U@@v47nsf|TM!a0yPadbYYCv?rwOor~ObE+Vy{Z-sO9A4x`-`c?=$O*>| z?ypB_yXw7Nv{+IJ3^wEx6DfQ8c7wwCu+HCuMg;#In=4r!KePMM%MU1$MQwDlwMC|Mo@H0p4 zv!2^IKx;fKEr|3vzQZ?7tbssJvR-0du7}*A`&O;|9s{#M@FhhLgvDT9w=75CGM(W| zT1Hhqj>N%ogciF}$N(1Yr9N4&l2wOhV2VnNcoio}e@bU{?n(GhfLgZXh&eU=S1K3x}M_%AkV~EBGn7Ni*4M2dsRz z&*^V>C8oOlc2;&^X_1ez%-r$5lat}A>8XT|lRnKbHum}4+(6y7>}5HLe4ni+;g3CA zE{Ghn%YAvYZ|)~zKy$u->zmO|%B_J9_bdvENP_x(oeJQmkZQbnsQ4QSf!6!J zH;6i^;l$mY`?)7J;ZF&CR(lLF%+4`V5 z7{kWnZw?xKAjHq_g#5Gb_0TCH(!U-Y5MszpxPd~ko6D& zrf}Kd5_o{7GemQ2`#6N-j6T(Zcfu22fP6+|W^(AJ*4&;GF32<{&jLbtGbsDdWXT{@ z%sqGeMQZ4hKT1nj60#tzRBF+qb>Q^|24M+I<27kNxWj`>j&V)kfiBN=o=n-{BN9j9 zctyB)*|`r$?7d25+rY?MAnANh&#-RbP+;Z0`TPwZGOD}h1!#zZ-wJgqGJ?@6+%Lu52`rMKjw34iF;{ks~*8Db9GYb};Ig-c2QYv8D!@A|q5%qY(q zqS3j`;n7T;lj(5juc)7}TP(7fhhu3(TEI$X%S3Z#D1D6!{0W4&DuT!na(LH7S%AU- z)gU`_G9cYRC%D!WCZ<8Tt7oa}Zb>s4!f8r~iyJ~f>6L@Jx6RMS z>^zz^!@jK1wzwft@tEq(Z~J^Q2bC^x9yrUk<7zcJVm4Rd_%Be?b4cD$Rf#AcCBfHY zh`71mY%oxF!YRi$aE(GI)jvVbLizmEc!ru`Tgj5mkp6zRa~PV)h&IkLdtELMiOk() z+|*!smlujn-^=|*k(+%SsCxxZYpyZNKMr*ZMMkVm64f2fN-L$0k^CK%_g}GQeq+`N zSgJS$Y!huDw^K-e_c(1S7kL$Uw|3y5%3~+2I7)0(uW*2IkyI%_<_-7fXi8IUM@ka; zlmNHFjOvGolAV!^TmV5pzQ1i`*E{Gf|9ubGRz4DDm6r=2UqFYbRskqz!~9glb%83y zR>#Ib&*P4DRY-4s_$CwR=HDss8KyFM7wNQyJWog2&k|2@Q9>Cf_H)8+Q{uW0(TT1Z zybHk(uGG0q{wq>TUZyMb-dTqx{CRjxPr;b%xxpkQ%R4wb=OcG0guOnP}Sf4d^E4=}PRmKtkfpGLV{ETyq z8L;Q1+&FRZiemRaqxwYU3A0@y9=X9)2QfWZfq7gMbZw9yS$9|#Y8M`+*oE0CE0(dJd z^4NGNcXMtq8f_FNvz$lS~iYix~DW5I7gE(bYEXa z-z!Q{#3*mm4(Wrpk+Ll(-|)fie>$m7igdl9A)Y3e>?}Z8$39~+Fnrg=GC}b)-pF>A ziwwzFf5>Ox=bVwDD0No^Nh3iTw@I|3&QK-8Ct=8P1?H%fs^|Ks7AVbf-i`CRXJ^@# z6t}3-M0JCoF@9uvKOCZvZU7oGDtM~Za3oFY{n-BVsj_B_Z*rhW*LFisNzqC`C{X#J zQsvx01BNo*_D_vt>pZ_se0g?>(4EZ0jMe9z-(to-zc60}rv;A4Vt{Uae+L#tVp}vO zyIx&uEFZS_)Zfh{izHRP1fWf?+&(SjbD;L?@=j02bv)K=oZTFpZLY=7FWFX)bUp#) zDk7FM(_Le6Ej(DXl_)vb_7J_bS)%j2ciX~4UQrftppQ(3&F9BbX?ZGnqpee}vQ!k! zAQa`>Skazrv)mPAZ7D-xJ@DcU2PHf&^Q?q4X}%lKL$u}>X+1tATy3}5 zdmpxe09N|G<)Q%of6JGX>f|K=U<|7v{)W=s6;amCK@ekd3)xNXqGxIl4W3IQd7uW?J zrP_L@Y)#+E@laBPR#5gtPW~kKZ{pS~qYV%C%g^&Za3Mae&IVMVZ7~o36S||7xQko_ zBIOmZwpR<^$jQfa7m2mxWc|X8giAp5SiVCQl$d^Tg=2ulD_a$u zxUQ2jkNTu2<+7ew`_F&*oD34^bNYdmiH@-S3C^G(9qC#=!Mx~SnM`BoN(JE@@8D0q zm$zg@T|N=%)Tcyo5FYZe=Un%J%^Jt+OJ(6n;=BkR8LpIUJ{-KYzSOPQ zRD3gg3GD=*UYMV^5veR2qgxl;P`F(|qJ%EZH~`gM;G4zHpB;w+JXC=35E5d0#865c za&ZVKy$7H?!4?b7TE17Bv3UH5qUY?RcQ(+I^D+4kT zf@0jxLzw81>ys3>fP!#`b9L|D;i4>F+|fl-RKv0%CUh}MblJYUP8nlCtPKm~b7eU- zAgtU81p&ATOmi32`RTQE`qC|8=$p6Xl*4Zd+>W?y(m1oQY0U;bSv8JSUqW>d?G10h zZC2u%H+~JLI^QBG>f^oKXg6tV1#Fk=!Hr0b#~9gmOtt&z2+En)6>=} zqEC6>xitLmf;d=sv663_jicJf;0Xb$F_3o2mW`Z9_{0p=0D2WxZ3&+?CdjO6k|ze( zaF!mr!rtAZo~yjJOx)uNRb}^G^f}k1fm|5IAjFW#P@Zhg8*P4Y_%Zt_v(93@|LMPO zn4YA`u3~DekKJ^uiU}WW*v-bKF@P0V-+PP0&sZ6-UV^-bm7v04#X)G+T)+1<%o1_h z4OSvOBN6Q+3jdaiePko`AGLVhcVaqS~Ur{c5F8VQY~hl1Lg;Li{%%ChOIZ% zN=wILKD~t{5+*DbuGB- z!pCxvS*{YNOPo6aOn8a{i3DOac{OulW?YPBQ@Asmz5Bpj^X)dUaoi;A*nv~amBdX6 z$_mz#9F2L7P|Ku6Zs>nh0fIn~!a8_|T-s>mS(pN_8qv^_gn3<_eMsauP|1hvnRS@6 zf3%j=)QGqNX_t$l)txyLT}*%&me4mvjmzi(ulY$OxW z`Rl)?F?6lu%7iDEnJWeyAr?Tk7X_YM7?f5aj)7W$A|m zs70Db#~Wkjs)`V6VZB0eq{}& z>%A9cmor2(0DQUt2ISxd1ag4w`X6qF=o=w-Qm&8OxykB^Pl);R$6c##KqdNnC~AsO zG{dx=!2DOhC6YLF1hRUk<^*6bymQD{tDC>NR+VGjF$TQWDKX-(O@AsK;%RI)t?TVJ ziVa(StUqY`>mUTzyAC~PSXR%x9gy}^u2C$!&c3)0u&I9P+56ka9AY-WA8P4dYO=WK zC{|r#`m?Q4bJxpx3U$Q-u6ApO(q+Y}2Nmxb^* zF0dC2Y7tqKLM7TYWN=P}6dPV?cnbEX-Uk?AgwtxgvzH~x4|6u(nFft94`a#{`jfC$ zrRHgnki3dApSIJCslelaOy%*TK_-TF6o_Q#^8;J@UdIp0CEvGo5n_jntHsc=49h;p-g4qLe45T>h zc^o2n@WWiJq1=?wiO;KO3Rh4BF7Vn(Jy|S#=9FMOOHr=hv4qm7Xhl*_rFn`2j*X~J z7Y#zdDH4E1F+p)T13#{Z&hxB}g@nJe=k@+`XX0hqoJDC%S<|&(KcD*b2=|B@mc^qO zmKdlcziW2HPMEz!=ZV|gKs2w={0%M|#r1B2Zl~Gkv3_>?n;DX6_-ec2zSRXgf0>wH z9}Q0IZ?ij|Xu7IUOeYLgg*e-)(ZZUwZ)*odQy3UUcp~tv7A~?%x6^$iGdQqrN%0PU z-MrKMbaO%G&cZRj<8)H5*Xu~P&t6co7EPz+BC!-WcW$?$kk|oX2)-8$X~E$b1;ghZ4hQU~USS9w zHq-%}!0}F>oimO(saG882j-^i&2rQ$fkCzh+jfY66#1tBf_(U;Xpr*5_Ez_M!*kZ(M5bVUNg7IfaPI@bfK)9GA!F&xqDiB2Oh zl*xfF=;Ys2vk(q}380K-bu|eq3k3Q=+(8Y5{ zh6WzAqER(rnfg4z_U(G%Zy`Nqn|Xk4n9qqF`d6X+tbowsfqTw7oF#Sy7YKo9I?X?r z?yZQYd8ZAxAo|CZ*cpc(V&~L5f}7g%?Kb?79VR856lDzQsn)noKk|F?Hj&KYeCB04 z6;IQE0e2YW+%{wr(f}-pPb7}Zby5!257*g%@urmLFJ<^)VE=Y#Ox>C!V0 zIU(w9krS57=rI;L9{?}Nno`YS-Dv<@w?Jf>05vX2=XFwx^ukuX>p4rCJ|YVd?H%92 z9@L4);zw+=)` zu!$zwDDbaM*+R)s;BF?v9~OTIdnxiYnM!2rax})P+K%(Gr#b~if7&N^1KqwX&YwA(0CkdX&*Fb=7=9qyrrBgGKt>_M=t6 zsVCYvBU!^upWTbHH^*wxq@71WmvimsdgbfT_s5FLO3)w;@K1{ZvNldg%B~_#+$v1u zrk5im@s&;35fVd**}u)eCz@?JwS&<*iO|-K@;{?>>t(EF7pCrz2HLFbaC(8#48Dk- zq!-T;@8PMK+8n-1?@dl)5UCTb^?+>VN9}+8#65CU-o`D|jutKT#2t=y>XQl}c(t1- zg+0f<1hj~;4MNF!|k4Df>%G zsphd4+!RL<@m=+;r7GO$%8^Xo$`0yuyp>?m7-g6X-~uOS-N(UT`zSGVSd#FNA=H)o z#*Ln)8JllI^i?|)Dvku4+H2t+*LP%rDM?@fXX>O6<%8T5@jx7av(cmQYSX` z+~qTvIf=X#BP2+zv$zp?-Xn3XUB>^1%6f5cUGT_KZeuJ8%Ren0xJ&Xm;aG6*OM;h3 zDJSc}c6ovNne@SSg@@hd52s?_oW5vxa7GqHWBg@VLEnigR+fJxN6Z`PeCAR_`jK@s z{Y3Zs;R@woY+3p$(azmSSvR)d4L=cKP_Qg|aG?_Pq7jK=D@wMOWUmk&N%jDGuu+QQ zoXXA<{ka98DIf?cg@8~dBv-V83{5g)@{1By27i<(MifYG@8SRDC9hG<9Vi;XQEdN3 z1}G_5j%V+lJCIICX0OKmX9arGAE5-DLoa@|I!>i;m84ituk6I>a)q3q$c)-D9Cc){ zR=H2ug8CZp(4&)?^8gO34K1Q+oxXSV0D<*%CwvBkX4}hWue%Ggpg0f}Yg81$1zFi2VfH{Ma)` zTaGYt0os@Gu1VyR4Jh>teM>SFv0KEL2!Ul*dAy0wSt#UbD^{W_-^Qm(vip+>_?DxJ z%|0#Jp8KQJU&y+h!*nfpS*ulZ3&e#`Imx75$Fb!Lit=P%r>+GZ$1$xUx@@+7`kj4z zKmllmmB&c~o4-0>H`%OUYGYMFn5?RBYLjy_RoseI$_t z9tipY?y(;_o?<)Rr4?+JQthN`9gKAnNsz(^kZ~QtL6M{k8)M{J;4*LXcCs|<(kQU*7kd+ ztpt^l_>kLfBpz9|D(%8T@$)I7$f>wgZa4sNbKW->A#@FbC(irQrq3>50CSnHW-RPR z#+&&r!iMW7b#EPc48h$MKhJQ!Um;=JHKtp1fW$<=eNNPcWUVrl;RThZMczVH36ajiMf; zp>%_pP6*9HwXshaqiPH?#Vd7SL?5+#LTvm?i6%E0$Zy_5sLx6ylplnJmx+7P(WQsQ zT=xDR=!)?J*GC_}%(|;@|ECv^J1C?JE3_>{)wKHG=hX>C0$qfF%!+9;b(QCrQ~2H1$Iq!wF#;1bHPJ$wia7o0bjiq0T;IhxPFY@ zaHHLLax@Q+n$okZTFWU9ENyfOBN-;w4qkMsI5W?X{?-9X!2=Y}(>=Li;9K@7cOw(C zX-Yu1s{funE8)A3c~eL5>HT;S}haz>PsQ)ljw{IZ-+Gmwit~JJR#jgwBPP%rC#!S zt9~(M)5Mk9xjF!?FEPi=4y;Iwx5!}mr16n!u(#LWB%)2^9Z)mot> z{=*J3MPKa~HG|ueYK2^PqG-_785a4a&}(i}C5z-{uZ|jt!0;5GD$*9VXK8E(A}Zg= zFDc=I6mF#qvNuhzz-QyK-gM7|H}QT3`s$z`LnSIYW5`Mt{5$Ug4O0S8T`gU9h6VBa z=mxvZ=IC`)+MdN&b@fL;l}C0zjrOBdFlh+SIYm4mUeEvELKZ*TuL1eSeI+w$Yksu> zkcV^E=k@d%lW0zL09padIVm&p4kO$DvbGQCf`ell?}IYc$PnV*QX8s0$oCPPuwM8% z2?R?onul|^UiePQVMnk~>?tp1J3FYsE5=CfO`piV54re) zV$EjcpRyf7{Y6l=<@IxRyOktC z+0CkCr0J&5Ip%*#Dm^u53K?5L)*i!D11HkH`R%k7q$A2!6y@j9`)6uER|~ zn;+~$5cy~$dz)rcMSui_Fc|mHty^vh7JXTvKJvA=dMdZrAE_PoMYC}bfm}RCcT7?s zsI0Pg?C=nLKg}>C1qvBCL;WUdVKIpANk?8w^$1NJu=wigYcww0`@&Oh#b9OIW`0x1 z#|~wI2Ca?QCGN_x#tJTh4_q&<_@#-oirWA?--x1(D3DwC(D%!u@x$X!0|RA}$q&_F z4wKX$E~tN&bxtAQzY>hItG~Xiiocw`1HiE2rIwReURrJr5K57M!x`UsJ4;UX-|29o zs{fImYkw^1ppBDYBo^nN;LHrF$Wqe~{=1P#JWNFku_snEwF7o^HkfJju*yChb#;=Y z7)(Zp%5!T%$kY+UAby-XcM1Bz2L|gmd88-xj`IX0PSb7_?De8d!5R=`t)_R;aEA*a zo?&s%YFO|R;VAg2pU~=SA0w8tv5!uq?RN}WDj^Sg`-_~HY?FZReJ!W3jF@75xm;fW z2V*F?V$Q=jQ<%kUc+*xpkp!#p=xgyFD*V!KHwW(@W~fsOa$jS|TOw=<3=qB(ti^qj2u!I5Hp}82O*Gla(30d4UP~swm zXXnll35xfQ3zof-jpq7&p#A;w2||ELwx`~MA~{U+jr12?hWec^`LgK= zTwnD53!?FKblF*0YYB=aj5w(B{4o{-oS`Mzt$~t?sfPzWK<28)rO%xJ&VV#*^$`Az z>CACjcAPh@T{B~^Lou%ZA^!XRUk39`OaAF8uCW-qI$=|{SOMZAfc0~z*-l!yM!v<* z(+q>eNj}LxtpeQoPPr!3D99P=Cqzu*QX}h1?3w<}%gLGqkTG!k-IxbA+-jxuf&f34 zs3`&|4GQEFRx#Bstkkc<6wbhN9mSuF!IZv!|65!l5I7i(bemSladQA-9i1;?rY+E( zCqCm8=RJ7qQNNi=J9{#_Q>?`kWs>krI}eAQ%Z)1wzP#p-FZ7;he{OvPMjc>q-=DJO z+FI?c-)(<#s}-8O_it6AW$(xB7J*buQwZ&g$EPvLv8|oKHv~`wp<+Cl9uVXMgiZW^ zk3P?;sR}PV_P3ay{)(cc=8Zk*c710bxB3s~vRffPXZ1D_3`q@fw2x~V&k!&kE(6h- z+$xd{MoVDTsOKO&_3DkvjJ#6;jJ?kD13G3$hT#+eLlP1l>zI7)k~d;tDLN>@bbmxr zn+5z5BWK|}>UGJ;p>-9o)Ac{~g4mT`cZri`yTtv*HneAwEjK@;B3Bl|_q8=bCum_- zcCE3geR;5?Ww*#hFhGmy%3kh5jz0WYwmT4}GyK~a#pCgO8qpLyAiKP~v-G}$^n({B zlJCe9W%`C|N?L`!TUy$i8pJ=&dJ?>D6^8jMU9nbP#b=xbI$cRN{%UTV%Tb{kDu|~E2p2B&2UH@({HQ33bR*9bscc$%0h=MZ3HgWpA z==0cWk`HU4`rENi$IMRDYT>9`s>4-S51#{g&@xrkb_|!I_J>F4YTUqE-sJZ?y_`kf z#f~*@KDz&joe0wk`u-`}TwiyT@G2Gi*|_nFPi?9F5il$9e*<}m5%9r90F+8*B+(sC zWDzV}Q$r3qh<6>T`=fV!Y%y zT^jy7gGgp+u{= zfmFceNh8;{$!o0W@C-eAnE0s`8E7T6cnQ8M-tWHrMd7jld;I%2(o%ju+?DpMP6 z7k2jwN4JHn)}%EEt)uoeBzXtFZ~6S&RvQGH1n6SnQJJ9l2cI$6!)ozS|D*Z1l(Bbs za9Fer{o}scz6~KJU)t?njAcP9x`F1AMr@5aF+g zxv}-*v&GU`JBJ0yaT#H1G>r~Viqu2o>hX?QBUON;M+CQVe87B9ezJ)dz!sZ0K~0_b zrN4pp?%1)Xj`dg`SmSTKlyQDIjT+$USAbuqC^a2F_z6Nxj$503m} zb5TLar=-?X2B6WY0rH&8ER=J7V=Y+=)lX2E6@|zd`qTcBJq0VVYaY3!H|jp#TG8G= z{N_gCN2AyX?4q7k!A0ld;$VjDVeu8x)zvVTs!Oe4g#KsWYuv}<`D?E)q;MFlCF>jd23AmcxBPZ@O58AaAE}FO zu8@Bmv`Vq~2smdyG^DVCyU6_nC)qZtD&#&S<~Y`f`?SqTX?j)=qzipja?K_nGmkRr z9!&G;h|`(WOvleca}BEbid>hcUR8qrPXZ$8_(`)Xr8(??en>=bXrB7-?PXQKvc{sP zA|hjV+k4O`{6qm!o3LJ5j53K|GRo=WvVLBS(D5l;EBbwvuq??LLK4sS(f#F85u62U zXWWVZrNV|+&!ZW4<42Z0&4P#mT!)Z`izcg;n0t4?{ELVi6;CTeD8*q_#=e6NM@+%kn&>yOg2{5D zbc!w(tiOcOgi#1(K?{K)0@0&`$0*3r*{OC)7&(G7R?0xQNVURP865g3o|6IwhjAH4 z+jT&J!#N!p~Pm4831)fsVgIgmyI|p0ij20gKy~e_#MBt&{5p?ubJElO&X~ac)|lELAulYc(_){rprC zXw4+J0V&uO&i*G+JA&bX^Tmro&CU6ce_LsK@A6fr7mz(v_8cbrhb;DNC3hl_mEjuYl6qumh9MFhJaC1KE(D)gA*k2EZLpE zc>3qTShhRUDlOhe+3#=JAYy>95#;d^&ZI!l77F?W82u7pT)v!k38Wz3Hw_l$@e(;) zKic2s9F~6w@|p!@&aA}t~7BP`+u`ObEUsFum z>LN$sC+ww8ASu3>)i4;r@Gn{GFg;Bo;?$k1n5Q@67@!Kn8~`Cu!;9zsn2fV%gqwC{ zJHB1~4CcuqD&eyz>EKEF+uu{uq3u}FQ3&W5ahYt>Lq-RvfVHxC1)^^0$SuN6=<(0f zN0W#m^reH&(6c9T&e^r9>w0u^`EK65vs#vxCk__uIOZ`gbi$I|*7i5&Ond`G?2S6B zi8R~D2A(gDags7)w|*0sb=n97WT=Z;T!2pjvNZ~djW80Kl}6VH*khO zqkkZq{}!7I#Gv91MmuBXY2_%a%x!Nj67>e5L3ul@t#JYlkYHMq@M52P?bGnIY=jbK za?C_rs>?VzwATDn4D+&~m_5vycTym}akZ~3 z7&fW@R)O$Sw&ph#(-yfHhLk|=-KmqHNzAksclOAOuuCjJg2$vfq~-30vON-?95YM|isk^;K)w#IH!5+=RB{JQlA=HA=k0w_V-;`sZLilRnQJQRQ6us&XgqlGCkdK? zs2yBYg~G4gVmPnWc?&*!HJrm57wM}_qH*?0rO;k~D>*aK`r+P{Pd`SK@KI6>4{-*ohga1a^1kQ?h)h)#&gp<{FmO2pp}X?I z!Q_>0NPxLemdY{+$gpsO5fU0A;o~j zH^uSJ5x@!&h!u8PfYGNZZ}1Zi%3-Vp`~I4NA$bjy{( zl{p76`QlO^S=JQ;c24_pi9uo)!3vE~?u8tgkipqx=N#*e_&YyGcpVA2_zmAy*mui2 zLqXRhccbM#vKWH@+Wn#Lj{=6>2N^QB$8jBp+8x#I+4@mtzY-D%f6>5`vx^H$#&WHC z)M?HEAM_q@)0aGtxTtlBrV9Mgd^`mQh_l95HDjtu3s%rD&9M~p$f8J-;Jv*0u~gZ8xUEUcX(f}H z1jfdHk|30GL8O zeFv6aYnYfq&%2H{u_n)7pN-1qIln39_*Hllk)Fds>$+V_ZdgZ^Gh;Ab^^x+-@%N9$ zf!Y`5Gey~=&kQ(^3{Q~`bXaDHfNq|Ttt3A$$I&q1gQVg(kZckq%y(S1>Ia_}5An38 zfvSi_9`k@ctup>ICYjI~HU@yn_l#wlQ)k4!EKP0%qS`jfM>N@g%nqlxHDM&v(J5kB z2*%o|yXwsgPve3T6-r1da;#h5_Uiwc_$$bx1>nF@=jOh7J^5sAOK5``bbvzabl4F! zp8ThIWS=nUTCy=ql4ODdZz;zcGJi&IF*mu^?5AbP{$Ac%Wd0g`We8Q35a8vz6o#WP zh;SWX##Hp$w&*#NAVVk4YAkKL@iMSKs%CRO5Zgu;C{xFiy8NB0qmwb3^I>#f z@>w+Cs$N~Wo@bARoU$*13f#0)q9iWcuiX>08#}9=m71QBI$^6EU^z1;u6TUaRqzmN zC}F}3uFRG_u<`6WoT#2h4S)`N+--sGe%MFcev3wxk}bT6OdS|#8YpE73`0w(goSqw1Y`fni!c0T=R{dV7&?KX3bx66!k!nwmY~a)>*LpP|6I9(7KWqL!-! zyeVh1GFHGCAEX~L9^<;d z<^3{TQ}d;r1tCPTwiRJIi`Do1gpHbozHeAh*H{%CWYy3;`3V}$BNFNk@&FHK)x(H{ zL=bww>#I#R&(6eNMRK@s_q2;5S~qj(M)#~fR2(0)-%vPfSW($}y_A$rEH(E&{HVgi z+TP-jw91?B$75kTRE(pS+c+p3YZGvWOuFrF;GR=+W4c~r=*bQ33Lq1U7P5pII$Eed z^3`~J)SI!5%N^8CoJ-I@sDBTSe~^0W5X7PW#-Mu_XsnzNu;X zE4K_ujD!~48V=I58iu(#OVK1n5q5+Q^%iv(LlT$PGuwy#9ao(B(-eWbFo927p^mWr zs@Ju9KsSp#ilg`CG8$WOW*qOh=0&>YQ3psj=i<)Pl1?QD;(AQ5N@G z2Gp{U`wDb4FR@S~53HPCYTLO6F?DHuxQRo5+lvQQYKgIQP)3V~ke9s_9x>ql;S6v6D3P_?@CLAJju%Xf8npC~>$S?l zAHiT+AJW)(!q~}v?F+7ITSe?OXTq@#eqD`_4tW2kCFqCS@j%ow@}h@T(=VguOSNGk zw@$I#eX@!moc1U4nskJSRrdnD+(C>}ge+Ax4g~f8+_C_}RlmT;hT>2>j1Y|T@UYlr znxL6UeGlrsYbmi-3~}SV&ycSrL>2VpmDCe^exQkxr-s0~c7KujZ;C*qi*zcesc-CE z);BrQRL*^jByD+XJ48v7v%_)9xFzau(#gfeBNW{Z(&Y7VL>4x*gUo+OVJHP#N#Pv5 z=l6*eI-w?+em*1P0MJpXKS7G}&KHim&Hu`P>BiI=d>o4_?lBGL3Vk|)pJvqb<5;2$ z33LH~SCTN#MIiw}G}(mOil4^pm$OX}paFmZflf~8Xe}l$mgI6~_Zz@xnvvda_Qpil z^^~H32h38=E)Tn6&vMM@h?ETbidkouZ>74y_0@1@@3Tfk&Gu`=qwrPbEf_4EOn^AN znE`0OY3q%iWMfJaF!zBS$Z(9Cwimc^#S-B+r@6Yq?m0XTjzbI|yvuvafg>jX!56t< z+I@jSWJTt*{M{Nwz-Up zJ~1e12cC{$)L)K!Z^J>Z({Bqdk?RjUQ|o97}u>wBqA%1O=MgNIwa?}9|kPAWm7CVG$ zsK{$sv|L+`#98Z^{SA4ZWnk3&vB*1}lzuIT<>(>%eg!Ri=~%-6YCJ_)9TFkP8hxo3 ze@(m})LGWDNqX<706}Bm-8!3+jVZ2FL31;@T9itQ$fg%JgFYbXQqDr@^ad8&`-WG3 zif9-n6YZ3(1vZn@VKM4V#wipEmB$Fg>Z+@88t?kWGj^+Pv9|rTdlcvUJMjbmDKD?X zZC>VR9g_g1l40s3=v{eoA&>d;?Hbz2g;GW`Qm)B?!AAa3)pxw?iRlObX~#@uQg<DT$$Z2#hEpP}Yl(?31^B5~L$mIE7YSELQQ(#1SnUQP{+suo1G0YtqHzhL z_NZJyXL-s5Lp2mTS3<$U{W`A2MtO*8&LY~e8S;=$$+m6{9=lE_@g}vYO_G-T$hpv- zdl@FD-EBCGIcO)TRq)QCw_ww9-W#$`!`4TZ7qM5pU|3~^{-mJiw_wbk@Q3}e^lenk zZgXt20>T2lTb$uy6ElQs;hNx}sR0n-I(Ik^^);x-_nGiFQKEM-A4KtBflUZ9!@ocE z1ewTKkp{JyheiHkqP;zUn>?I0ccuzQE{l7|q}P3|-Uyyq`Q4{nT6<75Gt|m6tb;JL2s_J`r)Kt-|VbKtz0V{T48*(;R60eQ0wzU<$;r zudpWvyx=3AdJFBHq{(hX*70w{p)C7C<`nX(-mb%H30BJ}s`?{+C_ zPSmmt4R$Vd;mzG4i?lnvRheFh*b6(KtZipsrRRc#Y>`51qU2O^uwP>1@yJV_HWsk;D%a(#ovmC||2{ zhkc7n@4tqRng?z%xL+ivhcg{s;Cy>Ca4>hU*nR2(aWVIi_;?><9zhjBXn1lY5qdQ= zA@a{7cVr{$@)m)rbhf$yu|mR{8;I5e=EqqP^pO5TpwuB@Bu>q!$wVmQNoN4E#0XTR zTAZ%`{TWz665f_7JF{U@uRmuO-|El3Yyg-dV{*IYHFv) zYb8in8r18ZyT16Tbuo(Ocwrfw1QLum1qn^(IBwS(4*O>~BL#O*h09z?k8$D;gu$kJ zkIyq9!Z%i4^9I;?I?4%5xDeCsNNlK9fC1~|v&Uk$dLM2Yfg($i35n3}s+!t8_*}E} z!EiC1A~Bx5RH1|aA%H1t5oo05)=lR9L(D=C->vn##D?@!8RLak1CWxOYbt2_KlX8` zfWoe6wOoipgk$QgtAIp%;0an|@uPtns|u>J4b&L3VRL8aj21Rgc-fd7H>*Yb3ey$Xo#WQ%MHbGqB>kYVFIAxO538eDhI!*hwnkAoUr zT@)$N2NPygkS$=ixbrPQ1R@idCqr`b;NP;t{MI3mPI!d@NjB@`V8wjjUhXcP_M;um8 zIeAq2q}O*Uc;~)wDqJ?X#qNF@eNG*nqV-4{~)SdZIhMCrk2hvE9vk{sRdS){{>zys;hSe@)^p{% zV+BLgYz+RY4t(V$R;qG)1gC2zyjwp6xU&vLs7S_`Ii=tohLKVAx_wWMY4;%@>Bq;s zDrlXRLccQu1pA_11rgIWOB4u6f4q&1aHW^GwP?oOE!gv^sN6)z$uA*~_q??NeIRh6 zYUw^U(F;*@|)Q3%nuOTDi1V+T>)_q2uebs}aPs%;`-u;HN16LCS$hJ%9n`x%(0 zV5()grMND9A4wA}nVZUYVCQqASaw=G%P9an>FOWw40chYN_4c}l+AQ1jc8I7E}TM< zb-u?P+r&fqu$Oel_wa=GScCs^Camh-3slzKx1 z8i5TYF>$J=D|P!awOp2&E!|urF!nlWqI3B;CO9Sqo)G{qoJoQ2t;??OPv6Rsu~}ua zCSz5Do>r7A<{hz{CZJnVUS^TrqH+NOIbBg0gIRbpLW+3II~WuyZT~jYQp`ee9Jm#{ zDvBC7wMeI?9>%+36go5gD&xs~k@BPB7xW^?w0}KV8;qW5S%hSK!GPbs{OIKAlhu3T zF=)k0bpAd}M4kQ3P8fwA;l>Vt$ot2pSQlXw{ID-5%>Q*>+&U)OOoWE4hKXe-dQWqj ze9yn6xBLXX;!_& z8v`OEYxoC1I0KPq6RlWYn7gl^LkVf;-1{qd)wCX564`EVu_VREg_akO{tzCVy)=KE zIfDUVEmpddS-S3)=HFeG!H^_+RM}NMPs%JTZu-9AGGD1LXMsAGw-k6lagQTA3C+$) zZ(}l(rE36@c~KQO#D1wknYf=S4Awa;X8b3oI~@IZF%U@PaB}YQn*PZ35mfZ@9)3S2 zcIv00@r6)RJ|u{{?xD@&Sd0iy*|rVYas-;v>r0fs=9X;|7u7l@T3t}uKPW2)S%UYJ zi3^Rr1;cd4U>E%&F+u|es&aLzfTOo=?PQjLeToddvVf?ceqaE1q=UFOLD(l1Xs-{Z z24xpzB2V6VfF`f!?SsP6v|H*wNm;U1)%O5xI-?1niJDfsTwmlL zdcnA6;IcgfAn>>Eipc4JGUq)p?KVkcYE8k|`bAjOZs$G!GIX8QM_%Lhq?&HFd0?Ky zfmC=>ft6G=&;)U9gbI-)R-{r@Tzh;#BFu}TGIAYWYt4n6y>pZ;L9;Ko+qP}nwolu( zZR@n%r)}G|ZJc(Wwr#tozjyDQ_tyM1Gr3pnjEc&vh+kz@?X@c-Blt`OX2=Moqq{Og zitML2w~=0A+-Fj>9~SR6Z2HYfZ=)^JU|YgI(G^-;#l&{vE95#coVXzk)UuU4^jgE$ zSC4#QSpTdQl?Ms-O1ttJLgh?%E=M;yk9barYSn#tB%3YXLZ6SCtxiJw>4!LH4ac^B$6 zmWGIiS45<9$cT5JeA6awg^8QwiDdNrsKZ5yfI~%{6srM{tdJ$R{=x&#W5(5 zWvtaMV2rE&Y6CawE3(9QW{Dp657Q%J4m|< z!ka&3+4jX7_sPnNJ|;X^QPBcrI7ZFVvY3g7{hPlU^eQMQipA zJX%GUoy&+ot4}+}c=84A&lP)0KrtEt_4a0PZ*KW-s=BD|oy62_ONZv@JP+*=Z4yb> zk9%5_7Lh=v?e`PF=U>#trJ3tn)ga!jf(z&aPjnO48?ba{#+_kqFqnu*kERVusEg^Q zg&(C@t;g#iZQnvLor*}DreBW@P0Y<>`AdZx@VInD>tSp|_Hu!*!|XiT)=2$8 zIz0Hp@v`!mv^$y1`T)3ZEzcHy&Qxr5B854dWul=O9V@v=I7epc+Cw7?kjqUix-vrl zDGzYF8OCgpdG&Q;vK8(J3mx*XJdI?ru@Upd--8b~ZZHps6`%4o_HDwCuO!}jsCk3G z$yHoef0U-m2AjMkiUkROd5%?0Z;17C)W7zl$yV&_g+hfBhv*h6_=P)OjCg1~X`nF?`D0bT5iMjT>d$#}n1v(P$`(vzrE z(y4%_Ik4@(&ZYvjCs6aEAZd-D)vPARiaY*HeRt;o&-;9_X0fb!oUDe66POb+oP|eg z8IQ5I;s0vXak{)*N?AA(X(~;=@ya{`A;d%WFen5G4FqLnY zue&b$&J=#0X$)qq5>?zi@1AA5sEf&c&5xTWQ*~YKBztgZE}csy(tss1C_>WUY(s80 zMh5e7FGN$a)F+%3U@>likiCi4tA~SxiKiLW@kSf8)EJl&OpAY&d&*9r6X(C8(-~*L znLI7^7jIU2HI~R@uy!7Zy5aZIPzNdO(f1J@vncVAy6Y|QzjNff(&hjnFdUI_TATe? zxP5zF>`5aW%Yk}d;`8XX+761nIz+oge*o_H<2tkfroR}Q6A6gYPOKHPpK*N6J=5gq zK1-#z%bD(U2v*m5So?zLe zAfK~OFvX?`lI!%jx^MZ{{Wo-mFT9C^8m%U zLN}!YeoBqTz@xy)td|E?-Y7>vl6GgU#hb#`9-Z_vt&v{`c~}i;$PeZ{Bh?LZd?XLr z?mrTTlGPy37&~rK!BAoeV-E!*1byv0KjSmQDIqHxBwif#JNRihSEKr_N78rdB2WkZ zDMKF-)+JrVylnD&7c23q2x0vGd$J>nhHmO^bEQAO8&GII1=rE^C}Jw4D?+F26n zz`Iy|4t};C&tv`97cRb%Sqf45-X7C}2XlqkMY=shziYPz*!g8Z_;BQpF#LcEK%`_AdFsWpYeA1~D2;6%6PkO9kh!dfhn`mMRU zkwip&f1x7)&bjN?!6RD=`Cg^9hTinl+hAiS>V$@VXHTuaJgiflB?VsccLFlV`IRHI z#oyg$hpcx?8zWonCU`Z=vM7>vzXN+Ha&n^JwXnF;f7OK759EBD>&2JPo|O>hnDW%g zM>nwOIiI*+S-_$d|NM0*eE{Q)$?n#=!WUZ1eA0^Soc}~<*@cMh{xSaUjtuG=G$Y%Xem5=2Ia6LI zUQB+`slfhoTz1zT>x>Z(6ol7l7K+`4pD*ls9)2mmL*;mK><*z%m~Muz^K0w^LofSP z>NDjEeK0!W5%dpn&cjmH$qJDCtcM#!F8W`l5|y8)5E9p|K}VYXwx{JMLX*(T*BpJ< zklXqlo`#!`-o2eMej4$giS@0Sc8BUDFs)SSBg4yI|8&)-fq$QFIjpI^ZbI{u16r~^ z1h^3A8l*FgM2;+DuU1YZfd|;k2SW;=VH{k=g4D*`tHS;&8lsRLED`}aIMKGxGFP|_ zq6^#jVXNQwD^I^c?S9PzJ#)^KTw?ia_>ofiGm_v07GHw9Yp~#QSN2d@ z(MAwaN9EuwyZXM!buO$fx~nU9xbvo%kqhHq@EO)WSFZSbX{Q4(;KSJ=jl|!PMio=J zpS_2inPkueEB-g@A>$1mZi)d;p4=y8fpKJ?wzDbNIqeK$8HSV=nmY}*=`Uw>t3ZYW z)Gw*gd19!^m&(gYJk<>LWV0(!UzpyMFpQCna*)H}u}Cu5^~_PCqUoa;kjP0YTy8#t z9daN%?C(#!=m-|U8VqCJS)1{BJNpF194(F;nyELba}?OzsD_s<`me@S)sL^qjpEd4&0(IWnutrBPS-;13tVMY=&D5dg)~@%!q$3bdeF%20le^uA z>NwV+?+_01ic0~%64zz_sXsL7v0=dMT}dSmc}MOLCN12iIw1wm`bgfnQ>t-duboHU z&DjuWgea-zW{a0>3xWz#l&t32MsjD>K>asJF% z^eZw9LK%(gX|7u|R^ymGk6wxV%`7q)u2W2Ypm$KbaECN4+~A1G-ZCDw%d#*uedhFy zKkqte`U4W7A^yO))>e&v3q?*>N`dcer$v&pMIF0V*Ouuu=baq?5^aCQ0- zE46HXo@(?5RAnU`NH_7hI%?$)W{p+#KrB!swJI2b+@l@U;)0hSZzhSLl6O*l8+)kL zb|>hq-l+|hYNtZB?3zHU85{^9j-AXp2H@o`-J*^<61j|JwM&_+m)zAg`9bg?(Z0W% z!GUf99C!^I=kETv>u|ewS{0tUdo=76)nFXB0VLx zv6A}O!yf89Rpb?sh7-;)-S}10N#g?Q$@O-9K~M#T)J;`Ti4o6niSa`i{v&#BM0JFC z@P2jw(JfW4B-vrcAKw?cN{}(|)A=xLSP7MyR=a#~;N5badn#|nAr9TJA!BWLPA_uo zq^62UejY8>js9m~8hZeXlu~)yBjoj4cFciFYx02h(Efq_#!7Fw;x?BQ-FDzxVWC`WPxyVf7#>Vwwsrx@T)p__+fkMx&`Qtnk=|f zxt@E|7w9V=>8V4}QCI22h(V@b6w0h_^anGrn(U*Qk6aX!73by$REg_A*-qG^-#r>ye&@B_1<3+l7aX8(nktByLA`+M#ElYJy@N*l+URbn|PLuweiK4IKcO#eCZd4aMUh%gUxo5&8*9}HY zeb6*)g`cpN9Lm~%H{UBvo+*Q=ez!^Ibz3gP>lOw@vbR6NwG_!uK=cnW1kjFXJs(IF zk%&$)od?r;+*-agPBI8i(Z<84un?*#)tMFhOk2T=dlLQxDEs0CQyyq#Rn6m{^yr1s6eNr5NT%%tHSk* zgsm(-%h$N7R*%XnTvBU}cn@&ksbHX(5^A~SHlm&fZf$|(Rtz}Mdr4*_SsmbDT9PoP z8x4@ZOvS1nM9YA+P<+?WPS$d1yYPj}h8!iggqe})zIT!H#i`}Up-3cQQ`bJ-)gx^h z9zF@6O5u6irTR*)ZTaG1w!i5Kzru9Q_XYK;_hZ#P>zrEn1$R)5hYz8j-GeP?bdaiE za8O!q`5PHkgqYzIsQPfB*;pgS|Oq&FRqQ^pBWLAw|z z?#1Gd26`190EJ`WKUMm)mTYjLP+87kQzTAifspKK)I8#2>k5rXb8PF6h|@Bh^fS`8|F)P1&W%32^0 zJ5K*@G-qD7WmM;;KjYSP--Y63s5m()04SyrjcA^0WOBP6o^F-nbV2Hkxv^&BIA|c$ z*cdf|1EyK0gj$yc2voP_&@6J+U249$(q~-U)-bzOHUU%fGjgxEV8DuK&SP&aDcD-To=ncWNQ|-U zCQ=q_5%{hoGbTOm98qMLJv`KS=hSz}e%zj%6A8)t1h@n7iG0Vnf_Ed#ld{zO5@mymimO}|+7*qeUMeNxrU9hF74(YT`mDzt5f>gMV57W$Z z6;xN9jPG$nIJL1c43V!h#9~eKOt|X4zd_Ks8|909*1~I4JJ1>VT1{PipYu@}6A{CJ zA@neG$`Y2}i#hD+IY(ytSQQ?qg#Ky5I>mRVsU;*t17`pO=G7k{VoavKT4Z;fNU~*~ z(ISn%E3<)sjQxi{(ndPzR5-p~jwn(R&T03pQ%^=IpE_mIf#clze-eTi?^ z+hM!cd#<&Ykzb$S1ez>R^bKk(B%WMK@c4J&ILp`zu3QC?87m*7mMl^}5&1E=N*5CcN#0X&6}m zMe22>PkMRZN!Ih$WpwthZnLX8t2ZHnfShLf9HNWp3HgTb=y6#`1uEkN=ewSpyy0-> zUlDkaD2V)AQ~;kK1vlCji~H3t+A71ItE6ywSb`8n;N#)ze4Dj1W>g2!zH}el*gLE~ z{3Iyt^04YWL4qo(#x;As@0}|yZ8jw(@gpjXs_oiSFsg+9f=R3U@2z7;xGF?o5biSEj`y{a#T!|}7WO3TIS z`SK0kJ2L=Ll0#OM^3?RL_$)7acs;HxHxC7Hw>#49J(83ap^Z!`r-}L@SYK)^>qum) z4s|pnw{zyRE6m8>sWd~;6ubPNh~WZD*^yukaFBKWF+{Sr>Ibz#?F|l7J6U)iGGCgH zLpou4WRqN_zfH}uf08U1hVt}^ilX7Z`Wkl-uyaFI*sB{?>obxn z1*Y-UTTqZv5GXx_kNQa6R8*|TPhMOg@y2y=Iv22o(PZs zX1L1k>1uCVSRH0c()k*cwUnG7mD*f7q7hm}sr4S?gS<#uGGyQ zrb`;PFBp0ESYQ|-s@yXxv}WvQNgUA%x-C~+wyu+$ac37vj201XaCLs0gs2c z<=@I{Iba1T0pXq1$Ra1^y5>Ywux*R%^b2!zdWI0~=a1b5(z^pkd2k$Gb=UcqdjHlA zIcSaEim3Cnc932J&O7XN^m&zO_k3FDlRN9jFa&568*-Hz*Ge}x7#{k;-?04)FSHK= zLeqAn8RIpeCwjX3`{G@K2`jWmoOl1SjV7ykB$!O2IgcwqN^A07Bz3=s^t_XOYD+Ft z{9gs_qDJ~Fb+aXDU`xu8Y?d5Wn*fW>9^K0fmG3@9!01SAe=@~9`y?4Qz-wSme*18M zq3@g|ah91y5h9Oh5syOeU>OWn-aJj$0A1HPwp_CTT5WFDB}E6Ig5Dxe@E=`6UEm3@I^p_(@r3_#!EaNUC`_Bk)6-Tn@=eRTdC z^l+ugN`Yot;W&vE3ARbK5T8End%L=rYzh|6# zSEOteMF`2VEQ-8NS5b^L3Kf{8)n5B8fK~AfB4lY0+*FuW8_0<+oS|)E^>^f-8pr6O z93AE@=8C6~CTPoh;vEQu?v-tXAW+>((4fJdm;)dyS5dRuAal53lwx0fvZZ!^if`AG zzuiRmCUy||56JHOK4UI){RYHw%D4q;GUY<5n*}OM=E63)BPwlht$wg~ip3&`aoG-o0EVyFSBtN>FYglSnS) zUM#}mCC}Z)ibLo7qMmU{+*v=@UH#t2~5As$H5 zp!^2-W}P#V-vSVyttyiXamOes2`%lTG&qJcSaX>aCNgQ75-!FTDU|FLuIE$duT7J+ zGEf-?iDlN5zhOAe zZ1iq#OXdzTF~57gxr~66dL1uZ&ciPaj?*Fc7nd0X1+$PJ1~qZS$V_#Q6wJ}gnESd= z$xTKl<3VdB*^%gY_^Fj?5uKJEhY2QhxNJO=?h=jVeIChYb3>2Jzn6_gJnhc1wRJh` zhCC4_;9s#&KTAUUrCva3MQ+Zrm*Mm{4=`z!UxJwQ@}<*vw4Mj`K7J!6eL1oxLYUMs zm%XFuN%53F8h}7SUVj{tvp5Aa>NU|Sr=m3%s#IYLI2(&IzCYZ*MFng=c$;2j?||A; znIi0#3KyF7$S`F<1-hwDs*jTXo3aa6AxspAeD`of?pz^ml6~K-88%9O{QRAnrh-A-UnLL3hd9^!gJ0<-W=u-8O3a zXF)Kb>W-ZOe8($mHW4A_u_#i})j`0RxEz9oVSzEPE5Y(HM#d;G@MUC$%sYESXuBCk z7hXoAmZDRVao~Kgh=@LA+*9E7i_^a#auf-L;QI4%S&MD`!sZ)_eK%&7xB!2X#XY%F z~r2b{)}I>CM^Bz)1-4CWsdCR2oHazeCVFem-)?#hGtF zyQLZflf?-5jg^dt4s_KOya*{lXCdzCQqNf)*E3=_}JZ0nJg_LoFV zV~GxpYziBaG6g@xL8emWRtb3o#-FXTC1$QdqFa4P5S_SVfSSY0kRGx;2v_TyAm~0r z%HsF6=AtuF#*GjEuZd&gxN&G&Xh9SLgJB*m6*|2KWRY(x%8`XD`DPDuGOw4Z%hIYNTF$Hq`)*b>g z=GkZ(2Ry5U>Q`dUR4zFIPk|LIF>MZ>SNO@$)p!wf(Z7AbY#A@8+5yYP0Nm1BXLzFC zuNoCC^#@NV7@)Cf7GUBPA3wEry} zVa%mj^{*X%TpPuzhj_2RfBn^f*$CVY$`ZswDu%;#JdBTmfC)WQcg(o#0SLsS7_~9r z`$pH)fvAgOJ9S7(t0nrkrvG`&*&Vo#tVDcAY!^87CxE;lxfZjAR>?S@n8&Qb@9#cJ zF|W^1UUd;k8n2Ip?QOc6l&epD>>|T?%q{fU&0`tg94I*gE!*GmdJos%L@W#kI@h!U z{j=9P;JSgAj1eb+E8J}lIu&5cphx55fQHHs=5_APBiuD2_tx3Dm}|@{WW4=sA^L*0 z;pq#pG=Gd*9Hsh0L2I0!2b0D@4j7Uj=b2^F9MgcAHrI<6ylbG^%S=BT;jNJie39`$ z5@m4MTn{%u2F=_oy4d#XpiyWTf|rb*>pGSEts=4@0l&IyOr(A&UumRl@0v_$7|UqZ zGCJia!Xn|ACuj9u9@_@?aiX+G-wmwE@~;qE%1lFUR(zU#NHCbx&{m^p8g~{~h3Bf? z<2e9sqr!F(CIPt7?hv{SdJkXAc3-MIqvm=XKf$)n+t8{souiiV+!zsUkd~fx(}1$| zL;dithzH<~)ikxU;JGWBMQ4(W^DtIi;eKAkH}oFYQ9ktC*p;fsXM&`tH8mP z6Fsxp@;oN=4Qh;DS}w>1{hrgl_;9zO*S8JJHsP0w7@>!%f^MsYIP>Tw3=8Ik^OHHS zi|?PqgJ+-0C_UOKuB6wWty?ka8RIsC>MAS?l8qR@o72=(KCJWDu#l{+>K+vs|+j(1MNdf9F{{Oow`H?sMf@eMcWm349_uQp+`-a}(9MMt3?n|XBYV+fW{(3ZaOLD8u&nxh5+X-q?< zfbjMCvK1$+E1h+@VwTqEcwEY*4bN^`*3=pnc9g_4UjL<*K@L9CWUvHc%$1b+N!H=` zDtz#qr9$YVQ8vINTl&;mV}JOX7?NFz6zK1Tl*sbsb7oKG`7={22{kX*>4iBT-T46| z8a(uJ_lo2WLS+;!7y6#;7zWJ`vOK0)8P>v0V+S zuLxu!8#rj!NuovhfG3#_<%E5U9Ii+erl^HN;7-&E2jr!YPHNVo7b3N<#L?(KC#CDZ z19WV&JM)K&`$fH7e3>cxasQksw)ux(i8lJOcX59rrzMg#SQI3d?_8x|O>NioV3e#! zdNrROYGg!pBiCAlTdEuq(Ld398^7&i161u++aq4NhbM0AMN`B zRLcL^ps$%_hwkL7ZNiZ@DGMPz(cLa;_NKrQj)x?W*GC zy8POVj#nh)`#G46O&VQGbZqdV5%%2e;+4VguyEi(lN?a88I%0W{CdECFHHIMH#jgD zg&+xHuF~x(M||mj&+@|e{NgZJ#$o^zdXtZMw4fPLa*{W{Lm~C;u^ch)LtzlSSzca0 z1tGH|v)vH2S>F(o~qboN=t?@$*N^hb#%&96|9&}!P0KI*SOb5D^dUF<4!U3 z6_Hr40Hf&RBDrYUtHdg~yGpzVD?{CM(t7RDJD!Qn8Fzg%x7l(9;&Yf(MmET6bA&_~ z(2<-PJNR%has!=-@1$aZYQ>%tv6A`B*d!0a-6%16~C3> zmHgEv(_KIha8$tTz}tE`frF++~w;UsCEJp|IDH?xONwY#8-HIMW9w zSQ4~%md9}amM(1?Qz?zvo)lf|tQ+W{%m)h5Eku5IHb@1$RuEAxz8wqYUDErYBC5q4 z1PR!yCj@Jlbmj$hC?W1JZkL$mvBX#xR97^Oo6p;lhv9md9H1W(ATrz`YuL#-hXOGi zysPn;hey4lXv?K{mv$|+rBJ(x>Hxpi7-|*00cjTS_V}AIh}T%3JH?yqI;=p}=twwZ zrV(@>Yq7KaaY+vyLZB*3gGe<5Q)nX4VAoXgXa&UsTcR_b{PZWB%ebc~ z^Icg=30S$!;d9`=hq%RMaYmoZ`w_0$hrGtWGm|00n2V%X@NT2cEiCD_$pMxL?%uJ% zf}8f%%cF(|jCV~`!}`PUPgM$fHX4Jn!2}cvZw5N={!N^A#ct8O05~ayMPm+D+7HQ; zd(;B;OAE&qWPQ^iv_H7+V_D5$>Z4q!x`+zwlfR{@e04?F=-O*n5P1-U(|ZpYRw2g| zx)t(3qG&=HV;*&P98X;Pli5bHAqC@8LvNRV623nfuWA+63aHt1l7g=tXtg>Vf+;Tq z)pzKQOr;NzeIUDJVC+;l?dkT?vG2rs7=yVNwC~Ahx1;%X&l9Pl*>>q`7D59x7>=va9LYg+lz$o-O*9Nj`T8Trs@;C&>- z)9IspYT>MU7RW!ahdX0S zB|OlQ>b{-qwaqASf4JQy#&e?`>OJLh+{stgS@!6#9Hvj)DZ!U~P2p-@#(-)!aJk(y zJy`E`vVwz%oyh4k;iU9UGAkD$EXT!aiK6pd4)V7_=MPtPW%t-=YybRjtoYKxK3b;L zZ1frdi#ghAu{N^Wh>L~=qtLDS{JGh5=fJ3Sr4<`Lw?V{6sseHt00ET*DRm_|^KX?>7)V-_d{Hc@QVKwM0oc6P9!W;=+ zhHb82YQjbbCZxk?$f7G%$YYkYGh^}&zy=GDyLHt8kOf~}rerNhF2He}BBat~wDO{h zLg+M&b=+m^HnC>3LQFCA;z3mf_d}4^NEEvi>&Ev!#1_h4Huw zMwui0)!97sDgEOVs?C&snd{W>A7iHQW>-03+7Xf$nGMzAwOj8nbrZ!_& zS__Q!GNvXspOA3XO$8kW3&hnF` zDma5c_p7YIas!G-e}Th%2Bg{zyay(C$PnpZ<~3-#t7V52TqhJ2nNlyO1+?)_gEvmZ zcstcwnUm`&vh#qwIJ$ZWI9TNQKMOUP(cKmQwdjlRnRR4w$+42LdEt>4Mp&h2xY!w2 zty{Vgv2u0o71`w|}C|!Vnm%qBdeRFB!fU+LTsrY{PSmv`I%tS}!&fpC! zim3fi$34p1+Mmd?0V6)@ncaC6>2|gm3jkrdi+>Vt0o7>>G*O=gUu5%IXSJo3%OOl) zBCS~3X!Dsw-7OAmS_4YLd!jl7fM~v_1&v(OU1rOdJW|j@yi{fH+v|$4iSUb@bqg0GSvP-HbXz^zRWftV{qdy0q z1vN2vWgZi^tMiIOYA`qJ* zppFCTx^2~=`#9atm=>0>n<#tXM)*)F=c0^*;J|sJg~dGHc@R*g0Qi4XK-jG+!jlZ5 z=(ortF9KA+1?$Mkf93r26w{Cr2c-l6q@<_;kU!hd000mu0O*G!1o>hAnDGr z`hoKPw?#i)0Z@Q1z<(Y4KQ{gkrvDiFKbZ7>#Q%dy_(u-%-}Zw4$ie>)9_|0Y0R;SC z$CUhO5B%SJC;5LA{EzM5tKT~S#9!i4;y;T1bAo=pzSjXF07!6f2yie+2nYx$C`f2n zR5(}|7+5T16a-W}Yyx~dY+PJIQhEwPVpH^niZA5(9vdfIyIdzJ~w=KX!rv{jc(0P=2<7 zK|sO4At0fkVSXAkBmU=1fdGSofPsO6{_OSr*$)6k0z)QZ5&}n2G=v~_L}d<$&xa%t zuJ1=vn!6!oF>(rof=0){#KI;cr=X;wW@TgN;N;>K5fu}ckd*qRtfH!>uA!-AY+`C= zZeeNV?BeR??&0Yb6dV#779J6qkeHO5lA4yDQBYV^TvA$AUeVCl)ZEhA_Os4>aA z1Qg;wxPXA&{{tKe6pV-o99c*a!q5?gm^lCvRX9Gsz8{K&Md=33$Y~B5os@N#?Djv< z{ui?UcfbPweYXDdfpr645K>`Q>p5JDdT&EdCLd=#JcACUFm1%bBpYVPb z**8l)VAaNdXx8e!{25YrUrAuGi%(&l5w$>o=HtvmDD2%eec|~EYWW5v`iBtQG<@KF z1BBN7$9o6bY5_hR3l#GSzT)##oBI-;`bRuzcB>U004hCC()!cLk=x#Z=^V1U)|(Hj z2rq4?PM>&Ntjz^N1A+xSN6m_e?k1clKC8iz4DhnE7LIR#1^qC_M8qmO2&p-q;|z`V zWxf9_&!6|3Z@{je_swUlJYga=8->noRVO175M6ZndrCxL^Quk2GnN$K} zaVR{1Yg8bhGCC=FdBC!I>}#Fiv3x(-e|4 zQy&O0VmM^*C9Pyc=d;-G2UeR=4ZY+q~h$PBNj}~HZ{I={4GZmYx@`BDTg&q zlUlnJBJ73P4CE{X7Q{`JZ_(nbrx(UVwRcWE!;n0*@H^QuaZJbVT>qDf)Gf+DJQ%Yz z5}{%8Ml3U5TP@W~X3gpTP=~1S5Q>?ar6ku@Isv&n-yeOg#67p}(k%;a(<(;r^szYU zc8xNSteqRV9S6=~6?5`^kLwqIJvXxAn$mKPA$_PSYZ7ZDP`hZw8-H8{e&QFIAye!j zJq=EV`rF(Zn&}VSJwER9-R#xRu9vXyJp$fUpH@usWL=6vwvCdvFWEWbG#BI9K)5JyQW7%PBMx> zt<-%04cz_g(m3aPRW2#^b~pW%#{<&jl+xJVVRIJw@8Qsl#XP$F8! ztA=8tcjNoNR1dtK!<$xnXtlP+P4Hn1>N^5)Xq`lYavZQ6bFZE%36R*Nt^c5(T!N?E z)0O-y76S?npXyY;SMI-Bq>^fCcNd&*Tzr)J84o#H&x|3dHWNDutWQe&A1$Klwnl_8 zbCLWAr+V7ABASg$HWyVkHrb^Rv-D}c6?vh!<`ASNZtGh7oJ-aAU0{}AEeW@>t__@d z0Q86exMvB%-$jn+Gu%qi2aCR&-+-DyOPVt;gb!MIXiq)+ry)H($6n+8`(c=$Yc4kW zv`TcW*E5g{XrNue$P% zKyZg#^^fnNy1Hjk#-;lxu6?tj^N8a(MK7B}Vv^lb@KSdC`I=p&VU-q4HTNA(8Pv#2 z79+&pH|%yjFl%eqo5{V9nCz@tvXF-;81dOb8g{N{EHwfhlY6~)6`}@b9A7veOSh`l z#!6tw_yCAjwkMT_A|&31AD`RyhzpwIT9i|x`@P96F@pt5C!L{r&fv6FTiv1CS*~e{ z0vkFvsh!>^f}1~|=Y3 z(NYk!)pZGm4>IoHVp7Cc#EO>dq}C~U{KCWI&)RB7Y_^dIwHTIhCmM5&|0 z%}9(k<;K4eFd_IKrAjVn@a^}68$BjvLT!&&mug>P(9*tcZ~=Wmvt>05!wIi`tUcMp z9{^P48I{k15Rrc6hk+LLxtu4y1O&pH!#S;V zvz6si8&QrIFJKl@s!@_1pu}4Wa*V0-hMztRceg!;+$nj~eELY!*=F~MLt(4ub<-6KtXV3L?EAQv_ zSF@6l)v&G;*Uk-iFqx5(xVhM!W0TMJ5a$&_`E|4klDs{};Aw$&+4N8=rnR%c6b7{j zD8*_lxF_yDaW{q#Kk_0kn~7MK@+*4EI8RC1J!%%nQP6t>yi-^7GjYme4~`aFaY{Wb zqs}n-tJ|s+N}S5R+aeYgAK>9_ZVH`~04^f6KZi6~Ykv|lavZr_IV-wFh}Rn_w(Ftz z1~J=YsU+k82CvXw<1d%t3MOw(SU~h!>xG~A7Vkz!S31Fcyzlo9HG&>t+NAzN`wHKHzSM63_Akp$;w&BaGk1KN zrN>T~b1a*~ZtFs`+iBL8IYx(<4e+J)MKANxDQBhgwc7CN2U{354h&=~nWO!wcjR3t z<&#bcxCID4Imlt&Yc0l}%ptELWVVsvXqnL;7c6?N8RjALJd%vj6_XX0Ym^O( z7O&+}m$?a&KNtw@GZ2^%wXDuG>vc|@&hFee)zbRyH>B#%$~sbx$9dr}WJ5;mIDTh4 zzFVcWGVT?VWoKHmA=g)InnSIWdYn5Z8vlZTrKw{IL%C)!bAs@!c?7wuufs!=t2}}f z7w)kPdoJ>61*vZm(UkYmzI-MdD6@s`%uk9@+sA~7P3#Jne*I52ViQ~rpS?OhRL-Iv-L zH|tLyO~x|bvlj(6EC?qiW^^>!CKv_C@UGE8(H04kLd-Jn(Xkm(h zuv4i5w9eRGF3Ul_yw>K1|5&qNo&;2Z4P z=lxpW?TGQ8X`|PEoFq4h_ko`H#^%N_xyaR_w3a`UQo8P}j>G}0Cb^je!dAs;xj}^2qKsqE7?7yXP_uX|2o@%XXwEwSmuKXYB z@B5F4ghYsDEDhc&>ln+73`s}x1VDN7QvXU|Tu@B5ymEMwo| zJ9;ml@Av!o{s-Up{B&RUbY-kSv)OIEQTqu-zki^aDppCD44XA$Etl*+A+SP`Qe1@~V*E zz$i3bFGdw%$8E3A=hYLk;l-;hJ1*C=x)OGOr93<-ph!P@iFEj**LnKlR8B4@fQsk> z7YT^o&;G1MF#FtokcZM@>I2&0~jdb46GcX$j)bL{?}KskD&O$gJv;C`=I`^8p@8pICkY3p7$~+iEP{yp6x8W3e=irVr8o+&Lho2`Ln>EEWYr#Eq~ei z==BHi_F8dDnpTDpa4gn1ZMzeFBZ!kvz={sZ?GsX@z`GkzSLPb%Y;xVC{LxX5WLcv* zRu({KpL*_gk(ofs>MCKQR95R|Mi9P2L#&7=Z<^sswqTrR6c{-Oa`^n(>}ysH+Ya!s zgqN>njL%f@f{9j`yyja{On)PjthT?=<5Z@dgL!J`YoDvOjpvWm#@_?yV*Xb!Fmon z7}s&Lng_T7oY>hdd%BDr)K}~yy*}2Z{wk=wWcpGpQbg52kfYjaFDi}@`)z(@hy5n* z`s<6kmIw9Bskcg8Wqj$m*gKyO`9bCic&U@-VcXv?zcnyeu-Qrc#-Ub)W&nLEb4xZ5 zew8}Q0f2BjHl>;Nc!GL%y@6T69Wu!$|f2{SX;XBy+|Px)Ti8HDVUs#6s>H$oigc~i8FfksxP~=XK~w`zZ5Mu zTqBy6yNd5VU1P=a3E<3Up3DsA=Y~&u5{}~5#%uR+M4IgPdD@+lQBC$8l-ZfcPBxS4 zG}{qRU#^IbS}_!2h7fQSr0g}UIL9pbl)9vvA&X>c#2GS!Gt104OV)IeL?Q zfGs)w;(~61W`5$VajTW}hX0wkYzq-c&#TfIc64|*{khtuk0}+Y%}hH_#}@3Nn`v*e zVi5kzY%5Y(45h;!FM;rMpGtxFJSY#OMcAMUtc{v#F)yO0F*W{?&-SR1QIb{SjlCLg z96|45sLw2&_(81CLh#i)*J_CMrJGs9n56D8CB^-p zrgYq=wWkfF6-y5D$C}MWOVaYj+|~Os zvs8l~XIop20pNl-Sc{8?agOEd=$`}CZ0K^bS9)B!kr5&_0efK#TJS4+KMF6v0NjrXWJlCt5Q0|mQWjNj9_1L?7`jt=&f#{NSEcq$X@{hq2pW5J6-IB)o)z=dBv|^b zh^%VgDX?lrec=-F8`N`oL1s|uUp<}tN+7`%sNv?&sQzWiZNI0;ciOq-up>||>$F#l zmeUtmUHo(h7m=E*(NvD7KMW*Da)w;YY zD56`NfKh#FbKCS?|&Kr$zZ3&l*h)BvTaNMB3i?89-3tNTrX>Z<{X=S7x zc;MEgh14zGi%n=B^Q>)+QAZHc_T4-yz7=s0ywJs31UA?FUx`4XZF$#r$+t(barIt+ zcD4B;>;yI$TEX;ID+h}NDKkKcK-PTsvp0Qre~?t3G$VC{DALPvVG zN+iLFf8Lg!~Wr1zSgQqH*8f zwD4M)&4)}YfOaEwyDP5aY{t1NKNpC!vCm#DcM$UcnKMTB4tyLN&(2O7ppx$aVQN*C z#Qi$mW4p`vKE9THK32vfOJ=UC;^|tI8Y;{(123<>Q@=U;M<=t=j>oyUV8XN!x1vGs zX13~xb7A7go{IbnBIb?&i5aG5(0osKiM(r$O=9<|vS!-S$YPL(xv&yn<*+B7vn%;J#W{p#-}y zSEKy1MWbZC3epiz4Hc=b&}F;rf^y(lHub2XAJL1QGvk$VqBo}%&zRt9={<+0p`4dg zYu7IFZ8dRq?BGJljghn&lVjo!$|^iOLOuAwDg~sdB!{FhrN5F`x_ADcn-QJ&j{J1$QJ^rZ3aSUiaYqmpis*6=Gz^2Tw=KCwd0WOCU zN2@u?d!I;j9fHMM{#2>fi(S?E;+#S$1ko!^5&*+6q z8m7ZkQ}jcIHP6GETD~3wN_NWD@41289liOwSWOt}92OH9$>Sz}$Tyt5+hh&h zC?v%1iyJCrW?mSEyYy_n2S0mCdrPxj7r&<@RLZx}#4deJUG{XjX0EW&mNzQwVU8Pg z;Sxu1wlxmxaeXN(s|nP<-kf3UaimAtt*JUbpY3(oST$v;l679sXi=)%r?^h&xzNLF z4gOhIVTjw@Ucx2W*n5i^Wo&Up=cA~E-sHv~-kyF=P!QCdW*~9BiJ0QzM-_g$L01J0 z*^kiL(%O_JzZy97>Np0N0QdUCO$?&*#!0c$?RnV(4uem7dQhp)?SD>vIzwkY(o_#Q&)N0~<>Bp{lBK)ZpB~c7+AYA6Uw==*!j(HCg2`=qAy6w& zb?Xf#8GPs3h}it;-W3tu;<54wB>*ZZFn!nX(YrOXpj*+m+Vk@CqkMH7+4q<&hyhEm zY!q8uv}o}bf?9<<@syC`irwePb?l#n=$|)dJr&S;jxvzv`Y=4q7Zkk_FzC`WkfuDz zg()HHinD$HZSyUmyv}ZE?8So1M ztJLk-Me@bEMDd{S$ADnVLdsmW3Czrw>VvowX^A4Yn#f{R=^nyS$Bb*s3R;-@z#I-y(o*%8l zED}kXEwHiX<|XgAYe_m~hKX`TAULqgNzUgSX@7m-OV^e$ADJ_RX+0kA9q#qkjUheQ-~nojRiuS@|k%CzxQ7H?WeuA}%H{c6K;FDP9PBy|hW1 zShJl-Q}T&HR73lz&VgKk?|HE!jrU)ZVa7g5P}Rt~lKqKSGVd~ta2H0u-Hs0~dXzUZ zxJ5Ici$JvbW;vUSHeYMU6Jya)X%^tpwqJ8Jj4W6hOF5Fky+Kj#uE#Ozn65p&hr*u&6=>54v zTBhpVIz%d$eh{bXfXbE+WIs1K6z#WLat!#8+F7Wnu(XZ-)YsPVg|clFQT+@ao*)=% zPE{^6B3(W;VnTbx85n-yLGOz<4`bBOEJx&10nHe0pwGQ8#2Bbft&1V3z%OITFig&` zfL7&{Jk zm4q_x5=F}n$m(@Tr+rPZJReUv##mN4xsH>IE?JmC`RUDyfti;F8uyF(z9*yN&aiV< zw}$z{Zw}3Fgy}v|PSKcFH`1=`HLupFxg`0M^Q^D%1%GG-v#lNj6MNq=K>wJszN%ed zG~E%rES^}WUZifSp%1O-PM@fN0eBpK?CQVACI*a>ynBBtxgo-2L-zQIpRW7Qqyv88 zYUJIx0_r>LEE7>|Ht7Z~bNfl;txfjjYDQ1QsoiUh>r2xfrFQQoHrnSbO#Rrbr~x|R zS8nzj*$T<5I&NpbZ{Z0O;|~VMBeX>ZIhaZfkwD0544fuu0kXmLYUlThrd&Tm5u(>~`6>UUHr?mo;iuo;kxcxt^9f1xzC<*{81 zSc~6!HjGkFD7Wn`!$w(+dzC4kJjnFZj!`e_4 zc*K`b8lKNhoL`y{{Xgw8DA<*M^Z8?tA%zp0F;6INgp}6J;5ak1TUF!G!Ln2=_ zbqJ4=tLaR}t-a4DXjZNze;S~6rPd;TpN*|)N~!6{aL--aT0NA_Ff&@>VehMtDRp-K z6rC>t;Fb&Xf-g~yoJn7($rPJR?W>49x29d)C9j@kI=-u+_lO{1_4t?HNGtI9GK_0Q z&Rxf;;QffFTKPcwT72&I)y7`hnw`tF;e$O}wP(9Ujh+-y&;i~LcrpF-y#+idu+_XKt zJ}kKoZxbo|Mt^=hcdv~{kj%2h%(_?{U*_|q$ctQ7O3Y|3zoB>9-BF!y-ySZFYrN>{ zJ`vEPnZFj13;Oxtl#kWt^HE>jXFAVA1}SS9gA1vdN>_5~9PN&*!e5rxtxY*;PjMUA zHRSm={d)Ze*Y>2sPZZZ)C2_B7>Uvfsutqa&jN%sVnWYGA@_YwPY}gDn-xK)q57QQv zb77YpR#reOJMy=`(A{7A9{qlplArnp-yIjP4XRCu0fu2q5)R4mbduDPoOqCQR_kke zo2VwwhHP?1^ABbbmnd3?=EcR4lFwb5J)w?X^(Uk=bgQOVk$L8gU)CDdG=^^Otd}%< zc5Es5?1o!q?I!LIZBkYQY(9s2FM8L2(Uip{mSo68DXc+nZ9Ic4Tsw@zZeLvX>JVcXf3YbA^f#9IeD5 za5!9CLQ-5(Qj{VgN_4YxLXt%7i2Q#e+`>skl&-|8nF1lqTxB*<-{XV2A`~M-)cI z1!L#L|F=3C^^dN-v!m_r0MICLj4cLF5hGHpLH;pyQt0@P^hv;0SiJpj4GOdWNI79G z|3l0F@aN>tZ}@?|(@C9p{N4g$%h{1eEiMKkBy-;1i>AXaWk0miyhrSV*DZ zmNIBjOBpCiR0;x@6-7d%k)krvma;H390`$uL;l85w<9_s?NFE#915}+mI5LpiAG7n zAy82$T#BM^0h1JkVI*WlEirH@2pWyDl$J*St*_;XrDPn^_P_gcf`g{uNJz@aNXVe1 zM5Uon2nELyB?^a0AVn=LBqSx^NNE`v85EcgjgnI(IO36%M~1~CtuW%Q7z=wa-wCyH zO838;D72^PxACn-qo-~ z%5As5GG7Pd@K?(g%lA9) -b 115200 + +Replace :code:`` with the port where the nRF9131 EK +can be found. For example, under Linux, :code:`/dev/ttyACM0`. + +Then build and flash the application in the usual way. + +.. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :board: nrf9131ek_nrf9131 + :goals: build flash + +Debugging +========= + +Refer to the :ref:`nordic_segger` page to learn about debugging Nordic boards with a +Segger IC. + + +Testing the LEDs and buttons in the nRF9131 EK +********************************************** + +There are 2 samples that allow you to test that the button and LED on +the board are working properly with Zephyr: + +* :zephyr:code-sample:`blinky` +* :zephyr:code-sample:`button` + +You can build and flash the examples to make sure Zephyr is running correctly on +your board. The button and LED definitions can be found in +:zephyr_file:`boards/arm/nrf9131ek_nrf9131/nrf9131ek_nrf9131_common.dtsi`. + +References +********** + +.. target-notes:: + +.. _IDAU: + https://developer.arm.com/docs/100690/latest/attribution-units-sau-and-idau +.. _Nordic Semiconductor Infocenter: https://infocenter.nordicsemi.com +.. _Trusted Firmware M: https://www.trustedfirmware.org/projects/tf-m/ diff --git a/boards/arm/nrf9131ek_nrf9131/nrf9131ek_nrf9131_common.dtsi b/boards/arm/nrf9131ek_nrf9131/nrf9131ek_nrf9131_common.dtsi index 35314cd0784..2c3b8481d2a 100644 --- a/boards/arm/nrf9131ek_nrf9131/nrf9131ek_nrf9131_common.dtsi +++ b/boards/arm/nrf9131ek_nrf9131/nrf9131ek_nrf9131_common.dtsi @@ -20,7 +20,7 @@ compatible = "gpio-leds"; led0: led_0 { gpios = <&gpio0 29 GPIO_ACTIVE_HIGH>; - label = "Green LED 1"; + label = "Red LED 1"; }; led1: led_1 { gpios = <&gpio0 30 GPIO_ACTIVE_HIGH>; @@ -28,7 +28,7 @@ }; led2: led_2 { gpios = <&gpio0 31 GPIO_ACTIVE_HIGH>; - label = "Green LED 3"; + label = "Blue LED 3"; }; }; From 56f475ad3e6fe5583a7478db6dfa47fad3485d35 Mon Sep 17 00:00:00 2001 From: Maximilian Deubel Date: Thu, 16 Nov 2023 14:19:25 +0100 Subject: [PATCH 412/421] [nrf noup] boards: arm: nrf9131ek: fix docs build This patch backports the nrf9131ek docs. To be reverted when after the next Zephyr update. Signed-off-by: Maximilian Deubel --- boards/arm/nrf9131ek_nrf9131/doc/index.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/boards/arm/nrf9131ek_nrf9131/doc/index.rst b/boards/arm/nrf9131ek_nrf9131/doc/index.rst index a72cd1526e3..ffb066d860d 100644 --- a/boards/arm/nrf9131ek_nrf9131/doc/index.rst +++ b/boards/arm/nrf9131ek_nrf9131/doc/index.rst @@ -210,8 +210,8 @@ Testing the LEDs and buttons in the nRF9131 EK There are 2 samples that allow you to test that the button and LED on the board are working properly with Zephyr: -* :zephyr:code-sample:`blinky` -* :zephyr:code-sample:`button` +* :ref:`blinky-sample` +* :ref:`button-sample` You can build and flash the examples to make sure Zephyr is running correctly on your board. The button and LED definitions can be found in From a69bb9315bcd02096bbf27f13038a5c0a1706632 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20B=C3=B8e?= Date: Mon, 16 Oct 2023 12:46:29 +0200 Subject: [PATCH 413/421] [nrf fromtree] tfm: Enable TFM_EXCEPTION_INFO_DUMP by default MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Exception info dump is a very basic feature so it should IMHO be enabled by default. For instance, a simple null-pointer exception in the non-secure app will not be logged unless this option is enabled. Signed-off-by: Sebastian Bøe (cherry picked from commit a4e9aed68de223968e43f4ea4fa1abdda5b49c26) Signed-off-by: Joakim Andersson --- modules/trusted-firmware-m/Kconfig.tfm | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/trusted-firmware-m/Kconfig.tfm b/modules/trusted-firmware-m/Kconfig.tfm index bafa5cf0bab..2a5edb64343 100644 --- a/modules/trusted-firmware-m/Kconfig.tfm +++ b/modules/trusted-firmware-m/Kconfig.tfm @@ -446,6 +446,7 @@ endchoice config TFM_EXCEPTION_INFO_DUMP bool "TF-M exception info dump" + default y help On fatal errors in the secure firmware, capture info about the exception. Print the info if the SPM log level is sufficient. From b96a183abe7f07a90ba844c7928740d2c1b3c96c Mon Sep 17 00:00:00 2001 From: Joakim Andersson Date: Wed, 15 Nov 2023 18:04:28 +0100 Subject: [PATCH 414/421] [nrf fromlist] tfm: Fix include order between platform_ns and tfm_api_ns libraries Fix include order between platform_ns and tfm_api_ns libraries. platform_ns functions may depend on tfm_api_ns. This would typically be platform specific IOCTL services added to the platform_ns library requiring the tfm_platform_ioctl from the TF-M platform partition exposed in tfm_platform_api.c Upstream PR: https://github.com/zephyrproject-rtos/zephyr/pull/65253 Signed-off-by: Joakim Andersson --- modules/trusted-firmware-m/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/trusted-firmware-m/CMakeLists.txt b/modules/trusted-firmware-m/CMakeLists.txt index f00116cda2c..177a47e28d6 100644 --- a/modules/trusted-firmware-m/CMakeLists.txt +++ b/modules/trusted-firmware-m/CMakeLists.txt @@ -435,8 +435,8 @@ if (CONFIG_BUILD_WITH_TFM) else() zephyr_library_link_libraries( - ${TFM_API_NS_PATH} ${PLATFORM_NS_FILE} + ${TFM_API_NS_PATH} ) endif() From 1687aaaac27cce09921a015a3f63c79666ebdc37 Mon Sep 17 00:00:00 2001 From: Joakim Andersson Date: Thu, 16 Nov 2023 14:29:55 +0100 Subject: [PATCH 415/421] [nrf fromlist] tfm: Change SFN and FP_HARDABI dependency TF-M only suports floating point in IPC model, not the SFN model. Since floating point is a basic feature of the architecture and TF-M has the limitation it makes more sense for the dependency to exist in TF-M and and limit the TF-M model choice instead of limiting the option to enable floating point. Upstream PR: https://github.com/zephyrproject-rtos/zephyr/pull/65304 Signed-off-by: Joakim Andersson --- arch/arm/core/aarch32/Kconfig | 1 - modules/trusted-firmware-m/Kconfig.tfm | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/core/aarch32/Kconfig b/arch/arm/core/aarch32/Kconfig index a14bcd0cb62..58d5253cb94 100644 --- a/arch/arm/core/aarch32/Kconfig +++ b/arch/arm/core/aarch32/Kconfig @@ -267,7 +267,6 @@ config FP_HARDABI # TF-M build system does not build the NS app and libraries correctly with Hard ABI. # This limitation should be removed in the next TF-M synchronization. depends on !TFM_BUILD_NS - depends on !(BUILD_WITH_TFM && !TFM_IPC) help This option selects the Floating point ABI in which hardware floating point instructions are generated and uses FPU-specific calling diff --git a/modules/trusted-firmware-m/Kconfig.tfm b/modules/trusted-firmware-m/Kconfig.tfm index 2a5edb64343..c09d922e9fd 100644 --- a/modules/trusted-firmware-m/Kconfig.tfm +++ b/modules/trusted-firmware-m/Kconfig.tfm @@ -323,6 +323,7 @@ config TFM_IPC config TFM_SFN bool "SFN model" + depends on !FP_HARDABI help Use the SFN Model as the SPM backend for the PSA API. The SFN model supports the SFN Partition model, and isolation level 1. From af993b28c1dcde6c52e55517801628b82429ad78 Mon Sep 17 00:00:00 2001 From: Robert Lubos Date: Tue, 14 Nov 2023 14:31:37 +0100 Subject: [PATCH 416/421] [nrf fromlist] net: pkt: Add function for allocating buffers w/o preconditions Add new function to allocate additional buffers for net_pkt, w/o any additional preconditions/checks. Just allocate what was requested. Upstream PR: https://github.com/zephyrproject-rtos/zephyr/pull/65251 Signed-off-by: Robert Lubos --- include/zephyr/net/net_pkt.h | 25 +++++++++++++++ subsys/net/ip/net_pkt.c | 61 ++++++++++++++++++++++++++++++++++++ 2 files changed, 86 insertions(+) diff --git a/include/zephyr/net/net_pkt.h b/include/zephyr/net/net_pkt.h index d4011d1f582..199f78d2361 100644 --- a/include/zephyr/net/net_pkt.h +++ b/include/zephyr/net/net_pkt.h @@ -1678,6 +1678,13 @@ int net_pkt_alloc_buffer_debug(struct net_pkt *pkt, net_pkt_alloc_buffer_debug(_pkt, _size, _proto, _timeout, \ __func__, __LINE__) +int net_pkt_alloc_buffer_raw_debug(struct net_pkt *pkt, size_t size, + k_timeout_t timeout, + const char *caller, int line); +#define net_pkt_alloc_buffer_raw(_pkt, _size, _timeout) \ + net_pkt_alloc_buffer_raw_debug(_pkt, _size, _timeout, \ + __func__, __LINE__) + struct net_pkt *net_pkt_alloc_with_buffer_debug(struct net_if *iface, size_t size, sa_family_t family, @@ -1792,6 +1799,24 @@ int net_pkt_alloc_buffer(struct net_pkt *pkt, k_timeout_t timeout); #endif +/** + * @brief Allocate buffer for a net_pkt, of specified size, w/o any additional + * preconditions + * + * @details: The actual buffer size may be larger than requested one if fixed + * size buffers are in use. + * + * @param pkt The network packet requiring buffer to be allocated. + * @param size The size of buffer being requested. + * @param timeout Maximum time to wait for an allocation. + * + * @return 0 on success, negative errno code otherwise. + */ +#if !defined(NET_PKT_DEBUG_ENABLED) +int net_pkt_alloc_buffer_raw(struct net_pkt *pkt, size_t size, + k_timeout_t timeout); +#endif + /** * @brief Allocate a network packet and buffer at once * diff --git a/subsys/net/ip/net_pkt.c b/subsys/net/ip/net_pkt.c index 57ba0f3bb0d..fb44490dd2b 100644 --- a/subsys/net/ip/net_pkt.c +++ b/subsys/net/ip/net_pkt.c @@ -1197,6 +1197,67 @@ int net_pkt_alloc_buffer(struct net_pkt *pkt, return 0; } + +#if NET_LOG_LEVEL >= LOG_LEVEL_DBG +int net_pkt_alloc_buffer_raw_debug(struct net_pkt *pkt, size_t size, + k_timeout_t timeout, const char *caller, + int line) +#else +int net_pkt_alloc_buffer_raw(struct net_pkt *pkt, size_t size, + k_timeout_t timeout) +#endif +{ + struct net_buf_pool *pool = NULL; + struct net_buf *buf; + + if (size == 0) { + return 0; + } + + if (k_is_in_isr()) { + timeout = K_NO_WAIT; + } + + NET_DBG("Data allocation size %zu", size); + + if (pkt->context) { + pool = get_data_pool(pkt->context); + } + + if (!pool) { + pool = pkt->slab == &tx_pkts ? &tx_bufs : &rx_bufs; + } + +#if NET_LOG_LEVEL >= LOG_LEVEL_DBG + buf = pkt_alloc_buffer(pool, size, timeout, caller, line); +#else + buf = pkt_alloc_buffer(pool, size, timeout); +#endif + + if (!buf) { +#if NET_LOG_LEVEL >= LOG_LEVEL_DBG + NET_ERR("Data buffer (%zd) allocation failed (%s:%d)", + size, caller, line); +#else + NET_ERR("Data buffer (%zd) allocation failed.", size); +#endif + return -ENOMEM; + } + + net_pkt_append_buffer(pkt, buf); + +#if IS_ENABLED(CONFIG_NET_BUF_FIXED_DATA_SIZE) + /* net_buf allocators shrink the buffer size to the requested size. + * We don't want this behavior here, so restore the real size of the + * last fragment. + */ + buf = net_buf_frag_last(buf); + buf->size = CONFIG_NET_BUF_DATA_SIZE; +#endif + + return 0; +} + #if NET_LOG_LEVEL >= LOG_LEVEL_DBG static struct net_pkt *pkt_alloc(struct k_mem_slab *slab, k_timeout_t timeout, const char *caller, int line) From 2242e9c7569a3651e2a07c11e0e24e2212e3dbd9 Mon Sep 17 00:00:00 2001 From: Robert Lubos Date: Tue, 14 Nov 2023 12:40:49 +0100 Subject: [PATCH 417/421] [nrf fromlist] net: tcp: Rework data queueing API Rework how data is queued for the TCP connections: * net_context no longer allocates net_pkt for TCP connections. This was not only inefficient (net_context has no knowledge of the TX window size), but also error-prone in certain configuration (for example when IP fragmentation was enabled, net_context may attempt to allocate enormous packet, instead of let the data be fragmented for the TCP stream. * Instead, implement already defined `net_tcp_queue()` API, which takes raw buffer and length. This allows to take TX window into account and also better manage the allocated net_buf's (like for example avoid allocation if there's still room in the buffer). In result, the TCP stack will not only no longer exceed the TX window, but also prevent empty gaps in allocated net_buf's, which should lead to less out-of-mem issues with the stack. * As net_pkt-based `net_tcp_queue_data()` is no longer in use, it was removed. Upstream PR: https://github.com/zephyrproject-rtos/zephyr/pull/65251 Signed-off-by: Robert Lubos --- subsys/net/ip/net_context.c | 27 +++--- subsys/net/ip/tcp.c | 166 +++++++++++++++++++++-------------- subsys/net/ip/tcp.h | 15 +--- subsys/net/ip/tcp_internal.h | 20 +++-- 4 files changed, 132 insertions(+), 96 deletions(-) diff --git a/subsys/net/ip/net_context.c b/subsys/net/ip/net_context.c index 1372398185a..6af67103721 100644 --- a/subsys/net/ip/net_context.c +++ b/subsys/net/ip/net_context.c @@ -1480,7 +1480,7 @@ static int context_sendto(struct net_context *context, { const struct msghdr *msghdr = NULL; struct net_if *iface; - struct net_pkt *pkt; + struct net_pkt *pkt = NULL; size_t tmp_len; int ret; @@ -1689,6 +1689,15 @@ static int context_sendto(struct net_context *context, return -ENETDOWN; } + context->send_cb = cb; + context->user_data = user_data; + + if (IS_ENABLED(CONFIG_NET_TCP) && + net_context_get_proto(context) == IPPROTO_TCP && + !net_if_is_ip_offloaded(net_context_get_iface(context))) { + goto skip_alloc; + } + pkt = context_alloc_pkt(context, len, PKT_WAIT_TIME); if (!pkt) { NET_ERR("Failed to allocate net_pkt"); @@ -1707,9 +1716,6 @@ static int context_sendto(struct net_context *context, len = tmp_len; } - context->send_cb = cb; - context->user_data = user_data; - if (IS_ENABLED(CONFIG_NET_CONTEXT_PRIORITY)) { uint8_t priority; @@ -1731,6 +1737,7 @@ static int context_sendto(struct net_context *context, } } +skip_alloc: if (IS_ENABLED(CONFIG_NET_OFFLOAD) && net_if_is_ip_offloaded(net_context_get_iface(context))) { ret = context_write_data(pkt, buf, len, msghdr); @@ -1762,16 +1769,12 @@ static int context_sendto(struct net_context *context, } else if (IS_ENABLED(CONFIG_NET_TCP) && net_context_get_proto(context) == IPPROTO_TCP) { - ret = context_write_data(pkt, buf, len, msghdr); + ret = net_tcp_queue(context, buf, len, msghdr); if (ret < 0) { goto fail; } - net_pkt_cursor_init(pkt); - ret = net_tcp_queue_data(context, pkt); - if (ret < 0) { - goto fail; - } + len = ret; ret = net_tcp_send_data(context, cb, user_data); } else if (IS_ENABLED(CONFIG_NET_SOCKETS_PACKET) && @@ -1827,7 +1830,9 @@ static int context_sendto(struct net_context *context, return len; fail: - net_pkt_unref(pkt); + if (pkt != NULL) { + net_pkt_unref(pkt); + } return ret; } diff --git a/subsys/net/ip/tcp.c b/subsys/net/ip/tcp.c index ad9cd1e4c98..2e70824b8ed 100644 --- a/subsys/net/ip/tcp.c +++ b/subsys/net/ip/tcp.c @@ -1252,6 +1252,49 @@ static int tcp_pkt_peek(struct net_pkt *to, struct net_pkt *from, size_t pos, return net_pkt_copy(to, from, len); } +static int tcp_pkt_append(struct net_pkt *pkt, const uint8_t *data, size_t len) +{ + size_t alloc_len = len; + struct net_buf *buf = NULL; + int ret = 0; + + if (pkt->buffer) { + buf = net_buf_frag_last(pkt->buffer); + + if (len > net_buf_tailroom(buf)) { + alloc_len -= net_buf_tailroom(buf); + } else { + alloc_len = 0; + } + } + + if (alloc_len > 0) { + ret = net_pkt_alloc_buffer_raw(pkt, alloc_len, + TCP_PKT_ALLOC_TIMEOUT); + if (ret < 0) { + return -ENOBUFS; + } + } + + if (buf == NULL) { + buf = pkt->buffer; + } + + while (buf != NULL && len > 0) { + size_t write_len = MIN(len, net_buf_tailroom(buf)); + + net_buf_add_mem(buf, data, write_len); + + data += write_len; + len -= write_len; + buf = buf->frags; + } + + NET_ASSERT(len == 0, "Not all bytes written"); + + return ret; +} + static bool tcp_window_full(struct tcp *conn) { bool window_full = (conn->send_data_total >= conn->send_win); @@ -3055,13 +3098,12 @@ int net_tcp_update_recv_wnd(struct net_context *context, int32_t delta) return ret; } -/* net_context queues the outgoing data for the TCP connection */ -int net_tcp_queue_data(struct net_context *context, struct net_pkt *pkt) +int net_tcp_queue(struct net_context *context, const void *data, size_t len, + const struct msghdr *msg) { struct tcp *conn = context->tcp; - struct net_buf *orig_buf = NULL; + size_t queued_len = 0; int ret = 0; - size_t len; if (!conn || conn->state != TCP_ESTABLISHED) { return -ENOTCONN; @@ -3078,72 +3120,69 @@ int net_tcp_queue_data(struct net_context *context, struct net_pkt *pkt) goto out; } - len = net_pkt_get_len(pkt); + if (msg) { + len = 0; - if (conn->send_data->buffer) { - orig_buf = net_buf_frag_last(conn->send_data->buffer); + for (int i = 0; i < msg->msg_iovlen; i++) { + len += msg->msg_iov[i].iov_len; + } } - net_pkt_append_buffer(conn->send_data, pkt->buffer); - conn->send_data_total += len; - NET_DBG("conn: %p Queued %zu bytes (total %zu)", conn, len, - conn->send_data_total); - pkt->buffer = NULL; + /* Queue no more than TX window permits. It's guaranteed at this point + * that conn->send_data_total is less than conn->send_win, as it was + * verified in tcp_window_full() check above. As the connection mutex + * is held, their values shall not change since. + */ + len = MIN(conn->send_win - conn->send_data_total, len); + + if (msg) { + for (int i = 0; i < msg->msg_iovlen; i++) { + int iovlen = MIN(msg->msg_iov[i].iov_len, len); + + ret = tcp_pkt_append(conn->send_data, + msg->msg_iov[i].iov_base, + iovlen); + if (ret < 0) { + if (queued_len == 0) { + goto out; + } else { + break; + } + } + queued_len += iovlen; + len -= iovlen; + + if (len == 0) { + break; + } + } + } else { + ret = tcp_pkt_append(conn->send_data, data, len); + if (ret < 0) { + goto out; + } + + queued_len = len; + } + + conn->send_data_total += queued_len; + + /* Successfully queued data for transmission. Even if there's a transmit + * failure now (out-of-buf case), it can be ignored for now, retransmit + * timer will take care of queued data retransmission. + */ ret = tcp_send_queued_data(conn); if (ret < 0 && ret != -ENOBUFS) { tcp_conn_close(conn, ret); goto out; } - if ((ret == -ENOBUFS) && - (conn->send_data_total < (conn->unacked_len + len))) { - /* Some of the data has been sent, we cannot remove the - * whole chunk, the remainder portion is already - * in the send_data and will be transmitted upon a - * received ack or the next send call - * - * Set the return code back to 0 to pretend we just - * transmitted the chunk - */ - ret = 0; + if (tcp_window_full(conn)) { + (void)k_sem_take(&conn->tx_sem, K_NO_WAIT); } - if (ret == -ENOBUFS) { - /* Restore the original data so that we do not resend the pkt - * data multiple times. - */ - conn->send_data_total -= len; - - if (orig_buf) { - pkt->buffer = orig_buf->frags; - orig_buf->frags = NULL; - } else { - pkt->buffer = conn->send_data->buffer; - conn->send_data->buffer = NULL; - } - - /* If we have out-of-bufs case, and the send_data buffer has - * become empty, till the retransmit timer, as there is no - * data to retransmit. - * The socket layer will catch this and resend data if needed. - * Only perform this when it is just the newly added packet, - * otherwise it can disrupt any pending transmission - */ - if (conn->send_data_total == 0) { - NET_DBG("No bufs, cancelling retransmit timer"); - k_work_cancel_delayable(&conn->send_data_timer); - } - } else { - if (tcp_window_full(conn)) { - (void)k_sem_take(&conn->tx_sem, K_NO_WAIT); - } - - /* We should not free the pkt if there was an error. It will be - * freed in net_context.c:context_sendto() - */ - tcp_pkt_unref(pkt); - } + ret = queued_len; out: k_mutex_unlock(&conn->lock); @@ -3498,7 +3537,9 @@ static size_t tp_tcp_recv_cb(struct tcp *conn, struct net_pkt *pkt) net_pkt_pull(up, net_pkt_get_len(up) - len); - net_tcp_queue_data(conn->context, up); + for (struct net_buf *buf = pkt->buffer; buf != NULL; buf = buf->frags) { + net_tcp_queue(conn->context, buf->data, buf->len); + } return len; } @@ -3641,12 +3682,7 @@ enum net_verdict tp_input(struct net_conn *net_conn, responded = true; NET_DBG("tcp_send(\"%s\")", tp->data); { - struct net_pkt *data_pkt; - - data_pkt = tcp_pkt_alloc(conn, len); - net_pkt_write(data_pkt, buf, len); - net_pkt_cursor_init(data_pkt); - net_tcp_queue_data(conn->context, data_pkt); + net_tcp_queue(conn->context, buf, len); } } break; diff --git a/subsys/net/ip/tcp.h b/subsys/net/ip/tcp.h index f6f481d5443..162407710eb 100644 --- a/subsys/net/ip/tcp.h +++ b/subsys/net/ip/tcp.h @@ -31,6 +31,7 @@ extern "C" { #endif +#include #include /** @@ -72,18 +73,7 @@ int net_tcp_listen(struct net_context *context); */ int net_tcp_accept(struct net_context *context, net_tcp_accept_cb_t cb, void *user_data); -/** - * @brief Enqueue data for transmission - * - * @param context Network context - * @param buf Pointer to the data - * @param len Number of bytes - * @param msghdr Data for a vector array operation - * - * @return 0 if ok, < 0 if error - */ -int net_tcp_queue(struct net_context *context, const void *buf, size_t len, - const struct msghdr *msghdr); + /* TODO: split into 2 functions, conn -> context, queue -> send? */ /* The following functions are provided solely for the compatibility @@ -112,7 +102,6 @@ void net_tcp_init(void); #define net_tcp_init(...) #endif int net_tcp_update_recv_wnd(struct net_context *context, int32_t delta); -int net_tcp_queue_data(struct net_context *context, struct net_pkt *pkt); int net_tcp_finalize(struct net_pkt *pkt); #if defined(CONFIG_NET_TEST_PROTOCOL) diff --git a/subsys/net/ip/tcp_internal.h b/subsys/net/ip/tcp_internal.h index e76ba859e49..17d4581aa3d 100644 --- a/subsys/net/ip/tcp_internal.h +++ b/subsys/net/ip/tcp_internal.h @@ -282,21 +282,27 @@ struct net_tcp_hdr *net_tcp_input(struct net_pkt *pkt, #endif /** - * @brief Enqueue a single packet for transmission + * @brief Enqueue data for transmission * - * @param context TCP context - * @param pkt Packet + * @param context Network context + * @param data Pointer to the data + * @param len Number of bytes + * @param msg Data for a vector array operation * * @return 0 if ok, < 0 if error */ #if defined(CONFIG_NET_NATIVE_TCP) -int net_tcp_queue_data(struct net_context *context, struct net_pkt *pkt); +int net_tcp_queue(struct net_context *context, const void *data, size_t len, + const struct msghdr *msg); #else -static inline int net_tcp_queue_data(struct net_context *context, - struct net_pkt *pkt) +static inline int net_tcp_queue(struct net_context *context, const void *data, + size_t len, const struct msghdr *msg) { ARG_UNUSED(context); - ARG_UNUSED(pkt); + ARG_UNUSED(data); + ARG_UNUSED(len); + ARG_UNUSED(msg); + return -EPROTONOSUPPORT; } #endif From f165bb7517c01c00eb42db01404408d7a2731ce0 Mon Sep 17 00:00:00 2001 From: Robert Lubos Date: Wed, 15 Nov 2023 16:32:22 +0100 Subject: [PATCH 418/421] [nrf fromlist] net: tcp: Feed TX semaphore on connection close Otherwise, if the application was for example blocked on poll() pending POLLOUT, it won't be notified. Upstream PR: https://github.com/zephyrproject-rtos/zephyr/pull/65251 Signed-off-by: Robert Lubos --- subsys/net/ip/tcp.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/subsys/net/ip/tcp.c b/subsys/net/ip/tcp.c index 2e70824b8ed..680fdcecb85 100644 --- a/subsys/net/ip/tcp.c +++ b/subsys/net/ip/tcp.c @@ -621,6 +621,8 @@ static int tcp_conn_close(struct tcp *conn, int status) status, conn->recv_user_data); } + k_sem_give(&conn->tx_sem); + return tcp_conn_unref(conn); } From 67fddd31afce6d47ae8645fc40a4479e26d23965 Mon Sep 17 00:00:00 2001 From: Robert Lubos Date: Wed, 15 Nov 2023 16:33:24 +0100 Subject: [PATCH 419/421] [nrf fromlist] net: sockets: tls: Set errno on TX waiting error In case underlying socket reported error while waiting for TX, the errno value was not set accordingly. This commit fixes this. Upstream PR: https://github.com/zephyrproject-rtos/zephyr/pull/65251 Signed-off-by: Robert Lubos --- subsys/net/lib/sockets/sockets_tls.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/subsys/net/lib/sockets/sockets_tls.c b/subsys/net/lib/sockets/sockets_tls.c index 20fdc3617af..f77bf51d668 100644 --- a/subsys/net/lib/sockets/sockets_tls.c +++ b/subsys/net/lib/sockets/sockets_tls.c @@ -2230,10 +2230,9 @@ static ssize_t send_tls(struct tls_context *ctx, const void *buf, timeout_ms = timeout_to_ms(&timeout); ret = wait_for_reason(ctx->sock, timeout_ms, ret); if (ret != 0) { - /* Retry. */ + errno = -ret; break; } - } else { (void)tls_mbedtls_reset(ctx); errno = EIO; From e8c9775db7c7dbdb833e025038d6067983ae4cad Mon Sep 17 00:00:00 2001 From: Robert Lubos Date: Wed, 15 Nov 2023 17:49:00 +0100 Subject: [PATCH 420/421] [nrf fromlist] net: zperf: Fix TCP packet counting Make sure we send the entire packet buffer before bumping the packet counter, send() does not guarantee that all of the requested data will be sent at once with STREAM socket. Upstream PR: https://github.com/zephyrproject-rtos/zephyr/pull/65251 Signed-off-by: Robert Lubos --- subsys/net/lib/zperf/zperf_tcp_uploader.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/subsys/net/lib/zperf/zperf_tcp_uploader.c b/subsys/net/lib/zperf/zperf_tcp_uploader.c index 3e72f81e54b..5fcc0530c5c 100644 --- a/subsys/net/lib/zperf/zperf_tcp_uploader.c +++ b/subsys/net/lib/zperf/zperf_tcp_uploader.c @@ -20,6 +20,22 @@ static char sample_packet[PACKET_SIZE_MAX]; static struct zperf_async_upload_context tcp_async_upload_ctx; +static ssize_t sendall(int sock, const void *buf, size_t len) +{ + while (len) { + ssize_t out_len = zsock_send(sock, buf, len, 0); + + if (out_len < 0) { + return out_len; + } + + buf = (const char *)buf + out_len; + len -= out_len; + } + + return 0; +} + static int tcp_upload(int sock, unsigned int duration_in_ms, unsigned int packet_size, @@ -50,7 +66,7 @@ static int tcp_upload(int sock, do { /* Send the packet */ - ret = zsock_send(sock, sample_packet, packet_size, 0); + ret = sendall(sock, sample_packet, packet_size); if (ret < 0) { if (nb_errors == 0 && ret != -ENOMEM) { NET_ERR("Failed to send the packet (%d)", errno); From 972ad64fcdd8ab60bb6bc260b6b3d8aac8241370 Mon Sep 17 00:00:00 2001 From: Bernard Lee Date: Fri, 25 Aug 2023 10:03:03 +0800 Subject: [PATCH 421/421] [nrf noup] ci: Trim the Gazell change scope Run CI Gazell tests only when the Zephyr API parts called is changed. Signed-off-by: Bernard Lee --- .github/test-spec.yml | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/.github/test-spec.yml b/.github/test-spec.yml index 789f1a4e235..196074fca1b 100644 --- a/.github/test-spec.yml +++ b/.github/test-spec.yml @@ -177,7 +177,15 @@ - "**/*" "CI-gazell-test": - - "**/*" + - "include/zephyr/crypto/**/*" + - "include/zephyr/drivers/clock_control.h" + - "include/zephyr/drivers/clock_control/**/*" + - "include/zephyr/drivers/entropy.h" + - "include/zephyr/settings/**/*" + - "drivers/clock_control/**/*" + - "drivers/crypto/**/*" + - "drivers/entropy/**/*" + - "subsys/settings/**/*" "CI-rpc-test": - "**/*"