From 05bde23b96dadb4557dd6c8356287dfb8f35b5c4 Mon Sep 17 00:00:00 2001 From: Carles Cufi Date: Fri, 30 Nov 2018 14:07:56 +0100 Subject: [PATCH 001/207] [nrf noup] ci: NCS-specific CI tweaks Necessary changes for NCS CI. - compliance: Add an additional check for sauce tags. Also, since, in the code, we refer to Kconfig symbols that are defined in the sdk-nrf repository, the Kconfig check will not pass. Use KconfigBasic instead, which will not grep the code for instances of CONFIG_. - Add a Jenkinsfile. - Extend the max commit line lengths for Gitlint. Signed-off-by: Carles Cufi (cherry picked from commit 83f7974bc454e7ff719bd0f32c2ce45317b5c7e7) --- .github/workflows/compliance.yml | 4 +++- .gitlint | 4 ++-- Jenkinsfile | 5 +++++ 3 files changed, 10 insertions(+), 3 deletions(-) create mode 100644 Jenkinsfile diff --git a/.github/workflows/compliance.yml b/.github/workflows/compliance.yml index 7abcd1243fc..760787bbf04 100644 --- a/.github/workflows/compliance.yml +++ b/.github/workflows/compliance.yml @@ -53,6 +53,8 @@ jobs: git config --global user.email "you@example.com" git config --global user.name "Your Name" git remote -v + # Sauce tag checks before rebasing + git log --oneline --first-parent origin/${BASE_REF}..HEAD | grep -E -v "\[nrf (mergeup|fromtree|fromlist|noup)\]" && { echo 'Sauce tag missing'; exit 1; } git rebase origin/${BASE_REF} # debug git log --pretty=oneline | head -n 10 @@ -69,7 +71,7 @@ jobs: # debug ls -la git log --pretty=oneline | head -n 10 - ./scripts/ci/check_compliance.py -m Codeowners -m Devicetree -m Gitlint -m Identity -m Nits -m pylint -m checkpatch -m Kconfig -c origin/${BASE_REF}.. + ./scripts/ci/check_compliance.py -m Codeowners -m Devicetree -m Gitlint -m Identity -m Nits -m pylint -m checkpatch -m KconfigBasic -c origin/${BASE_REF}.. - name: upload-results uses: actions/upload-artifact@master diff --git a/.gitlint b/.gitlint index 851fd915d38..b05227ed86f 100644 --- a/.gitlint +++ b/.gitlint @@ -13,7 +13,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 @@ -39,7 +39,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 04230f071417e5ddba7a8234acb38f817908df51 Mon Sep 17 00:00:00 2001 From: Torsten Rasmussen Date: Tue, 26 Jan 2021 15:43:08 +0100 Subject: [PATCH 002/207] [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 ad7f60e54ad1a7e08aae58aeb5e4e53f9be8f8d7) --- 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 7ddb20044b8..2dc7f68a928 100755 --- a/scripts/ci/check_compliance.py +++ b/scripts/ci/check_compliance.py @@ -257,6 +257,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() @@ -266,6 +273,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 parse_kconfig(self): From 767ebb1d6b818d54496812d3232b04324138ab6a Mon Sep 17 00:00:00 2001 From: Maciej Perkowski Date: Wed, 26 Jan 2022 13:43:55 +0100 Subject: [PATCH 003/207] [nrf noup] ci: workflows: set the name of checkout repo to zephyr MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit West update cannot import submanifests because the repo is checked out as "sdk-zephyr". This patch sets the checkout dir to "zephyr" in a variety of places where that's required for NCS. Signed-off-by: Maciej Perkowski Signed-off-by: Martí Bolívar (cherry picked from commit 75a8006fd25980664dc048bad3a716f48edc7a35) (cherry picked from commit 9f76a85ab2b2084492b9ce3b45a96c2189c8921a) --- .github/workflows/bluetooth.yaml | 5 ++++- .github/workflows/clang.yaml | 11 +++++++++-- .github/workflows/compliance.yml | 8 +++++++- .github/workflows/doc-build.yml | 22 ++++++++++++++++------ .github/workflows/twister_tests.yml | 3 +++ 5 files changed, 39 insertions(+), 10 deletions(-) diff --git a/.github/workflows/bluetooth.yaml b/.github/workflows/bluetooth.yaml index a52e9f27f6b..1ccd2d53e80 100644 --- a/.github/workflows/bluetooth.yaml +++ b/.github/workflows/bluetooth.yaml @@ -42,14 +42,17 @@ jobs: with: ref: ${{ github.event.pull_request.head.sha }} fetch-depth: 0 + path: ./zephyr - name: west setup + working-directory: ./zephyr run: | west init -l . || true west config --global update.narrow true west update 2>&1 1> west.update.log || west update 2>&1 1> west.update2.log - name: Run Bluetooth Tests with BSIM + working-directory: ./zephyr run: | export ZEPHYR_BASE=${PWD} WORK_DIR=${ZEPHYR_BASE}/bsim_bt_out tests/bluetooth/bsim_bt/compile.sh @@ -61,7 +64,7 @@ jobs: uses: actions/upload-artifact@v2 with: name: Bluetooth Test Results - path: ./bsim_bt_out/bsim_results.xml + path: ./zephyr/bsim_bt_out/bsim_results.xml bluetooth-test-results: name: "Publish Bluetooth Test Results" diff --git a/.github/workflows/clang.yaml b/.github/workflows/clang.yaml index 29464db4b2c..5732e6f492c 100644 --- a/.github/workflows/clang.yaml +++ b/.github/workflows/clang.yaml @@ -11,7 +11,7 @@ jobs: with: access_token: ${{ github.token }} clang-build: - runs-on: zephyr_runner + runs-on: ubuntu-latest needs: clang-build-prep container: image: zephyrprojectrtos/ci:v0.21.0 @@ -39,8 +39,10 @@ jobs: with: ref: ${{ github.event.pull_request.head.sha }} fetch-depth: 0 + path: ./zephyr - name: Environment Setup + working-directory: ./zephyr run: | pip3 install GitPython echo "$HOME/.local/bin" >> $GITHUB_PATH @@ -59,6 +61,7 @@ jobs: west update --path-cache /github/cache/zephyrproject 2>&1 1> west.log || west update --path-cache /github/cache/zephyrproject 2>&1 1> west2.log || ( rm -rf ../modules ../bootloader ../tools && west update --path-cache /github/cache/zephyrproject) - name: Check Environment + working-directory: ./zephyr run: | cmake --version ${CLANG_ROOT_DIR}/bin/clang --version @@ -66,6 +69,7 @@ jobs: ls -la - name: Prepare ccache timestamp/data + working-directory: ./zephyr id: ccache_cache_timestamp shell: cmake -P {0} run: | @@ -85,11 +89,13 @@ jobs: aws-region: us-east-2 - name: ccache stats initial + working-directory: ./zephyr run: | test -d github/home/.ccache && rm -rf /github/home/.ccache && mv github/home/.ccache /github/home/.ccache ccache -M 10G -s - name: Run Tests with Twister + working-directory: ./zephyr id: twister run: | export ZEPHYR_BASE=${PWD} @@ -109,6 +115,7 @@ jobs: fi - name: ccache stats post + working-directory: ./zephyr run: | ccache -s @@ -117,7 +124,7 @@ jobs: uses: actions/upload-artifact@v2 with: name: Unit Test Results (Subset ${{ matrix.platform }}) - path: twister-out/twister.xml + path: zephyr/twister-out/twister.xml clang-build-results: name: "Publish Unit Tests Results" diff --git a/.github/workflows/compliance.yml b/.github/workflows/compliance.yml index 760787bbf04..184fb057417 100644 --- a/.github/workflows/compliance.yml +++ b/.github/workflows/compliance.yml @@ -12,7 +12,9 @@ jobs: with: ref: ${{ github.event.pull_request.head.sha }} fetch-depth: 0 + path: ./zephyr - name: Run Maintainers Script + working-directory: ./zephyr id: maintainer env: BASE_REF: ${{ github.base_ref }} @@ -32,6 +34,7 @@ jobs: with: ref: ${{ github.event.pull_request.head.sha }} fetch-depth: 0 + path: ./zephyr - name: cache-pip uses: actions/cache@v1 @@ -47,6 +50,7 @@ jobs: pip3 install west - name: west setup + working-directory: ./zephyr env: BASE_REF: ${{ github.base_ref }} run: | @@ -62,6 +66,7 @@ jobs: west update 2>&1 1> west.update.log || west update 2>&1 1> west.update2.log - name: Run Compliance Tests + working-directory: ./zephyr continue-on-error: true id: compliance env: @@ -78,9 +83,10 @@ jobs: continue-on-error: True with: name: compliance.xml - path: compliance.xml + path: zephyr/compliance.xml - name: check-warns + working-directory: ./zephyr run: | if [[ ! -s "compliance.xml" ]]; then exit 1; diff --git a/.github/workflows/doc-build.yml b/.github/workflows/doc-build.yml index cb3f365a591..9c7a4223970 100644 --- a/.github/workflows/doc-build.yml +++ b/.github/workflows/doc-build.yml @@ -44,8 +44,11 @@ jobs: steps: - name: checkout uses: actions/checkout@v2 + with: + path: ./zephyr - name: install-pkgs + working-directory: ./zephyr run: | sudo apt-get install -y ninja-build graphviz libclang1-9 libclang-cpp9 wget -q https://www.doxygen.nl/files/doxygen-${DOXYGEN_VERSION}.linux.bin.tar.gz @@ -56,20 +59,22 @@ jobs: uses: actions/cache@v1 with: path: ~/.cache/pip - key: pip-${{ hashFiles('scripts/requirements-doc.txt') }} + key: pip-${{ hashFiles('zephyr/scripts/requirements-doc.txt') }} - name: install-pip run: | sudo pip3 install -U setuptools wheel pip - pip3 install -r scripts/requirements-doc.txt + pip3 install -r zephyr/scripts/requirements-doc.txt pip3 install west==${WEST_VERSION} pip3 install cmake==${CMAKE_VERSION} - name: west setup + working-directory: ./zephyr run: | west init -l . - name: build-docs + working-directory: ./zephyr run: | if [[ "$GITHUB_REF" =~ "refs/tags/v" ]]; then DOC_TAG="release" @@ -86,6 +91,7 @@ jobs: DOC_TAG=${DOC_TAG} SPHINXOPTS="-q -W -t publish" make -C doc ${DOC_TARGET} - name: compress-docs + working-directory: ./zephyr run: | tar cfJ html-output.tar.xz --directory=doc/_build html @@ -93,7 +99,7 @@ jobs: uses: actions/upload-artifact@master with: name: html-output - path: html-output.tar.xz + path: zephyr/html-output.tar.xz doc-build-pdf: name: "Documentation Build (PDF)" @@ -107,6 +113,8 @@ jobs: steps: - name: checkout uses: actions/checkout@v2 + with: + path: ./zephyr - name: install-pkgs run: | @@ -117,20 +125,22 @@ jobs: uses: actions/cache@v1 with: path: ~/.cache/pip - key: pip-${{ hashFiles('scripts/requirements-doc.txt') }} + key: pip-${{ hashFiles('zephyr/scripts/requirements-doc.txt') }} - name: install-pip run: | pip3 install -U setuptools wheel pip - pip3 install -r scripts/requirements-doc.txt + pip3 install -r zephyr/scripts/requirements-doc.txt pip3 install west==${WEST_VERSION} pip3 install cmake==${CMAKE_VERSION} - name: west setup + working-directory: ./zephyr run: | west init -l . - name: build-docs + working-directory: ./zephyr run: | if [[ "$GITHUB_REF" =~ "refs/tags/v" ]]; then DOC_TAG="release" @@ -144,4 +154,4 @@ jobs: uses: actions/upload-artifact@master with: name: pdf-output - path: doc/_build/latex/zephyr.pdf + path: zephyr/doc/_build/latex/zephyr.pdf diff --git a/.github/workflows/twister_tests.yml b/.github/workflows/twister_tests.yml index 19f747b0432..b6e93014bba 100644 --- a/.github/workflows/twister_tests.yml +++ b/.github/workflows/twister_tests.yml @@ -28,6 +28,8 @@ jobs: steps: - name: checkout uses: actions/checkout@v2 + with: + path: ./zephyr - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v1 with: @@ -44,6 +46,7 @@ jobs: run: | pip3 install pytest colorama pyyaml ply mock - name: Run pytest + working-directory: ./zephyr env: ZEPHYR_BASE: ./ ZEPHYR_TOOLCHAIN_VARIANT: zephyr From bd4254de3a0d78020630377efcbf461e271ad1b7 Mon Sep 17 00:00:00 2001 From: Robert Lubos Date: Mon, 1 Oct 2018 10:27:32 +0200 Subject: [PATCH 004/207] [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. 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: Dominik Ermel 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 (cherry picked from commit 55d771849cc1b6bd44c10431ae69a1aa7077cb6c) (cherry picked from commit d4cde89906b0738436bb566f75b6fbbf57ff741f) --- include/net/socket.h | 1 + include/net/socket_ncs.h | 110 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 111 insertions(+) create mode 100644 include/net/socket_ncs.h diff --git a/include/net/socket.h b/include/net/socket.h index 0663b19e84b..b11c1803975 100644 --- a/include/net/socket.h +++ b/include/net/socket.h @@ -27,6 +27,7 @@ #include #include #include +#include #include #ifdef __cplusplus diff --git a/include/net/socket_ncs.h b/include/net/socket_ncs.h new file mode 100644 index 00000000000..3008ea1ccfd --- /dev/null +++ b/include/net/socket_ncs.h @@ -0,0 +1,110 @@ +/* + * 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 options */ + +/** Socket option to control TLS session caching. Accepted values: + * - 0 - Disabled. + * - 1 - Enabled. + */ +#define TLS_SESSION_CACHE 10 +/** Socket option to purge session cache immediately. + * This option accepts any value. + */ +#define TLS_SESSION_CACHE_PURGE 11 +/** 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 12 + +/* 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_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 */ + +/* NCS specific socket options */ + +/** sockopt: disable all replies to unexpected traffics */ +#define SO_SILENCE_ALL 30 +/** sockopt: disable IPv4 ICMP replies */ +#define SO_IP_ECHO_REPLY 31 +/** sockopt: disable IPv6 ICMP replies */ +#define SO_IPV6_ECHO_REPLY 32 +/** 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 50 +/** sockopt: Release Assistance Indication feature: This will indicate that the + * application will not send any more data. + */ +#define SO_RAI_NO_DATA 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 +/** 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 + +#ifdef __cplusplus +} +#endif + +#endif /* ZEPHYR_INCLUDE_NET_SOCKET_NCS_H_ */ From c02b2a3deee3f6bb05ff5b33abd1506ace29ce66 Mon Sep 17 00:00:00 2001 From: Jan Tore Guggedal Date: Mon, 18 May 2020 20:50:13 +0200 Subject: [PATCH 005/207] [nrf noup] net: lib: 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 ab16331de501629e14fa965dda18a6b542c78631) --- include/net/mqtt.h | 3 +++ subsys/net/lib/mqtt/mqtt_transport_socket_tls.c | 10 ++++++++++ 2 files changed, 13 insertions(+) diff --git a/include/net/mqtt.h b/include/net/mqtt.h index a939be9f6b0..437fff18671 100644 --- a/include/net/mqtt.h +++ b/include/net/mqtt.h @@ -350,6 +350,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 d418d24f9c0..a7c8dbf95ed 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 0cfbcc2f3eec0b80b75cd498d3569378d9f07d7f Mon Sep 17 00:00:00 2001 From: Czeslaw Makarski Date: Mon, 30 Nov 2020 11:39:06 +0100 Subject: [PATCH 006/207] [nrf noup] drivers: ieee802154: secure services and tf-m MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adaptations of the upstream driver to use secure services and TF-M. This commit allows the setting of ieee802154 EUI64 address in the non-secure build by reading the FICR or UICR registers out of the secure zone. When CONFIG_BUILD_WITH_TFM=y, use tfm_platform_mem_read() to read EUI64 from the non-secure zone. Include secure_services.h header only if SPM=y. Signed-off-by: Czeslaw Makarski Signed-off-by: Eduardo Montoya Signed-off-by: Andrzej Głąbek Signed-off-by: Damian Krolik (cherry picked from commit 1a6d50b4e4c45535192bbc7b3c83ee27577e618b) --- drivers/ieee802154/ieee802154_nrf5.c | 45 ++++++++++++++++++++++++++-- 1 file changed, 42 insertions(+), 3 deletions(-) diff --git a/drivers/ieee802154/ieee802154_nrf5.c b/drivers/ieee802154/ieee802154_nrf5.c index fbf74d351b9..ee3a403f1fc 100644 --- a/drivers/ieee802154/ieee802154_nrf5.c +++ b/drivers/ieee802154/ieee802154_nrf5.c @@ -39,6 +39,14 @@ LOG_MODULE_REGISTER(LOG_MODULE_NAME); #include +#if defined(CONFIG_SOC_NRF5340_CPUAPP) && defined(CONFIG_TRUSTED_EXECUTION_NONSECURE) +#if defined(CONFIG_SPM_SERVICE_READ) +#include +#elif defined(CONFIG_BUILD_WITH_TFM) +#include +#endif +#endif + #include "ieee802154_nrf5.h" #include "nrf_802154.h" #include "nrf_802154_const.h" @@ -70,13 +78,21 @@ static struct nrf5_802154_data nrf5_data; #if defined(CONFIG_IEEE802154_NRF5_UICR_EUI64_ENABLE) #if defined(CONFIG_SOC_NRF5340_CPUAPP) +#if defined(CONFIG_TRUSTED_EXECUTION_NONSECURE) +#define EUI64_ADDR (NRF_UICR_S->OTP) +#else #define EUI64_ADDR (NRF_UICR->OTP) +#endif /* CONFIG_TRUSTED_EXECUTION_NONSECURE */ #else #define EUI64_ADDR (NRF_UICR->CUSTOMER) #endif /* CONFIG_SOC_NRF5340_CPUAPP */ #else #if defined(CONFIG_SOC_NRF5340_CPUAPP) || defined(CONFIG_SOC_NRF5340_CPUNET) +#if defined(CONFIG_TRUSTED_EXECUTION_NONSECURE) +#define EUI64_ADDR (NRF_FICR_S->INFO.DEVICEID) +#else #define EUI64_ADDR (NRF_FICR->INFO.DEVICEID) +#endif /* CONFIG_TRUSTED_EXECUTION_NONSECURE */ #else #define EUI64_ADDR (NRF_FICR->DEVICEID) #endif /* CONFIG_SOC_NRF5340_CPUAPP || CONFIG_SOC_NRF5340_CPUNET */ @@ -115,9 +131,32 @@ static void nrf5_get_eui64(uint8_t *mac) mac[index++] = IEEE802154_NRF5_VENDOR_OUI & 0xff; #endif -#if defined(CONFIG_SOC_NRF5340_CPUAPP) && \ - defined(CONFIG_TRUSTED_EXECUTION_NONSECURE) -#error Accessing EUI64 on the non-secure mode is not supported at the moment +#if defined(CONFIG_SOC_NRF5340_CPUAPP) && defined(CONFIG_TRUSTED_EXECUTION_NONSECURE) + int ret = -EPERM; +#if defined(CONFIG_SPM_SERVICE_READ) + ret = spm_request_read(&factoryAddress, + (uint32_t)&EUI64_ADDR[EUI64_ADDR_HIGH], + sizeof(factoryAddress)); +#elif defined(CONFIG_BUILD_WITH_TFM) + enum tfm_platform_err_t tfmError; + uint32_t tfmServiceError; + + tfmError = tfm_platform_mem_read(&factoryAddress, (uint32_t)&EUI64_ADDR[EUI64_ADDR_HIGH], + sizeof(factoryAddress), &tfmServiceError); + + if (tfmError == TFM_PLATFORM_ERR_SUCCESS && tfmServiceError == 0) { + ret = 0; + } else if (tfmError == TFM_PLATFORM_ERR_INVALID_PARAM) { + ret = -EINVAL; + } else if (tfmError == TFM_PLATFORM_ERR_NOT_SUPPORTED) { + ret = -ENOTSUP; + } +#endif + if (ret != 0) { + LOG_ERR("Unable to read EUI64 from the secure zone: %d", ret); + LOG_ERR("Setting EUI64 to 0"); + factoryAddress = 0ULL; + } #else /* Use device identifier assigned during the production. */ factoryAddress = (uint64_t)EUI64_ADDR[EUI64_ADDR_HIGH] << 32; From 770da847c3204e14ccbf94da4bb0dd46e1ad36e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=98yvind=20R=C3=B8nningstad?= Date: Tue, 1 Jun 2021 19:01:00 +0200 Subject: [PATCH 007/207] [nrf noup] kconfig: Disallow FPU for SPM MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add depends on !IS_SPM in config FPU. depends on !FPU gives a Kconfig dependency loop. This is not meant as a permanent solution. Signed-off-by: Øyvind Rønningstad (cherry picked from commit 26c6ff335900d62bdf1f50359cf9294871096792) --- arch/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/Kconfig b/arch/Kconfig index 1c907c9ec1f..9ae26228720 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -846,6 +846,7 @@ menu "Floating Point Options" config FPU bool "Enable floating point unit (FPU)" depends on CPU_HAS_FPU + depends on !IS_SPM help This option enables the hardware Floating Point Unit (FPU), in order to support using the floating point registers and instructions. From 689e9f3fe97e40db4c9361258069dded6f14cbee Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Tue, 5 Jan 2021 13:57:41 +0000 Subject: [PATCH 008/207] [nrf noup] boards: disable BUILD_WITH_TFM on some non-secure builds MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit SPM is the default for NCS. Revert an nRF9160-DK change to ensure that SPM is set for NCS. Similarly, the configuration for samples with non-secure nrf5340 is not supported. Ref: NCSDK-9282 Signed-off-by: Dominik Ermel Signed-off-by: Johann Fischer Signed-off-by: Andrzej Głąbek Signed-off-by: Martí Bolívar Signed-off-by: Håkon Øye Amundsen (cherry picked from commit fe168637cd125cd37d07962fa182791cf5b17c35) --- boards/arm/nrf5340dk_nrf5340/Kconfig.defconfig | 5 ++++- boards/arm/nrf9160dk_nrf9160/Kconfig.defconfig | 6 ------ 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/boards/arm/nrf5340dk_nrf5340/Kconfig.defconfig b/boards/arm/nrf5340dk_nrf5340/Kconfig.defconfig index ce5086e5052..ea0896d8c3f 100644 --- a/boards/arm/nrf5340dk_nrf5340/Kconfig.defconfig +++ b/boards/arm/nrf5340dk_nrf5340/Kconfig.defconfig @@ -12,7 +12,10 @@ config BOARD # force building with TF-M as the Secure Execution Environment. config BUILD_WITH_TFM - default y if BOARD_NRF5340DK_NRF5340_CPUAPP_NS + # Temporarily disable building Non-Secure images with TF-M support by + # default. + # default y if BOARD_NRF5340DK_NRF5340_CPUAPP_NS + default n if BUILD_WITH_TFM diff --git a/boards/arm/nrf9160dk_nrf9160/Kconfig.defconfig b/boards/arm/nrf9160dk_nrf9160/Kconfig.defconfig index 4b30798ae73..e51bc95b55d 100644 --- a/boards/arm/nrf9160dk_nrf9160/Kconfig.defconfig +++ b/boards/arm/nrf9160dk_nrf9160/Kconfig.defconfig @@ -8,12 +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, -# force 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 From 2d8363a813289e6274d667375337860803124a0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=98yvind=20R=C3=B8nningstad?= Date: Thu, 3 Jun 2021 10:39:10 +0200 Subject: [PATCH 009/207] [nrf noup] tfm: Kconfig: Disable TFM_BL2 when using CryptoCell MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit NOTE: This is a workaround to avoid a regression. There is a regression in nrf_security with regards to building BL2 and Crypto Services making the BL2 non-functional. This will be resolved later. Signed-off-by: Øyvind Rønningstad (cherry picked from commit 2671126d02aa99a2300af349cdfdfc662279475a) --- modules/trusted-firmware-m/Kconfig.tfm | 3 +++ 1 file changed, 3 insertions(+) diff --git a/modules/trusted-firmware-m/Kconfig.tfm b/modules/trusted-firmware-m/Kconfig.tfm index e1c30796b4c..dffb1265686 100644 --- a/modules/trusted-firmware-m/Kconfig.tfm +++ b/modules/trusted-firmware-m/Kconfig.tfm @@ -169,9 +169,12 @@ config TFM_ITS_MAX_ASSET_SIZE config TFM_BL2 bool "Add MCUboot to TFM" default y + depends on !NORDIC_SECURITY_BACKEND help TFM is designed to run with MCUboot in a certain configuration. This config adds MCUboot to the build - built via TFM's build system. + We currently do not support builds with MCUboot and TF-M if the + Nordic Security backend is used. if TFM_BL2 From 3b34482737710058be96bbfd4913027d4f864f00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Frank=20Audun=20Kvamtr=C3=B8?= Date: Mon, 26 Apr 2021 08:07:14 +0200 Subject: [PATCH 010/207] [nrf noup] samples: echo_server: add overlay-tfm MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Hopefully, this change can be dropped at some point when code is reworked. Override some configuration settings. Signed-off-by: Frank Audun Kvamtrø Signed-off-by: Torsten Rasmussen (cherry picked from commit 92b131a1398397c1b9c7e70f63273812f41dde08) --- samples/net/sockets/echo_server/overlay-tfm.conf | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 samples/net/sockets/echo_server/overlay-tfm.conf diff --git a/samples/net/sockets/echo_server/overlay-tfm.conf b/samples/net/sockets/echo_server/overlay-tfm.conf new file mode 100644 index 00000000000..44e2ab32b70 --- /dev/null +++ b/samples/net/sockets/echo_server/overlay-tfm.conf @@ -0,0 +1,7 @@ +# Kconfig fragment for building with TF-M and nRF Security +CONFIG_BUILD_WITH_TFM=y +CONFIG_NORDIC_SECURITY_BACKEND=y +CONFIG_MBEDTLS_PSA_CRYPTO_C=y + +CONFIG_MBEDTLS_ENABLE_HEAP=y +CONFIG_MBEDTLS_HEAP_SIZE=8192 From 3a4054672c18a8b0f3d366d896874d1961e5f382 Mon Sep 17 00:00:00 2001 From: Azizah Ibrahim Date: Wed, 7 Apr 2021 13:03:19 +0100 Subject: [PATCH 011/207] [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 194c11196a29ac537ebb9100dcc5d1a189658eb4) --- 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 9d9ba23fa1edf59c436fc81e25dbb3b5a622e3ea Mon Sep 17 00:00:00 2001 From: Joakim Andersson Date: Fri, 20 Nov 2020 14:44:03 +0100 Subject: [PATCH 012/207] [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. Signed-off-by: Joakim Andersson Signed-off-by: Trond Einar Snekvik Signed-off-by: Martí Bolívar Signed-off-by: Robert Lubos (cherry picked from commit 3f7a45c9a322e23e1fb468611e69eda1ed25d163) --- subsys/bluetooth/Kconfig.adv | 3 +-- subsys/bluetooth/controller/Kconfig | 3 ++- subsys/bluetooth/host/Kconfig.l2cap | 3 ++- subsys/bluetooth/mesh/Kconfig | 3 ++- 4 files changed, 7 insertions(+), 5 deletions(-) diff --git a/subsys/bluetooth/Kconfig.adv b/subsys/bluetooth/Kconfig.adv index b051935db37..3a35d8cbb3f 100644 --- a/subsys/bluetooth/Kconfig.adv +++ b/subsys/bluetooth/Kconfig.adv @@ -15,8 +15,7 @@ config BT_LIM_ADV_TIMEOUT than 180s. config BT_EXT_ADV - bool "Extended Advertising and Scanning support [EXPERIMENTAL]" - select EXPERIMENTAL + bool "Extended Advertising and Scanning support" help Select this to enable Extended Advertising API support. This enables support for advertising with multiple advertising sets, diff --git a/subsys/bluetooth/controller/Kconfig b/subsys/bluetooth/controller/Kconfig index 4dcf8d4084c..1c6d947237d 100644 --- a/subsys/bluetooth/controller/Kconfig +++ b/subsys/bluetooth/controller/Kconfig @@ -100,7 +100,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 BT_RECV_IS_RX_THREAD select ENTROPY_GENERATOR select NRF_HW_TIMER0_RESERVED diff --git a/subsys/bluetooth/host/Kconfig.l2cap b/subsys/bluetooth/host/Kconfig.l2cap index 514e5bf31c1..dc94fbf5c9a 100644 --- a/subsys/bluetooth/host/Kconfig.l2cap +++ b/subsys/bluetooth/host/Kconfig.l2cap @@ -46,7 +46,8 @@ 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]" + select EXPERIMENTAL depends on BT_L2CAP_DYNAMIC_CHANNEL help This option enables support for LE Connection oriented Channels with diff --git a/subsys/bluetooth/mesh/Kconfig b/subsys/bluetooth/mesh/Kconfig index 5f97d60fb9f..9eeba460688 100644 --- a/subsys/bluetooth/mesh/Kconfig +++ b/subsys/bluetooth/mesh/Kconfig @@ -4,7 +4,8 @@ # SPDX-License-Identifier: Apache-2.0 menuconfig BT_MESH - bool "Bluetooth mesh support" + bool "Bluetooth mesh support [EXPERIMENTAL]" + select EXPERIMENTAL select TINYCRYPT select TINYCRYPT_AES select TINYCRYPT_AES_CMAC From 1be5e92fba59ed14a4bb7c4b63c5353898d2eaee Mon Sep 17 00:00:00 2001 From: Sigvart Hovland Date: Fri, 3 May 2019 14:21:52 +0200 Subject: [PATCH 013/207] [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: Dominik Ermel 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 (cherry picked from commit 32b99c7063bc0bb25fd1dbe868e8d789a9bfc3e8) (cherry picked from commit 30f63cb384fccdfd917787bcf93dc0a94425fba0) (cherry picked from commit c1017afdf66982c039dc6d77d21b9d4fba477abc) --- Kconfig.zephyr | 4 +- cmake/app/boilerplate.cmake | 4 ++ drivers/flash/soc_flash_nrf.c | 14 ++++++ .../arm/aarch32/cortex_m/scripts/linker.ld | 46 +++++++++++++++++++ include/storage/flash_map.h | 7 +++ soc/arm/common/cortex_m/arm_mpu_regions.c | 14 ++++++ subsys/fs/littlefs_fs.c | 12 ++++- subsys/ipc/rpmsg_service/rpmsg_backend.h | 27 +++++++++++ 8 files changed, 124 insertions(+), 4 deletions(-) diff --git a/Kconfig.zephyr b/Kconfig.zephyr index d2d3e0a8db1..ae6835721fd 100644 --- a/Kconfig.zephyr +++ b/Kconfig.zephyr @@ -120,9 +120,7 @@ config FLASH_LOAD_SIZE endif # HAS_FLASH_LOAD_OFFSET config ROM_START_OFFSET - hex - prompt "ROM start offset" if !BOOTLOADER_MCUBOOT - default 0x200 if BOOTLOADER_MCUBOOT + hex "ROM start offset" default 0 help If the application is built for chain-loading by a bootloader this diff --git a/cmake/app/boilerplate.cmake b/cmake/app/boilerplate.cmake index 6102d739c9f..ea9cfb8f88b 100644 --- a/cmake/app/boilerplate.cmake +++ b/cmake/app/boilerplate.cmake @@ -674,6 +674,10 @@ set_property(TARGET app PROPERTY ARCHIVE_OUTPUT_DIRECTORY app) add_subdirectory(${ZEPHYR_BASE} ${__build_dir}) +if(ZEPHYR_NRF_MODULE_DIR) + include(${ZEPHYR_NRF_MODULE_DIR}/cmake/partition_manager.cmake) +endif() + # Link 'app' with the Zephyr interface libraries. # # NB: This must be done in boilerplate.cmake because 'app' can only be diff --git a/drivers/flash/soc_flash_nrf.c b/drivers/flash/soc_flash_nrf.c index f6833430cb6..81e6b3aab39 100644 --- a/drivers/flash/soc_flash_nrf.c +++ b/drivers/flash/soc_flash_nrf.c @@ -37,6 +37,13 @@ LOG_MODULE_REGISTER(flash_nrf); #define SOC_NV_FLASH_NODE DT_INST(0, soc_nv_flash) +#if CONFIG_ARM_NONSECURE_FIRMWARE && CONFIG_SPM +#include +#if USE_PARTITION_MANAGER +#include +#endif /* USE_PARTITION_MANAGER */ +#endif /* CONFIG_ARM_NONSECURE_FIRMWARE && CONFIG_SPM */ + #ifndef CONFIG_SOC_FLASH_NRF_RADIO_SYNC_NONE #define FLASH_SLOT_WRITE 7500 #if defined(CONFIG_SOC_FLASH_NRF_PARTIAL_ERASE) @@ -146,6 +153,13 @@ static int flash_nrf_read(const struct device *dev, off_t addr, return 0; } +#if CONFIG_ARM_NONSECURE_FIRMWARE && CONFIG_SPM && USE_PARTITION_MANAGER \ + && CONFIG_SPM_SECURE_SERVICES + if (addr < PM_APP_ADDRESS) { + return spm_request_read(data, addr, len); + } +#endif + memcpy(data, (void *)addr, len); return 0; diff --git a/include/arch/arm/aarch32/cortex_m/scripts/linker.ld b/include/arch/arm/aarch32/cortex_m/scripts/linker.ld index 6ccb15dbc75..87f2063c917 100644 --- a/include/arch/arm/aarch32/cortex_m/scripts/linker.ld +++ b/include/arch/arm/aarch32/cortex_m/scripts/linker.ld @@ -28,6 +28,35 @@ #define RAMABLE_REGION SRAM #endif +#if USE_PARTITION_MANAGER + +#include + +#if CONFIG_NCS_IS_VARIANT_IMAGE +/* 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 @@ -54,6 +83,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/storage/flash_map.h b/include/storage/flash_map.h index dda7f78a513..08eb4fcbfa5 100644 --- a/include/storage/flash_map.h +++ b/include/storage/flash_map.h @@ -256,6 +256,10 @@ const struct device *flash_area_get_device(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) \ DT_HAS_FIXED_PARTITION_LABEL(label) @@ -281,6 +285,9 @@ uint8_t flash_area_erased_val(const struct flash_area *fa); #define FLASH_AREA_DEVICE(label) \ DEVICE_DT_GET(DT_MTD_FROM_FIXED_PARTITION(DT_NODE_BY_FIXED_PARTITION_LABEL(label))) + +#endif /* USE_PARTITION_MANAGER */ + #ifdef __cplusplus } #endif diff --git a/soc/arm/common/cortex_m/arm_mpu_regions.c b/soc/arm/common/cortex_m/arm_mpu_regions.c index 6ba05377ba5..f1bca61ef14 100644 --- a/soc/arm/common/cortex_m/arm_mpu_regions.c +++ b/soc/arm/common/cortex_m/arm_mpu_regions.c @@ -8,6 +8,9 @@ #include #include "arm_mpu_mem_cfg.h" +#if USE_PARTITION_MANAGER +#include +#endif static const struct arm_mpu_region mpu_regions[] = { /* Region 0 */ @@ -21,6 +24,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, \ @@ -28,6 +39,9 @@ static const struct arm_mpu_region mpu_regions[] = { #else REGION_RAM_ATTR(REGION_SRAM_SIZE)), #endif + +#endif /* USE_PARTITION_MANAGER */ + }; const struct arm_mpu_config mpu_config = { diff --git a/subsys/fs/littlefs_fs.c b/subsys/fs/littlefs_fs.c index f9b2bb621bd..85718d5983f 100644 --- a/subsys/fs/littlefs_fs.c +++ b/subsys/fs/littlefs_fs.c @@ -775,6 +775,12 @@ static const struct fs_file_system_t littlefs_fs = { .statvfs = littlefs_statvfs, }; +#ifdef USE_PARTITION_MANAGER +#define _LFS_USE_NCS_PM 1 +#else +#define _LFS_USE_NCS_PM 0 +#endif + #define DT_DRV_COMPAT zephyr_fstab_littlefs #define FS_PARTITION(inst) DT_PHANDLE_BY_IDX(DT_DRV_INST(inst), partition, 0) @@ -809,7 +815,11 @@ 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 *) (_LFS_USE_NCS_PM ?\ + COND_CODE_1(FLASH_AREA_LABEL_EXISTS(littlefs_storage), \ + (FLASH_AREA_ID(littlefs_storage)), \ + (FLASH_AREA_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 ab5df7c4297..b4adec43445 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 CONFIG_RPMSG_SERVICE_SHM_BASE_ADDRESS #define VDEV_SIZE CONFIG_RPMSG_SERVICE_SHM_SIZE +#endif /* defined(PM_RPMSG_NRF53_SRAM_ADDRESS) || defined(PM__RPMSG_NRF53_SRAM_ADDRESS) */ + +#else + +#define VDEV_START_ADDR CONFIG_RPMSG_SERVICE_SHM_BASE_ADDRESS +#define VDEV_SIZE CONFIG_RPMSG_SERVICE_SHM_SIZE + +#endif /* CONFIG_PARTITION_MANAGER_ENABLED */ #define VDEV_STATUS_ADDR VDEV_START_ADDR #define VDEV_STATUS_SIZE 0x400 From 3cce74e9dfe035f94dfdf68470f8bcdf1dde268a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=AD=20Bol=C3=ADvar?= Date: Fri, 24 Apr 2020 16:20:07 -0700 Subject: [PATCH 014/207] [nrf noup] dts: choose cryptocell for entropy when available MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is a noup patch because driver support is NCS-only. Add compatibles for CC310 and CC312 NS access. These downstream-only compatibles allow accessing the cryptocell from non-secure code. Use these, as well as pre-existing nodes for accessing the hardware directly from the secure world, in the relevant .dtsi files. Signed-off-by: Martí Bolívar Signed-off-by: Joakim Andersson Signed-off-by: Frank Audun Kvamtrø Signed-off-by: Ioannis Glaropoulos Signed-off-by: Robert Lubos (cherry picked from commit 6a6883488143f36ab975d527f7f40ecd7550ad10) --- dts/arm/nordic/nrf52840.dtsi | 2 +- dts/arm/nordic/nrf5340_cpuapp.dtsi | 1 + dts/arm/nordic/nrf5340_cpuappns.dtsi | 16 ++++++++++++++++ dts/arm/nordic/nrf9160.dtsi | 1 + dts/arm/nordic/nrf9160ns.dtsi | 16 ++++++++++++++++ dts/bindings/crypto/nordic,nrf-cc310-sw.yaml | 17 +++++++++++++++++ dts/bindings/crypto/nordic,nrf-cc312-sw.yaml | 17 +++++++++++++++++ 7 files changed, 69 insertions(+), 1 deletion(-) create mode 100644 dts/bindings/crypto/nordic,nrf-cc310-sw.yaml create mode 100644 dts/bindings/crypto/nordic,nrf-cc312-sw.yaml diff --git a/dts/arm/nordic/nrf52840.dtsi b/dts/arm/nordic/nrf52840.dtsi index 93ddfd1be5f..db6ff79b740 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 b65ed1cdc0d..6c4bf87ddfb 100644 --- a/dts/arm/nordic/nrf5340_cpuapp.dtsi +++ b/dts/arm/nordic/nrf5340_cpuapp.dtsi @@ -28,6 +28,7 @@ }; chosen { + zephyr,entropy = &cryptocell; zephyr,flash-controller = &flash_controller; }; diff --git a/dts/arm/nordic/nrf5340_cpuappns.dtsi b/dts/arm/nordic/nrf5340_cpuappns.dtsi index eb39f04ff40..1620249c767 100644 --- a/dts/arm/nordic/nrf5340_cpuappns.dtsi +++ b/dts/arm/nordic/nrf5340_cpuappns.dtsi @@ -30,6 +30,15 @@ chosen { zephyr,flash-controller = &flash_controller; + + /* + * By default, system entropy comes from the entropy_cc310.c + * driver in the nrf repository. This is devicetree glue + * needed to make the system aware of that fact. Individual + * applications can override this by changing this property + * value. + */ + zephyr,entropy = &cryptocell_sw; }; soc { @@ -48,6 +57,13 @@ #include "nrf5340_cpuapp_peripherals.dtsi" }; }; + + /* For cryptocell access via platform library; see above */ + cryptocell_sw: cryptocell-sw { + compatible = "nordic,nrf-cc312-sw"; + #address-cells = <0>; + label = "CRYPTOCELL_SW"; + }; }; &nvic { diff --git a/dts/arm/nordic/nrf9160.dtsi b/dts/arm/nordic/nrf9160.dtsi index 09b030d1358..e797d79ab52 100644 --- a/dts/arm/nordic/nrf9160.dtsi +++ b/dts/arm/nordic/nrf9160.dtsi @@ -28,6 +28,7 @@ }; chosen { + zephyr,entropy = &cryptocell; zephyr,flash-controller = &flash_controller; }; diff --git a/dts/arm/nordic/nrf9160ns.dtsi b/dts/arm/nordic/nrf9160ns.dtsi index 1742580e76c..a85dada2ba6 100644 --- a/dts/arm/nordic/nrf9160ns.dtsi +++ b/dts/arm/nordic/nrf9160ns.dtsi @@ -29,6 +29,15 @@ chosen { zephyr,flash-controller = &flash_controller; + + /* + * By default, system entropy comes from the entropy_cc310.c + * driver in the nrf repository. This is devicetree glue + * needed to make the system aware of that fact. Individual + * applications can override this by changing this property + * value. + */ + zephyr,entropy = &cryptocell_sw; }; soc { @@ -54,6 +63,13 @@ label = "GPIOTE_1"; }; }; + + + /* For cryptocell access via platform library; see above */ + cryptocell_sw: cryptocell-sw { + compatible = "nordic,nrf-cc310-sw"; + label = "CRYPTOCELL_SW"; + }; }; &nvic { diff --git a/dts/bindings/crypto/nordic,nrf-cc310-sw.yaml b/dts/bindings/crypto/nordic,nrf-cc310-sw.yaml new file mode 100644 index 00000000000..a0724a45938 --- /dev/null +++ b/dts/bindings/crypto/nordic,nrf-cc310-sw.yaml @@ -0,0 +1,17 @@ +# Copyright (c) 2020, Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +description: | + Stub access to cryptocell via platform driver + + Non-secure configurations can use this compatible to declare + devicetree nodes which access the CC310 via callbacks into secure + code. + +compatible: "nordic,nrf-cc310-sw" + +include: base.yaml + +properties: + label: + required: true diff --git a/dts/bindings/crypto/nordic,nrf-cc312-sw.yaml b/dts/bindings/crypto/nordic,nrf-cc312-sw.yaml new file mode 100644 index 00000000000..9c3f936bf20 --- /dev/null +++ b/dts/bindings/crypto/nordic,nrf-cc312-sw.yaml @@ -0,0 +1,17 @@ +# Copyright (c) 2021, Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +description: | + Stub access to cryptocell via platform driver + + Non-secure configurations can use this compatible to declare + devicetree nodes which access the CC312 via callbacks into secure + code. + +compatible: "nordic,nrf-cc312-sw" + +include: base.yaml + +properties: + label: + required: true From ef87deda1b86153316b623f214eff668e5b64c93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20B=C3=B8e?= Date: Wed, 29 Dec 2021 12:35:55 +0100 Subject: [PATCH 015/207] [nrf noup] kconfig: Bump python recursion limit from 1k to 5k MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Increase the python recursion limit from 1k to 5k. See python comment for details. Signed-off-by: Sebastian Bøe --- scripts/kconfig/kconfiglib.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/scripts/kconfig/kconfiglib.py b/scripts/kconfig/kconfiglib.py index 14142c7b742..177f1c3fff0 100644 --- a/scripts/kconfig/kconfiglib.py +++ b/scripts/kconfig/kconfiglib.py @@ -556,6 +556,16 @@ def my_other_fn(kconf, name, arg_1, arg_2, ...): VERSION = (14, 1, 0) +# Bump the recursion limit from 1k to 5k. The limit was observed to be +# broken in NCS when gen_kconfig_rest.py was executed. Specifically, +# the function expr_str would indirectly invoke itself many times. It +# appeared that the expression that was too large was one that +# contained configs from many different SoC's. Perhaps SoC's should be +# moved into Zephyr modules in the future to reduce the size of the +# Kconfig tree. Or perhaps there is another optimization that could be +# done so we don't get thousands of recursions. +sys.setrecursionlimit(5000) + # File layout: # From fd63c84a9b19f897a0eca2e8a8c5f7cc237b2c9b 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 016/207] [nrf noup] Adding PSA configurations to mbed TLS 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 Signed-off-by: Frank Audun Kvamtrø --- modules/mbedtls/Kconfig | 4 +- modules/mbedtls/Kconfig.psa | 445 ++++++++++++++++++++++++++++++++++++ 2 files changed, 448 insertions(+), 1 deletion(-) create mode 100644 modules/mbedtls/Kconfig.psa diff --git a/modules/mbedtls/Kconfig b/modules/mbedtls/Kconfig index 32aa000f1a9..96899f545d5 100644 --- a/modules/mbedtls/Kconfig +++ b/modules/mbedtls/Kconfig @@ -13,7 +13,6 @@ config MBEDTLS_PROMPTLESS mbed TLS menu prompt and instead handle the selection of MBEDTLS from dependent sub-configurations and thus preven stuck symbol behavior. - menuconfig MBEDTLS bool "mbed TLS Support" if !MBEDTLS_PROMPTLESS help @@ -167,4 +166,7 @@ config APP_LINK_WITH_MBEDTLS disabled if the include paths for MBEDTLS are causing aliasing issues for 'app'. +# Add PSA configurations +rsource "Kconfig.psa" + endif # MBEDTLS diff --git a/modules/mbedtls/Kconfig.psa b/modules/mbedtls/Kconfig.psa new file mode 100644 index 00000000000..7da962f17e9 --- /dev/null +++ b/modules/mbedtls/Kconfig.psa @@ -0,0 +1,445 @@ +# +# Copyright (c) 2022 Nordic Semiconductor +# +# SPDX-License-Identifier: Apache-2.0 +# +menu "PSA RNG support" + +config PSA_WANT_ALG_CTR_DRBG + bool + prompt "PSA RNG using CTR_DRBG" + help + Provide CTR_DRBG as the random number generator. + Note: This configuration is currently not described and has no effect. + +config PSA_WANT_ALG_HMAC_DRBG + bool + prompt "PSA RNG using HMAC_DRBG" + help + Provide HMAC_DRBG as the random number generator. + Note: This configuration is currently not described and has no effect. + +endmenu # RNG support + +menu "PSA Key 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_AES || \ + PSA_WANT_KEY_TYPE_ARIA || \ + PSA_WANT_KEY_TYPE_CAMELLIA || \ + PSA_WANT_KEY_TYPE_CHACHA20 || \ + PSA_WANT_KEY_TYPE_DES || \ + 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 + +config PSA_WANT_KEY_TYPE_DERIVE + bool + prompt "PSA Key derivation support" if !PSA_PROMPTLESS + default y if !PSA_DEFAULT_OFF + +config PSA_WANT_KEY_TYPE_HMAC + bool + prompt "PSA Key type HMAC support" if !PSA_PROMPTLESS + default y if !PSA_DEFAULT_OFF + depends on PSA_HAS_MAC_SUPPORT + +config PSA_WANT_KEY_TYPE_AES + bool + prompt "PSA Key Type AES support" if !PSA_PROMPTLESS + default y if !PSA_DEFAULT_OFF + depends on PSA_HAS_CIPHER_SUPPORT || PSA_HAS_AEAD_SUPPORT + +config PSA_WANT_KEY_TYPE_ARIA + bool + default y if !PSA_DEFAULT_OFF + help + Currently not supported + +config PSA_WANT_KEY_TYPE_CAMELLIA + bool + depends on PSA_HAS_CIPHER_SUPPORT + help + Currently not supported + +config PSA_WANT_KEY_TYPE_CHACHA20 + bool + prompt "PSA Key type Chacha20 support" if !PSA_PROMPTLESS + default y if !PSA_DEFAULT_OFF + depends on PSA_WANT_ALG_CHACHA20_POLY1305 + +config PSA_WANT_KEY_TYPE_DES + bool + depends on PSA_HAS_CIPHER_SUPPORT + help + Currently not supported + +config PSA_WANT_KEY_TYPE_ECC_KEY_PAIR + bool + prompt "PSA Key type ECC key pair support" if !PSA_PROMPTLESS + default y if !PSA_DEFAULT_OFF + depends on PSA_HAS_ECC_SUPPORT + +config PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY + bool + prompt "PSA Key type ECC public key support" if !PSA_PROMPTLESS + default y if !PSA_DEFAULT_OFF + depends on PSA_HAS_ECC_SUPPORT + +config PSA_WANT_KEY_TYPE_RAW_DATA + bool + prompt "PSA Key type RAW key support" if !PSA_PROMPTLESS + default y if !PSA_DEFAULT_OFF + +config PSA_WANT_KEY_TYPE_RSA_KEY_PAIR + bool + prompt "PSA Key type RSA key pair support" if !PSA_PROMPTLESS + default y if !PSA_DEFAULT_OFF + depends on PSA_HAS_RSA_SUPPORT + +config PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY + bool + prompt "PSA Key type RSA Public key support" if !PSA_PROMPTLESS + default y if !PSA_DEFAULT_OFF + depends on PSA_HAS_RSA_SUPPORT + +endmenu # PSA_KEY_DERIVATION + +menu "PSA AEAD support" + +config PSA_HAS_AEAD_SUPPORT + bool + default y + depends on PSA_WANT_ALG_CCM || \ + PSA_WANT_ALG_GCM || \ + PSA_WANT_ALG_CHACHA20_POLY1305 + +config PSA_WANT_ALG_CCM + bool + prompt "PSA AES CCM support" if !PSA_PROMPTLESS + default y if !PSA_DEFAULT_OFF + +config PSA_WANT_ALG_GCM + bool + prompt "PSA AES GCM support" if !PSA_PROMPTLESS + default y if !PSA_DEFAULT_OFF + +config PSA_WANT_ALG_CHACHA20_POLY1305 + bool + prompt "PSA ChaCha20/Poly1305 support" if !PSA_PROMPTLESS + default y if !PSA_DEFAULT_OFF + +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 the PSA APIs enables + a configuration that adds the PSA mac module. + +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 AES CMAC support" if !PSA_PROMPTLESS + default y if !PSA_DEFAULT_OFF + +config PSA_WANT_ALG_HMAC + bool + prompt "PSA HMAC support" if !PSA_PROMPTLESS + default y if !PSA_DEFAULT_OFF + +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 + +config PSA_WANT_ALG_SHA_1 + bool + prompt "PSA SHA1 support" if !PSA_PROMPTLESS + default y if !PSA_DEFAULT_OFF + +config PSA_WANT_ALG_SHA_224 + bool + prompt "PSA SHA-224 support" if !PSA_PROMPTLESS + default y if !PSA_DEFAULT_OFF + +config PSA_WANT_ALG_SHA_256 + bool + prompt "PSA SSH-256 support" if !PSA_PROMPTLESS + default y if !PSA_DEFAULT_OFF + +config PSA_WANT_ALG_SHA_384 + bool + prompt "PSA SHA-384 support" if !PSA_PROMPTLESS + default y if !PSA_DEFAULT_OFF + +config PSA_WANT_ALG_SHA_512 + bool + prompt "PSA SHA-512 support" if !PSA_PROMPTLESS + default y if !PSA_DEFAULT_OFF + +config PSA_WANT_ALG_RIPEMD160 + bool + prompt "PSA RIPEMD160 support" if !PSA_PROMPTLESS + default y if !PSA_DEFAULT_OFF + +config PSA_WANT_ALG_MD5 + bool + prompt "PSA MD5 support" if !PSA_PROMPTLESS + default y if !PSA_DEFAULT_OFF + +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 + help + Prompt-less configuration that states the PSA APIs enables + a configuration that adds the PSA Cipher module. + +config PSA_WANT_ALG_ECB_NO_PADDING + bool + prompt "PSA AES ECB (no padding)" if !PSA_PROMPTLESS + default y if !PSA_DEFAULT_OFF + +config PSA_WANT_ALG_CBC_NO_PADDING + bool + prompt "PSA CBC support (without padding)" if !PSA_PROMPTLESS + default y if !PSA_DEFAULT_OFF + +config PSA_WANT_ALG_CBC_PKCS7 + bool + prompt "PSA CBC support (padded with PKCS#7)" if !PSA_PROMPTLESS + default y if !PSA_DEFAULT_OFF + +config PSA_WANT_ALG_CFB + bool + prompt "PSA AES CFB support" if !PSA_PROMPTLESS + default y if !PSA_DEFAULT_OFF + +config PSA_WANT_ALG_CTR + bool + prompt "PSA AES CTR mode support" if !PSA_PROMPTLESS + default y if !PSA_DEFAULT_OFF + +config PSA_WANT_ALG_OFB + bool + prompt "PSA AES OFB mode support" if !PSA_PROMPTLESS + default y if !PSA_DEFAULT_OFF + +config PSA_WANT_ALG_XTS + bool + help + AES XTS is currently not supported + +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_PBKDF2_HMAC || \ + PSA_WANT_ALG_TLS12_PRF || \ + PSA_WANT_ALG_TLS12_PSK_TO_MS + help + Prompt-less configuration that states the PSA APIs enables + a configuration that adds the PSA key derivation module. + +config PSA_WANT_ALG_HKDF + bool + prompt "PSA HKFD support" if !PSA_PROMPTLESS + default y if !PSA_DEFAULT_OFF + depends on PSA_WANT_ALG_HMAC + +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 Assymetric 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 the PSA APIs enables + a configuration that adds the PSA Assymetric encrypt module. + + +config PSA_HAS_ASYM_SIGN_SUPPORT + bool + default y + depends on PSA_WANT_ALG_ECDSA || \ + PSA_WANT_ALG_RSA_PKCS1V15_SIGN || \ + PSA_WANT_ALG_RSA_PSS + + help + Prompt-less configuration that states the PSA APIs enables + a configuration that adds the PSA Assymetric sign module. + +config PSA_HAS_ECC_SUPPORT + bool + depends on PSA_WANT_ALG_ECDH || PSA_WANT_ALG_ECDSA || PSA_WANT_ALG_DETERMINISTIC_ECDSA + default y + help + Prompt-less configuration that states the PSA APIs enables + a configuration that adds the PSA encrypt/sign module for ECC. + +config PSA_WANT_ALG_ECDH + bool + prompt "PSA ECDH support" if !PSA_PROMPTLESS + default y if !PSA_DEFAULT_OFF + +config PSA_WANT_ALG_ECDSA + bool + prompt "PSA ECDSA support" if !PSA_PROMPTLESS + default y if !PSA_DEFAULT_OFF + +config PSA_WANT_ALG_DETERMINISTIC_ECDSA + bool + prompt "PSA ECDSA support (deterministic mode)" if !PSA_PROMPTLESS + default y if !PSA_DEFAULT_OFF + +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 support" + +config PSA_WANT_ECC_MONTGOMERY_448 + bool "PSA ECC Curve448 support" + default n + +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 + default y if !PSA_DEFAULT_OFF + +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 + default y + help + Prompt-less configuration that states the PSA APIs enables + a configuration that adds the PSA encrypt/sign module for RSA. + +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 (PKCS1V15 mode)" if !PSA_PROMPTLESS + +config PSA_WANT_ALG_RSA_PKCS1V15_SIGN + bool + prompt "PSA RSA signature support (PKCS1V15 mode)" if !PSA_PROMPTLESS + +config PSA_WANT_ALG_RSA_PSS + bool + prompt "PSA RSA (PSS mode)" if !PSA_PROMPTLESS + +endmenu # PSA_ASSYMETRIC_SUPPORT + +config PSA_WANT_ALG_STREAM_CIPHER + bool + prompt "PSA stream cipher support" if !PSA_PROMPTLESS + default y if !PSA_DEFAULT_OFF From 1dc9e6ecb5a6b25ade0e6db49fedaed1dc2c88e7 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 017/207] [nrf noup] TF-M Make 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ø --- 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 1b4f7e1b17a..eb33b9101bd 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.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 eced2a88ec3c6341d7702ef76759b57205b59d0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20B=C3=B8e?= Date: Thu, 20 Jan 2022 10:50:05 +0100 Subject: [PATCH 018/207] [nrf noup] tfm: Set CRYPTO_HW_ACCELERATOR=True MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Set CRYPTO_HW_ACCELERATOR=True. This prevents a mulitple definition error between TF-M and nrf_security. Signed-off-by: Sebastian Bøe --- modules/trusted-firmware-m/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/trusted-firmware-m/CMakeLists.txt b/modules/trusted-firmware-m/CMakeLists.txt index 6723e1b5c2b..8845fa01409 100644 --- a/modules/trusted-firmware-m/CMakeLists.txt +++ b/modules/trusted-firmware-m/CMakeLists.txt @@ -241,6 +241,7 @@ if (CONFIG_BUILD_WITH_TFM) -DCROSS_COMPILE=${TFM_TOOLCHAIN_PATH}/${TFM_TOOLCHAIN_PREFIX} -DCMAKE_BUILD_TYPE=${TFM_CMAKE_BUILD_TYPE} -DTFM_PLATFORM=${CONFIG_TFM_BOARD} + -DCRYPTO_HW_ACCELERATOR=True ${TFM_CMAKE_ARGS} $> -DTFM_TEST_REPO_PATH=${ZEPHYR_TF_M_TESTS_MODULE_DIR} From f62f740e6e7a71dc8379c119d544156b61a69916 Mon Sep 17 00:00:00 2001 From: Azizah Ibrahim Date: Fri, 21 Jan 2022 09:41:46 +0000 Subject: [PATCH 019/207] [nrf noup] modules: Make nrfx_glue work with bluetooth softdevice Make PPI channels used by softdevice visible to nrfx_glue. Signed-off-by: Azizah Ibrahim --- modules/hal_nordic/nrfx/nrfx_glue.h | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/modules/hal_nordic/nrfx/nrfx_glue.h b/modules/hal_nordic/nrfx/nrfx_glue.h index 6fef79ab101..af29ccc2538 100644 --- a/modules/hal_nordic/nrfx/nrfx_glue.h +++ b/modules/hal_nordic/nrfx/nrfx_glue.h @@ -275,11 +275,26 @@ void nrfx_busy_wait(uint32_t usec_to_wait); #define NRFX_GPIOTE_CHANNELS_USED NRFX_GPIOTE_CHANNELS_USED_BY_BT_CTLR #if defined(CONFIG_BT_CTLR) -#include <../subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5_resources.h> +#if defined(CONFIG_BT_LL_SOFTDEVICE) +#include +#if defined(PPI_PRESENT) + /* PPI channels 17 - 31, for the nRF52 Series */ + #define PPI_CHANNELS_USED_BY_CTLR (BIT_MASK(15) << 17) +#else + /* DPPI channels 0 - 13, for the nRF53 Series */ + #define PPI_CHANNELS_USED_BY_CTLR BIT_MASK(14) +#endif +#define NRFX_PPI_CHANNELS_USED_BY_BT_CTLR (PPI_CHANNELS_USED_BY_CTLR | MPSL_RESERVED_PPI_CHANNELS) +#define NRFX_PPI_GROUPS_USED_BY_BT_CTLR 0 +#define NRFX_GPIOTE_CHANNELS_USED_BY_BT_CTLR 0 +#else +#include <../subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5_resources.h> #define NRFX_PPI_CHANNELS_USED_BY_BT_CTLR BT_CTLR_USED_PPI_CHANNELS #define NRFX_PPI_GROUPS_USED_BY_BT_CTLR BT_CTLR_USED_PPI_GROUPS #define NRFX_GPIOTE_CHANNELS_USED_BY_BT_CTLR BT_CTLR_USED_GPIOTE_CHANNELS +#endif + #else #define NRFX_PPI_CHANNELS_USED_BY_BT_CTLR 0 #define NRFX_PPI_GROUPS_USED_BY_BT_CTLR 0 From b74e166e97eff0c4c8b32e6f228a6a22f6128e45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jani=20Hirsim=C3=A4ki?= Date: Wed, 12 Jan 2022 12:03:39 +0100 Subject: [PATCH 020/207] [nrf fromtree] drivers: net: ppp: async uart support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implemented an option to use asyncronous uart api (CONFIG_NET_PPP_ASYNC_UART). From https://github.com/zephyrproject-rtos/zephyr/pull/41649 Signed-off-by: Jani Hirsimäki --- drivers/net/Kconfig | 31 ++++++++ drivers/net/ppp.c | 186 ++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 212 insertions(+), 5 deletions(-) diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index c61bf461271..34ca6c2256f 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -18,6 +18,11 @@ menuconfig NET_PPP if NET_PPP +config NET_PPP_ASYNC_UART + bool "Asynchronous UART API is used" + depends on UART_ASYNC_API + depends on !GSM_MUX + config NET_PPP_UART_NAME string "UART device name the PPP is connected to" depends on !MODEM_GSM_PPP @@ -89,6 +94,32 @@ config PPP_NET_IF_NO_AUTO_START This option allows user to disable autostarting of the PPP interface immediately after initialization. +if NET_PPP_ASYNC_UART + +config NET_PPP_ASYNC_UART_TX_BUF_LEN + int "Buffer length from where the write to async UART is done" + default 2048 + help + This options sets the size of the UART TX buffer where data + is being written from to UART. + +config NET_PPP_ASYNC_UART_RX_RECOVERY_TIMEOUT + int "UART RX recovery timeout in milliseconds" + default 200 + help + The time that UART RX is in disabled state in case + when we cannot receive more data from UART. + +config NET_PPP_ASYNC_UART_RX_ENABLE_TIMEOUT + int "A timeout for uart_rx_enable()" + default 100 + +config NET_PPP_ASYNC_UART_TX_TIMEOUT + int "A timeout for uart_tx()" + default 100 + +endif # NET_PPP_ASYNC_UART + module = NET_PPP module-dep = LOG module-str = Log level for ppp driver diff --git a/drivers/net/ppp.c b/drivers/net/ppp.c index eeeee459130..f672d5d96a3 100644 --- a/drivers/net/ppp.c +++ b/drivers/net/ppp.c @@ -37,6 +37,7 @@ LOG_MODULE_REGISTER(net_ppp, LOG_LEVEL); #include "../../subsys/net/ip/net_private.h" #define UART_BUF_LEN CONFIG_NET_PPP_UART_BUF_LEN +#define UART_TX_BUF_LEN CONFIG_NET_PPP_ASYNC_UART_TX_BUF_LEN enum ppp_driver_state { STATE_HDLC_FRAME_START, @@ -61,9 +62,17 @@ struct ppp_driver_context { /* ppp data is read into this buf */ uint8_t buf[UART_BUF_LEN]; +#if defined(CONFIG_NET_PPP_ASYNC_UART) + /* with async we use 2 rx buffers */ + uint8_t buf2[UART_BUF_LEN]; + struct k_work_delayable uart_recovery_work; + /* ppp buf use when sending data */ + uint8_t send_buf[UART_TX_BUF_LEN]; +#else /* ppp buf use when sending data */ uint8_t send_buf[UART_BUF_LEN]; +#endif uint8_t mac_addr[6]; struct net_linkaddr ll_addr; @@ -95,6 +104,155 @@ struct ppp_driver_context { static struct ppp_driver_context ppp_driver_context_data; +#if defined(CONFIG_NET_PPP_ASYNC_UART) +static bool rx_retry_pending; +static bool uart_recovery_pending; +static uint8_t *next_buf; + +static K_SEM_DEFINE(uarte_tx_finished, 0, 1); + +static void uart_callback(const struct device *dev, + struct uart_event *evt, + void *user_data) +{ + struct ppp_driver_context *context = user_data; + uint8_t *p; + int err, ret, len, space_left; + + switch (evt->type) { + case UART_TX_DONE: + LOG_DBG("UART_TX_DONE: sent %d bytes", evt->data.tx.len); + k_sem_give(&uarte_tx_finished); + break; + + case UART_TX_ABORTED: + LOG_DBG("Tx aborted"); + k_sem_give(&uarte_tx_finished); + break; + + case UART_RX_RDY: + len = evt->data.rx.len; + p = evt->data.rx.buf + evt->data.rx.offset; + + LOG_DBG("Received data %d bytes", len); + + ret = ring_buf_put(&context->rx_ringbuf, p, len); + if (ret < evt->data.rx.len) { + LOG_WRN("Rx buffer doesn't have enough space. " + "Bytes pending: %d, written only: %d. " + "Disabling RX for now.", + evt->data.rx.len, ret); + + /* No possibility to set flow ctrl ON towards PC, + * thus workrounding this lack in async API by turning + * rx off for now and re-enabling that later. + */ + if (!rx_retry_pending) { + uart_rx_disable(dev); + rx_retry_pending = true; + } + } + + space_left = ring_buf_space_get(&context->rx_ringbuf); + if (!rx_retry_pending && space_left < (sizeof(context->rx_buf) / 8)) { + /* Not much room left in buffer after a write to ring buffer. + * We submit a work, but enable flow ctrl also + * in this case to avoid packet losses. + */ + uart_rx_disable(dev); + rx_retry_pending = true; + LOG_WRN("%d written to RX buf, but after that only %d space left. " + "Disabling RX for now.", + ret, space_left); + } + + k_work_submit_to_queue(&context->cb_workq, &context->cb_work); + break; + + case UART_RX_BUF_REQUEST: + { + LOG_DBG("UART_RX_BUF_REQUEST: buf %p", next_buf); + + if (next_buf) { + err = uart_rx_buf_rsp(dev, next_buf, sizeof(context->buf)); + if (err) { + LOG_ERR("uart_rx_buf_rsp() err: %d", err); + } + } + + break; + } + + case UART_RX_BUF_RELEASED: + next_buf = evt->data.rx_buf.buf; + LOG_DBG("UART_RX_BUF_RELEASED: buf %p", next_buf); + break; + + case UART_RX_DISABLED: + LOG_DBG("UART_RX_DISABLED - re-enabling in a while"); + + if (rx_retry_pending && !uart_recovery_pending) { + k_work_schedule(&context->uart_recovery_work, + K_MSEC(CONFIG_NET_PPP_ASYNC_UART_RX_RECOVERY_TIMEOUT)); + rx_retry_pending = false; + uart_recovery_pending = true; + } + break; + + case UART_RX_STOPPED: + LOG_DBG("UART_RX_STOPPED: stop reason %d", evt->data.rx_stop.reason); + + if (evt->data.rx_stop.reason != 0) { + rx_retry_pending = true; + } + break; + } +} + +static int ppp_async_uart_rx_enable(struct ppp_driver_context *context) +{ + int err; + + next_buf = context->buf2; + err = uart_callback_set(context->dev, uart_callback, (void *)context); + if (err) { + LOG_ERR("Failed to set uart callback, err %d", err); + } + + err = uart_rx_enable(context->dev, context->buf, sizeof(context->buf), + CONFIG_NET_PPP_ASYNC_UART_RX_ENABLE_TIMEOUT); + if (err) { + LOG_ERR("uart_rx_enable() failed, err %d", err); + } else { + LOG_DBG("RX enabled"); + } + rx_retry_pending = false; + return err; +} + +static void uart_recovery(struct k_work *work) +{ + struct ppp_driver_context *ppp = + CONTAINER_OF(work, struct ppp_driver_context, uart_recovery_work); + int ret; + + ret = ring_buf_space_get(&ppp->rx_ringbuf); + if (ret >= (sizeof(ppp->rx_buf) / 2)) { + ret = ppp_async_uart_rx_enable(ppp); + if (ret) { + LOG_ERR("ppp_async_uart_rx_enable() failed, err %d", ret); + } else { + LOG_WRN("UART RX recovered"); + } + uart_recovery_pending = false; + } else { + LOG_ERR("Rx buffer still doesn't have enough room %d to be re-enabled", ret); + k_work_schedule(&ppp->uart_recovery_work, + K_MSEC(CONFIG_NET_PPP_ASYNC_UART_RX_RECOVERY_TIMEOUT)); + } +} +#endif + static int ppp_save_byte(struct ppp_driver_context *ppp, uint8_t byte) { int ret; @@ -206,6 +364,18 @@ static int ppp_send_flush(struct ppp_driver_context *ppp, int off) */ if (IS_ENABLED(CONFIG_GSM_MUX)) { (void)uart_fifo_fill(ppp->dev, buf, off); + } else if (IS_ENABLED(CONFIG_NET_PPP_ASYNC_UART)) { +#if defined(CONFIG_NET_PPP_ASYNC_UART) + int ret; + + k_sem_take(&uarte_tx_finished, K_FOREVER); + + ret = uart_tx(ppp->dev, buf, off, CONFIG_NET_PPP_ASYNC_UART_TX_TIMEOUT); + if (ret) { + LOG_ERR("uart_tx() failed, err %d", ret); + k_sem_give(&uarte_tx_finished); + } +#endif } else { while (off--) { uart_poll_out(ppp->dev, *buf++); @@ -350,7 +520,7 @@ static int ppp_input_byte(struct ppp_driver_context *ppp, uint8_t byte) break; default: - LOG_DBG("[%p] Invalid state %d", ppp, ppp->state); + LOG_ERR("[%p] Invalid state %d", ppp, ppp->state); break; } @@ -720,8 +890,10 @@ static int ppp_driver_init(const struct device *dev) K_KERNEL_STACK_SIZEOF(ppp_workq), K_PRIO_COOP(PPP_WORKQ_PRIORITY), NULL); k_thread_name_set(&ppp->cb_workq.thread, "ppp_workq"); +#if defined(CONFIG_NET_PPP_ASYNC_UART) + k_work_init_delayable(&ppp->uart_recovery_work, uart_recovery); +#endif #endif - ppp->pkt = NULL; ppp_change_state(ppp, STATE_HDLC_FRAME_START); #if defined(CONFIG_PPP_CLIENT_CLIENTSERVER) @@ -800,7 +972,7 @@ static struct net_stats_ppp *ppp_get_stats(const struct device *dev) } #endif -#if !defined(CONFIG_NET_TEST) +#if !defined(CONFIG_NET_TEST) && !defined(CONFIG_NET_PPP_ASYNC_UART) static void ppp_uart_flush(const struct device *dev) { uint8_t c; @@ -833,7 +1005,7 @@ static void ppp_uart_isr(const struct device *uart, void *user_data) k_work_submit_to_queue(&context->cb_workq, &context->cb_work); } } -#endif /* !CONFIG_NET_TEST */ +#endif /* !CONFIG_NET_TEST && !CONFIG_NET_PPP_ASYNC_UART */ static int ppp_start(const struct device *dev) { @@ -880,13 +1052,17 @@ static int ppp_start(const struct device *dev) LOG_ERR("Cannot find dev %s", dev_name); return -ENODEV; } - +#if defined(CONFIG_NET_PPP_ASYNC_UART) + k_sem_give(&uarte_tx_finished); + ppp_async_uart_rx_enable(context); +#else uart_irq_rx_disable(context->dev); uart_irq_tx_disable(context->dev); ppp_uart_flush(context->dev); uart_irq_callback_user_data_set(context->dev, ppp_uart_isr, context); uart_irq_rx_enable(context->dev); +#endif } #endif /* !CONFIG_NET_TEST */ From 9948b5d2292f75ace27699297bc95d316b248513 Mon Sep 17 00:00:00 2001 From: Krzysztof Chruscinski Date: Thu, 13 Jan 2022 15:41:34 +0100 Subject: [PATCH 021/207] [nrf fromtree] drivers: gpio: nrf: Free channel when pin is reconfigured GPIOTE channel was not freed when pin was reconfigured. This lead to channel pool draining when pin was frequently reconfigured. Signed-off-by: Krzysztof Chruscinski --- drivers/gpio/gpio_nrfx.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/gpio/gpio_nrfx.c b/drivers/gpio/gpio_nrfx.c index e22db2e9451..9c9aa7e9519 100644 --- a/drivers/gpio/gpio_nrfx.c +++ b/drivers/gpio/gpio_nrfx.c @@ -111,6 +111,8 @@ static int gpio_nrfx_pin_configure(const struct device *port, gpio_pin_t pin, gpio_flags_t flags) { nrfx_err_t err; + uint8_t ch; + bool free_ch; const struct gpio_nrfx_cfg *cfg = get_port_cfg(port); nrfx_gpiote_pin_t abs_pin = NRF_GPIO_PIN_MAP(cfg->port_num, pin); @@ -122,12 +124,19 @@ static int gpio_nrfx_pin_configure(const struct device *port, gpio_pin_t pin, .trigger = NRFX_GPIOTE_TRIGGER_NONE }; + err = nrfx_gpiote_channel_get(pin, &ch); + free_ch = (err == NRFX_SUCCESS); + /* 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); + } + if (flags & GPIO_OUTPUT) { nrf_gpio_pin_drive_t drive; int rv = get_drive(flags, &drive); From b946361dc3c9237ee5e25daeb5b5ccda8899cc5f Mon Sep 17 00:00:00 2001 From: Dominik Chat Date: Fri, 26 Nov 2021 10:22:54 +0100 Subject: [PATCH 022/207] [nrf fromlist] sensors: Implement MPU9250 driver MPU9250 driver for 9-axis gyroscope, accelerometer, magnetometer Signed-off-by: Dominik Chat --- drivers/sensor/CMakeLists.txt | 1 + drivers/sensor/Kconfig | 2 + drivers/sensor/mpu9250/CMakeLists.txt | 7 + drivers/sensor/mpu9250/Kconfig | 58 +++ drivers/sensor/mpu9250/ak8963.c | 401 ++++++++++++++++++ drivers/sensor/mpu9250/ak8963.h | 21 + drivers/sensor/mpu9250/mpu9250.c | 366 ++++++++++++++++ drivers/sensor/mpu9250/mpu9250.h | 78 ++++ drivers/sensor/mpu9250/mpu9250_trigger.c | 178 ++++++++ dts/bindings/sensor/invensense,mpu9250.yaml | 85 ++++ tests/drivers/build_all/sensor/i2c.dtsi | 12 + tests/drivers/build_all/sensor/prj.conf | 1 + .../build_all/sensor/sensors_trigger_own.conf | 1 + 13 files changed, 1211 insertions(+) create mode 100644 drivers/sensor/mpu9250/CMakeLists.txt create mode 100644 drivers/sensor/mpu9250/Kconfig create mode 100644 drivers/sensor/mpu9250/ak8963.c create mode 100644 drivers/sensor/mpu9250/ak8963.h create mode 100644 drivers/sensor/mpu9250/mpu9250.c create mode 100644 drivers/sensor/mpu9250/mpu9250.h create mode 100644 drivers/sensor/mpu9250/mpu9250_trigger.c create mode 100644 dts/bindings/sensor/invensense,mpu9250.yaml diff --git a/drivers/sensor/CMakeLists.txt b/drivers/sensor/CMakeLists.txt index 3244ac0d001..fb4dde2e7fa 100644 --- a/drivers/sensor/CMakeLists.txt +++ b/drivers/sensor/CMakeLists.txt @@ -67,6 +67,7 @@ add_subdirectory_ifdef(CONFIG_MCP9808 mcp9808) add_subdirectory_ifdef(CONFIG_MHZ19B mhz19b) add_subdirectory_ifdef(CONFIG_MPR mpr) add_subdirectory_ifdef(CONFIG_MPU6050 mpu6050) +add_subdirectory_ifdef(CONFIG_MPU9250 mpu9250) add_subdirectory_ifdef(CONFIG_MS5607 ms5607) add_subdirectory_ifdef(CONFIG_MS5837 ms5837) add_subdirectory_ifdef(CONFIG_OPT3001 opt3001) diff --git a/drivers/sensor/Kconfig b/drivers/sensor/Kconfig index 6681449292f..2909d735e86 100644 --- a/drivers/sensor/Kconfig +++ b/drivers/sensor/Kconfig @@ -174,6 +174,8 @@ source "drivers/sensor/mpr/Kconfig" source "drivers/sensor/mpu6050/Kconfig" +source "drivers/sensor/mpu9250/Kconfig" + source "drivers/sensor/ms5837/Kconfig" source "drivers/sensor/ms5607/Kconfig" diff --git a/drivers/sensor/mpu9250/CMakeLists.txt b/drivers/sensor/mpu9250/CMakeLists.txt new file mode 100644 index 00000000000..49ba5d8613d --- /dev/null +++ b/drivers/sensor/mpu9250/CMakeLists.txt @@ -0,0 +1,7 @@ +# SPDX-License-Identifier: Apache-2.0 + +zephyr_library() + +zephyr_library_sources(mpu9250.c) +zephyr_library_sources_ifdef(CONFIG_MPU9250_TRIGGER mpu9250_trigger.c) +zephyr_library_sources_ifdef(CONFIG_MPU9250_MAGN_EN ak8963.c) diff --git a/drivers/sensor/mpu9250/Kconfig b/drivers/sensor/mpu9250/Kconfig new file mode 100644 index 00000000000..2f1e9733501 --- /dev/null +++ b/drivers/sensor/mpu9250/Kconfig @@ -0,0 +1,58 @@ +# MPU9250 Nine-Axis Motion Tracking device configuration options + +# Copyright (c) 2021 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +menuconfig MPU9250 + bool "MPU9250 Nine-Axis Motion Tracking Device" + depends on I2C + help + Enable driver for MPU9250 I2C-based nine-axis motion tracking device. + +if MPU9250 + +choice + prompt "Trigger mode" + default MPU9250_TRIGGER_GLOBAL_THREAD + help + Specify the type of triggering to be used by the driver. + +config MPU9250_TRIGGER_NONE + bool "No trigger" + +config MPU9250_TRIGGER_GLOBAL_THREAD + bool "Use global thread" + depends on GPIO + select MPU9250_TRIGGER + +config MPU9250_TRIGGER_OWN_THREAD + bool "Use own thread" + depends on GPIO + select MPU9250_TRIGGER + +endchoice + +config MPU9250_TRIGGER + bool + +config MPU9250_THREAD_PRIORITY + int "Thread priority" + depends on MPU9250_TRIGGER_OWN_THREAD + default 10 + help + Priority of thread used by the driver to handle interrupts. + +config MPU9250_THREAD_STACK_SIZE + int "Thread stack size" + depends on MPU9250_TRIGGER_OWN_THREAD + default 1024 + help + Stack size of thread used by the driver to handle interrupts. + +config MPU9250_MAGN_EN + bool "Magnetometer enable" + default y + help + Enable AK8963 builtin magnetometer. + +endif # MPU9250 diff --git a/drivers/sensor/mpu9250/ak8963.c b/drivers/sensor/mpu9250/ak8963.c new file mode 100644 index 00000000000..0321f7a1152 --- /dev/null +++ b/drivers/sensor/mpu9250/ak8963.c @@ -0,0 +1,401 @@ +/* + * Copyright (c) 2021, Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +#include "mpu9250.h" +#include "ak8963.h" + +LOG_MODULE_DECLARE(MPU9250, CONFIG_SENSOR_LOG_LEVEL); + + +#define I2C_READ_FLAG BIT(7) + +#define AK8963_I2C_ADDR 0x0C + +#define AK8963_REG_ID 0x00 +#define AK8963_REG_ID_VAL 0x48 + +#define AK8963_REG_DATA 0x03 + +#define AK8963_ST2_OVRFL_BIT BIT(3) + +#define AK8963_REG_CNTL1 0x0A +#define AK8963_REG_CNTL1_POWERDOWN_VAL 0x00 +#define AK8963_REG_CNTL1_FUSE_ROM_VAL 0x0F +#define AK8963_REG_CNTL1_16BIT_100HZ_VAL 0x16 +#define AK8963_SET_MODE_DELAY_MS 1 + +#define AK8963_REG_CNTL2 0x0B +#define AK8963_REG_CNTL2_RESET_VAL 0x01 +#define AK8963_RESET_DELAY_MS 1 + +#define AK8963_REG_ADJ_DATA_X 0x10 +#define AK8963_REG_ADJ_DATA_Y 0x11 +#define AK8963_REG_ADJ_DATA_Z 0x12 + +#define AK9863_SCALE_TO_UG 1499 + +#define MPU9250_REG_I2C_MST_CTRL 0x24 +#define MPU9250_REG_I2C_MST_CTRL_WAIT_MAG_400KHZ_VAL 0x4D + +#define MPU9250_REG_I2C_SLV0_ADDR 0x25 +#define MPU9250_REG_I2C_SLV0_REG 0x26 +#define MPU9250_REG_I2C_SLV0_CTRL 0x27 +#define MPU9250_REG_I2C_SLV0_DATA0 0x63 +#define MPU9250_REG_READOUT_CTRL_VAL (BIT(7) | 0x07) + +#define MPU9250_REG_USER_CTRL 0x6A +#define MPU9250_REG_USER_CTRL_I2C_MASTERMODE_VAL 0x20 + +#define MPU9250_REG_EXT_DATA00 0x49 + +#define MPU9250_REG_I2C_SLV4_ADDR 0x31 +#define MPU9250_REG_I2C_SLV4_REG 0x32 +#define MPU9250_REG_I2C_SLV4_DO 0x33 +#define MPU9250_REG_I2C_SLV4_CTRL 0x34 +#define MPU9250_REG_I2C_SLV4_CTRL_VAL 0x80 +#define MPU9250_REG_I2C_SLV4_DI 0x35 + +#define MPU9250_I2C_MST_STS 0x36 +#define MPU9250_I2C_MST_STS_SLV4_DONE BIT(6) + + +int ak8963_convert_magn(struct sensor_value *val, int16_t raw_val, + int16_t scale, uint8_t st2) +{ + /* The sensor device returns 10^-9 Teslas after scaling. + * Scale adjusts for calibration data and units + * So sensor instance returns Gauss units + */ + + /* If overflow happens then value is invalid */ + if ((st2 & AK8963_ST2_OVRFL_BIT) != 0) { + LOG_INF("Magnetometer value overflow."); + return -EOVERFLOW; + } + + int32_t scaled_val = (int32_t)raw_val * (int32_t)scale; + + val->val1 = scaled_val / 1000000; + val->val2 = scaled_val % 1000000; + return 0; +} + + +static int ak8963_execute_rw(const struct device *dev, uint8_t reg, bool write) +{ + /* Instruct the MPU9250 to access over its external i2c bus + * given device register with given details + */ + const struct mpu9250_config *cfg = dev->config; + uint8_t mode_bit = 0x00; + uint8_t status; + int ret; + + if (!write) { + mode_bit = I2C_READ_FLAG; + } + + /* Set target i2c address */ + ret = i2c_reg_write_byte_dt(&cfg->i2c, + MPU9250_REG_I2C_SLV4_ADDR, + AK8963_I2C_ADDR | mode_bit); + if (ret < 0) { + LOG_ERR("Failed to write i2c target slave address."); + return ret; + } + + /* Set target i2c register */ + ret = i2c_reg_write_byte_dt(&cfg->i2c, + MPU9250_REG_I2C_SLV4_REG, + reg); + if (ret < 0) { + LOG_ERR("Failed to write i2c target slave register."); + return ret; + } + + /* Initiate transfer */ + ret = i2c_reg_write_byte_dt(&cfg->i2c, + MPU9250_REG_I2C_SLV4_CTRL, + MPU9250_REG_I2C_SLV4_CTRL_VAL); + if (ret < 0) { + LOG_ERR("Failed to initiate i2c slave transfer."); + return ret; + } + + /* Wait for a transfer to be ready */ + do { + ret = i2c_reg_read_byte_dt(&cfg->i2c, + MPU9250_I2C_MST_STS, &status); + if (ret < 0) { + LOG_ERR("Waiting for slave failed."); + return ret; + } + } while (!(status & MPU9250_I2C_MST_STS_SLV4_DONE)); + + return 0; +} + +static int ak8963_read_reg(const struct device *dev, uint8_t reg, uint8_t *data) +{ + const struct mpu9250_config *cfg = dev->config; + int ret; + + /* Execute transfer */ + ret = ak8963_execute_rw(dev, reg, false); + if (ret < 0) { + LOG_ERR("Failed to prepare transfer."); + return ret; + } + + /* Read the result */ + ret = i2c_reg_read_byte_dt(&cfg->i2c, + MPU9250_REG_I2C_SLV4_DI, data); + if (ret < 0) { + LOG_ERR("Failed to read data from slave."); + return ret; + } + + return 0; +} + +static int ak8963_write_reg(const struct device *dev, uint8_t reg, uint8_t data) +{ + const struct mpu9250_config *cfg = dev->config; + int ret; + + /* Set the data to write */ + ret = i2c_reg_write_byte_dt(&cfg->i2c, + MPU9250_REG_I2C_SLV4_DO, data); + if (ret < 0) { + LOG_ERR("Failed to write data to slave."); + return ret; + } + + /* Execute transfer */ + ret = ak8963_execute_rw(dev, reg, true); + if (ret < 0) { + LOG_ERR("Failed to transfer write to slave."); + return ret; + } + + return 0; +} + + +static int ak8963_set_mode(const struct device *dev, uint8_t mode) +{ + int ret; + + ret = ak8963_write_reg(dev, AK8963_REG_CNTL1, mode); + if (ret < 0) { + LOG_ERR("Failed to set AK8963 mode."); + return ret; + } + + /* Wait for mode to change */ + k_msleep(AK8963_SET_MODE_DELAY_MS); + return 0; +} + +static int16_t ak8963_calc_adj(int16_t val) +{ + + /** Datasheet says the actual register value is in 16bit output max + * value of 32760 that corresponds to 4912 uT flux, yielding factor + * of 0.149938. + * + * Now Zephyr unit is Gauss, and conversion is 1T = 10^4G + * -> 0.1499 * 10^4 = 1499 + * So if we multiply with scaling with 1499 the unit is uG. + * + * Calculation from MPU-9250 Register Map and Descriptions + * adj = (((val-128)*0.5)/128)+1 + */ + return ((AK9863_SCALE_TO_UG * (val - 128)) / 256) + AK9863_SCALE_TO_UG; +} + +static int ak8963_fetch_adj(const struct device *dev) +{ + /* Read magnetometer adjustment data from the AK8963 chip */ + struct mpu9250_data *drv_data = dev->data; + uint8_t buf; + int ret; + + /* Change to FUSE access mode to access adjustment registers */ + ret = ak8963_set_mode(dev, AK8963_REG_CNTL1_FUSE_ROM_VAL); + if (ret < 0) { + LOG_ERR("Failed to set chip in fuse access mode."); + return ret; + } + + ret = ak8963_read_reg(dev, AK8963_REG_ADJ_DATA_X, &buf); + if (ret < 0) { + LOG_ERR("Failed to read adjustment data."); + return ret; + } + drv_data->magn_scale_x = ak8963_calc_adj(buf); + + ret = ak8963_read_reg(dev, AK8963_REG_ADJ_DATA_Y, &buf); + if (ret < 0) { + LOG_ERR("Failed to read adjustment data."); + return ret; + } + drv_data->magn_scale_y = ak8963_calc_adj(buf); + + ret = ak8963_read_reg(dev, AK8963_REG_ADJ_DATA_Z, &buf); + if (ret < 0) { + LOG_ERR("Failed to read adjustment data."); + return ret; + } + drv_data->magn_scale_z = ak8963_calc_adj(buf); + + /* Change back to the powerdown mode */ + ret = ak8963_set_mode(dev, AK8963_REG_CNTL1_POWERDOWN_VAL); + if (ret < 0) { + LOG_ERR("Failed to set chip in power down mode."); + return ret; + } + + LOG_DBG("Adjustment values %d %d %d", drv_data->magn_scale_x, + drv_data->magn_scale_y, drv_data->magn_scale_z); + + return 0; +} + +static int ak8963_reset(const struct device *dev) +{ + int ret; + + /* Reset the chip -> reset all settings. */ + ret = ak8963_write_reg(dev, AK8963_REG_CNTL2, + AK8963_REG_CNTL2_RESET_VAL); + if (ret < 0) { + LOG_ERR("Failed to reset AK8963."); + return ret; + } + + /* Wait for reset */ + k_msleep(AK8963_RESET_DELAY_MS); + + return 0; +} + +static int ak8963_init_master(const struct device *dev) +{ + const struct mpu9250_config *cfg = dev->config; + int ret; + + /* Instruct MPU9250 to use its external I2C bus as master */ + ret = i2c_reg_write_byte_dt(&cfg->i2c, + MPU9250_REG_USER_CTRL, + MPU9250_REG_USER_CTRL_I2C_MASTERMODE_VAL); + if (ret < 0) { + LOG_ERR("Failed to set MPU9250 master i2c mode."); + return ret; + } + + /* Set MPU9250 I2C bus as 400kHz and issue interrupt at data ready. */ + ret = i2c_reg_write_byte_dt(&cfg->i2c, + MPU9250_REG_I2C_MST_CTRL, + MPU9250_REG_I2C_MST_CTRL_WAIT_MAG_400KHZ_VAL); + if (ret < 0) { + LOG_ERR("Failed to set MPU9250 master i2c speed."); + return ret; + } + + return 0; +} + +static int ak8963_init_readout(const struct device *dev) +{ + const struct mpu9250_config *cfg = dev->config; + int ret; + + /* Set target i2c address */ + ret = i2c_reg_write_byte_dt(&cfg->i2c, + MPU9250_REG_I2C_SLV0_ADDR, + AK8963_I2C_ADDR | I2C_READ_FLAG); + if (ret < 0) { + LOG_ERR("Failed to set AK8963 slave address."); + return ret; + } + + /* Set target as data registers */ + ret = i2c_reg_write_byte_dt(&cfg->i2c, + MPU9250_REG_I2C_SLV0_REG, AK8963_REG_DATA); + if (ret < 0) { + LOG_ERR("Failed to set AK8963 register address."); + return ret; + } + + /* Initiate readout at sample rate */ + ret = i2c_reg_write_byte_dt(&cfg->i2c, + MPU9250_REG_I2C_SLV0_CTRL, + MPU9250_REG_READOUT_CTRL_VAL); + if (ret < 0) { + LOG_ERR("Failed to init AK8963 value readout."); + return ret; + } + + return 0; +} + +int ak8963_init(const struct device *dev) +{ + uint8_t buf; + int ret; + + ret = ak8963_init_master(dev); + if (ret < 0) { + LOG_ERR("Initializing MPU9250 master mode failed."); + return ret; + } + + ret = ak8963_reset(dev); + if (ret < 0) { + LOG_ERR("Resetting AK8963 failed."); + return ret; + } + + /* First check that the chip says hello */ + ret = ak8963_read_reg(dev, AK8963_REG_ID, &buf); + if (ret < 0) { + LOG_ERR("Failed to read AK8963 chip id."); + return ret; + } + + if (buf != AK8963_REG_ID_VAL) { + LOG_ERR("Invalid AK8963 chip id (0x%X).", buf); + return -ENOTSUP; + } + + /* Fetch calibration data */ + ret = ak8963_fetch_adj(dev); + if (ret < 0) { + LOG_ERR("Calibrating AK8963 failed."); + return ret; + } + + /* Set AK sample rate and resolution */ + ret = ak8963_set_mode(dev, AK8963_REG_CNTL1_16BIT_100HZ_VAL); + if (ret < 0) { + LOG_ERR("Failed set sample rate for AK8963."); + return ret; + } + + /* Init constant readouts at sample rate */ + ret = ak8963_init_readout(dev); + if (ret < 0) { + LOG_ERR("Initializing AK8963 readout failed."); + return ret; + } + + return 0; +} diff --git a/drivers/sensor/mpu9250/ak8963.h b/drivers/sensor/mpu9250/ak8963.h new file mode 100644 index 00000000000..2afe513e50a --- /dev/null +++ b/drivers/sensor/mpu9250/ak8963.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2021, Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_DRIVERS_SENSOR_MPU9250_AK8963_H_ +#define ZEPHYR_DRIVERS_SENSOR_MPU9250_AK8963_H_ + +#include + +#include +#include + + +int ak8963_convert_magn(struct sensor_value *val, int16_t raw_val, + int16_t scale, uint8_t st2); + +int ak8963_init(const struct device *dev); + +#endif /* ZEPHYR_DRIVERS_SENSOR_MPU9250_AK8963_H_ */ diff --git a/drivers/sensor/mpu9250/mpu9250.c b/drivers/sensor/mpu9250/mpu9250.c new file mode 100644 index 00000000000..cecf9612b84 --- /dev/null +++ b/drivers/sensor/mpu9250/mpu9250.c @@ -0,0 +1,366 @@ +/* + * Copyright (c) 2021, Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT invensense_mpu9250 + +#include +#include +#include + +#include "mpu9250.h" + +#ifdef CONFIG_MPU9250_MAGN_EN +#include "ak8963.h" +#endif + +LOG_MODULE_REGISTER(MPU9250, CONFIG_SENSOR_LOG_LEVEL); + + +#define MPU9250_REG_CHIP_ID 0x75 +#define MPU9250_CHIP_ID 0x71 + +#define MPU9250_REG_SR_DIV 0x19 + +#define MPU9250_REG_CONFIG 0x1A +#define MPU9250_GYRO_DLPF_MAX 7 + +#define MPU9250_REG_GYRO_CFG 0x1B +#define MPU9250_GYRO_FS_SHIFT 3 +#define MPU9250_GYRO_FS_MAX 3 + +#define MPU9250_REG_ACCEL_CFG 0x1C +#define MPU9250_ACCEL_FS_SHIFT 3 +#define MPU9250_ACCEL_FS_MAX 3 + +#define MPU9250_REG_ACCEL_CFG2 0x1D +#define MPU9250_ACCEL_DLPF_MAX 7 + +#define MPU9250_REG_DATA_START 0x3B + +#define MPU0259_TEMP_SENSITIVITY 334 +#define MPU9250_TEMP_OFFSET 21 + +#define MPU9250_REG_PWR_MGMT1 0x6B +#define MPU9250_SLEEP_EN BIT(6) + + +#ifdef CONFIG_MPU9250_MAGN_EN +#define MPU9250_READ_BUF_SIZE 11 +#else +#define MPU9250_READ_BUF_SIZE 7 +#endif + + +/* see "Accelerometer Measurements" section from register map description */ +static void mpu9250_convert_accel(struct sensor_value *val, int16_t raw_val, + uint16_t sensitivity_shift) +{ + int64_t conv_val; + + conv_val = ((int64_t)raw_val * SENSOR_G) >> sensitivity_shift; + val->val1 = conv_val / 1000000; + val->val2 = conv_val % 1000000; +} + +/* see "Gyroscope Measurements" section from register map description */ +static void mpu9250_convert_gyro(struct sensor_value *val, int16_t raw_val, + uint16_t sensitivity_x10) +{ + int64_t conv_val; + + conv_val = ((int64_t)raw_val * SENSOR_PI * 10) / + (sensitivity_x10 * 180U); + val->val1 = conv_val / 1000000; + val->val2 = conv_val % 1000000; +} + +/* see "Temperature Measurement" section from register map description */ +static inline void mpu9250_convert_temp(struct sensor_value *val, + int16_t raw_val) +{ + /* Temp[*C] = (raw / sensitivity) + offset */ + val->val1 = (raw_val / MPU0259_TEMP_SENSITIVITY) + MPU9250_TEMP_OFFSET; + val->val2 = (((int64_t)(raw_val % MPU0259_TEMP_SENSITIVITY) * 1000000) + / MPU0259_TEMP_SENSITIVITY); + + if (val->val2 < 0) { + val->val1--; + val->val2 += 1000000; + } else if (val->val2 >= 1000000) { + val->val1++; + val->val2 -= 1000000; + } +} + +static int mpu9250_channel_get(const struct device *dev, + enum sensor_channel chan, + struct sensor_value *val) +{ + struct mpu9250_data *drv_data = dev->data; +#ifdef CONFIG_MPU9250_MAGN_EN + int ret; +#endif + + switch (chan) { + case SENSOR_CHAN_ACCEL_XYZ: + mpu9250_convert_accel(val, drv_data->accel_x, + drv_data->accel_sensitivity_shift); + mpu9250_convert_accel(val + 1, drv_data->accel_y, + drv_data->accel_sensitivity_shift); + mpu9250_convert_accel(val + 2, drv_data->accel_z, + drv_data->accel_sensitivity_shift); + break; + case SENSOR_CHAN_ACCEL_X: + mpu9250_convert_accel(val, drv_data->accel_x, + drv_data->accel_sensitivity_shift); + break; + case SENSOR_CHAN_ACCEL_Y: + mpu9250_convert_accel(val, drv_data->accel_y, + drv_data->accel_sensitivity_shift); + break; + case SENSOR_CHAN_ACCEL_Z: + mpu9250_convert_accel(val, drv_data->accel_z, + drv_data->accel_sensitivity_shift); + break; + case SENSOR_CHAN_GYRO_XYZ: + mpu9250_convert_gyro(val, drv_data->gyro_x, + drv_data->gyro_sensitivity_x10); + mpu9250_convert_gyro(val + 1, drv_data->gyro_y, + drv_data->gyro_sensitivity_x10); + mpu9250_convert_gyro(val + 2, drv_data->gyro_z, + drv_data->gyro_sensitivity_x10); + break; + case SENSOR_CHAN_GYRO_X: + mpu9250_convert_gyro(val, drv_data->gyro_x, + drv_data->gyro_sensitivity_x10); + break; + case SENSOR_CHAN_GYRO_Y: + mpu9250_convert_gyro(val, drv_data->gyro_y, + drv_data->gyro_sensitivity_x10); + break; + case SENSOR_CHAN_GYRO_Z: + mpu9250_convert_gyro(val, drv_data->gyro_z, + drv_data->gyro_sensitivity_x10); + break; +#ifdef CONFIG_MPU9250_MAGN_EN + case SENSOR_CHAN_MAGN_XYZ: + ret = ak8963_convert_magn(val, drv_data->magn_x, + drv_data->magn_scale_x, + drv_data->magn_st2); + if (ret < 0) { + return ret; + } + ret = ak8963_convert_magn(val + 1, drv_data->magn_y, + drv_data->magn_scale_y, + drv_data->magn_st2); + if (ret < 0) { + return ret; + } + ret = ak8963_convert_magn(val + 2, drv_data->magn_z, + drv_data->magn_scale_z, + drv_data->magn_st2); + return ret; + case SENSOR_CHAN_MAGN_X: + return ak8963_convert_magn(val, drv_data->magn_x, + drv_data->magn_scale_x, + drv_data->magn_st2); + case SENSOR_CHAN_MAGN_Y: + return ak8963_convert_magn(val, drv_data->magn_y, + drv_data->magn_scale_y, + drv_data->magn_st2); + case SENSOR_CHAN_MAGN_Z: + return ak8963_convert_magn(val, drv_data->magn_z, + drv_data->magn_scale_z, + drv_data->magn_st2); + case SENSOR_CHAN_DIE_TEMP: + mpu9250_convert_temp(val, drv_data->temp); + break; +#endif + default: + return -ENOTSUP; + } + + return 0; +} + +static int mpu9250_sample_fetch(const struct device *dev, + enum sensor_channel chan) +{ + struct mpu9250_data *drv_data = dev->data; + const struct mpu9250_config *cfg = dev->config; + int16_t buf[MPU9250_READ_BUF_SIZE]; + int ret; + + ret = i2c_burst_read_dt(&cfg->i2c, + MPU9250_REG_DATA_START, (uint8_t *)buf, + sizeof(buf)); + if (ret < 0) { + LOG_ERR("Failed to read data sample."); + return ret; + } + + drv_data->accel_x = sys_be16_to_cpu(buf[0]); + drv_data->accel_y = sys_be16_to_cpu(buf[1]); + drv_data->accel_z = sys_be16_to_cpu(buf[2]); + drv_data->temp = sys_be16_to_cpu(buf[3]); + drv_data->gyro_x = sys_be16_to_cpu(buf[4]); + drv_data->gyro_y = sys_be16_to_cpu(buf[5]); + drv_data->gyro_z = sys_be16_to_cpu(buf[6]); +#ifdef CONFIG_MPU9250_MAGN_EN + drv_data->magn_x = sys_be16_to_cpu(buf[7]); + drv_data->magn_y = sys_be16_to_cpu(buf[8]); + drv_data->magn_z = sys_be16_to_cpu(buf[9]); + drv_data->magn_st2 = ((uint8_t *)buf)[20]; + LOG_DBG("magn_st2: %u", drv_data->magn_st2); +#endif + + return 0; +} + +static const struct sensor_driver_api mpu9250_driver_api = { +#if CONFIG_MPU9250_TRIGGER + .trigger_set = mpu9250_trigger_set, +#endif + .sample_fetch = mpu9250_sample_fetch, + .channel_get = mpu9250_channel_get, +}; + +/* measured in degrees/sec x10 to avoid floating point */ +static const uint16_t mpu9250_gyro_sensitivity_x10[] = { + 1310, 655, 328, 164 +}; + +static int mpu9250_init(const struct device *dev) +{ + struct mpu9250_data *drv_data = dev->data; + const struct mpu9250_config *cfg = dev->config; + uint8_t id; + int ret; + + if (!device_is_ready(cfg->i2c.bus)) { + LOG_ERR("I2C dev %s not ready", cfg->i2c.bus->name); + return -ENODEV; + } + + /* check chip ID */ + ret = i2c_reg_read_byte_dt(&cfg->i2c, MPU9250_REG_CHIP_ID, &id); + if (ret < 0) { + LOG_ERR("Failed to read chip ID."); + return ret; + } + + if (id != MPU9250_CHIP_ID) { + LOG_ERR("Invalid chip ID."); + return -ENOTSUP; + } + + /* wake up chip */ + ret = i2c_reg_update_byte_dt(&cfg->i2c, + MPU9250_REG_PWR_MGMT1, + MPU9250_SLEEP_EN, 0); + if (ret < 0) { + LOG_ERR("Failed to wake up chip."); + return ret; + } + + if (cfg->accel_fs > MPU9250_ACCEL_FS_MAX) { + LOG_ERR("Accel FS is too big: %d", cfg->accel_fs); + return -EINVAL; + } + + ret = i2c_reg_write_byte_dt(&cfg->i2c, MPU9250_REG_ACCEL_CFG, + cfg->accel_fs << MPU9250_ACCEL_FS_SHIFT); + if (ret < 0) { + LOG_ERR("Failed to write accel full-scale range."); + return ret; + } + drv_data->accel_sensitivity_shift = 14 - cfg->accel_fs; + + if (cfg->gyro_fs > MPU9250_GYRO_FS_MAX) { + LOG_ERR("Gyro FS is too big: %d", cfg->accel_fs); + return -EINVAL; + } + + ret = i2c_reg_write_byte_dt(&cfg->i2c, MPU9250_REG_GYRO_CFG, + cfg->gyro_fs << MPU9250_GYRO_FS_SHIFT); + if (ret < 0) { + LOG_ERR("Failed to write gyro full-scale range."); + return ret; + } + + if (cfg->gyro_dlpf > MPU9250_GYRO_DLPF_MAX) { + LOG_ERR("Gyro DLPF is too big: %d", cfg->gyro_dlpf); + return -EINVAL; + } + + ret = i2c_reg_write_byte_dt(&cfg->i2c, MPU9250_REG_CONFIG, + cfg->gyro_dlpf); + if (ret < 0) { + LOG_ERR("Failed to write gyro digital LPF settings."); + return ret; + } + + if (cfg->accel_dlpf > MPU9250_ACCEL_DLPF_MAX) { + LOG_ERR("Accel DLPF is too big: %d", cfg->accel_dlpf); + return -EINVAL; + } + + ret = i2c_reg_write_byte_dt(&cfg->i2c, MPU9250_REG_ACCEL_CFG2, + cfg->gyro_dlpf); + if (ret < 0) { + LOG_ERR("Failed to write accel digital LPF settings."); + return ret; + } + + ret = i2c_reg_write_byte_dt(&cfg->i2c, MPU9250_REG_SR_DIV, + cfg->gyro_sr_div); + if (ret < 0) { + LOG_ERR("Failed to write gyro ODR divider."); + return ret; + } + + drv_data->gyro_sensitivity_x10 = + mpu9250_gyro_sensitivity_x10[cfg->gyro_fs]; + +#ifdef CONFIG_MPU9250_MAGN_EN + ret = ak8963_init(dev); + if (ret < 0) { + LOG_ERR("Failed to initialize AK8963."); + return ret; + } +#endif + +#ifdef CONFIG_MPU9250_TRIGGER + ret = mpu9250_init_interrupt(dev); + if (ret < 0) { + LOG_ERR("Failed to initialize interrupts."); + return ret; + } +#endif + + return 0; +} + + +#define INIT_MPU9250_INST(inst) \ + static struct mpu9250_data mpu9250_data_##inst; \ + static const struct mpu9250_config mpu9250_cfg_##inst = { \ + .i2c = I2C_DT_SPEC_INST_GET(inst), \ + .gyro_sr_div = DT_INST_PROP(inst, gyro_sr_div), \ + .gyro_dlpf = DT_INST_ENUM_IDX(inst, gyro_dlpf), \ + .gyro_fs = DT_INST_ENUM_IDX(inst, gyro_fs), \ + .accel_fs = DT_INST_ENUM_IDX(inst, accel_fs), \ + .accel_dlpf = DT_INST_ENUM_IDX(inst, accel_dlpf), \ + IF_ENABLED(CONFIG_MPU9250_TRIGGER, \ + (.int_pin = GPIO_DT_SPEC_INST_GET(inst, irq_gpios))) \ + }; \ + \ + DEVICE_DT_INST_DEFINE(inst, mpu9250_init, NULL, \ + &mpu9250_data_##inst, &mpu9250_cfg_##inst,\ + POST_KERNEL, CONFIG_SENSOR_INIT_PRIORITY, \ + &mpu9250_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(INIT_MPU9250_INST) diff --git a/drivers/sensor/mpu9250/mpu9250.h b/drivers/sensor/mpu9250/mpu9250.h new file mode 100644 index 00000000000..b636ded7ecc --- /dev/null +++ b/drivers/sensor/mpu9250/mpu9250.h @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2021, Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_DRIVERS_SENSOR_MPU9250_MPU9250_H_ +#define ZEPHYR_DRIVERS_SENSOR_MPU9250_MPU9250_H_ + +#include +#include +#include +#include +#include +#include + +struct mpu9250_data { + int16_t accel_x; + int16_t accel_y; + int16_t accel_z; + uint16_t accel_sensitivity_shift; + + int16_t temp; + + int16_t gyro_x; + int16_t gyro_y; + int16_t gyro_z; + uint16_t gyro_sensitivity_x10; + +#ifdef CONFIG_MPU9250_MAGN_EN + int16_t magn_x; + int16_t magn_scale_x; + int16_t magn_y; + int16_t magn_scale_y; + int16_t magn_z; + int16_t magn_scale_z; + uint8_t magn_st2; +#endif + +#ifdef CONFIG_MPU9250_TRIGGER + const struct device *dev; + struct gpio_callback gpio_cb; + + struct sensor_trigger data_ready_trigger; + sensor_trigger_handler_t data_ready_handler; + +#if defined(CONFIG_MPU9250_TRIGGER_OWN_THREAD) + K_KERNEL_STACK_MEMBER(thread_stack, CONFIG_MPU9250_THREAD_STACK_SIZE); + struct k_thread thread; + struct k_sem gpio_sem; +#elif defined(CONFIG_MPU9250_TRIGGER_GLOBAL_THREAD) + struct k_work work; +#endif + +#endif /* CONFIG_MPU9250_TRIGGER */ +}; + +struct mpu9250_config { + const struct i2c_dt_spec i2c; + uint8_t gyro_sr_div; + uint8_t gyro_dlpf; + uint8_t gyro_fs; + uint8_t accel_fs; + uint8_t accel_dlpf; +#ifdef CONFIG_MPU9250_TRIGGER + const struct gpio_dt_spec int_pin; +#endif /* CONFIG_MPU9250_TRIGGER */ +}; + +#ifdef CONFIG_MPU9250_TRIGGER +int mpu9250_trigger_set(const struct device *dev, + const struct sensor_trigger *trig, + sensor_trigger_handler_t handler); + +int mpu9250_init_interrupt(const struct device *dev); +#endif + +#endif /* ZEPHYR_DRIVERS_SENSOR_MPU9250_MPU9250_H_ */ diff --git a/drivers/sensor/mpu9250/mpu9250_trigger.c b/drivers/sensor/mpu9250/mpu9250_trigger.c new file mode 100644 index 00000000000..3bdeda4f747 --- /dev/null +++ b/drivers/sensor/mpu9250/mpu9250_trigger.c @@ -0,0 +1,178 @@ +/* + * Copyright (c) 2021, Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#include "mpu9250.h" + +LOG_MODULE_DECLARE(MPU9250, CONFIG_SENSOR_LOG_LEVEL); + + +#define MPU9250_REG_INT_EN 0x38 +#define MPU9250_DRDY_EN BIT(0) + + +int mpu9250_trigger_set(const struct device *dev, + const struct sensor_trigger *trig, + sensor_trigger_handler_t handler) +{ + struct mpu9250_data *drv_data = dev->data; + const struct mpu9250_config *cfg = dev->config; + int ret; + + if (trig->type != SENSOR_TRIG_DATA_READY) { + return -ENOTSUP; + } + + ret = gpio_pin_interrupt_configure_dt(&cfg->int_pin, GPIO_INT_DISABLE); + if (ret < 0) { + LOG_ERR("Failed to disable gpio interrupt."); + return ret; + } + + drv_data->data_ready_handler = handler; + if (handler == NULL) { + return 0; + } + + drv_data->data_ready_trigger = *trig; + + ret = gpio_pin_interrupt_configure_dt(&cfg->int_pin, + GPIO_INT_EDGE_TO_ACTIVE); + if (ret < 0) { + LOG_ERR("Failed to enable gpio interrupt."); + return ret; + } + + return 0; +} + +static void mpu9250_gpio_callback(const struct device *dev, + struct gpio_callback *cb, uint32_t pins) +{ + struct mpu9250_data *drv_data = + CONTAINER_OF(cb, struct mpu9250_data, gpio_cb); + const struct mpu9250_config *cfg = drv_data->dev->config; + int ret; + + ARG_UNUSED(pins); + + ret = gpio_pin_interrupt_configure_dt(&cfg->int_pin, GPIO_INT_DISABLE); + if (ret < 0) { + LOG_ERR("Disabling gpio interrupt failed with err: %d", ret); + return; + } + +#if defined(CONFIG_MPU9250_TRIGGER_OWN_THREAD) + k_sem_give(&drv_data->gpio_sem); +#elif defined(CONFIG_MPU9250_TRIGGER_GLOBAL_THREAD) + k_work_submit(&drv_data->work); +#endif +} + +static void mpu9250_thread_cb(const struct device *dev) +{ + struct mpu9250_data *drv_data = dev->data; + const struct mpu9250_config *cfg = dev->config; + int ret; + + if (drv_data->data_ready_handler != NULL) { + drv_data->data_ready_handler(dev, + &drv_data->data_ready_trigger); + } + + ret = gpio_pin_interrupt_configure_dt(&cfg->int_pin, + GPIO_INT_EDGE_TO_ACTIVE); + if (ret < 0) { + LOG_ERR("Enabling gpio interrupt failed with err: %d", ret); + } + +} + +#ifdef CONFIG_MPU9250_TRIGGER_OWN_THREAD +static void mpu9250_thread(struct mpu9250_data *drv_data) +{ + while (1) { + k_sem_take(&drv_data->gpio_sem, K_FOREVER); + mpu9250_thread_cb(drv_data->dev); + } +} +#endif + +#ifdef CONFIG_MPU9250_TRIGGER_GLOBAL_THREAD +static void mpu9250_work_cb(struct k_work *work) +{ + struct mpu9250_data *drv_data = + CONTAINER_OF(work, struct mpu9250_data, work); + + mpu9250_thread_cb(drv_data->dev); +} +#endif + +int mpu9250_init_interrupt(const struct device *dev) +{ + struct mpu9250_data *drv_data = dev->data; + const struct mpu9250_config *cfg = dev->config; + int ret; + + /* setup data ready gpio interrupt */ + if (!device_is_ready(cfg->int_pin.port)) { + LOG_ERR("Interrupt pin is not ready."); + return -EIO; + } + + drv_data->dev = dev; + + ret = gpio_pin_configure_dt(&cfg->int_pin, GPIO_INPUT); + if (ret < 0) { + LOG_ERR("Failed to configure interrupt pin."); + return ret; + } + + gpio_init_callback(&drv_data->gpio_cb, + mpu9250_gpio_callback, + BIT(cfg->int_pin.pin)); + + ret = gpio_add_callback(cfg->int_pin.port, &drv_data->gpio_cb); + if (ret < 0) { + LOG_ERR("Failed to set gpio callback."); + return ret; + } + + /* enable data ready interrupt */ + ret = i2c_reg_write_byte_dt(&cfg->i2c, MPU9250_REG_INT_EN, + MPU9250_DRDY_EN); + if (ret < 0) { + LOG_ERR("Failed to enable data ready interrupt."); + return ret; + } + +#if defined(CONFIG_MPU9250_TRIGGER_OWN_THREAD) + ret = k_sem_init(&drv_data->gpio_sem, 0, K_SEM_MAX_LIMIT); + if (ret < 0) { + LOG_ERR("Failed to enable semaphore"); + return ret; + } + + k_thread_create(&drv_data->thread, drv_data->thread_stack, + CONFIG_MPU9250_THREAD_STACK_SIZE, + (k_thread_entry_t)mpu9250_thread, drv_data, + NULL, NULL, K_PRIO_COOP(CONFIG_MPU9250_THREAD_PRIORITY), + 0, K_NO_WAIT); +#elif defined(CONFIG_MPU9250_TRIGGER_GLOBAL_THREAD) + drv_data->work.handler = mpu9250_work_cb; +#endif + + ret = gpio_pin_interrupt_configure_dt(&cfg->int_pin, + GPIO_INT_EDGE_TO_ACTIVE); + if (ret < 0) { + LOG_ERR("Failed to enable interrupt"); + return ret; + } + + return 0; +} diff --git a/dts/bindings/sensor/invensense,mpu9250.yaml b/dts/bindings/sensor/invensense,mpu9250.yaml new file mode 100644 index 00000000000..fb9590554f3 --- /dev/null +++ b/dts/bindings/sensor/invensense,mpu9250.yaml @@ -0,0 +1,85 @@ +# Copyright (c) 2021 Nordic Semiconductor +# SPDX-License-Identifier: Apache-2.0 + +description: | + InvenSense MPU-9250 Nine-Axis (Gyro + Accelerometer + Compass). See more + info at https://www.invensense.com/products/motion-tracking/9-axis/mpu-9250/ + +compatible: "invensense,mpu9250" + +include: i2c-device.yaml + +properties: + irq-gpios: + type: phandle-array + required: false + description: | + The INT signal default configuration is active-high. The + property value should ensure the flags properly describe the + signal that is presented to the driver. + This property is required when the trigger mode is used. + + gyro-sr-div: + type: int + required: true + description: | + Default gyrscope sample rate divider. This divider is only effective + when gyro-dlpf is in range 5-184. + rate = sample_rate / (1 + gyro-sr-div) + Valid range: 0 - 255 + + gyro-dlpf: + type: int + required: true + description: | + Default digital low pass filter frequency of gyroscope. + Maps to DLPF_CFG field in Configuration setting. + enum: + - 250 + - 184 + - 92 + - 41 + - 20 + - 10 + - 5 + - 3600 + + gyro-fs: + type: int + required: true + description: | + Default full scale of gyroscope. (Unit - DPS). + Maps to GYRO_FS_SEL field in Gyroscope Configuration setting. + enum: + - 250 + - 500 + - 1000 + - 2000 + + accel-fs: + type: int + required: true + description: | + Default full scale of accelerometer. (Unit - g) + Maps to ACCEL_FS_SEL field in Accelerometer Configuration setting + enum: + - 2 + - 4 + - 8 + - 16 + + accel-dlpf: + type: string + required: true + description: | + Default digital low pass filter frequency of accelerometer. + Maps to DLPF_CFG field in Accelerometer Configuration 2 setting. + enum: + - "218.1" + - "218.1a" + - "99" + - "44.8" + - "21.2" + - "10.2" + - "5.05" + - "420" diff --git a/tests/drivers/build_all/sensor/i2c.dtsi b/tests/drivers/build_all/sensor/i2c.dtsi index 052ec758364..1b2fe44f0a8 100644 --- a/tests/drivers/build_all/sensor/i2c.dtsi +++ b/tests/drivers/build_all/sensor/i2c.dtsi @@ -154,6 +154,18 @@ test_i2c_mpu9150: mpu9150@16 { reg = <0x16>; }; +test_i2c_mpu9250: mpu9250@1e { + compatible = "invensense,mpu9250"; + reg = <0x1e>; + irq-gpios = <&test_gpio 0 0>; + gyro-sr-div = <10>; + gyro-dlpf = <5>; + gyro-fs = <250>; + accel-fs = <2>; + accel-dlpf="5.05"; + label = "MPU9250"; +}; + test_i2c_ina219: ina219@40 { compatible = "ti,ina219"; label = "INA219"; diff --git a/tests/drivers/build_all/sensor/prj.conf b/tests/drivers/build_all/sensor/prj.conf index ef269aaf698..f2ac144eb7e 100644 --- a/tests/drivers/build_all/sensor/prj.conf +++ b/tests/drivers/build_all/sensor/prj.conf @@ -72,6 +72,7 @@ CONFIG_MAX6675=y CONFIG_MCP9808=y CONFIG_MPR=y CONFIG_MPU6050=y +CONFIG_MPU9250=y CONFIG_MS5607=y CONFIG_MS5837=y CONFIG_OPT3001=y diff --git a/tests/drivers/build_all/sensor/sensors_trigger_own.conf b/tests/drivers/build_all/sensor/sensors_trigger_own.conf index 28a05c164b8..7c77279dcda 100644 --- a/tests/drivers/build_all/sensor/sensors_trigger_own.conf +++ b/tests/drivers/build_all/sensor/sensors_trigger_own.conf @@ -30,6 +30,7 @@ CONFIG_LSM9DS0_GYRO_TRIGGER_DRDY=y CONFIG_LSM9DS0_GYRO_TRIGGERS=y CONFIG_MCP9808_TRIGGER_OWN_THREAD=y CONFIG_MPU6050_TRIGGER_OWN_THREAD=y +CONFIG_MPU9250_TRIGGER_OWN_THREAD=y CONFIG_SHT3XD_TRIGGER_OWN_THREAD=y CONFIG_SM351LT_TRIGGER_OWN_THREAD=y CONFIG_STTS751_TRIGGER_OWN_THREAD=y From e25992ba220aa9b23ee6b0327b541068b961406d Mon Sep 17 00:00:00 2001 From: Krzysztof Chruscinski Date: Wed, 29 Dec 2021 08:06:05 +0100 Subject: [PATCH 023/207] [nrf fromtree] logging: Improve algorithm for waking up the thread Use value returned by atomic_inc to decide on action. Previously direct value was used and that could lead to delays in logging processing because thread waking up could be mishandled. merged: https://github.com/zephyrproject-rtos/zephyr/pull/41490 Signed-off-by: Krzysztof Chruscinski --- subsys/logging/log_core.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/subsys/logging/log_core.c b/subsys/logging/log_core.c index 38308157afd..a8fca68860f 100644 --- a/subsys/logging/log_core.c +++ b/subsys/logging/log_core.c @@ -226,16 +226,17 @@ static void detect_missed_strdup(struct log_msg *msg) static void z_log_msg_post_finalize(void) { - atomic_inc(&buffered_cnt); + atomic_val_t cnt = atomic_inc(&buffered_cnt); + if (panic_mode) { unsigned int key = irq_lock(); (void)log_process(false); irq_unlock(key); - } else if (proc_tid != NULL && buffered_cnt == 1) { + } else if (proc_tid != NULL && cnt == 0) { k_timer_start(&log_process_thread_timer, K_MSEC(CONFIG_LOG_PROCESS_THREAD_SLEEP_MS), K_NO_WAIT); } else if (CONFIG_LOG_PROCESS_TRIGGER_THRESHOLD) { - if ((buffered_cnt == CONFIG_LOG_PROCESS_TRIGGER_THRESHOLD) && + if ((cnt == CONFIG_LOG_PROCESS_TRIGGER_THRESHOLD) && (proc_tid != NULL)) { k_timer_stop(&log_process_thread_timer); k_sem_give(&log_process_thread_sem); From e9b1c0d8910cd7f8f2cb4f3935fe85f96cce490c Mon Sep 17 00:00:00 2001 From: Krzysztof Chruscinski Date: Wed, 29 Dec 2021 08:08:53 +0100 Subject: [PATCH 024/207] [nrf fromtree] logging: Fix counting of buffered messages When message is dropped then log_process is called with bypass flag set and additionally z_log_dropped() is called. In both functions counter of buffered messages was decremented. That resulted in counter being decremented twice. It resulted in logging misbehavior after messages being dropped (delayed processing). Fixing it by decrementing the counter in log_process only when bypass flag is not set. Merged: https://github.com/zephyrproject-rtos/zephyr/pull/41490 Signed-off-by: Krzysztof Chruscinski --- subsys/logging/log_core.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/subsys/logging/log_core.c b/subsys/logging/log_core.c index a8fca68860f..cbbf4959318 100644 --- a/subsys/logging/log_core.c +++ b/subsys/logging/log_core.c @@ -817,7 +817,9 @@ bool z_impl_log_process(bool bypass) msg = get_msg(); if (msg.msg) { - atomic_dec(&buffered_cnt); + if (!bypass) { + atomic_dec(&buffered_cnt); + } msg_process(msg, bypass); } From e692f7960914405da547298f942036b2c6240b06 Mon Sep 17 00:00:00 2001 From: Marc Herbert Date: Tue, 11 Jan 2022 00:18:18 +0000 Subject: [PATCH 025/207] [nrf fromtree] twister: remove spurious quoting of EXTRA_xFLAGS=-Werror 19e4e12c03e6d04b1250d49bf8a879328c9dfedc Testing shows cmake is invoked directly, not through a shell. Fixes commit 5092541e2b59 ("sanitycheck: disable erroring on warnings"). Note EXTRA_AFLAGS was quoted only on the left side! Signed-off-by: Marc Herbert --- scripts/pylib/twister/twisterlib.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/pylib/twister/twisterlib.py b/scripts/pylib/twister/twisterlib.py index 2f8fd7b3c88..359d73c1afe 100755 --- a/scripts/pylib/twister/twisterlib.py +++ b/scripts/pylib/twister/twisterlib.py @@ -2149,9 +2149,9 @@ def run_cmake(self, args=[]): cmake_args = [ f'-B{self.build_dir}', f'-S{self.source_dir}', - f'-DEXTRA_CFLAGS="{cflags}"', - f'-DEXTRA_AFLAGS="{aflags}', - f'-DEXTRA_LDFLAGS="{ldflags}"', + f'-DEXTRA_CFLAGS={cflags}', + f'-DEXTRA_AFLAGS={aflags}', + f'-DEXTRA_LDFLAGS={ldflags}', f'-DEXTRA_GEN_DEFINES_ARGS={gen_defines_args}', f'-G{self.generator}' ] From 726a73bfa5b2e6aea265344af73fec7a42a03171 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jani=20Hirsim=C3=A4ki?= Date: Tue, 25 Jan 2022 10:30:08 +0200 Subject: [PATCH 026/207] [nrf fromlist] drivers: net: ppp: asynch api: use microseconds MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Updated uart_rx_enable() and uart_tx() to use timeout given in microseconds. Previously argument was given in milliseconds. API change was done in: https://github.com/zephyrproject-rtos/zephyr/pull/39041 Signed-off-by: Jani Hirsimäki --- drivers/net/ppp.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/net/ppp.c b/drivers/net/ppp.c index f672d5d96a3..34643b5db1e 100644 --- a/drivers/net/ppp.c +++ b/drivers/net/ppp.c @@ -220,7 +220,7 @@ static int ppp_async_uart_rx_enable(struct ppp_driver_context *context) } err = uart_rx_enable(context->dev, context->buf, sizeof(context->buf), - CONFIG_NET_PPP_ASYNC_UART_RX_ENABLE_TIMEOUT); + CONFIG_NET_PPP_ASYNC_UART_RX_ENABLE_TIMEOUT * USEC_PER_MSEC); if (err) { LOG_ERR("uart_rx_enable() failed, err %d", err); } else { @@ -370,7 +370,8 @@ static int ppp_send_flush(struct ppp_driver_context *ppp, int off) k_sem_take(&uarte_tx_finished, K_FOREVER); - ret = uart_tx(ppp->dev, buf, off, CONFIG_NET_PPP_ASYNC_UART_TX_TIMEOUT); + ret = uart_tx(ppp->dev, buf, off, + CONFIG_NET_PPP_ASYNC_UART_TX_TIMEOUT * USEC_PER_MSEC); if (ret) { LOG_ERR("uart_tx() failed, err %d", ret); k_sem_give(&uarte_tx_finished); From 3aedc0fddc683d4361da3f5e81d874f39781df93 Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Mon, 17 Jan 2022 11:35:05 +0100 Subject: [PATCH 027/207] [nrf fromtree] doc: use extlink for github issue links Use extlink for GitHub issue links in documentation. Signed-off-by: Henrik Brix Andersen (cherry picked from commit 2c0e0a74af0c16a3ec3080645fa09e4f340283d6) --- boards/arm/nucleo_f767zi/doc/index.rst | 2 +- doc/contribute/coding_guidelines/index.rst | 3 +-- doc/contribute/external.rst | 6 ++---- doc/development_process/project_roles.rst | 4 ++-- doc/getting_started/installation_win.rst | 2 +- doc/guides/west/why.rst | 2 +- samples/bluetooth/ipsp/README.rst | 4 ++-- 7 files changed, 10 insertions(+), 13 deletions(-) diff --git a/boards/arm/nucleo_f767zi/doc/index.rst b/boards/arm/nucleo_f767zi/doc/index.rst index 4a375722313..1bd38ad492c 100644 --- a/boards/arm/nucleo_f767zi/doc/index.rst +++ b/boards/arm/nucleo_f767zi/doc/index.rst @@ -127,7 +127,7 @@ features: (*) nucleo_f767zi with soc cut-A (Device marking A) has some ethernet - instability (https://github.com/zephyrproject-rtos/zephyr/issues/26519). + instability (:github:`26519`). Use of cut-Z is advised. see restrictions errata: https://www.st.com/content/ccc/resource/technical/document/errata_sheet/group0/23/a6/11/0b/30/24/46/a5/DM00257543/files/DM00257543.pdf/jcr:content/translations/en.DM00257543.pdf diff --git a/doc/contribute/coding_guidelines/index.rst b/doc/contribute/coding_guidelines/index.rst index 01504a8d177..b26bcf5efd7 100644 --- a/doc/contribute/coding_guidelines/index.rst +++ b/doc/contribute/coding_guidelines/index.rst @@ -926,7 +926,7 @@ Related GitHub Issues and Pull Requests are tagged with the `Inclusive Language terminology is confirmed by a public announcement or updated specification. - See `Zephyr issue 27033`_. + See :github:`Zephyr issue 27033 <27033>`. * - :ref:`i2s_api` - * ``master / slave`` => TBD @@ -951,7 +951,6 @@ Related GitHub Issues and Pull Requests are tagged with the `Inclusive Language .. _I2C Specification: https://www.nxp.com/docs/en/user-guide/UM10204.pdf .. _Bluetooth Appropriate Language Mapping Tables: https://btprodspecificationrefs.blob.core.windows.net/language-mapping/Appropriate_Language_Mapping_Table.pdf .. _OSHWA Resolution to Redefine SPI Signal Names: https://www.oshwa.org/a-resolution-to-redefine-spi-signal-names/ -.. _Zephyr issue 27033: https://github.com/zephyrproject-rtos/zephyr/issues/27033 Parasoft Codescan Tool ********************** diff --git a/doc/contribute/external.rst b/doc/contribute/external.rst index 09381213a47..004c4ec037a 100644 --- a/doc/contribute/external.rst +++ b/doc/contribute/external.rst @@ -124,7 +124,8 @@ Follow the steps below to begin the submission process: #. Make sure to read through the :ref:`external-contributions` section in detail, so that you are informed of the criteria used by the TSC and board in order to approve or reject a request -#. Use the `New External Source Code Issue`_ to open an issue +#. Use the :github:`New External Source Code Issue + ` to open an issue #. Fill out all required sections, making sure you provide enough detail for the TSC to assess the merit of the request. Optionally you can also create a Pull Request that demonstrates the integration of the external source code and @@ -163,6 +164,3 @@ The flowchart below shows an overview of the process: :align: center Submission process - -.. _New External Source Code Issue: - https://github.com/zephyrproject-rtos/zephyr/issues/new?assignees=&labels=RFC&template=ext-source.md&title= diff --git a/doc/development_process/project_roles.rst b/doc/development_process/project_roles.rst index acba6a0f432..adc10ce0faf 100644 --- a/doc/development_process/project_roles.rst +++ b/doc/development_process/project_roles.rst @@ -60,8 +60,8 @@ Contributors who show dedication and skill are granted the Triage permission level to the Zephyr GitHub repository. You may nominate yourself, or another GitHub user, for promotion to the Triage -permission level by creating a GitHub issue, using the `nomination template -`_. +permission level by creating a GitHub issue, using the :github:`nomination +template `. Contributors granted the Triage permission level are permitted to add reviewers to a pull request and can be added as a reviewer by other GitHub users. diff --git a/doc/getting_started/installation_win.rst b/doc/getting_started/installation_win.rst index c71a9e3a9cc..c961b6ed750 100644 --- a/doc/getting_started/installation_win.rst +++ b/doc/getting_started/installation_win.rst @@ -33,4 +33,4 @@ command-prompt. This allows you to use software such as the :ref:`Zephyr SDK the documentation itself here. .. _Install the Windows Subsystem for Linux (WSL): https://msdn.microsoft.com/en-us/commandline/wsl/install_guide -.. _Zephyr Issue 10420: https://github.com/zephyrproject-rtos/zephyr/issues/10420 +.. _Zephyr Issue 10420: :github:`10420` diff --git a/doc/guides/west/why.rst b/doc/guides/west/why.rst index e1f513812c7..87220b6b7b9 100644 --- a/doc/guides/west/why.rst +++ b/doc/guides/west/why.rst @@ -120,4 +120,4 @@ West is: See `Zephyr issue #6205`_ and for more details and discussion. .. _Zephyr issue #6205: - https://github.com/zephyrproject-rtos/zephyr/issues/6205 + :github:`6205` diff --git a/samples/bluetooth/ipsp/README.rst b/samples/bluetooth/ipsp/README.rst index 120e885ef1d..fef4dfdefe6 100644 --- a/samples/bluetooth/ipsp/README.rst +++ b/samples/bluetooth/ipsp/README.rst @@ -38,8 +38,8 @@ Building and Running for Linux kernels released before 4.12 For hosts using kernels released before 4.12, option :kconfig:`CONFIG_NET_L2_BT_ZEP1656` - must be selected. For more information, see `Zephyr issue #3111 - `_ + must be selected. For more information, see :github:`Zephyr issue #3111 + <3111>`. .. zephyr-app-commands:: :zephyr-app: samples/bluetooth/ipsp From 499e975f0595b3199b7d614ec409fe9be5edce91 Mon Sep 17 00:00:00 2001 From: Gerard Marull-Paretas Date: Mon, 17 Jan 2022 18:01:10 +0100 Subject: [PATCH 028/207] [nrf fromtree] doc: fix PDF build issue due to extlink references LaTeX code generated by Sphinx causes problems when using extlinks in references. Mitigate the problem by just using the extlink role directly. Signed-off-by: Gerard Marull-Paretas (cherry picked from commit d2538475c6929cdce2278138fbea44e2c44930ff) --- doc/getting_started/installation_win.rst | 3 +-- doc/guides/west/why.rst | 5 +---- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/doc/getting_started/installation_win.rst b/doc/getting_started/installation_win.rst index c961b6ed750..2bf569d52c1 100644 --- a/doc/getting_started/installation_win.rst +++ b/doc/getting_started/installation_win.rst @@ -16,7 +16,7 @@ command-prompt. This allows you to use software such as the :ref:`Zephyr SDK .. warning:: Windows 10 version 1803 has an issue that will cause CMake to not work properly and is fixed in version 1809 (and later). - More information can be found in `Zephyr Issue 10420`_ + More information can be found in :github:`Zephyr Issue 10420 <10420>`. #. `Install the Windows Subsystem for Linux (WSL)`_. @@ -33,4 +33,3 @@ command-prompt. This allows you to use software such as the :ref:`Zephyr SDK the documentation itself here. .. _Install the Windows Subsystem for Linux (WSL): https://msdn.microsoft.com/en-us/commandline/wsl/install_guide -.. _Zephyr Issue 10420: :github:`10420` diff --git a/doc/guides/west/why.rst b/doc/guides/west/why.rst index 87220b6b7b9..628d557592e 100644 --- a/doc/guides/west/why.rst +++ b/doc/guides/west/why.rst @@ -117,7 +117,4 @@ West is: interoperability with third party tools, and means Zephyr developers can always find out what is happening "under the hood" when using west. -See `Zephyr issue #6205`_ and for more details and discussion. - -.. _Zephyr issue #6205: - :github:`6205` +See :github:`Zephyr issue #6205 <6205>` and for more details and discussion. From 358dcb70b5489af2f91ed9f340a8f07d2b0f098a Mon Sep 17 00:00:00 2001 From: Torsten Rasmussen Date: Fri, 7 Jan 2022 12:36:25 +0100 Subject: [PATCH 029/207] [nrf fromtree] linker: update posix linker template, linker.ld The function `zephyr_linker_sources()` states: > When placing into NOINIT, RWDATA, RODATA, ROM_START, the contents of > the files will be placed inside an output section, so assume the > section definition is already present. However, in the posix linker.ld template the NOINIT, RWDATA, RODATA, and ROM_START was not placed inside a pre-defined output section, which means that linker scripts created for native_posix when `zephyr_linker_sources()` is used are invalid This result in the following failure: > /usr/bin/ld:zephyr/linker_zephyr_prebuilt.cmd:81: syntax error > collect2: error: ld returned 1 exit status This PR fixes this issue be predefining output sections according to the documented behavior. Signed-off-by: Torsten Rasmussen --- include/arch/posix/linker.ld | 46 +++++++++++++++++++++++------------- 1 file changed, 29 insertions(+), 17 deletions(-) diff --git a/include/arch/posix/linker.ld b/include/arch/posix/linker.ld index d56260e76af..dccb4593c58 100644 --- a/include/arch/posix/linker.ld +++ b/include/arch/posix/linker.ld @@ -22,22 +22,31 @@ SECTIONS { -/* Located in generated directory. This file is populated by the - * zephyr_linker_sources() Cmake function. - */ -#include +SECTION_PROLOGUE(rom_start,,) +{ + /* Located in generated directory. This file is populated by the + * zephyr_linker_sources() Cmake function. + */ + #include +} GROUP_LINK_IN(ROMABLE_REGION) #include -/* Located in generated directory. This file is populated by the - * zephyr_linker_sources() Cmake function. - */ -#include - -/* Located in generated directory. This file is populated by the - * zephyr_linker_sources() Cmake function. - */ -#include +SECTION_PROLOGUE(_RODATA_SECTION_NAME,,) +{ + /* Located in generated directory. This file is populated by the + * zephyr_linker_sources() Cmake function. + */ + #include +} GROUP_LINK_IN(ROMABLE_REGION) + +SECTION_DATA_PROLOGUE(_DATA_SECTION_NAME,,) +{ + /* Located in generated directory. This file is populated by the + * zephyr_linker_sources() Cmake function. + */ + #include +} GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION) #include @@ -55,10 +64,13 @@ SECTIONS __data_region_end = .; -/* Located in generated directory. This file is populated by the - * zephyr_linker_sources() Cmake function. - */ -#include +SECTION_DATA_PROLOGUE(_NOINIT_SECTION_NAME,,) +{ + /* Located in generated directory. This file is populated by the + * zephyr_linker_sources() Cmake function. + */ + #include +} GROUP_LINK_IN(RAMABLE_REGION) /* Located in generated directory. This file is populated by the * zephyr_linker_sources() Cmake function. From 3d5b143900d9ef8971fca827f69489aef9649a27 Mon Sep 17 00:00:00 2001 From: Jedrzej Ciupis Date: Fri, 14 Jan 2022 15:06:23 +0100 Subject: [PATCH 030/207] [nrf fromtree] drivers: ieee802154: extend support for nRF53 This commit updates the ieee802154 driver to match the current feature set of the nRF 802.15.4 radio driver for nRF53 SoCs. Signed-off-by: Jedrzej Ciupis (cherry picked from commit 81ea5299600e742d830426a130a49a751109cd9f) --- drivers/ieee802154/ieee802154_nrf5.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/ieee802154/ieee802154_nrf5.c b/drivers/ieee802154/ieee802154_nrf5.c index ee3a403f1fc..0b20fc623e1 100644 --- a/drivers/ieee802154/ieee802154_nrf5.c +++ b/drivers/ieee802154/ieee802154_nrf5.c @@ -501,8 +501,7 @@ static bool nrf5_tx_csma_ca(struct net_pkt *pkt, uint8_t *payload) return nrf_802154_transmit_csma_ca_raw(payload, &metadata); } -/* This function cannot be used in the serialized version yet. */ -#if defined(CONFIG_NET_PKT_TXTIME) && !defined(CONFIG_NRF_802154_SER_HOST) +#if IS_ENABLED(CONFIG_NET_PKT_TXTIME) static bool nrf5_tx_at(struct net_pkt *pkt, uint8_t *payload, bool cca) { nrf_802154_transmit_at_metadata_t metadata = { @@ -554,8 +553,7 @@ static int nrf5_tx(const struct device *dev, case IEEE802154_TX_MODE_CSMA_CA: ret = nrf5_tx_csma_ca(pkt, nrf5_radio->tx_psdu); break; -/* This function cannot be used in the serialized version yet. */ -#if defined(CONFIG_NET_PKT_TXTIME) && !defined(CONFIG_NRF_802154_SER_HOST) +#if IS_ENABLED(CONFIG_NET_PKT_TXTIME) case IEEE802154_TX_MODE_TXTIME: case IEEE802154_TX_MODE_TXTIME_CCA: __ASSERT_NO_MSG(pkt); @@ -942,7 +940,7 @@ void nrf_802154_received_timestamp_raw(uint8_t *data, int8_t power, uint8_t lqi, nrf5_data.rx_frames[i].rssi = power; nrf5_data.rx_frames[i].lqi = lqi; -#if !defined(CONFIG_NRF_802154_SER_HOST) && defined(CONFIG_NET_PKT_TIMESTAMP) +#if IS_ENABLED(CONFIG_NET_PKT_TIMESTAMP) nrf5_data.rx_frames[i].time = nrf_802154_first_symbol_timestamp_get(time, data[0]); #endif @@ -1022,7 +1020,7 @@ void nrf_802154_transmitted_raw(uint8_t *frame, nrf5_data.ack_frame.rssi = metadata->data.transmitted.power; nrf5_data.ack_frame.lqi = metadata->data.transmitted.lqi; -#if !IS_ENABLED(CONFIG_NRF_802154_SER_HOST) && IS_ENABLED(CONFIG_NET_PKT_TIMESTAMP) +#if IS_ENABLED(CONFIG_NET_PKT_TIMESTAMP) nrf5_data.ack_frame.time = nrf_802154_first_symbol_timestamp_get( metadata->data.transmitted.time, nrf5_data.ack_frame.psdu[0]); From 45edc31284ccd50c190141c188ec4fe55619c44e Mon Sep 17 00:00:00 2001 From: Eduardo Montoya Date: Wed, 26 Jan 2022 13:43:16 +0100 Subject: [PATCH 031/207] [nrf fromtree] manifest: openthread upmerge up to commit `a04a68b5` Update OpenThread revision. Signed-off-by: Eduardo Montoya (cherry picked from commit a9b73a419ef4d2d06bfdf311266ab9e044d845b6) --- west.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/west.yml b/west.yml index 282997c1c25..a689d908e51 100644 --- a/west.yml +++ b/west.yml @@ -190,7 +190,7 @@ manifest: revision: cfd050ff38a9d028dc211690b2ec35971128e45e path: modules/lib/open-amp - name: openthread - revision: 41bc49da49736fbdfdfa231f7b2311f29dcc4979 + revision: b7aa7686d3f4e326bd25abc234b209159977c26d path: modules/lib/openthread - name: segger revision: 3a52ab222133193802d3c3b4d21730b9b1f1d2f6 From 10c1468d26334523114025c1554081861fd014bc Mon Sep 17 00:00:00 2001 From: Eduardo Montoya Date: Wed, 26 Jan 2022 13:43:31 +0100 Subject: [PATCH 032/207] [nrf fromtree] net: openthread: remove obsolete define Remove `OPENTHREAD_CONFIG_PLAT_LOG_MACRO_NAME` which has been deprecated in OpenThread. Signed-off-by: Eduardo Montoya (cherry picked from commit 48a5d42313a0fea22b6932dfe4c0995c91e165ca) --- .../platform/openthread-core-zephyr-config.h | 32 ------------------- 1 file changed, 32 deletions(-) diff --git a/subsys/net/lib/openthread/platform/openthread-core-zephyr-config.h b/subsys/net/lib/openthread/platform/openthread-core-zephyr-config.h index dfa753f2744..5c35c4b137b 100644 --- a/subsys/net/lib/openthread/platform/openthread-core-zephyr-config.h +++ b/subsys/net/lib/openthread/platform/openthread-core-zephyr-config.h @@ -272,38 +272,6 @@ */ #define RADIO_CONFIG_SRC_MATCH_EXT_ENTRY_NUM 0 -/** - * @def OPENTHREAD_CONFIG_PLAT_LOG_MACRO_NAME - * - * The platform logging function for openthread. - * - */ -#define _OT_CONF_PLAT_LOG_FUN_NARGS__IMPL( \ - _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10,\ - _11, _12, _13, _14, N, ...) N - -#define _OT_CONF_PLAT_LOG_FUN_NARGS__GET(...) \ - _OT_CONF_PLAT_LOG_FUN_NARGS__IMPL(__VA_ARGS__,\ - 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, ~) - -#define OPENTHREAD_CONFIG_PLAT_LOG_MACRO_NAME__COUNT_ARGS(aLogLevel, unused, \ - aFormat, ...) \ - do { \ - ARG_UNUSED(unused); \ - otPlatLog( \ - aLogLevel, \ - (otLogRegion)_OT_CONF_PLAT_LOG_FUN_NARGS__GET(__VA_ARGS__),\ - aFormat, ##__VA_ARGS__); \ - } while (false) - -#ifdef OPENTHREAD_CONFIG_PLAT_LOG_MACRO_NAME -#error OPENTHREAD_CONFIG_PLAT_LOG_MACRO_NAME \ - "OPENTHREAD_CONFIG_PLAT_LOG_MACRO_NAME mustn't be defined before" -#endif - -#define OPENTHREAD_CONFIG_PLAT_LOG_MACRO_NAME \ - OPENTHREAD_CONFIG_PLAT_LOG_MACRO_NAME__COUNT_ARGS - /** * @def OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE * From 21120b3657cc0bff9fa73488cb15d67c48283404 Mon Sep 17 00:00:00 2001 From: Eduardo Montoya Date: Wed, 26 Jan 2022 13:44:17 +0100 Subject: [PATCH 033/207] [nrf fromtree] net: openthread: revert CLI prompt workaround `OPENTHREAD_CONFIG_CLI_PROMPT_ENABLE` can be used now. Signed-off-by: Eduardo Montoya (cherry picked from commit e9245a6198c0ab512395d793ff9841600b75e6ab) --- subsys/net/lib/openthread/platform/shell.c | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/subsys/net/lib/openthread/platform/shell.c b/subsys/net/lib/openthread/platform/shell.c index cf34887a778..e72fd34a6e6 100644 --- a/subsys/net/lib/openthread/platform/shell.c +++ b/subsys/net/lib/openthread/platform/shell.c @@ -25,19 +25,8 @@ static bool is_shell_initialized; static int ot_console_cb(void *context, const char *format, va_list arg) { - char prompt_check[4]; - ARG_UNUSED(context); - /* A temporary workaround to avoid printing OT prompt in Zehyr shell. - * Eventually, OT should add an option which would allow to disable - * prompt on the CLI output. - */ - vsnprintf(prompt_check, sizeof(prompt_check), format, arg); - if (strcmp(prompt_check, "> ") == 0) { - return 0; - } - if (shell_p == NULL) { return 0; } From 47b94f3926f068e666af14db1c6e9bcdf2cbd6db Mon Sep 17 00:00:00 2001 From: Eduardo Montoya Date: Wed, 26 Jan 2022 13:44:32 +0100 Subject: [PATCH 034/207] [nrf fromtree] net: openthread: disable CLI prompt Avoid printing OpenThread prompt in Zephyr. Signed-off-by: Eduardo Montoya (cherry picked from commit c6e31a888f3a57a80c84e5b6f8dad06914eacf7e) --- .../platform/openthread-core-zephyr-config.h | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/subsys/net/lib/openthread/platform/openthread-core-zephyr-config.h b/subsys/net/lib/openthread/platform/openthread-core-zephyr-config.h index 5c35c4b137b..68c6240ca3d 100644 --- a/subsys/net/lib/openthread/platform/openthread-core-zephyr-config.h +++ b/subsys/net/lib/openthread/platform/openthread-core-zephyr-config.h @@ -349,6 +349,17 @@ #define OPENTHREAD_CONFIG_CLI_MAX_LINE_LENGTH CONFIG_OPENTHREAD_CLI_MAX_LINE_LENGTH #endif /* CONFIG_OPENTHREAD_CLI_MAX_LINE_LENGTH */ +/** + * @def OPENTHREAD_CONFIG_CLI_PROMPT_ENABLE + * + * Enable CLI prompt. + * + * When enabled, the CLI will print prompt on the output after processing a command. + * Otherwise, no prompt is added to the output. + * + */ +#define OPENTHREAD_CONFIG_CLI_PROMPT_ENABLE 0 + /** * @def OPENTHREAD_CONFIG_IP6_MAX_EXT_UCAST_ADDRS * From c461cb2a296ff820d05a8c52d1b4549707280d57 Mon Sep 17 00:00:00 2001 From: Eduardo Montoya Date: Wed, 26 Jan 2022 13:44:47 +0100 Subject: [PATCH 035/207] [nrf fromtree] libc: add `stddef.h` to the minimal libc It is required for using `size_t`. Signed-off-by: Eduardo Montoya (cherry picked from commit b2ca5772561117afc53a0888a6c1e368d5dc51bd) --- lib/libc/minimal/include/strings.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/libc/minimal/include/strings.h b/lib/libc/minimal/include/strings.h index db7670154aa..5c930194003 100644 --- a/lib/libc/minimal/include/strings.h +++ b/lib/libc/minimal/include/strings.h @@ -9,6 +9,8 @@ #ifndef ZEPHYR_LIB_LIBC_MINIMAL_INCLUDE_STRINGS_H_ #define ZEPHYR_LIB_LIBC_MINIMAL_INCLUDE_STRINGS_H_ +#include + #ifdef __cplusplus extern "C" { #endif From b93bad93327baac957dae76b856f07ed70187b0b Mon Sep 17 00:00:00 2001 From: Przemyslaw Bida Date: Wed, 26 Jan 2022 14:08:14 +0100 Subject: [PATCH 036/207] [nrf fromtree] net: openthread: Fix warinig in nrf5_config_mac_keys. This commit fixes compilation warning (unused variable) generated in nrf5_config_mac_keys function, when the ASSERT macros were disabled. Signed-off-by: Przemyslaw Bida (cherry picked from commit b5e34561eb43b9ae5f17a3ec2f76a0a4d5270b9a) --- drivers/ieee802154/ieee802154_nrf5.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/ieee802154/ieee802154_nrf5.c b/drivers/ieee802154/ieee802154_nrf5.c index 0b20fc623e1..0b61c0fc239 100644 --- a/drivers/ieee802154/ieee802154_nrf5.c +++ b/drivers/ieee802154/ieee802154_nrf5.c @@ -748,7 +748,8 @@ static void nrf5_config_mac_keys(struct ieee802154_key *mac_keys) } i = 0; - for (struct ieee802154_key *keys = mac_keys; keys->key_value; keys++) { + for (struct ieee802154_key *keys = mac_keys; keys->key_value + && i < NRF_802154_SECURITY_KEY_STORAGE_SIZE; keys++, i++) { nrf_802154_key_t key = { .value.p_cleartext_key = keys->key_value, .id.mode = keys->key_id_mode, @@ -758,16 +759,15 @@ static void nrf5_config_mac_keys(struct ieee802154_key *mac_keys) .use_global_frame_counter = !(keys->frame_counter_per_key), }; - nrf_802154_security_error_t err = nrf_802154_security_key_store(&key); - __ASSERT(err == NRF_802154_SECURITY_ERROR_NONE || - err == NRF_802154_SECURITY_ERROR_ALREADY_PRESENT, - "Storing key failed, err: %d", err); + __ASSERT_EVAL((void)nrf_802154_security_key_store(&key), + nrf_802154_security_error_t err = nrf_802154_security_key_store(&key), + err == NRF_802154_SECURITY_ERROR_NONE || + err == NRF_802154_SECURITY_ERROR_ALREADY_PRESENT, + "Storing key failed, err: %d", err); - __ASSERT(i < NRF_802154_SECURITY_KEY_STORAGE_SIZE, "Store buffer is full"); stored_ids[i] = *key.id.p_key_id; stored_key_ids[i].mode = key.id.mode; stored_key_ids[i].p_key_id = &stored_ids[i]; - i++; }; } #endif /* CONFIG_NRF_802154_ENCRYPTION */ From 94d44331282e83986697f955483c9d0455360657 Mon Sep 17 00:00:00 2001 From: Przemyslaw Bida Date: Wed, 26 Jan 2022 14:08:37 +0100 Subject: [PATCH 037/207] [nrf fromtree] net: openthread: Add openthread CSL clock uncert This commit adds OPENTHREAD_PLATFORM_CSL_UNCERToption to Kconfig. This option will allow user to configure openthreads CSL clock uncertianity during build time. Signed-off-by: Przemyslaw Bida (cherry picked from commit 00ef3d2fa7c1ac9b5d9f0fd43784a70906c36782) --- subsys/net/l2/openthread/Kconfig.thread | 6 ++++++ .../platform/openthread-core-zephyr-config.h | 10 ++++++++++ 2 files changed, 16 insertions(+) diff --git a/subsys/net/l2/openthread/Kconfig.thread b/subsys/net/l2/openthread/Kconfig.thread index c9aad6a816d..dc1fd366d82 100644 --- a/subsys/net/l2/openthread/Kconfig.thread +++ b/subsys/net/l2/openthread/Kconfig.thread @@ -100,6 +100,12 @@ config OPENTHREAD_CSL_MIN_RECEIVE_ON help The minimum CSL receive window (in microseconds) required to receive a full IEEE 802.15.4 frame +config OPENTHREAD_PLATFORM_CSL_UNCERT + int "CSL clock uncertainty" + default 255 + help + The Uncertainty of the scheduling CSL of transmission by the parent, in ±10 us units. + config OPENTHREAD_MAC_SOFTWARE_TX_SECURITY_ENABLE bool "Enable software transmission security logic" default y if OPENTHREAD_THREAD_VERSION_1_2 diff --git a/subsys/net/lib/openthread/platform/openthread-core-zephyr-config.h b/subsys/net/lib/openthread/platform/openthread-core-zephyr-config.h index 68c6240ca3d..8855fd123cb 100644 --- a/subsys/net/lib/openthread/platform/openthread-core-zephyr-config.h +++ b/subsys/net/lib/openthread/platform/openthread-core-zephyr-config.h @@ -328,6 +328,16 @@ #define OPENTHREAD_CONFIG_CSL_MIN_RECEIVE_ON CONFIG_OPENTHREAD_CSL_MIN_RECEIVE_ON #endif /* CONFIG_OPENTHREAD_CSL_MIN_RECEIVE_ON */ +/** + * @def OPENTHREAD_CONFIG_PLATFORM_CSL_UNCERT + * + * The Uncertainty of the scheduling CSL of transmission by the parent, in ±10 us units. + */ + +#ifdef CONFIG_OPENTHREAD_PLATFORM_CSL_UNCERT +#define OPENTHREAD_CONFIG_PLATFORM_CSL_UNCERT CONFIG_OPENTHREAD_PLATFORM_CSL_UNCERT +#endif /* CONFIG_OPENTHREAD_PLATFORM_CSL_UNCERT */ + /** * @def OPENTHREAD_CONFIG_MAC_SOFTWARE_TX_SECURITY_ENABLE * From 7b72e10236bb87c39eb4097c5bdc12ef94b8b7e6 Mon Sep 17 00:00:00 2001 From: Eduardo Montoya Date: Wed, 26 Jan 2022 14:08:58 +0100 Subject: [PATCH 038/207] [nrf fromtree] net: openthread: blank `otPlatLog` when logging is disabled Implement an empty `otPlatLog` function when `CONFIG_LOG` is not enabled. This also fixes the issue with `log_count_args` not being available when logging is disabled. Signed-off-by: Eduardo Montoya (cherry picked from commit 587d77a637ca2dde81a12959d18b3b1c5a1a31ee) --- subsys/net/lib/openthread/platform/logging.c | 32 +++++--------------- 1 file changed, 8 insertions(+), 24 deletions(-) diff --git a/subsys/net/lib/openthread/platform/logging.c b/subsys/net/lib/openthread/platform/logging.c index 5788eb95aa5..5c113b8c722 100644 --- a/subsys/net/lib/openthread/platform/logging.c +++ b/subsys/net/lib/openthread/platform/logging.c @@ -39,35 +39,14 @@ static inline int log_translate(otLogLevel aLogLevel) return -1; } -void otPlatLog(otLogLevel aLogLevel, otLogRegion aLogRegion, - const char *aFormat, ...) +void otPlatLog(otLogLevel aLogLevel, otLogRegion aLogRegion, const char *aFormat, ...) { - /* - * The following speed optimization have been used: - * - arguments are counted at compile time - * - for none arguments aFormat is not checked for %s - * - for up to three arguments program uses fast path - * - time consuming string formatting is posponed to idle time - * TODO : add support for ll (problem for 32 bit processors) - */ - - -#ifdef OPENTHREAD_CONFIG_PLAT_LOG_MACRO_NAME__COUNT_ARGS - /* The arguments number has been counted by macro at compile time, - * and the value has been passed in unused (now) aLogRegion. - * If LogRegion value from OT is needed, rewrite macro - * OPENTHREAD_CONFIG_PLAT_LOG_MACRO_NAME__COUNT_ARGS and use higher - * bits to pass args_num. - */ - uint32_t args_num = (uint32_t) aLogRegion; -#else ARG_UNUSED(aLogRegion); +#if defined(CONFIG_LOG) + int level = log_translate(aLogLevel); uint32_t args_num = log_count_args(aFormat); -#endif - va_list param_list; - int level = log_translate(aLogLevel); if (level < 0) { return; @@ -82,4 +61,9 @@ void otPlatLog(otLogLevel aLogLevel, otLogRegion aLogRegion, */ Z_LOG_VA(level, aFormat, param_list, args_num, LOG_STRDUP_EXEC); va_end(param_list); +#else + ARG_UNUSED(aLogLevel); + ARG_UNUSED(aFormat); +#endif + } From 896359ca34be8560d31db5d97d43a747accc7e87 Mon Sep 17 00:00:00 2001 From: Eduardo Montoya Date: Thu, 27 Jan 2022 10:15:57 +0100 Subject: [PATCH 039/207] [nrf fromlist] net: openthread: bring back `LOG_MODE_MINIMAL` support A previous commit fixed OpenThread logging when `LOG=n`, but introduced regression when `LOG_MODE_MINIMAL=y`. This commit fixes the latest. Signed-off-by: Eduardo Montoya --- subsys/net/lib/openthread/platform/logging.c | 24 +++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/subsys/net/lib/openthread/platform/logging.c b/subsys/net/lib/openthread/platform/logging.c index 5c113b8c722..7569b3b7f8a 100644 --- a/subsys/net/lib/openthread/platform/logging.c +++ b/subsys/net/lib/openthread/platform/logging.c @@ -39,13 +39,35 @@ static inline int log_translate(otLogLevel aLogLevel) return -1; } +#if defined(CONFIG_LOG) +static uint32_t count_args(const char *fmt) +{ + uint32_t args = 0U; + bool prev = false; /* if previous char was a modificator. */ + + while (*fmt != '\0') { + if (*fmt == '%') { + prev = !prev; + } else if (prev) { + args++; + prev = false; + } else { + ; /* standard character, continue walk */ + } + fmt++; + } + + return args; +} +#endif + void otPlatLog(otLogLevel aLogLevel, otLogRegion aLogRegion, const char *aFormat, ...) { ARG_UNUSED(aLogRegion); #if defined(CONFIG_LOG) int level = log_translate(aLogLevel); - uint32_t args_num = log_count_args(aFormat); + uint32_t args_num = count_args(aFormat); va_list param_list; if (level < 0) { From 337356c19b52e0645d31dc1051cc3dce7fbef5e3 Mon Sep 17 00:00:00 2001 From: Rubin Gerritsen Date: Mon, 3 Jan 2022 11:14:38 +0100 Subject: [PATCH 040/207] [nrf fromtree] Bluetooth: Host: Extract out ad_stream to set long adv data This structure can be reused to set periodic advertising data. The structure tries fills the buffer as much as possible. Later this can be reused for setting advertising data in other cases as well. Signed-off-by: Rubin Gerritsen (cherry picked from commit acaf4eedaf597485f16c62841d6fb0137f8206db) --- subsys/bluetooth/host/adv.c | 225 ++++++++++++++++++++++++------------ 1 file changed, 149 insertions(+), 76 deletions(-) diff --git a/subsys/bluetooth/host/adv.c b/subsys/bluetooth/host/adv.c index c1b24c4fa00..41d1226c21e 100644 --- a/subsys/bluetooth/host/adv.c +++ b/subsys/bluetooth/host/adv.c @@ -27,6 +27,126 @@ enum adv_name_type { ADV_NAME_TYPE_SD, }; +struct bt_ad { + /* Pointer to an LTV structure */ + const struct bt_data *data; + /* Number of elements in @p data */ + size_t len; +}; + +struct ad_stream { + /* ad is a two dimensional array of struct bt_data elements. */ + const struct bt_ad *ad; + /* The number of struct bt_ad elements. */ + size_t ad_len; + + /* The current index in the array of struct bt_ad elements */ + size_t ad_index; + /* The current index in the array of ad.data elements */ + size_t data_index; + + /* Current LTV offset contains the data offset in the ad[x].data[y].data value array + * The length and type are included in this offset. + */ + uint16_t current_ltv_offset; +}; + +static void ad_stream_new(struct ad_stream *stream, const struct bt_ad *ad, size_t ad_len) +{ + (void)memset(stream, 0, sizeof(*stream)); + stream->ad = ad; + stream->ad_len = ad_len; +} + +/** + * @brief Returns true if the current stream is empty. + * + * @param stream AD stream, @ref ad_stream_new + * + * @returns true if the stream is now empty. + */ +static bool ad_stream_is_empty(const struct ad_stream *stream) +{ + /* If ad_index == ad_len, then we are past the last element in the ad array */ + return stream->ad_index == stream->ad_len; +} + +/** + * @brief Returns the bt_data structure that is currently being read + * + * If the structure has been fully read, the function iterates to the next + * + * @param stream AD stream, @ref ad_stream_new + * + * @returns The current LTV structure or NULL if there are no left. + */ +static const struct bt_data *ad_stream_current_ltv_update(struct ad_stream *stream) +{ + const struct bt_data *current_ltv = &stream->ad[stream->ad_index].data[stream->data_index]; + const bool done_reading_ltv = (stream->current_ltv_offset == current_ltv->data_len + 2); + + if (done_reading_ltv) { + stream->current_ltv_offset = 0; + + if (stream->data_index + 1 == stream->ad[stream->ad_index].len) { + stream->data_index = 0; + stream->ad_index++; + } else { + stream->data_index++; + } + } + + if (ad_stream_is_empty(stream)) { + return NULL; + } else { + return &stream->ad[stream->ad_index].data[stream->data_index]; + } +} + +/** + * @brief Read at max buf_len data from the flattened AD stream. + * + * The read data can contain multiple LTV AD structures. + * + * @param stream AD stream, @ref ad_stream_new + * @param buf Buffer where the data will be put + * @param buf_len Buffer length + * + * @returns The number of bytes read from the stream written to the provided buffer + */ +static uint8_t ad_stream_read(struct ad_stream *stream, uint8_t *buf, uint8_t buf_len) +{ + uint8_t read_len = 0; + + while (read_len < buf_len) { + const struct bt_data *current_ltv = ad_stream_current_ltv_update(stream); + + if (!current_ltv) { + break; + } + + if (stream->current_ltv_offset == 0) { + buf[read_len] = current_ltv->data_len + 1; + stream->current_ltv_offset++; + read_len++; + } else if (stream->current_ltv_offset == 1) { + buf[read_len] = current_ltv->type; + stream->current_ltv_offset++; + read_len++; + } else { + const size_t size_to_copy = MIN(buf_len, current_ltv->data_len); + + (void)memcpy(&buf[read_len], + ¤t_ltv->data[stream->current_ltv_offset - 2], + size_to_copy); + stream->current_ltv_offset += size_to_copy; + read_len += size_to_copy; + } + } + + return read_len; +} + enum adv_name_type get_adv_name_type(const struct bt_le_ext_adv *adv) { if (atomic_test_bit(adv->flags, BT_ADV_INCLUDE_NAME_SD)) { @@ -338,12 +458,6 @@ static bool valid_adv_param(const struct bt_le_adv_param *param) return valid_adv_ext_param(param); } - -struct bt_ad { - const struct bt_data *data; - size_t len; -}; - static int set_data_add_complete(uint8_t *set_data, uint8_t set_data_len_max, const struct bt_ad *ad, size_t ad_len, uint8_t *data_len) { @@ -447,85 +561,44 @@ static int hci_set_adv_ext_complete(struct bt_le_ext_adv *adv, uint16_t hci_op, static int hci_set_adv_ext_fragmented(struct bt_le_ext_adv *adv, uint16_t hci_op, const struct bt_ad *ad, size_t ad_len) { - struct bt_hci_cp_le_set_ext_adv_data *set_data; - struct net_buf *buf; - int err; + struct ad_stream stream; - for (size_t i = 0; i < ad_len; i++) { + ad_stream_new(&stream, ad, ad_len); - const struct bt_data *data = ad[i].data; + bool is_first_iteration = true; - for (size_t j = 0; j < ad[i].len; j++) { - size_t len = data[j].data_len; - uint8_t type = data[j].type; - size_t offset = 0; + while (!ad_stream_is_empty(&stream)) { + struct bt_hci_cp_le_set_ext_adv_data *set_data; + struct net_buf *buf; + int err; - /* We can't necessarily set one AD field in a single step. */ - while (offset < data[j].data_len) { - buf = bt_hci_cmd_create(hci_op, sizeof(*set_data)); - if (!buf) { - return -ENOBUFS; - } + buf = bt_hci_cmd_create(hci_op, sizeof(*set_data)); + if (!buf) { + return -ENOBUFS; + } - set_data = net_buf_add(buf, sizeof(*set_data)); - (void)memset(set_data, 0, sizeof(*set_data)); - - set_data->handle = adv->handle; - set_data->frag_pref = BT_HCI_LE_EXT_ADV_FRAG_DISABLED; - - /* Determine the operation parameter value. */ - if ((i == 0) && (j == 0) && (offset == 0)) { - set_data->op = BT_HCI_LE_EXT_ADV_OP_FIRST_FRAG; - } else if ((i == ad_len - 1) && (j == ad[i].len - 1)) { - /* The last AD field may be split into - * one or two commands. - */ - if (offset != 0) { - /* We can always set the data in two operations - * Therefore, we know that this is the last. - */ - set_data->op = BT_HCI_LE_EXT_ADV_OP_LAST_FRAG; - } else if (len + 2 <= BT_HCI_LE_EXT_ADV_FRAG_MAX_LEN) { - /* First part fits. */ - set_data->op = BT_HCI_LE_EXT_ADV_OP_LAST_FRAG; - } else { - /* The data must be split into two - * commands. - */ - set_data->op = BT_HCI_LE_EXT_ADV_OP_INTERM_FRAG; - } - } else { - set_data->op = BT_HCI_LE_EXT_ADV_OP_INTERM_FRAG; - } + set_data = net_buf_add(buf, sizeof(*set_data)); - if (offset == 0) { - set_data->len = MIN(len + 2, - BT_HCI_LE_EXT_ADV_FRAG_MAX_LEN); - } else { - /* No need to take min operation here, - * as we can always fit the second part. - */ - set_data->len = len - offset; - } + set_data->handle = adv->handle; + set_data->frag_pref = BT_HCI_LE_EXT_ADV_FRAG_ENABLED; + set_data->len = ad_stream_read(&stream, set_data->data, sizeof(set_data->data)); - if (offset == 0) { - set_data->data[0] = len + 1; - set_data->data[1] = type; - memcpy(&set_data->data[2], data[j].data, set_data->len - 2); - offset += set_data->len - 2; - } else { - memcpy(&set_data->data[0], &data[j].data[offset], - set_data->len); - offset += set_data->len; - } - - err = bt_hci_cmd_send_sync(hci_op, buf, NULL); - if (err) { - return err; - } - } + if (is_first_iteration && ad_stream_is_empty(&stream)) { + set_data->op = BT_HCI_LE_EXT_ADV_OP_COMPLETE_DATA; + } else if (is_first_iteration) { + set_data->op = BT_HCI_LE_EXT_ADV_OP_FIRST_FRAG; + } else if (ad_stream_is_empty(&stream)) { + set_data->op = BT_HCI_LE_EXT_ADV_OP_LAST_FRAG; + } else { + set_data->op = BT_HCI_LE_EXT_ADV_OP_INTERM_FRAG; + } + err = bt_hci_cmd_send_sync(hci_op, buf, NULL); + if (err) { + return err; } + + is_first_iteration = false; } return 0; From 460441a049af45117d227bacacb42ffb488a3aa8 Mon Sep 17 00:00:00 2001 From: Rubin Gerritsen Date: Thu, 11 Nov 2021 09:13:01 +0100 Subject: [PATCH 041/207] [nrf fromtree] Bluetooth: HCI: Max periodic adv data length is 252 bytes Use the define instead Signed-off-by: Rubin Gerritsen (cherry picked from commit 90cf4a8ba378eb65bbb8c216d1bb6cae922d9c10) --- include/bluetooth/hci.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/bluetooth/hci.h b/include/bluetooth/hci.h index 1061d0c2a27..001e5f79993 100644 --- a/include/bluetooth/hci.h +++ b/include/bluetooth/hci.h @@ -1372,7 +1372,7 @@ struct bt_hci_cp_le_set_per_adv_data { uint8_t handle; uint8_t op; uint8_t len; - uint8_t data[251]; + uint8_t data[BT_HCI_LE_PER_ADV_FRAG_MAX_LEN]; } __packed; #define BT_HCI_LE_SET_PER_ADV_ENABLE_ENABLE BIT(0) From e04a5f3b8e8ff9830f35fd491a32903603bfeb50 Mon Sep 17 00:00:00 2001 From: Rubin Gerritsen Date: Fri, 7 Jan 2022 16:30:38 +0100 Subject: [PATCH 042/207] [nrf fromtree] Bluetooth: Host: Support setting long periodic adv data If the advertiser is not running, the host can now set periodic advertising data in multiple operations. Signed-off-by: Rubin Gerritsen (cherry picked from commit a722c014adb80fb0d4b8691abe85d25e5fb6eb3c) --- subsys/bluetooth/host/adv.c | 90 ++++++++++++++++++++++++------------- 1 file changed, 58 insertions(+), 32 deletions(-) diff --git a/subsys/bluetooth/host/adv.c b/subsys/bluetooth/host/adv.c index 41d1226c21e..8dcd6e8933a 100644 --- a/subsys/bluetooth/host/adv.c +++ b/subsys/bluetooth/host/adv.c @@ -659,6 +659,54 @@ static int set_sd(struct bt_le_ext_adv *adv, const struct bt_ad *sd, return hci_set_ad(BT_HCI_OP_LE_SET_SCAN_RSP_DATA, sd, sd_len); } +#if defined(CONFIG_BT_PER_ADV) +static int hci_set_per_adv_data(const struct bt_le_ext_adv *adv, + const struct bt_data *ad, size_t ad_len) +{ + struct ad_stream stream; + struct bt_ad d = { .data = ad, .len = ad_len }; + bool is_first_iteration = true; + + ad_stream_new(&stream, &d, 1); + + while (!ad_stream_is_empty(&stream)) { + struct bt_hci_cp_le_set_per_adv_data *set_data; + struct net_buf *buf; + int err; + + buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_PER_ADV_DATA, sizeof(*set_data)); + if (!buf) { + return -ENOBUFS; + } + + set_data = net_buf_add(buf, sizeof(*set_data)); + (void)memset(set_data, 0, sizeof(*set_data)); + + set_data->handle = adv->handle; + set_data->len = ad_stream_read(&stream, set_data->data, sizeof(set_data->data)); + + if (is_first_iteration && ad_stream_is_empty(&stream)) { + set_data->op = BT_HCI_LE_EXT_ADV_OP_COMPLETE_DATA; + } else if (is_first_iteration) { + set_data->op = BT_HCI_LE_EXT_ADV_OP_FIRST_FRAG; + } else if (ad_stream_is_empty(&stream)) { + set_data->op = BT_HCI_LE_EXT_ADV_OP_LAST_FRAG; + } else { + set_data->op = BT_HCI_LE_EXT_ADV_OP_INTERM_FRAG; + } + + err = bt_hci_cmd_send_sync(BT_HCI_OP_LE_SET_PER_ADV_DATA, buf, NULL); + if (err) { + return err; + } + + is_first_iteration = false; + } + + return 0; +} +#endif /* CONFIG_BT_PER_ADV */ + static inline bool ad_has_name(const struct bt_data *ad, size_t ad_len) { size_t i; @@ -1686,10 +1734,7 @@ int bt_le_per_adv_set_param(struct bt_le_ext_adv *adv, int bt_le_per_adv_set_data(const struct bt_le_ext_adv *adv, const struct bt_data *ad, size_t ad_len) { - struct bt_hci_cp_le_set_per_adv_data *cp; - struct net_buf *buf; - struct bt_ad d = { .data = ad, .len = ad_len }; - int err; + size_t total_len_bytes = 0; if (!BT_FEAT_LE_EXT_PER_ADV(bt_dev.le.features)) { return -ENOTSUP; @@ -1703,38 +1748,19 @@ int bt_le_per_adv_set_data(const struct bt_le_ext_adv *adv, return -EINVAL; } - if (ad_len > BT_HCI_LE_PER_ADV_FRAG_MAX_LEN) { - return -EINVAL; - } - - - buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_PER_ADV_DATA, sizeof(*cp)); - if (!buf) { - return -ENOBUFS; - } - - cp = net_buf_add(buf, sizeof(*cp)); - (void)memset(cp, 0, sizeof(*cp)); - - cp->handle = adv->handle; - - /* TODO: If data is longer than what the controller can manage, - * split the data. Read size from controller on boot. - */ - cp->op = BT_HCI_LE_PER_ADV_OP_COMPLETE_DATA; - - err = set_data_add_complete(cp->data, BT_HCI_LE_PER_ADV_FRAG_MAX_LEN, &d, 1, - &cp->len); - if (err) { - return err; + for (size_t i = 0; i < ad_len; i++) { + total_len_bytes += ad[i].data_len + 2; } - err = bt_hci_cmd_send_sync(BT_HCI_OP_LE_SET_PER_ADV_DATA, buf, NULL); - if (err) { - return err; + if ((total_len_bytes > BT_HCI_LE_PER_ADV_FRAG_MAX_LEN) && + atomic_test_bit(adv->flags, BT_PER_ADV_ENABLED)) { + /* It is not allowed to set periodic advertising data + * in multiple operations while it is running. + */ + return -EINVAL; } - return 0; + return hci_set_per_adv_data(adv, ad, ad_len); } static int bt_le_per_adv_enable(struct bt_le_ext_adv *adv, bool enable) From 9c96841c58d8a6700ea7c7b51afd5508643df2a0 Mon Sep 17 00:00:00 2001 From: Rubin Gerritsen Date: Wed, 12 Jan 2022 14:59:26 +0100 Subject: [PATCH 043/207] [nrf fromtree] Bluetooth: Fix default event size when periodic adv sync is enabled Periodic Advertising reports can be up to 255. Signed-off-by: Rubin Gerritsen (cherry picked from commit 727ea490292255e3d0462f583fbc490a5c4936e4) --- subsys/bluetooth/common/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subsys/bluetooth/common/Kconfig b/subsys/bluetooth/common/Kconfig index 83d668efd79..456b5366f26 100644 --- a/subsys/bluetooth/common/Kconfig +++ b/subsys/bluetooth/common/Kconfig @@ -109,7 +109,7 @@ config BT_BUF_ACL_RX_COUNT config BT_BUF_EVT_RX_SIZE int "Maximum supported HCI Event buffer length" - default 255 if (BT_EXT_ADV && !(BT_BUF_EVT_DISCARDABLE_COUNT > 0)) || BT_PER_ADV + default 255 if (BT_EXT_ADV && !(BT_BUF_EVT_DISCARDABLE_COUNT > 0)) || BT_PER_ADV_SYNC # LE Read Supported Commands command complete event. default 68 range 68 255 From ac08690cf49115927fa03f5728b6467134c9a9ed Mon Sep 17 00:00:00 2001 From: Herman Berget Date: Mon, 20 Dec 2021 16:33:49 +0100 Subject: [PATCH 044/207] [nrf fromtree] Bluetooth: Host: Reassemble extended advertising reports The host reassembles fragmented advertising reports from the controller. Non-complete advertising reports from different advertisers may not be interleaved. If non-complete advertising reports from an advertiser is received while advertising reports from another advertiser is reassembled, an error message is logged and the advertising report is discarded. Future scan results may be incomplete. Advertising reports from legacy PDUs or complete extended advertising reports may be interleaved as these do not require reassembly. If the controller sends more advertising data than fits in the reassembly buffer, the data is truncated. Further advertising reports from the advertiser are discarded until the final complete advertising report is received and discarded. Signed-off-by: Herman Berget (cherry picked from commit 6ede31428de3e03c4e482d3b83610245b777d192) --- drivers/bluetooth/hci/h4.c | 3 +- drivers/bluetooth/hci/hci_esp32.c | 2 - drivers/bluetooth/hci/ipm_stm32wb.c | 3 +- drivers/bluetooth/hci/rpmsg.c | 2 - drivers/bluetooth/hci/spi.c | 3 +- drivers/bluetooth/hci/userchan.c | 3 +- subsys/bluetooth/host/Kconfig | 11 + subsys/bluetooth/host/scan.c | 183 +++++-- .../host_long_adv_recv/CMakeLists.txt | 8 + tests/bluetooth/host_long_adv_recv/prj.conf | 19 + tests/bluetooth/host_long_adv_recv/src/main.c | 493 ++++++++++++++++++ .../host_long_adv_recv/testcase.yaml | 4 + 12 files changed, 692 insertions(+), 42 deletions(-) create mode 100644 tests/bluetooth/host_long_adv_recv/CMakeLists.txt create mode 100644 tests/bluetooth/host_long_adv_recv/prj.conf create mode 100644 tests/bluetooth/host_long_adv_recv/src/main.c create mode 100644 tests/bluetooth/host_long_adv_recv/testcase.yaml diff --git a/drivers/bluetooth/hci/h4.c b/drivers/bluetooth/hci/h4.c index b8c77282b49..9b145be82de 100644 --- a/drivers/bluetooth/hci/h4.c +++ b/drivers/bluetooth/hci/h4.c @@ -164,8 +164,7 @@ static inline void get_evt_hdr(void) if (!rx.remaining) { if (rx.evt.evt == BT_HCI_EVT_LE_META_EVENT && - (rx.hdr[sizeof(*hdr)] == BT_HCI_EVT_LE_ADVERTISING_REPORT || - rx.hdr[sizeof(*hdr)] == BT_HCI_EVT_LE_EXT_ADVERTISING_REPORT)) { + (rx.hdr[sizeof(*hdr)] == BT_HCI_EVT_LE_ADVERTISING_REPORT)) { BT_DBG("Marking adv report as discardable"); rx.discardable = true; } diff --git a/drivers/bluetooth/hci/hci_esp32.c b/drivers/bluetooth/hci/hci_esp32.c index 70da2163da9..0a866e2199f 100644 --- a/drivers/bluetooth/hci/hci_esp32.c +++ b/drivers/bluetooth/hci/hci_esp32.c @@ -41,8 +41,6 @@ static bool is_hci_event_discardable(const uint8_t *evt_data) switch (subevt_type) { case BT_HCI_EVT_LE_ADVERTISING_REPORT: return true; - case BT_HCI_EVT_LE_EXT_ADVERTISING_REPORT: - return true; default: return false; } diff --git a/drivers/bluetooth/hci/ipm_stm32wb.c b/drivers/bluetooth/hci/ipm_stm32wb.c index fb0c6a1f494..a487b8b0193 100644 --- a/drivers/bluetooth/hci/ipm_stm32wb.c +++ b/drivers/bluetooth/hci/ipm_stm32wb.c @@ -181,8 +181,7 @@ static void bt_ipm_rx_thread(void) default: mev = (void *)&hcievt->evtserial.evt.payload; if (hcievt->evtserial.evt.evtcode == BT_HCI_EVT_LE_META_EVENT && - (mev->subevent == BT_HCI_EVT_LE_ADVERTISING_REPORT || - mev->subevent == BT_HCI_EVT_LE_EXT_ADVERTISING_REPORT)) { + (mev->subevent == BT_HCI_EVT_LE_ADVERTISING_REPORT)) { discardable = true; timeout = K_NO_WAIT; } diff --git a/drivers/bluetooth/hci/rpmsg.c b/drivers/bluetooth/hci/rpmsg.c index 1f702089ab8..281a77d90e9 100644 --- a/drivers/bluetooth/hci/rpmsg.c +++ b/drivers/bluetooth/hci/rpmsg.c @@ -41,8 +41,6 @@ static bool is_hci_event_discardable(const uint8_t *evt_data) switch (subevt_type) { case BT_HCI_EVT_LE_ADVERTISING_REPORT: return true; - case BT_HCI_EVT_LE_EXT_ADVERTISING_REPORT: - return true; default: return false; } diff --git a/drivers/bluetooth/hci/spi.c b/drivers/bluetooth/hci/spi.c index 642c3799c24..359667aad69 100644 --- a/drivers/bluetooth/hci/spi.c +++ b/drivers/bluetooth/hci/spi.c @@ -370,8 +370,7 @@ static void bt_spi_rx_thread(void) continue; default: if (rxmsg[1] == BT_HCI_EVT_LE_META_EVENT && - (rxmsg[3] == BT_HCI_EVT_LE_ADVERTISING_REPORT || - rxmsg[3] == BT_HCI_EVT_LE_EXT_ADVERTISING_REPORT)) { + (rxmsg[3] == BT_HCI_EVT_LE_ADVERTISING_REPORT)) { discardable = true; timeout = K_NO_WAIT; } diff --git a/drivers/bluetooth/hci/userchan.c b/drivers/bluetooth/hci/userchan.c index 1dc5a9f5dc5..d856f89e94c 100644 --- a/drivers/bluetooth/hci/userchan.c +++ b/drivers/bluetooth/hci/userchan.c @@ -64,8 +64,7 @@ static struct net_buf *get_rx(const uint8_t *buf) switch (buf[0]) { case H4_EVT: if (buf[1] == BT_HCI_EVT_LE_META_EVENT && - (buf[3] == BT_HCI_EVT_LE_ADVERTISING_REPORT || - buf[3] == BT_HCI_EVT_LE_EXT_ADVERTISING_REPORT)) { + (buf[3] == BT_HCI_EVT_LE_ADVERTISING_REPORT)) { discardable = true; timeout = K_NO_WAIT; } diff --git a/subsys/bluetooth/host/Kconfig b/subsys/bluetooth/host/Kconfig index 3468a6d462d..d9ba7824064 100644 --- a/subsys/bluetooth/host/Kconfig +++ b/subsys/bluetooth/host/Kconfig @@ -485,6 +485,17 @@ config BT_BACKGROUND_SCAN_WINDOW int "Scan window used for background scanning in 0.625 ms units" default 18 range 4 16384 + +config BT_EXT_SCAN_BUF_SIZE + int "Maximum advertisement report size" + depends on BT_EXT_ADV + range 1 1650 + default 229 + help + Maximum size of an advertisement report in octets. If the advertisement + provided by the controller is larger than this buffer size, + the remaining data will be discarded. + endif # BT_OBSERVER config BT_SCAN_WITH_IDENTITY diff --git a/subsys/bluetooth/host/scan.c b/subsys/bluetooth/host/scan.c index 033c9ca9cad..84124863244 100644 --- a/subsys/bluetooth/host/scan.c +++ b/subsys/bluetooth/host/scan.c @@ -13,6 +13,7 @@ #include #include #include +#include #include "hci_core.h" #include "conn_internal.h" @@ -27,6 +28,42 @@ static bt_le_scan_cb_t *scan_dev_found_cb; static sys_slist_t scan_cbs = SYS_SLIST_STATIC_INIT(&scan_cbs); #if defined(CONFIG_BT_EXT_ADV) +/* A buffer used to reassemble advertisement data from the controller. */ +NET_BUF_SIMPLE_DEFINE(ext_scan_buf, CONFIG_BT_EXT_SCAN_BUF_SIZE); + +struct fragmented_advertiser { + bt_addr_le_t addr; + uint8_t sid; + enum { + FRAG_ADV_INACTIVE, + FRAG_ADV_REASSEMBLING, + FRAG_ADV_DISCARDING, + } state; +}; + +static struct fragmented_advertiser reassembling_advertiser; + +static bool fragmented_advertisers_equal(const struct fragmented_advertiser *a, + const bt_addr_le_t *addr, uint8_t sid) +{ + /* Two advertisers are equal if they are the same adv set from the same device */ + return a->sid == sid && bt_addr_le_cmp(&a->addr, addr) == 0; +} + +/* Sets the address and sid of the advertiser to be reassembled. */ +static void init_reassembling_advertiser(const bt_addr_le_t *addr, uint8_t sid) +{ + bt_addr_le_copy(&reassembling_advertiser.addr, addr); + reassembling_advertiser.sid = sid; + reassembling_advertiser.state = FRAG_ADV_REASSEMBLING; +} + +static void reset_reassembling_advertiser(void) +{ + net_buf_simple_reset(&ext_scan_buf); + reassembling_advertiser.state = FRAG_ADV_INACTIVE; +} + #if defined(CONFIG_BT_PER_ADV_SYNC) static struct bt_le_per_adv_sync *get_pending_per_adv_sync(void); static struct bt_le_per_adv_sync per_adv_sync_pool[CONFIG_BT_PER_ADV_SYNC_MAX]; @@ -37,6 +74,9 @@ static sys_slist_t pa_sync_cbs = SYS_SLIST_STATIC_INIT(&pa_sync_cbs); void bt_scan_reset(void) { scan_dev_found_cb = NULL; +#if defined(CONFIG_BT_EXT_ADV) + reset_reassembling_advertiser(); +#endif } static int set_le_ext_scan_enable(uint8_t enable, uint16_t duration) @@ -392,7 +432,7 @@ static uint8_t get_adv_props(uint8_t evt_type) } static void le_adv_recv(bt_addr_le_t *addr, struct bt_le_scan_recv_info *info, - struct net_buf *buf, uint8_t len) + struct net_buf_simple *buf, uint16_t len) { struct bt_le_scan_cb *listener, *next; struct net_buf_simple_state state; @@ -423,23 +463,22 @@ static void le_adv_recv(bt_addr_le_t *addr, struct bt_le_scan_recv_info *info, info->addr = &id_addr; if (scan_dev_found_cb) { - net_buf_simple_save(&buf->b, &state); + net_buf_simple_save(buf, &state); buf->len = len; - scan_dev_found_cb(&id_addr, info->rssi, info->adv_type, - &buf->b); + scan_dev_found_cb(&id_addr, info->rssi, info->adv_type, buf); - net_buf_simple_restore(&buf->b, &state); + net_buf_simple_restore(buf, &state); } SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&scan_cbs, listener, next, node) { if (listener->recv) { - net_buf_simple_save(&buf->b, &state); + net_buf_simple_save(buf, &state); buf->len = len; - listener->recv(info, &buf->b); + listener->recv(info, buf); - net_buf_simple_restore(&buf->b, &state); + net_buf_simple_restore(buf, &state); } } @@ -507,15 +546,34 @@ static uint8_t get_adv_type(uint8_t evt_type) } } +static void create_ext_adv_info(struct bt_hci_evt_le_ext_advertising_info const *const evt, + struct bt_le_scan_recv_info *const scan_info) +{ + scan_info->primary_phy = bt_get_phy(evt->prim_phy); + scan_info->secondary_phy = bt_get_phy(evt->sec_phy); + scan_info->tx_power = evt->tx_power; + scan_info->rssi = evt->rssi; + scan_info->sid = evt->sid; + scan_info->interval = sys_le16_to_cpu(evt->interval); + scan_info->adv_type = get_adv_type(evt->evt_type); + /* Convert "Legacy" property to Extended property. */ + scan_info->adv_props = evt->evt_type ^ BT_HCI_LE_ADV_PROP_LEGACY; + scan_info->adv_props &= BIT_MASK(5); +} + void bt_hci_le_adv_ext_report(struct net_buf *buf) { uint8_t num_reports = net_buf_pull_u8(buf); - BT_DBG("Adv number of reports %u", num_reports); + BT_DBG("Adv number of reports %u", num_reports); while (num_reports--) { struct bt_hci_evt_le_ext_advertising_info *evt; - struct bt_le_scan_recv_info adv_info; + struct bt_le_scan_recv_info scan_info; + uint16_t data_status; + bool is_report_complete; + bool more_to_come; + bool is_new_advertiser; if (buf->len < sizeof(*evt)) { BT_ERR("Unexpected end of buffer"); @@ -523,34 +581,99 @@ void bt_hci_le_adv_ext_report(struct net_buf *buf) } evt = net_buf_pull_mem(buf, sizeof(*evt)); + data_status = BT_HCI_LE_ADV_EVT_TYPE_DATA_STATUS(evt->evt_type); + is_report_complete = data_status == BT_HCI_LE_ADV_EVT_TYPE_DATA_STATUS_COMPLETE; + more_to_come = data_status == BT_HCI_LE_ADV_EVT_TYPE_DATA_STATUS_PARTIAL; - adv_info.primary_phy = bt_get_phy(evt->prim_phy); - adv_info.secondary_phy = bt_get_phy(evt->sec_phy); - adv_info.tx_power = evt->tx_power; - adv_info.rssi = evt->rssi; - adv_info.sid = evt->sid; - adv_info.interval = sys_le16_to_cpu(evt->interval); - - adv_info.adv_type = get_adv_type(evt->evt_type); - /* Convert "Legacy" property to Extended property. */ - adv_info.adv_props = evt->evt_type ^ BT_HCI_LE_ADV_PROP_LEGACY; - - if (BT_HCI_LE_ADV_EVT_TYPE_DATA_STATUS(evt->evt_type) == - BT_HCI_LE_ADV_EVT_TYPE_DATA_STATUS_PARTIAL) { - /* Handling of incomplete reports is currently not - * handled in the host. The remaining advertising - * reports may therefore contain partial data. + if (evt->evt_type & BT_HCI_LE_ADV_EVT_TYPE_LEGACY) { + /* Legacy advertising reports are complete. + * Create event immediately. */ - BT_WARN("Incomplete adv report"); + create_ext_adv_info(evt, &scan_info); + le_adv_recv(&evt->addr, &scan_info, &buf->b, evt->length); + continue; } - le_adv_recv(&evt->addr, &adv_info, buf, evt->length); + is_new_advertiser = reassembling_advertiser.state == FRAG_ADV_INACTIVE || + !fragmented_advertisers_equal(&reassembling_advertiser, + &evt->addr, evt->sid); + + if (is_new_advertiser && is_report_complete) { + /* Only advertising report from this advertiser. + * Create event immediately. + */ + create_ext_adv_info(evt, &scan_info); + le_adv_recv(&evt->addr, &scan_info, &buf->b, evt->length); + continue; + } + + if (is_new_advertiser && reassembling_advertiser.state == FRAG_ADV_REASSEMBLING) { + BT_WARN("Received an incomplete advertising report while reassembling " + "advertising reports from a different advertiser. The advertising " + "report is discarded and future scan results may be incomplete. " + "Interleaving of fragmented advertising reports from different " + "advertisers is not yet supported."); + (void)net_buf_pull_mem(buf, evt->length); + continue; + } + + if (data_status == BT_HCI_LE_ADV_EVT_TYPE_DATA_STATUS_INCOMPLETE) { + /* Controller truncated, no more data will come. + * We do not need to keep track of this advertiser. + * Discard this report. + */ + (void)net_buf_pull_mem(buf, evt->length); + reset_reassembling_advertiser(); + continue; + } + + if (is_new_advertiser) { + /* We are not reassembling reports from an advertiser and + * this is the first report from the new advertiser. + * Initialize the new advertiser. + */ + __ASSERT_NO_MSG(reassembling_advertiser.state == FRAG_ADV_INACTIVE); + init_reassembling_advertiser(&evt->addr, evt->sid); + } + + if (evt->length + ext_scan_buf.len > ext_scan_buf.size) { + /* The report does not fit in the reassemby buffer + * Discard this and future reports from the advertiser. + */ + reassembling_advertiser.state = FRAG_ADV_DISCARDING; + } + + if (reassembling_advertiser.state == FRAG_ADV_DISCARDING) { + (void)net_buf_pull_mem(buf, evt->length); + if (!more_to_come) { + /* We do no longer need to keep track of this advertiser as + * all the expected data is received. + */ + reset_reassembling_advertiser(); + } + continue; + } + + net_buf_simple_add_mem(&ext_scan_buf, buf->data, evt->length); + if (more_to_come) { + /* The controller will send additional reports to be reassembled */ + continue; + } + + /* No more data coming from the controller. + * Create event. + */ + __ASSERT_NO_MSG(is_report_complete); + create_ext_adv_info(evt, &scan_info); + le_adv_recv(&evt->addr, &scan_info, &ext_scan_buf, ext_scan_buf.len); + + /* We do no longer need to keep track of this advertiser. */ + reset_reassembling_advertiser(); net_buf_pull(buf, evt->length); } } - #if defined(CONFIG_BT_PER_ADV_SYNC) static void per_adv_sync_delete(struct bt_le_per_adv_sync *per_adv_sync) { @@ -991,7 +1114,7 @@ void bt_hci_le_adv_report(struct net_buf *buf) adv_info.adv_type = evt->evt_type; adv_info.adv_props = get_adv_props(evt->evt_type); - le_adv_recv(&evt->addr, &adv_info, buf, evt->length); + le_adv_recv(&evt->addr, &adv_info, &buf->b, evt->length); net_buf_pull(buf, evt->length + sizeof(adv_info.rssi)); } diff --git a/tests/bluetooth/host_long_adv_recv/CMakeLists.txt b/tests/bluetooth/host_long_adv_recv/CMakeLists.txt new file mode 100644 index 00000000000..da5b449c986 --- /dev/null +++ b/tests/bluetooth/host_long_adv_recv/CMakeLists.txt @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(host_long_adv_recv) + +target_sources(app PRIVATE src/main.c) diff --git a/tests/bluetooth/host_long_adv_recv/prj.conf b/tests/bluetooth/host_long_adv_recv/prj.conf new file mode 100644 index 00000000000..c7b3600e999 --- /dev/null +++ b/tests/bluetooth/host_long_adv_recv/prj.conf @@ -0,0 +1,19 @@ +CONFIG_TEST=y +CONFIG_ZTEST=y +CONFIG_ZTEST_MOCKING=y + +CONFIG_BT=y +CONFIG_BT_CTLR=n +CONFIG_BT_HCI=n +CONFIG_BT_HCI_RAW=n +CONFIG_BT_OBSERVER=y +CONFIG_BT_NO_DRIVER=y +CONFIG_BT_RECV_IS_RX_THREAD=y +CONFIG_BT_EXT_ADV=y + +CONFIG_BT_DEBUG_LOG=y +CONFIG_BT_DEBUG_HCI_CORE=n +CONFIG_BT_DEBUG_HCI_DRIVER=n +CONFIG_BT_LOG_LEVEL_DBG=y + +CONFIG_BT_EXT_SCAN_BUF_SIZE=91 diff --git a/tests/bluetooth/host_long_adv_recv/src/main.c b/tests/bluetooth/host_long_adv_recv/src/main.c new file mode 100644 index 00000000000..14164705f7d --- /dev/null +++ b/tests/bluetooth/host_long_adv_recv/src/main.c @@ -0,0 +1,493 @@ +/* main.c - Host long advertising receive */ + +/* + * Copyright (c) 2021 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + +#define LOG_LEVEL CONFIG_BT_LOG_LEVEL +#include +LOG_MODULE_REGISTER(host_test_app); + +struct test_adv_report { + uint8_t data[CONFIG_BT_EXT_SCAN_BUF_SIZE]; + uint8_t length; + uint16_t evt_prop; + bt_addr_le_t addr; +}; + +#define COMPLETE BT_HCI_LE_ADV_EVT_TYPE_DATA_STATUS_COMPLETE << 5 +#define MORE_TO_COME BT_HCI_LE_ADV_EVT_TYPE_DATA_STATUS_PARTIAL << 5 +#define TRUNCATED BT_HCI_LE_ADV_EVT_TYPE_DATA_STATUS_INCOMPLETE << 5 + +/* Command handler structure for cmd_handle(). */ +struct cmd_handler { + uint16_t opcode; /* HCI command opcode */ + uint8_t len; /* HCI command response length */ + void (*handler)(struct net_buf *buf, struct net_buf **evt, uint8_t len, uint16_t opcode); +}; + +/* Add event to net_buf. */ +static void evt_create(struct net_buf *buf, uint8_t evt, uint8_t len) +{ + struct bt_hci_evt_hdr *hdr; + + hdr = net_buf_add(buf, sizeof(*hdr)); + hdr->evt = evt; + hdr->len = len; +} + +static void le_meta_evt_create(struct bt_hci_evt_le_meta_event *evt, uint8_t subevent) +{ + evt->subevent = subevent; +} + +static void adv_info_create(struct bt_hci_evt_le_ext_advertising_info *evt, uint16_t evt_type, + const bt_addr_le_t *const addr, uint8_t length) +{ + evt->evt_type = evt_type; + bt_addr_le_copy(&evt->addr, addr); + evt->prim_phy = 0; + evt->sec_phy = 0; + evt->sid = 0; + evt->tx_power = 0; + evt->rssi = 0; + evt->interval = 0; + bt_addr_le_copy(&evt->direct_addr, BT_ADDR_LE_NONE); + evt->length = length; +} + +/* Create a command complete event. */ +static void *cmd_complete(struct net_buf **buf, uint8_t plen, uint16_t opcode) +{ + struct bt_hci_evt_cmd_complete *cc; + + *buf = bt_buf_get_evt(BT_HCI_EVT_CMD_COMPLETE, false, K_FOREVER); + evt_create(*buf, BT_HCI_EVT_CMD_COMPLETE, sizeof(*cc) + plen); + cc = net_buf_add(*buf, sizeof(*cc)); + cc->ncmd = 1U; + cc->opcode = sys_cpu_to_le16(opcode); + + return net_buf_add(*buf, plen); +} + +/* Loop over handlers to try to handle the command given by opcode. */ +static int cmd_handle_helper(uint16_t opcode, struct net_buf *cmd, struct net_buf **evt, + const struct cmd_handler *handlers, size_t num_handlers) +{ + for (size_t i = 0; i < num_handlers; i++) { + const struct cmd_handler *handler = &handlers[i]; + + if (handler->opcode != opcode) { + continue; + } + + if (handler->handler) { + handler->handler(cmd, evt, handler->len, opcode); + + return 0; + } + } + + zassert_unreachable("opcode %X failed", opcode); + + return -EINVAL; +} + +/* Lookup the command opcode and invoke handler. */ +static int cmd_handle(struct net_buf *cmd, const struct cmd_handler *handlers, size_t num_handlers) +{ + struct net_buf *evt = NULL; + struct bt_hci_evt_cc_status *ccst; + struct bt_hci_cmd_hdr *chdr; + uint16_t opcode; + int err; + + chdr = net_buf_pull_mem(cmd, sizeof(*chdr)); + opcode = sys_le16_to_cpu(chdr->opcode); + + err = cmd_handle_helper(opcode, cmd, &evt, handlers, num_handlers); + + if (err == -EINVAL) { + ccst = cmd_complete(&evt, sizeof(*ccst), opcode); + ccst->status = BT_HCI_ERR_UNKNOWN_CMD; + } + + if (evt) { + bt_recv_prio(evt); + } + + return err; +} + +/* Generic command complete with success status. */ +static void generic_success(struct net_buf *buf, struct net_buf **evt, uint8_t len, uint16_t opcode) +{ + struct bt_hci_evt_cc_status *ccst; + + ccst = cmd_complete(evt, len, opcode); + + /* Fill any event parameters with zero */ + (void)memset(ccst, 0, len); + + ccst->status = BT_HCI_ERR_SUCCESS; +} + +/* Bogus handler for BT_HCI_OP_READ_LOCAL_FEATURES. */ +static void read_local_features(struct net_buf *buf, struct net_buf **evt, uint8_t len, + uint16_t opcode) +{ + struct bt_hci_rp_read_local_features *rp; + + rp = cmd_complete(evt, sizeof(*rp), opcode); + rp->status = 0x00; + (void)memset(rp->features, 0xFF, sizeof(rp->features)); +} + +/* Bogus handler for BT_HCI_OP_READ_SUPPORTED_COMMANDS. */ +static void read_supported_commands(struct net_buf *buf, struct net_buf **evt, uint8_t len, + uint16_t opcode) +{ + struct bt_hci_rp_read_supported_commands *rp; + + rp = cmd_complete(evt, sizeof(*rp), opcode); + (void)memset(rp->commands, 0xFF, sizeof(rp->commands)); + rp->status = 0x00; +} + +/* Bogus handler for BT_HCI_OP_LE_READ_LOCAL_FEATURES. */ +static void le_read_local_features(struct net_buf *buf, struct net_buf **evt, uint8_t len, + uint16_t opcode) +{ + struct bt_hci_rp_le_read_local_features *rp; + + rp = cmd_complete(evt, sizeof(*rp), opcode); + rp->status = 0x00; + (void)memset(rp->features, 0xFF, sizeof(rp->features)); +} + +/* Bogus handler for BT_HCI_OP_LE_READ_SUPP_STATES. */ +static void le_read_supp_states(struct net_buf *buf, struct net_buf **evt, uint8_t len, + uint16_t opcode) +{ + struct bt_hci_rp_le_read_supp_states *rp; + + rp = cmd_complete(evt, sizeof(*rp), opcode); + rp->status = 0x00; + (void)memset(&rp->le_states, 0xFF, sizeof(rp->le_states)); +} + +/* Setup handlers needed for bt_enable to function. */ +static const struct cmd_handler cmds[] = { + { BT_HCI_OP_READ_LOCAL_VERSION_INFO, sizeof(struct bt_hci_rp_read_local_version_info), + generic_success }, + { BT_HCI_OP_READ_SUPPORTED_COMMANDS, sizeof(struct bt_hci_rp_read_supported_commands), + read_supported_commands }, + { BT_HCI_OP_READ_LOCAL_FEATURES, sizeof(struct bt_hci_rp_read_local_features), + read_local_features }, + { BT_HCI_OP_READ_BD_ADDR, sizeof(struct bt_hci_rp_read_bd_addr), generic_success }, + { BT_HCI_OP_SET_EVENT_MASK, sizeof(struct bt_hci_evt_cc_status), generic_success }, + { BT_HCI_OP_LE_SET_EVENT_MASK, sizeof(struct bt_hci_evt_cc_status), generic_success }, + { BT_HCI_OP_LE_READ_LOCAL_FEATURES, sizeof(struct bt_hci_rp_le_read_local_features), + le_read_local_features }, + { BT_HCI_OP_LE_READ_SUPP_STATES, sizeof(struct bt_hci_rp_le_read_supp_states), + le_read_supp_states }, + { BT_HCI_OP_LE_RAND, sizeof(struct bt_hci_rp_le_rand), generic_success }, + { BT_HCI_OP_LE_SET_RANDOM_ADDRESS, sizeof(struct bt_hci_cp_le_set_random_address), + generic_success }, + { BT_HCI_OP_RESET, 0, generic_success }, +}; + +/* HCI driver open. */ +static int driver_open(void) +{ + return 0; +} + +/* HCI driver send. */ +static int driver_send(struct net_buf *buf) +{ + zassert_true(cmd_handle(buf, cmds, ARRAY_SIZE(cmds)) == 0, "Unknown HCI command"); + + net_buf_unref(buf); + + return 0; +} + +/* HCI driver structure. */ +static const struct bt_hci_driver drv = { + .name = "test", + .bus = BT_HCI_DRIVER_BUS_VIRTUAL, + .open = driver_open, + .send = driver_send, + .quirks = 0, +}; + +struct bt_recv_job_data { + struct k_work work; /* Work item */ + struct k_sem *sync; /* Semaphore to synchronize with */ + struct net_buf *buf; /* Net buffer to be passed to bt_recv() */ +} job_data[CONFIG_BT_BUF_EVT_RX_COUNT]; + +#define job(buf) (&job_data[net_buf_id(buf)]) + +/* Work item handler for bt_recv() jobs. */ +static void bt_recv_job_cb(struct k_work *item) +{ + struct bt_recv_job_data *data = CONTAINER_OF(item, struct bt_recv_job_data, work); + + /* Send net buffer to host */ + bt_recv(data->buf); + + /* Wake up bt_recv_job_submit */ + k_sem_give(job(data->buf)->sync); +} + +/* Prepare a job to call bt_recv() to be submitted to the system workqueue. */ +static void bt_recv_job_submit(struct net_buf *buf) +{ + struct k_sem sync_sem; + + /* Store the net buffer to be passed to bt_recv */ + job(buf)->buf = buf; + + /* Initialize job work item/semaphore */ + k_work_init(&job(buf)->work, bt_recv_job_cb); + k_sem_init(&sync_sem, 0, 1); + job(buf)->sync = &sync_sem; + + /* Make sure the buffer stays around until the command completes */ + buf = net_buf_ref(buf); + + /* Submit the work item */ + k_work_submit(&job(buf)->work); + + /* Wait for bt_recv_job_cb to be done */ + k_sem_take(&sync_sem, K_FOREVER); + + net_buf_unref(buf); +} + +/* Semaphore to test if the prop callback was called. */ +static K_SEM_DEFINE(prop_cb_sem, 0, 1); + +static void *adv_report_evt(struct net_buf *buf, uint8_t data_len, uint16_t evt_type, + const bt_addr_le_t *const addr) +{ + struct bt_hci_evt_le_meta_event *meta_evt; + struct bt_hci_evt_le_ext_advertising_info *evt; + + evt_create(buf, BT_HCI_EVT_LE_META_EVENT, sizeof(*meta_evt) + sizeof(*evt) + data_len + 1); + meta_evt = net_buf_add(buf, sizeof(*meta_evt)); + le_meta_evt_create(meta_evt, BT_HCI_EVT_LE_EXT_ADVERTISING_REPORT); + net_buf_add_u8(buf, 1); /* Number of reports */ + evt = net_buf_add(buf, sizeof(*evt)); + adv_info_create(evt, evt_type, addr, data_len); + + return net_buf_add(buf, data_len); +} + +/* Send a prop event report wit the given data. */ +static void send_adv_report(const struct test_adv_report *report) +{ + LOG_DBG("Sending adv report"); + struct net_buf *buf; + uint8_t *adv_data; + + buf = bt_buf_get_rx(BT_BUF_EVT, K_FOREVER); + adv_data = adv_report_evt(buf, report->length, report->evt_prop, &report->addr); + memcpy(adv_data, &report->data, report->length); + + /* Submit job */ + bt_recv_job_submit(buf); +} + +static uint16_t get_expected_length(void) +{ + return ztest_get_return_value(); +} + +static uint8_t *get_expected_data(void) +{ + return ztest_get_return_value_ptr(); +} + +static void scan_recv_cb(const struct bt_le_scan_recv_info *info, struct net_buf_simple *buf) +{ + ARG_UNUSED(info); + + LOG_DBG("Received event with length %u", buf->len); + + const uint16_t expected_length = get_expected_length(); + const uint8_t *expected_data = get_expected_data(); + + zassert_equal(buf->len, expected_length, "Lengths should be equal"); + zassert_mem_equal(buf->data, expected_data, buf->len, "Data should be equal"); +} + +static void scan_timeout_cb(void) +{ + zassert_unreachable("Timeout should not happen"); +} + +static void generate_sequence(uint8_t *dest, uint16_t len, uint8_t range_start, uint8_t range_end) +{ + uint16_t written = 0; + uint8_t value = range_start; + + while (written < len) { + *dest++ = value++; + written++; + if (value > range_end) { + value = range_start; + } + } +} + +/* Test. */ +static void test_host_long_adv_recv(void) +{ + /* Register the test HCI driver */ + bt_hci_driver_register(&drv); + + /* Go! Wait until Bluetooth initialization is done */ + zassert_true((bt_enable(NULL) == 0), "bt_enable failed"); + + static struct bt_le_scan_cb scan_callbacks = { .recv = scan_recv_cb, + .timeout = scan_timeout_cb }; + bt_le_scan_cb_register(&scan_callbacks); + bt_addr_le_t addr_a; + bt_addr_le_t addr_b; + bt_addr_le_t addr_c; + bt_addr_le_t addr_d; + + bt_addr_le_create_static(&addr_a); + bt_addr_le_create_static(&addr_b); + bt_addr_le_create_static(&addr_c); + bt_addr_le_create_static(&addr_d); + + struct test_adv_report report_a_1 = { .length = 30, .evt_prop = MORE_TO_COME }; + struct test_adv_report report_a_2 = { .length = 30, .evt_prop = COMPLETE }; + + bt_addr_le_copy(&report_a_1.addr, &addr_a); + bt_addr_le_copy(&report_a_2.addr, &addr_a); + + struct test_adv_report report_b_1 = { .length = 30, .evt_prop = MORE_TO_COME }; + struct test_adv_report report_b_2 = { .length = 30, .evt_prop = COMPLETE }; + + bt_addr_le_copy(&report_b_1.addr, &addr_b); + bt_addr_le_copy(&report_b_2.addr, &addr_b); + + struct test_adv_report report_c = { .length = 30, + .evt_prop = COMPLETE | BT_HCI_LE_ADV_EVT_TYPE_LEGACY }; + + bt_addr_le_copy(&report_c.addr, &addr_c); + + struct test_adv_report report_d = { .length = 30, .evt_prop = TRUNCATED }; + + bt_addr_le_copy(&report_c.addr, &addr_c); + + struct test_adv_report report_a_combined = { .length = report_a_1.length + + report_a_2.length }; + + struct test_adv_report report_a_1_repeated = { .length = CONFIG_BT_EXT_SCAN_BUF_SIZE }; + + struct test_adv_report report_b_combined = { .length = report_b_1.length + + report_b_2.length }; + + generate_sequence(report_a_combined.data, report_a_combined.length, 'A', 'Z'); + generate_sequence(report_b_combined.data, report_b_combined.length, 'a', 'z'); + generate_sequence(report_c.data, report_c.length, '0', '9'); + + (void)memcpy(report_a_1.data, report_a_combined.data, report_a_1.length); + (void)memcpy(report_a_2.data, &report_a_combined.data[report_a_1.length], + report_a_2.length); + + for (int i = 0; i < report_a_1_repeated.length; i += report_a_1.length) { + memcpy(&report_a_1_repeated.data[i], report_a_1.data, + MIN(report_a_1.length, (report_a_1_repeated.length - i))); + } + + (void)memcpy(report_b_1.data, report_b_combined.data, report_b_1.length); + (void)memcpy(report_b_2.data, &report_b_combined.data[report_b_1.length], + report_b_2.length); + + /* Check that non-interleaved fragmented adv reports work */ + ztest_returns_value(get_expected_data, report_a_combined.data); + ztest_returns_value(get_expected_length, report_a_combined.length); /* Expect a */ + ztest_returns_value(get_expected_data, report_b_combined.data); + ztest_returns_value(get_expected_length, report_b_combined.length); /* Then b */ + send_adv_report(&report_a_1); + send_adv_report(&report_a_2); + send_adv_report(&report_b_1); + send_adv_report(&report_b_2); + + /* Check that legacy adv reports interleaved with fragmented adv reports work */ + ztest_returns_value(get_expected_data, report_c.data); + ztest_returns_value(get_expected_length, report_c.length); /* Expect c */ + ztest_returns_value(get_expected_data, report_a_combined.data); + ztest_returns_value(get_expected_length, report_a_combined.length); /* Then a */ + send_adv_report(&report_a_1); + send_adv_report(&report_c); /* Interleaved legacy adv report */ + send_adv_report(&report_a_2); + + /* Check that complete adv reports interleaved with fragmented adv reports work */ + ztest_returns_value(get_expected_data, report_b_2.data); + ztest_returns_value(get_expected_length, report_b_2.length); /* Expect b */ + ztest_returns_value(get_expected_data, report_a_combined.data); + ztest_returns_value(get_expected_length, report_a_combined.length); /* Then a */ + send_adv_report(&report_a_1); + send_adv_report(&report_b_2); /* Interleaved short extended adv report */ + send_adv_report(&report_a_2); + + /* Check that fragmented adv reports from one peer are received, + * and that interleaved fragmented adv reports from other peers are discarded + */ + ztest_returns_value(get_expected_data, report_a_combined.data); + ztest_returns_value(get_expected_length, report_a_combined.length); /* Expect a */ + ztest_returns_value(get_expected_data, report_b_2.data); + ztest_returns_value(get_expected_length, + report_b_2.length); /* Then b, INCOMPLETE REPORT */ + send_adv_report(&report_a_1); + send_adv_report(&report_b_1); /* Interleaved fragmented adv report, NOT SUPPORTED */ + send_adv_report(&report_a_2); + send_adv_report(&report_b_2); + + /* Check that host discards the data if the controller keeps sending + * incomplete packets. + */ + for (int i = 0; i < (2 + (CONFIG_BT_EXT_SCAN_BUF_SIZE / report_a_1.length)); i++) { + send_adv_report(&report_a_1); + } + send_adv_report(&report_a_2); + + /* Check that controller truncated reports do not generate events */ + send_adv_report(&report_d); + + /* Check that reports from a different advertiser works after truncation */ + ztest_returns_value(get_expected_data, report_b_combined.data); + ztest_returns_value(get_expected_length, report_b_combined.length); /* Expect b */ + send_adv_report(&report_b_1); + send_adv_report(&report_b_2); +} + +/* test case main entry */ +void test_main(void) +{ + ztest_test_suite(test_host_long_adv_recv, ztest_unit_test(test_host_long_adv_recv)); + + ztest_run_test_suite(test_host_long_adv_recv); +} diff --git a/tests/bluetooth/host_long_adv_recv/testcase.yaml b/tests/bluetooth/host_long_adv_recv/testcase.yaml new file mode 100644 index 00000000000..54f11d81b09 --- /dev/null +++ b/tests/bluetooth/host_long_adv_recv/testcase.yaml @@ -0,0 +1,4 @@ +tests: + bluetooth.host_long_adv_recv: + platform_allow: native_posix native_posix_64 + tags: bluetooth host From 2557038b813b6b988b556f67dd0c4cd95ab6eadd Mon Sep 17 00:00:00 2001 From: Herman Berget Date: Mon, 20 Dec 2021 15:29:10 +0100 Subject: [PATCH 045/207] [nrf fromtree] Bluetooth: Host: Move ext adv property conversion to separate function How the conversion worked was unclear. Moving the conversion out to a separate function and documenting how it works makes the code easier to understand. Signed-off-by: Herman Berget (cherry picked from commit 4c110f8f1753aa3dba1317c5ce20d78972076131) --- subsys/bluetooth/host/scan.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/subsys/bluetooth/host/scan.c b/subsys/bluetooth/host/scan.c index 84124863244..fb4ff7b8943 100644 --- a/subsys/bluetooth/host/scan.c +++ b/subsys/bluetooth/host/scan.c @@ -401,7 +401,7 @@ static void check_pending_conn(const bt_addr_le_t *id_addr, #endif /* CONFIG_BT_CENTRAL */ /* Convert Legacy adv report evt_type field to adv props */ -static uint8_t get_adv_props(uint8_t evt_type) +static uint8_t get_adv_props_legacy(uint8_t evt_type) { switch (evt_type) { case BT_GAP_ADV_TYPE_ADV_IND: @@ -546,6 +546,17 @@ static uint8_t get_adv_type(uint8_t evt_type) } } +/* Convert extended adv report evt_type field to adv props */ +static uint16_t get_adv_props_extended(uint16_t evt_type) +{ + /* Converts from BT_HCI_LE_ADV_EVT_TYPE_* to BT_GAP_ADV_PROP_* + * The first 4 bits are the same (conn, scan, direct, scan_rsp). + * Bit 4 must be flipped as the meaning of 1 is opposite (legacy -> extended) + * The rest of the bits are zeroed out. + */ + return (evt_type ^ BT_HCI_LE_ADV_EVT_TYPE_LEGACY) & BIT_MASK(5); +} + static void create_ext_adv_info(struct bt_hci_evt_le_ext_advertising_info const *const evt, struct bt_le_scan_recv_info *const scan_info) { @@ -556,9 +567,7 @@ static void create_ext_adv_info(struct bt_hci_evt_le_ext_advertising_info const scan_info->sid = evt->sid; scan_info->interval = sys_le16_to_cpu(evt->interval); scan_info->adv_type = get_adv_type(evt->evt_type); - /* Convert "Legacy" property to Extended property. */ - scan_info->adv_props = evt->evt_type ^ BT_HCI_LE_ADV_PROP_LEGACY; - scan_info->adv_props &= BIT_MASK(5); + scan_info->adv_props = get_adv_props_extended(evt->evt_type); } void bt_hci_le_adv_ext_report(struct net_buf *buf) @@ -1112,7 +1121,7 @@ void bt_hci_le_adv_report(struct net_buf *buf) adv_info.interval = 0U; adv_info.adv_type = evt->evt_type; - adv_info.adv_props = get_adv_props(evt->evt_type); + adv_info.adv_props = get_adv_props_legacy(evt->evt_type); le_adv_recv(&evt->addr, &adv_info, &buf->b, evt->length); From 273944978fec46b5e3c18d16aeda3a8310aa677c Mon Sep 17 00:00:00 2001 From: Herman Berget Date: Wed, 29 Dec 2021 16:23:35 +0100 Subject: [PATCH 046/207] [nrf fromtree] Bluetooth: Host: Reset scan state on scan stop bt_le_stop() previously did the same restting as bt_scan_reset(). After the recent changes they were out of sync. Signed-off-by: Herman Berget (cherry picked from commit acd2b8fdcce412b2a35df1cfdd869dbfa565bafe) --- subsys/bluetooth/host/scan.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subsys/bluetooth/host/scan.c b/subsys/bluetooth/host/scan.c index fb4ff7b8943..5fbedf8ec6d 100644 --- a/subsys/bluetooth/host/scan.c +++ b/subsys/bluetooth/host/scan.c @@ -1254,7 +1254,7 @@ int bt_le_scan_stop(void) return -EALREADY; } - scan_dev_found_cb = NULL; + bt_scan_reset(); if (IS_ENABLED(CONFIG_BT_EXT_ADV) && atomic_test_and_clear_bit(bt_dev.flags, BT_DEV_SCAN_LIMITED)) { From 7702ecb20e4c025b0c7a071dee47cdd12308c6d4 Mon Sep 17 00:00:00 2001 From: Rubin Gerritsen Date: Fri, 28 Jan 2022 10:03:39 +0100 Subject: [PATCH 047/207] [nrf fromtree] Bluetooth: Host: Fix address and SID in the sync established cb When the periodic advertiser list is used, the address and SID may not be identical to those passed in by the application. Signed-off-by: Rubin Gerritsen (cherry picked from commit 4e88c91964e87d0a5dd27678e926bb8693719759) --- subsys/bluetooth/host/scan.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/subsys/bluetooth/host/scan.c b/subsys/bluetooth/host/scan.c index 5fbedf8ec6d..bdb690754f9 100644 --- a/subsys/bluetooth/host/scan.c +++ b/subsys/bluetooth/host/scan.c @@ -935,6 +935,14 @@ void bt_hci_le_per_adv_sync_established(struct net_buf *buf) memset(&sync_info, 0, sizeof(sync_info)); sync_info.interval = pending_per_adv_sync->interval; sync_info.phy = bt_get_phy(pending_per_adv_sync->phy); + + if (atomic_test_bit(pending_per_adv_sync->flags, + BT_PER_ADV_SYNC_SYNCING_USE_LIST)) { + /* Now we know which address and SID we synchronized to. */ + bt_addr_le_copy(&pending_per_adv_sync->addr, &evt->adv_addr); + pending_per_adv_sync->sid = evt->sid; + } + sync_info.addr = &pending_per_adv_sync->addr; sync_info.sid = pending_per_adv_sync->sid; From 4487c5e1f2c0688cba4dbaff676abb25dc2fa633 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 048/207] [nrf fromlist] kconfig: 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. This patch gives out-of-tree mbedtls implementations the ability to supplant the Zephyr mbedtls. https://github.com/zephyrproject-rtos/zephyr/pull/42289 Signed-off-by: Sebastian Bøe --- modules/mbedtls/Kconfig | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/modules/mbedtls/Kconfig b/modules/mbedtls/Kconfig index 96899f545d5..2109afe072c 100644 --- a/modules/mbedtls/Kconfig +++ b/modules/mbedtls/Kconfig @@ -26,6 +26,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 @@ -39,6 +40,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 5c6234e8e46d07ced08e2f76a411fb3f8dfc3278 Mon Sep 17 00:00:00 2001 From: Joakim Andersson Date: Mon, 31 Jan 2022 11:19:05 +0100 Subject: [PATCH 049/207] [nrf fromlist] manifest: Update psa-arch-tests with nordic platform build fixes. Update psa-arch-tests to include build fixes for the nordic platform. https://github.com/zephyrproject-rtos/zephyr/pull/40725 Signed-off-by: Joakim Andersson --- west.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/west.yml b/west.yml index a689d908e51..0309df68db8 100644 --- a/west.yml +++ b/west.yml @@ -228,7 +228,7 @@ manifest: groups: - tee - name: psa-arch-tests - revision: 186cba2543dff73d0cda5509d26f02a0b39ee66e + revision: 0aab24602cbef30f6422e7ef1066a8473073e586 path: modules/tee/tf-m/psa-arch-tests groups: - tee From 5b3681f35e74d5737141a3e97360a641c6d573f3 Mon Sep 17 00:00:00 2001 From: Eduardo Montoya Date: Mon, 31 Jan 2022 11:38:54 +0100 Subject: [PATCH 050/207] [nrf fromlist] net: openthread: Align Kconfig with cmake symbols OPENTHREAD_BORDER_ROUTING_NAT64 OPENTHREAD_DNS_DSO OPENTHREAD_EXCLUDE_TCPLP_LIB Signed-off-by: Eduardo Montoya --- subsys/net/l2/openthread/Kconfig.features | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/subsys/net/l2/openthread/Kconfig.features b/subsys/net/l2/openthread/Kconfig.features index c058644e626..50f2eed83f6 100644 --- a/subsys/net/l2/openthread/Kconfig.features +++ b/subsys/net/l2/openthread/Kconfig.features @@ -29,6 +29,9 @@ config OPENTHREAD_BORDER_AGENT config OPENTHREAD_BORDER_ROUTER bool "Enable Border Router support" +config OPENTHREAD_BORDER_ROUTING_NAT64 + bool "Enable border routing NAT64 support" + config OPENTHREAD_COAP bool "Enable OpenThread CoAP support" help @@ -81,6 +84,9 @@ config OPENTHREAD_DIAG config OPENTHREAD_DNS_CLIENT bool "Enable DNS client support" +config OPENTHREAD_DNS_DSO + bool "Enable DNS Stateful Operations (DSO) support" + config OPENTHREAD_DNSSD_SERVER bool "Enable DNS-SD server support" @@ -95,6 +101,9 @@ config OPENTHREAD_LOG_LEVEL_DYNAMIC config OPENTHREAD_ECDSA bool "Enable ECDSA support" +config OPENTHREAD_EXCLUDE_TCPLP_LIB + bool "Exclude TCPlp library from build" + config OPENTHREAD_EXTERNAL_HEAP bool "Enable external heap support" From 28ad5aadbca3a360c0b4716b568e5eea174a8d66 Mon Sep 17 00:00:00 2001 From: Lukasz Duda Date: Mon, 31 Jan 2022 12:57:30 +0100 Subject: [PATCH 051/207] [nrf fromlist] openthread: platform: implement otPlatCryptoRand API This commit utilizes psa_crypto_get function to fetch cryptographically secure pseudorandom numbers. Signed-off-by: Lukasz Duda --- subsys/net/lib/openthread/platform/crypto_psa.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/subsys/net/lib/openthread/platform/crypto_psa.c b/subsys/net/lib/openthread/platform/crypto_psa.c index f581ec0a572..00eb217336a 100644 --- a/subsys/net/lib/openthread/platform/crypto_psa.c +++ b/subsys/net/lib/openthread/platform/crypto_psa.c @@ -115,9 +115,9 @@ static void ensureKeyIsLoaded(otCryptoKeyRef aKeyRef) psa_reset_key_attributes(&attributes); } -otError otPlatCryptoInit(void) +void otPlatCryptoInit(void) { - return psaToOtError(psa_crypto_init()); + psa_crypto_init(); } otError otPlatCryptoImportKey(otCryptoKeyRef *aKeyRef, @@ -405,3 +405,16 @@ otError otPlatCryptoSha256Finish(otCryptoContext *aContext, uint8_t *aHash, uint return psaToOtError(psa_hash_finish(operation, aHash, aHashSize, &hash_size)); } + +void otPlatCryptoRandomInit(void) +{ +} + +void otPlatCryptoRandomDeinit(void) +{ +} + +otError otPlatCryptoRandomGet(uint8_t *aBuffer, uint16_t aSize) +{ + return psaToOtError(psa_generate_random(aBuffer, aSize)); +} From 0ed193f9ab233597612727667946bc324c106518 Mon Sep 17 00:00:00 2001 From: Andrzej Puzdrowski Date: Wed, 26 Jan 2022 17:02:27 +0100 Subject: [PATCH 052/207] [nrf fromtree] test/subsys/storage/stream_flash: fix build size issue This test uses SoC's flash from offset of 64 KB which might overlap with executable for a target (for instance nrf52840dk_nrf52840). This patch moves this region to 128 KB which solves the issue. upstream commit: 7adee4dc23bacd6879df5e47c36d17952c22aeea Signed-off-by: Andrzej Puzdrowski --- tests/subsys/storage/stream/stream_flash/src/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/subsys/storage/stream/stream_flash/src/main.c b/tests/subsys/storage/stream/stream_flash/src/main.c index 93d803e6db6..0ea9fa177bc 100644 --- a/tests/subsys/storage/stream/stream_flash/src/main.c +++ b/tests/subsys/storage/stream/stream_flash/src/main.c @@ -22,7 +22,7 @@ #define FLASH_NAME DT_CHOSEN_ZEPHYR_FLASH_CONTROLLER_LABEL /* so that we don't overwrite the application when running on hw */ -#define FLASH_BASE (64*1024) +#define FLASH_BASE (128*1024) #define FLASH_AVAILABLE (FLASH_SIZE-FLASH_BASE) static const struct device *fdev; From 2e258f513e665095bae4a0b4710f5a05d16683b8 Mon Sep 17 00:00:00 2001 From: Rubin Gerritsen Date: Mon, 31 Jan 2022 15:40:20 +0100 Subject: [PATCH 053/207] [nrf fromlist] Bluetooth: Host: Remove experimental tag from periodic adv and sync We have done sufficient testing to claim that the host is no longer experimental. Upstream PR: https://github.com/zephyrproject-rtos/zephyr/pull/42318 Signed-off-by: Rubin Gerritsen --- subsys/bluetooth/Kconfig.adv | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/subsys/bluetooth/Kconfig.adv b/subsys/bluetooth/Kconfig.adv index 3a35d8cbb3f..dac03e6aa17 100644 --- a/subsys/bluetooth/Kconfig.adv +++ b/subsys/bluetooth/Kconfig.adv @@ -44,8 +44,7 @@ config BT_EXT_ADV_MAX_ADV_SET supported. config BT_PER_ADV - bool "Periodic Advertising and Scanning support [EXPERIMENTAL]" - select EXPERIMENTAL + bool "Periodic Advertising and Scanning support" help Select this to enable Periodic Advertising API support. This allows the device to send advertising data periodically at deterministic @@ -53,9 +52,8 @@ config BT_PER_ADV to periodically get the data. config BT_PER_ADV_SYNC - bool "Periodic advertising sync support [EXPERIMENTAL]" + bool "Periodic advertising sync support" depends on BT_OBSERVER - select EXPERIMENTAL help Select this to enable Periodic Advertising Sync API support. Syncing with a periodic advertiser allows the device to periodically From ea090a43fe526418e190f323e17b19dbdd5531d7 Mon Sep 17 00:00:00 2001 From: Rubin Gerritsen Date: Tue, 1 Feb 2022 09:47:33 +0100 Subject: [PATCH 054/207] [nrf fromlist] Bluetooth: Host: Non-discardable event buffer size is 255 for ext adv After https://github.com/zephyrproject-rtos/zephyr/pull/41337, extended advertising reports are no longer discardable. Ensure the non-discardable events are large enough. Upstream PR: https://github.com/zephyrproject-rtos/zephyr/pull/42344 Signed-off-by: Rubin Gerritsen --- subsys/bluetooth/common/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/subsys/bluetooth/common/Kconfig b/subsys/bluetooth/common/Kconfig index 456b5366f26..6e8a8b3f405 100644 --- a/subsys/bluetooth/common/Kconfig +++ b/subsys/bluetooth/common/Kconfig @@ -109,7 +109,7 @@ config BT_BUF_ACL_RX_COUNT config BT_BUF_EVT_RX_SIZE int "Maximum supported HCI Event buffer length" - default 255 if (BT_EXT_ADV && !(BT_BUF_EVT_DISCARDABLE_COUNT > 0)) || BT_PER_ADV_SYNC + default 255 if (BT_EXT_ADV && BT_OBSERVER) || BT_PER_ADV_SYNC # LE Read Supported Commands command complete event. default 68 range 68 255 @@ -136,7 +136,7 @@ config BT_BUF_EVT_DISCARDABLE_SIZE int "Maximum supported discardable HCI Event buffer length" range 43 255 # LE Extended Advertising Report event - default 255 if BT_BREDR || BT_EXT_ADV + default 255 if BT_BREDR # Le Advertising Report event default 43 help From 214765bc5be88282b628271739c8df1192ad41a3 Mon Sep 17 00:00:00 2001 From: Andreas Chmielewski Date: Wed, 5 Jan 2022 12:03:19 +0100 Subject: [PATCH 055/207] [nrf fromtree] net: lwm2m: enable monitoring of fw update state/result The intention behind this patch is to know the current state/result of a firmware update process in the application code. It makes it possible to use pre/post_write_callbacks to get the proper value of state (5/0/3) and result (5/0/5) resource. Signed-off-by: Andreas Chmielewski --- subsys/net/lib/lwm2m/lwm2m_obj_firmware.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/subsys/net/lib/lwm2m/lwm2m_obj_firmware.c b/subsys/net/lib/lwm2m/lwm2m_obj_firmware.c index 980bd507361..bc0dd573c03 100644 --- a/subsys/net/lib/lwm2m/lwm2m_obj_firmware.c +++ b/subsys/net/lib/lwm2m/lwm2m_obj_firmware.c @@ -116,9 +116,9 @@ void lwm2m_firmware_set_update_state(uint8_t state) update_state, state); } - update_state = state; - NOTIFY_OBSERVER(LWM2M_OBJECT_FIRMWARE_ID, 0, FIRMWARE_STATE_ID); - LOG_DBG("Update state = %d", update_state); + lwm2m_engine_set_u8("5/0/3", state); + + LOG_DBG("Update state = %d", state); } uint8_t lwm2m_firmware_get_update_result(void) @@ -185,9 +185,9 @@ void lwm2m_firmware_set_update_result(uint8_t result) result, state); } - update_result = result; - NOTIFY_OBSERVER(LWM2M_OBJECT_FIRMWARE_ID, 0, FIRMWARE_UPDATE_RESULT_ID); - LOG_DBG("Update result = %d", update_result); + lwm2m_engine_set_u8("5/0/5", result); + + LOG_DBG("Update result = %d", result); } static int package_write_cb(uint16_t obj_inst_id, uint16_t res_id, From 9ae787e54a9fab13abc6fc9b50832de73e9292ea Mon Sep 17 00:00:00 2001 From: Veijo Pesonen Date: Tue, 15 Jun 2021 16:05:56 +0300 Subject: [PATCH 056/207] [nrf fromtree] net: lwm2m: separate FW update object instances - /5/* This is a proof-of-concept implementation. A device might have multiple firmware images which needs to be updated separately. For example a single device might have * A bootloader image * An application image * External firmware image Instead of pushing all these updates through the object instance 0 - /5/0 - here a split to multiple has been made possible. Signed-off-by: Veijo Pesonen --- subsys/net/lib/lwm2m/Kconfig | 15 ++ subsys/net/lib/lwm2m/lwm2m_engine.h | 6 +- subsys/net/lib/lwm2m/lwm2m_obj_firmware.c | 199 ++++++++++-------- .../net/lib/lwm2m/lwm2m_obj_firmware_pull.c | 2 +- 4 files changed, 127 insertions(+), 95 deletions(-) diff --git a/subsys/net/lib/lwm2m/Kconfig b/subsys/net/lib/lwm2m/Kconfig index 4c3b137b371..4b97fa24e40 100644 --- a/subsys/net/lib/lwm2m/Kconfig +++ b/subsys/net/lib/lwm2m/Kconfig @@ -310,6 +310,21 @@ config LWM2M_FIRMWARE_UPDATE_OBJ_SUPPORT help Include support for LWM2M Firmware Update Object (ID 5) +config LWM2M_FIRMWARE_UPDATE_OBJ_SUPPORT_MULTIPLE + bool "Support multiple firmware update objects [EXPERIMENTAL]" + depends on LWM2M_FIRMWARE_UPDATE_OBJ_SUPPORT + select EXPERIMENTAL + help + Support multiple instances of LWM2M Firwmare Update Object (ID 5) + +config LWM2M_FIRMWARE_UPDATE_OBJ_INSTANCE_COUNT + int "Maximum # of LWM2M Firmware update object instances" + default 1 + depends on LWM2M_FIRMWARE_UPDATE_OBJ_SUPPORT_MULTIPLE + help + This setting establishes the total count of LWM2M Firmware update + object instances available to the client. + config LWM2M_FIRMWARE_UPDATE_PULL_SUPPORT bool "Firmware Update object pull support" default y diff --git a/subsys/net/lib/lwm2m/lwm2m_engine.h b/subsys/net/lib/lwm2m/lwm2m_engine.h index 8ad786dd345..0a76e65b946 100644 --- a/subsys/net/lib/lwm2m/lwm2m_engine.h +++ b/subsys/net/lib/lwm2m/lwm2m_engine.h @@ -128,10 +128,8 @@ int32_t lwm2m_server_get_pmax(uint16_t obj_inst_id); int lwm2m_server_short_id_to_inst(uint16_t short_id); #if defined(CONFIG_LWM2M_FIRMWARE_UPDATE_OBJ_SUPPORT) -uint8_t lwm2m_firmware_get_update_state(void); -void lwm2m_firmware_set_update_state(uint8_t state); -void lwm2m_firmware_set_update_result(uint8_t result); -uint8_t lwm2m_firmware_get_update_result(void); +void lwm2m_firmware_set_update_state(uint16_t obj_inst_id, uint8_t state); +void lwm2m_firmware_set_update_result(uint16_t obj_inst_id, uint8_t result); #endif /* Attribute handling. */ diff --git a/subsys/net/lib/lwm2m/lwm2m_obj_firmware.c b/subsys/net/lib/lwm2m/lwm2m_obj_firmware.c index bc0dd573c03..a58afd6e1ec 100644 --- a/subsys/net/lib/lwm2m/lwm2m_obj_firmware.c +++ b/subsys/net/lib/lwm2m/lwm2m_obj_firmware.c @@ -12,6 +12,7 @@ LOG_MODULE_REGISTER(LOG_MODULE_NAME); #include +#include #include #include "lwm2m_object.h" @@ -20,6 +21,12 @@ LOG_MODULE_REGISTER(LOG_MODULE_NAME); #define FIRMWARE_VERSION_MAJOR 1 #define FIRMWARE_VERSION_MINOR 0 +#if defined(LWM2M_FIRMWARE_UPDATE_OBJ_SUPPORT_MULTIPLE) +#define MAX_INSTANCE_COUNT LWM2M_FIRMWARE_UPDATE_OBJ_INSTANCE_COUNT +#else +#define MAX_INSTANCE_COUNT 1 +#endif + /* Firmware resource IDs */ #define FIRMWARE_PACKAGE_ID 0 #define FIRMWARE_PACKAGE_URI_ID 1 @@ -47,12 +54,12 @@ LOG_MODULE_REGISTER(LOG_MODULE_NAME); #define RESOURCE_INSTANCE_COUNT (FIRMWARE_MAX_ID - 1) /* resource state variables */ -static uint8_t update_state; -static uint8_t update_result; -static uint8_t delivery_method; -static char package_uri[PACKAGE_URI_LEN]; +static uint8_t update_state[MAX_INSTANCE_COUNT]; +static uint8_t update_result[MAX_INSTANCE_COUNT]; +static uint8_t delivery_method[MAX_INSTANCE_COUNT]; +static char package_uri[MAX_INSTANCE_COUNT][PACKAGE_URI_LEN]; -/* only 1 instance of firmware object exists */ +/* A varying number of firmware object exists */ static struct lwm2m_engine_obj firmware; static struct lwm2m_engine_obj_field fields[] = { OBJ_FIELD_DATA(FIRMWARE_PACKAGE_ID, W, OPAQUE), @@ -66,41 +73,42 @@ static struct lwm2m_engine_obj_field fields[] = { OBJ_FIELD_DATA(FIRMWARE_UPDATE_DELIV_METHOD_ID, R, U8) }; -static struct lwm2m_engine_obj_inst inst; -static struct lwm2m_engine_res res[FIRMWARE_MAX_ID]; -static struct lwm2m_engine_res_inst res_inst[RESOURCE_INSTANCE_COUNT]; +static struct lwm2m_engine_obj_inst inst[MAX_INSTANCE_COUNT]; +static struct lwm2m_engine_res res[MAX_INSTANCE_COUNT][FIRMWARE_MAX_ID]; +static struct lwm2m_engine_res_inst res_inst[MAX_INSTANCE_COUNT][RESOURCE_INSTANCE_COUNT]; static lwm2m_engine_set_data_cb_t write_cb; static lwm2m_engine_execute_cb_t update_cb; #ifdef CONFIG_LWM2M_FIRMWARE_UPDATE_PULL_SUPPORT -extern int lwm2m_firmware_start_transfer(char *package_uri); +extern int lwm2m_firmware_start_transfer(uint16_t obj_inst_id, char *package_uri); #endif -uint8_t lwm2m_firmware_get_update_state(void) +uint8_t lwm2m_firmware_get_update_state(uint16_t obj_inst_id) { - return update_state; + return update_state[obj_inst_id]; } -void lwm2m_firmware_set_update_state(uint8_t state) +void lwm2m_firmware_set_update_state(uint16_t obj_inst_id, uint8_t state) { bool error = false; + char path[sizeof("5/65535/5")]; /* Check LWM2M SPEC appendix E.6.1 */ switch (state) { case STATE_DOWNLOADING: - if (update_state != STATE_IDLE) { + if (update_state[obj_inst_id] != STATE_IDLE) { error = true; } break; case STATE_DOWNLOADED: - if (update_state != STATE_DOWNLOADING && - update_state != STATE_UPDATING) { + if (update_state[obj_inst_id] != STATE_DOWNLOADING && + update_state[obj_inst_id] != STATE_UPDATING) { error = true; } break; case STATE_UPDATING: - if (update_state != STATE_DOWNLOADED) { + if (update_state[obj_inst_id] != STATE_DOWNLOADED) { error = true; } break; @@ -113,36 +121,39 @@ void lwm2m_firmware_set_update_state(uint8_t state) if (error) { LOG_ERR("Invalid state transition: %u -> %u", - update_state, state); + update_state[obj_inst_id], state); } - lwm2m_engine_set_u8("5/0/3", state); + snprintf(path, sizeof(path), "5/%" PRIu16 "/3", obj_inst_id); + + lwm2m_engine_set_u8(path, state); LOG_DBG("Update state = %d", state); } -uint8_t lwm2m_firmware_get_update_result(void) +uint8_t lwm2m_firmware_get_update_result(uint16_t obj_inst_id) { - return update_result; + return update_result[obj_inst_id]; } -void lwm2m_firmware_set_update_result(uint8_t result) +void lwm2m_firmware_set_update_result(uint16_t obj_inst_id, uint8_t result) { uint8_t state; bool error = false; + char path[sizeof("5/65535/5")]; /* Check LWM2M SPEC appendix E.6.1 */ switch (result) { case RESULT_DEFAULT: - lwm2m_firmware_set_update_state(STATE_IDLE); + lwm2m_firmware_set_update_state(obj_inst_id, STATE_IDLE); break; case RESULT_SUCCESS: - if (update_state != STATE_UPDATING) { + if (update_state[obj_inst_id] != STATE_UPDATING) { error = true; - state = update_state; + state = update_state[obj_inst_id]; } - lwm2m_firmware_set_update_state(STATE_IDLE); + lwm2m_firmware_set_update_state(obj_inst_id, STATE_IDLE); break; case RESULT_NO_STORAGE: case RESULT_OUT_OF_MEM: @@ -150,30 +161,30 @@ void lwm2m_firmware_set_update_result(uint8_t result) case RESULT_UNSUP_FW: case RESULT_INVALID_URI: case RESULT_UNSUP_PROTO: - if (update_state != STATE_DOWNLOADING) { + if (update_state[obj_inst_id] != STATE_DOWNLOADING) { error = true; - state = update_state; + state = update_state[obj_inst_id]; } - lwm2m_firmware_set_update_state(STATE_IDLE); + lwm2m_firmware_set_update_state(obj_inst_id, STATE_IDLE); break; case RESULT_INTEGRITY_FAILED: - if (update_state != STATE_DOWNLOADING && - update_state != STATE_UPDATING) { + if (update_state[obj_inst_id] != STATE_DOWNLOADING && + update_state[obj_inst_id] != STATE_UPDATING) { error = true; - state = update_state; + state = update_state[obj_inst_id]; } - lwm2m_firmware_set_update_state(STATE_IDLE); + lwm2m_firmware_set_update_state(obj_inst_id, STATE_IDLE); break; case RESULT_UPDATE_FAILED: - if (update_state != STATE_DOWNLOADING && - update_state != STATE_UPDATING) { + if (update_state[obj_inst_id] != STATE_DOWNLOADING && + update_state[obj_inst_id] != STATE_UPDATING) { error = true; - state = update_state; + state = update_state[obj_inst_id]; } - lwm2m_firmware_set_update_state(STATE_IDLE); + lwm2m_firmware_set_update_state(obj_inst_id, STATE_IDLE); break; default: LOG_ERR("Unhandled result: %u", result); @@ -185,7 +196,9 @@ void lwm2m_firmware_set_update_result(uint8_t result) result, state); } - lwm2m_engine_set_u8("5/0/5", result); + snprintf(path, sizeof(path), "5/%" PRIu16 "/3", obj_inst_id); + + lwm2m_engine_set_u8(path, result); LOG_DBG("Update result = %d", result); } @@ -197,16 +210,16 @@ static int package_write_cb(uint16_t obj_inst_id, uint16_t res_id, uint8_t state; int ret; - state = lwm2m_firmware_get_update_state(); + state = lwm2m_firmware_get_update_state(obj_inst_id); if (state == STATE_IDLE) { /* TODO: setup timer to check download status, * make sure it fail after timeout */ - lwm2m_firmware_set_update_state(STATE_DOWNLOADING); + lwm2m_firmware_set_update_state(obj_inst_id, STATE_DOWNLOADING); } else if (state != STATE_DOWNLOADING) { if (data_len == 0U && state == STATE_DOWNLOADED) { /* reset to state idle and result default */ - lwm2m_firmware_set_update_result(RESULT_DEFAULT); + lwm2m_firmware_set_update_result(obj_inst_id, RESULT_DEFAULT); return 0; } @@ -219,21 +232,23 @@ static int package_write_cb(uint16_t obj_inst_id, uint16_t res_id, last_block, total_size) : 0; if (ret >= 0) { if (last_block) { - lwm2m_firmware_set_update_state(STATE_DOWNLOADED); + lwm2m_firmware_set_update_state(obj_inst_id, STATE_DOWNLOADED); } return 0; } else if (ret == -ENOMEM) { - lwm2m_firmware_set_update_result(RESULT_OUT_OF_MEM); + lwm2m_firmware_set_update_result(obj_inst_id, RESULT_OUT_OF_MEM); } else if (ret == -ENOSPC) { - lwm2m_firmware_set_update_result(RESULT_NO_STORAGE); + lwm2m_firmware_set_update_result(obj_inst_id, RESULT_NO_STORAGE); /* Response 4.13 (RFC7959, section 2.9.3) */ /* TODO: should include size1 option to indicate max size */ ret = -EFBIG; } else if (ret == -EFAULT) { - lwm2m_firmware_set_update_result(RESULT_INTEGRITY_FAILED); + lwm2m_firmware_set_update_result(obj_inst_id, RESULT_INTEGRITY_FAILED); + } else if (ret == -ENOMSG) { + lwm2m_firmware_set_update_result(obj_inst_id, RESULT_UNSUP_FW); } else { - lwm2m_firmware_set_update_result(RESULT_UPDATE_FAILED); + lwm2m_firmware_set_update_result(obj_inst_id, RESULT_UPDATE_FAILED); } return ret; @@ -243,20 +258,20 @@ static int package_uri_write_cb(uint16_t obj_inst_id, uint16_t res_id, uint16_t res_inst_id, uint8_t *data, uint16_t data_len, bool last_block, size_t total_size) { - LOG_DBG("PACKAGE_URI WRITE: %s", log_strdup(package_uri)); + LOG_DBG("PACKAGE_URI WRITE: %s", log_strdup(package_uri[obj_inst_id])); #ifdef CONFIG_LWM2M_FIRMWARE_UPDATE_PULL_SUPPORT - uint8_t state = lwm2m_firmware_get_update_state(); + uint8_t state = lwm2m_firmware_get_update_state(obj_inst_id); if (state == STATE_IDLE) { - lwm2m_firmware_set_update_result(RESULT_DEFAULT); + lwm2m_firmware_set_update_result(obj_inst_id, RESULT_DEFAULT); if (data_len > 0) { - lwm2m_firmware_start_transfer(package_uri); + lwm2m_firmware_start_transfer(obj_inst_id, package_uri[obj_inst_id]); } } else if (state == STATE_DOWNLOADED && data_len == 0U) { /* reset to state idle and result default */ - lwm2m_firmware_set_update_result(RESULT_DEFAULT); + lwm2m_firmware_set_update_result(obj_inst_id, RESULT_DEFAULT); } return 0; @@ -292,20 +307,20 @@ static int firmware_update_cb(uint16_t obj_inst_id, uint8_t state; int ret; - state = lwm2m_firmware_get_update_state(); + state = lwm2m_firmware_get_update_state(obj_inst_id); if (state != STATE_DOWNLOADED) { LOG_ERR("State other than downloaded: %d", state); return -EPERM; } - lwm2m_firmware_set_update_state(STATE_UPDATING); + lwm2m_firmware_set_update_state(obj_inst_id, STATE_UPDATING); callback = lwm2m_firmware_get_update_cb(); if (callback) { ret = callback(obj_inst_id, args, args_len); if (ret < 0) { LOG_ERR("Failed to update firmware: %d", ret); - lwm2m_firmware_set_update_result( + lwm2m_firmware_set_update_result(obj_inst_id, ret == -EINVAL ? RESULT_INTEGRITY_FAILED : RESULT_UPDATE_FAILED); return 0; @@ -319,31 +334,32 @@ static struct lwm2m_engine_obj_inst *firmware_create(uint16_t obj_inst_id) { int i = 0, j = 0; - init_res_instance(res_inst, ARRAY_SIZE(res_inst)); + init_res_instance(res_inst[obj_inst_id], ARRAY_SIZE(res_inst[obj_inst_id])); /* initialize instance resource data */ - INIT_OBJ_RES_OPT(FIRMWARE_PACKAGE_ID, res, i, res_inst, j, 1, false, - true, NULL, NULL, NULL, package_write_cb, NULL); - INIT_OBJ_RES(FIRMWARE_PACKAGE_URI_ID, res, i, res_inst, j, 1, false, - true, package_uri, PACKAGE_URI_LEN, - NULL, NULL, NULL, package_uri_write_cb, NULL); - INIT_OBJ_RES_EXECUTE(FIRMWARE_UPDATE_ID, res, i, firmware_update_cb); - INIT_OBJ_RES_DATA(FIRMWARE_STATE_ID, res, i, res_inst, j, - &update_state, sizeof(update_state)); - INIT_OBJ_RES_DATA(FIRMWARE_UPDATE_RESULT_ID, res, i, res_inst, j, - &update_result, sizeof(update_result)); - INIT_OBJ_RES_OPTDATA(FIRMWARE_PACKAGE_NAME_ID, res, i, res_inst, j); - INIT_OBJ_RES_OPTDATA(FIRMWARE_PACKAGE_VERSION_ID, res, i, res_inst, j); - INIT_OBJ_RES_MULTI_OPTDATA(FIRMWARE_UPDATE_PROTO_SUPPORT_ID, res, i, - res_inst, j, 1, false); - INIT_OBJ_RES_DATA(FIRMWARE_UPDATE_DELIV_METHOD_ID, res, i, res_inst, j, - &delivery_method, sizeof(delivery_method)); - - inst.resources = res; - inst.resource_count = i; + INIT_OBJ_RES_OPT(FIRMWARE_PACKAGE_ID, res[obj_inst_id], i, res_inst[obj_inst_id], j, 1, + false, true, NULL, NULL, NULL, package_write_cb, NULL); + INIT_OBJ_RES(FIRMWARE_PACKAGE_URI_ID, res[obj_inst_id], i, res_inst[obj_inst_id], j, 1, + false, true, package_uri[obj_inst_id], PACKAGE_URI_LEN, NULL, NULL, NULL, + package_uri_write_cb, NULL); + INIT_OBJ_RES_EXECUTE(FIRMWARE_UPDATE_ID, res[obj_inst_id], i, firmware_update_cb); + INIT_OBJ_RES_DATA(FIRMWARE_STATE_ID, res[obj_inst_id], i, res_inst[obj_inst_id], j, + &(update_state[obj_inst_id]), sizeof(update_state[obj_inst_id])); + INIT_OBJ_RES_DATA(FIRMWARE_UPDATE_RESULT_ID, res[obj_inst_id], i, res_inst[obj_inst_id], j, + &(update_result[obj_inst_id]), sizeof(update_result[obj_inst_id])); + INIT_OBJ_RES_OPTDATA(FIRMWARE_PACKAGE_NAME_ID, res[obj_inst_id], i, + res_inst[obj_inst_id], j); + INIT_OBJ_RES_OPTDATA(FIRMWARE_PACKAGE_VERSION_ID, res[obj_inst_id], i, + res_inst[obj_inst_id], j); + INIT_OBJ_RES_DATA(FIRMWARE_UPDATE_DELIV_METHOD_ID, res[obj_inst_id], i, + res_inst[obj_inst_id], j, &(delivery_method[obj_inst_id]), + sizeof(delivery_method[obj_inst_id])); + + inst[obj_inst_id].resources = res[obj_inst_id]; + inst[obj_inst_id].resource_count = i; LOG_DBG("Create LWM2M firmware instance: %d", obj_inst_id); - return &inst; + return &inst[obj_inst_id]; } static int lwm2m_firmware_init(const struct device *dev) @@ -352,31 +368,34 @@ static int lwm2m_firmware_init(const struct device *dev) int ret = 0; /* Set default values */ - package_uri[0] = '\0'; - /* Initialize state machine */ - /* TODO: should be restored from the permanent storage */ - update_state = STATE_IDLE; - update_result = RESULT_DEFAULT; -#ifdef CONFIG_LWM2M_FIRMWARE_UPDATE_PULL_SUPPORT - delivery_method = DELIVERY_METHOD_BOTH; -#else - delivery_method = DELIVERY_METHOD_PUSH_ONLY; -#endif - firmware.obj_id = LWM2M_OBJECT_FIRMWARE_ID; firmware.version_major = FIRMWARE_VERSION_MAJOR; firmware.version_minor = FIRMWARE_VERSION_MINOR; firmware.is_core = true; firmware.fields = fields; firmware.field_count = ARRAY_SIZE(fields); - firmware.max_instance_count = 1U; + firmware.max_instance_count = MAX_INSTANCE_COUNT; firmware.create_cb = firmware_create; lwm2m_register_obj(&firmware); - /* auto create the only instance */ - ret = lwm2m_create_obj_inst(LWM2M_OBJECT_FIRMWARE_ID, 0, &obj_inst); - if (ret < 0) { - LOG_DBG("Create LWM2M instance 0 error: %d", ret); + + for (int idx = 0; idx < MAX_INSTANCE_COUNT; idx++) { + package_uri[idx][0] = '\0'; + + /* Initialize state machine */ + /* TODO: should be restored from the permanent storage */ + update_state[idx] = STATE_IDLE; + update_result[idx] = RESULT_DEFAULT; +#ifdef CONFIG_LWM2M_FIRMWARE_UPDATE_PULL_SUPPORT + delivery_method[idx] = DELIVERY_METHOD_BOTH; +#else + delivery_method[idx] = DELIVERY_METHOD_PUSH_ONLY; +#endif + ret = lwm2m_create_obj_inst(LWM2M_OBJECT_FIRMWARE_ID, idx, &obj_inst); + if (ret < 0) { + LOG_DBG("Create LWM2M instance %d error: %d", idx, ret); + break; + } } return ret; diff --git a/subsys/net/lib/lwm2m/lwm2m_obj_firmware_pull.c b/subsys/net/lib/lwm2m/lwm2m_obj_firmware_pull.c index c206365ec87..f2349fcf6c7 100644 --- a/subsys/net/lib/lwm2m/lwm2m_obj_firmware_pull.c +++ b/subsys/net/lib/lwm2m/lwm2m_obj_firmware_pull.c @@ -65,7 +65,7 @@ int lwm2m_firmware_cancel_transfer(void) return 0; } -int lwm2m_firmware_start_transfer(char *package_uri) +int lwm2m_firmware_start_transfer(uint16_t obj_inst_id, char *package_uri) { int error_code; From b87062adab1130bfbaa3f536d9d9488005c94342 Mon Sep 17 00:00:00 2001 From: Jarno Lamsa Date: Tue, 14 Dec 2021 09:52:54 +0200 Subject: [PATCH 057/207] [nrf fromtree] net: lwm2m: Provide backwards compatibility for single object 5 Previously the object 5 was only single instance object. Provide backwards compatibility, so it can be continued to use with single instance. Signed-off-by: Jarno Lamsa --- subsys/net/lib/lwm2m/lwm2m_engine.h | 6 +- subsys/net/lib/lwm2m/lwm2m_obj_firmware.c | 68 ++++++++++++------- .../net/lib/lwm2m/lwm2m_obj_firmware_pull.c | 4 +- 3 files changed, 50 insertions(+), 28 deletions(-) diff --git a/subsys/net/lib/lwm2m/lwm2m_engine.h b/subsys/net/lib/lwm2m/lwm2m_engine.h index 0a76e65b946..f01ce3e1ff0 100644 --- a/subsys/net/lib/lwm2m/lwm2m_engine.h +++ b/subsys/net/lib/lwm2m/lwm2m_engine.h @@ -128,8 +128,10 @@ int32_t lwm2m_server_get_pmax(uint16_t obj_inst_id); int lwm2m_server_short_id_to_inst(uint16_t short_id); #if defined(CONFIG_LWM2M_FIRMWARE_UPDATE_OBJ_SUPPORT) -void lwm2m_firmware_set_update_state(uint16_t obj_inst_id, uint8_t state); -void lwm2m_firmware_set_update_result(uint16_t obj_inst_id, uint8_t result); +void lwm2m_firmware_set_update_state_inst(uint16_t obj_inst_id, uint8_t state); +void lwm2m_firmware_set_update_result_inst(uint16_t obj_inst_id, uint8_t result); +void lwm2m_firmware_set_update_state(uint8_t state); +void lwm2m_firmware_set_update_result(uint8_t result); #endif /* Attribute handling. */ diff --git a/subsys/net/lib/lwm2m/lwm2m_obj_firmware.c b/subsys/net/lib/lwm2m/lwm2m_obj_firmware.c index a58afd6e1ec..e0861a6752f 100644 --- a/subsys/net/lib/lwm2m/lwm2m_obj_firmware.c +++ b/subsys/net/lib/lwm2m/lwm2m_obj_firmware.c @@ -84,12 +84,17 @@ static lwm2m_engine_execute_cb_t update_cb; extern int lwm2m_firmware_start_transfer(uint16_t obj_inst_id, char *package_uri); #endif -uint8_t lwm2m_firmware_get_update_state(uint16_t obj_inst_id) +uint8_t lwm2m_firmware_get_update_state_inst(uint16_t obj_inst_id) { return update_state[obj_inst_id]; } -void lwm2m_firmware_set_update_state(uint16_t obj_inst_id, uint8_t state) +uint8_t lwm2m_firmware_get_update_state(void) +{ + return lwm2m_firmware_get_update_state_inst(0); +} + +void lwm2m_firmware_set_update_state_inst(uint16_t obj_inst_id, uint8_t state) { bool error = false; char path[sizeof("5/65535/5")]; @@ -131,12 +136,22 @@ void lwm2m_firmware_set_update_state(uint16_t obj_inst_id, uint8_t state) LOG_DBG("Update state = %d", state); } -uint8_t lwm2m_firmware_get_update_result(uint16_t obj_inst_id) +void lwm2m_firmware_set_update_state(uint8_t state) +{ + lwm2m_firmware_set_update_state_inst(0, state); +} + +uint8_t lwm2m_firmware_get_update_result_inst(uint16_t obj_inst_id) { return update_result[obj_inst_id]; } -void lwm2m_firmware_set_update_result(uint16_t obj_inst_id, uint8_t result) +uint8_t lwm2m_firmware_get_update_result(void) +{ + return lwm2m_firmware_get_update_result_inst(0); +} + +void lwm2m_firmware_set_update_result_inst(uint16_t obj_inst_id, uint8_t result) { uint8_t state; bool error = false; @@ -145,7 +160,7 @@ void lwm2m_firmware_set_update_result(uint16_t obj_inst_id, uint8_t result) /* Check LWM2M SPEC appendix E.6.1 */ switch (result) { case RESULT_DEFAULT: - lwm2m_firmware_set_update_state(obj_inst_id, STATE_IDLE); + lwm2m_firmware_set_update_state_inst(obj_inst_id, STATE_IDLE); break; case RESULT_SUCCESS: if (update_state[obj_inst_id] != STATE_UPDATING) { @@ -153,7 +168,7 @@ void lwm2m_firmware_set_update_result(uint16_t obj_inst_id, uint8_t result) state = update_state[obj_inst_id]; } - lwm2m_firmware_set_update_state(obj_inst_id, STATE_IDLE); + lwm2m_firmware_set_update_state_inst(obj_inst_id, STATE_IDLE); break; case RESULT_NO_STORAGE: case RESULT_OUT_OF_MEM: @@ -166,7 +181,7 @@ void lwm2m_firmware_set_update_result(uint16_t obj_inst_id, uint8_t result) state = update_state[obj_inst_id]; } - lwm2m_firmware_set_update_state(obj_inst_id, STATE_IDLE); + lwm2m_firmware_set_update_state_inst(obj_inst_id, STATE_IDLE); break; case RESULT_INTEGRITY_FAILED: if (update_state[obj_inst_id] != STATE_DOWNLOADING && @@ -175,7 +190,7 @@ void lwm2m_firmware_set_update_result(uint16_t obj_inst_id, uint8_t result) state = update_state[obj_inst_id]; } - lwm2m_firmware_set_update_state(obj_inst_id, STATE_IDLE); + lwm2m_firmware_set_update_state_inst(obj_inst_id, STATE_IDLE); break; case RESULT_UPDATE_FAILED: if (update_state[obj_inst_id] != STATE_DOWNLOADING && @@ -184,7 +199,7 @@ void lwm2m_firmware_set_update_result(uint16_t obj_inst_id, uint8_t result) state = update_state[obj_inst_id]; } - lwm2m_firmware_set_update_state(obj_inst_id, STATE_IDLE); + lwm2m_firmware_set_update_state_inst(obj_inst_id, STATE_IDLE); break; default: LOG_ERR("Unhandled result: %u", result); @@ -203,6 +218,11 @@ void lwm2m_firmware_set_update_result(uint16_t obj_inst_id, uint8_t result) LOG_DBG("Update result = %d", result); } +void lwm2m_firmware_set_update_result(uint8_t result) +{ + lwm2m_firmware_set_update_result_inst(0, result); +} + static int package_write_cb(uint16_t obj_inst_id, uint16_t res_id, uint16_t res_inst_id, uint8_t *data, uint16_t data_len, bool last_block, size_t total_size) @@ -210,16 +230,16 @@ static int package_write_cb(uint16_t obj_inst_id, uint16_t res_id, uint8_t state; int ret; - state = lwm2m_firmware_get_update_state(obj_inst_id); + state = lwm2m_firmware_get_update_state_inst(obj_inst_id); if (state == STATE_IDLE) { /* TODO: setup timer to check download status, * make sure it fail after timeout */ - lwm2m_firmware_set_update_state(obj_inst_id, STATE_DOWNLOADING); + lwm2m_firmware_set_update_state_inst(obj_inst_id, STATE_DOWNLOADING); } else if (state != STATE_DOWNLOADING) { if (data_len == 0U && state == STATE_DOWNLOADED) { /* reset to state idle and result default */ - lwm2m_firmware_set_update_result(obj_inst_id, RESULT_DEFAULT); + lwm2m_firmware_set_update_result_inst(obj_inst_id, RESULT_DEFAULT); return 0; } @@ -232,23 +252,23 @@ static int package_write_cb(uint16_t obj_inst_id, uint16_t res_id, last_block, total_size) : 0; if (ret >= 0) { if (last_block) { - lwm2m_firmware_set_update_state(obj_inst_id, STATE_DOWNLOADED); + lwm2m_firmware_set_update_state_inst(obj_inst_id, STATE_DOWNLOADED); } return 0; } else if (ret == -ENOMEM) { - lwm2m_firmware_set_update_result(obj_inst_id, RESULT_OUT_OF_MEM); + lwm2m_firmware_set_update_result_inst(obj_inst_id, RESULT_OUT_OF_MEM); } else if (ret == -ENOSPC) { - lwm2m_firmware_set_update_result(obj_inst_id, RESULT_NO_STORAGE); + lwm2m_firmware_set_update_result_inst(obj_inst_id, RESULT_NO_STORAGE); /* Response 4.13 (RFC7959, section 2.9.3) */ /* TODO: should include size1 option to indicate max size */ ret = -EFBIG; } else if (ret == -EFAULT) { - lwm2m_firmware_set_update_result(obj_inst_id, RESULT_INTEGRITY_FAILED); + lwm2m_firmware_set_update_result_inst(obj_inst_id, RESULT_INTEGRITY_FAILED); } else if (ret == -ENOMSG) { - lwm2m_firmware_set_update_result(obj_inst_id, RESULT_UNSUP_FW); + lwm2m_firmware_set_update_result_inst(obj_inst_id, RESULT_UNSUP_FW); } else { - lwm2m_firmware_set_update_result(obj_inst_id, RESULT_UPDATE_FAILED); + lwm2m_firmware_set_update_result_inst(obj_inst_id, RESULT_UPDATE_FAILED); } return ret; @@ -261,17 +281,17 @@ static int package_uri_write_cb(uint16_t obj_inst_id, uint16_t res_id, LOG_DBG("PACKAGE_URI WRITE: %s", log_strdup(package_uri[obj_inst_id])); #ifdef CONFIG_LWM2M_FIRMWARE_UPDATE_PULL_SUPPORT - uint8_t state = lwm2m_firmware_get_update_state(obj_inst_id); + uint8_t state = lwm2m_firmware_get_update_state_inst(obj_inst_id); if (state == STATE_IDLE) { - lwm2m_firmware_set_update_result(obj_inst_id, RESULT_DEFAULT); + lwm2m_firmware_set_update_result_inst(obj_inst_id, RESULT_DEFAULT); if (data_len > 0) { lwm2m_firmware_start_transfer(obj_inst_id, package_uri[obj_inst_id]); } } else if (state == STATE_DOWNLOADED && data_len == 0U) { /* reset to state idle and result default */ - lwm2m_firmware_set_update_result(obj_inst_id, RESULT_DEFAULT); + lwm2m_firmware_set_update_result_inst(obj_inst_id, RESULT_DEFAULT); } return 0; @@ -307,20 +327,20 @@ static int firmware_update_cb(uint16_t obj_inst_id, uint8_t state; int ret; - state = lwm2m_firmware_get_update_state(obj_inst_id); + state = lwm2m_firmware_get_update_state_inst(obj_inst_id); if (state != STATE_DOWNLOADED) { LOG_ERR("State other than downloaded: %d", state); return -EPERM; } - lwm2m_firmware_set_update_state(obj_inst_id, STATE_UPDATING); + lwm2m_firmware_set_update_state_inst(obj_inst_id, STATE_UPDATING); callback = lwm2m_firmware_get_update_cb(); if (callback) { ret = callback(obj_inst_id, args, args_len); if (ret < 0) { LOG_ERR("Failed to update firmware: %d", ret); - lwm2m_firmware_set_update_result(obj_inst_id, + lwm2m_firmware_set_update_result_inst(obj_inst_id, ret == -EINVAL ? RESULT_INTEGRITY_FAILED : RESULT_UPDATE_FAILED); return 0; diff --git a/subsys/net/lib/lwm2m/lwm2m_obj_firmware_pull.c b/subsys/net/lib/lwm2m/lwm2m_obj_firmware_pull.c index f2349fcf6c7..ee685bfb3a7 100644 --- a/subsys/net/lib/lwm2m/lwm2m_obj_firmware_pull.c +++ b/subsys/net/lib/lwm2m/lwm2m_obj_firmware_pull.c @@ -21,7 +21,7 @@ static void set_update_result(uint16_t obj_inst_id, int error_code) int result; if (!error_code) { - lwm2m_firmware_set_update_state(STATE_DOWNLOADED); + lwm2m_firmware_set_update_state_inst(obj_inst_id, STATE_DOWNLOADED); return; } @@ -78,7 +78,7 @@ int lwm2m_firmware_start_transfer(uint16_t obj_inst_id, char *package_uri) return error_code; } - lwm2m_firmware_set_update_state(STATE_DOWNLOADING); + lwm2m_firmware_set_update_state_inst(obj_inst_id, STATE_DOWNLOADING); return 0; } From f2f087655bf53ce44554b9e3d96e70d3c86f24ec Mon Sep 17 00:00:00 2001 From: Jarno Lamsa Date: Tue, 4 Jan 2022 14:25:32 +0200 Subject: [PATCH 058/207] [nrf fromtree] net: lwm2m: Instance specific callbacks Provide possibility to have instance specific callbacks for writing the FW image and executing the update Signed-off-by: Jarno Lamsa --- include/net/lwm2m.h | 38 +++++++++++++++++++ subsys/net/lib/lwm2m/lwm2m_obj_firmware.c | 46 +++++++++++++++++------ 2 files changed, 73 insertions(+), 11 deletions(-) diff --git a/include/net/lwm2m.h b/include/net/lwm2m.h index 751d3d5fdcf..310fd6689fc 100644 --- a/include/net/lwm2m.h +++ b/include/net/lwm2m.h @@ -371,6 +371,25 @@ void lwm2m_firmware_set_write_cb(lwm2m_engine_set_data_cb_t cb); */ lwm2m_engine_set_data_cb_t lwm2m_firmware_get_write_cb(void); +/** + * @brief Set data callback for firmware block transfer. + * + * LwM2M clients use this function to register a callback for receiving the + * block transfer data when performing a firmware update. + * + * @param[in] obj_inst_id Object instance ID + * @param[in] cb A callback function to receive the block transfer data + */ +void lwm2m_firmware_set_write_cb_inst(uint16_t obj_inst_id, lwm2m_engine_set_data_cb_t cb); + +/** + * @brief Get the data callback for firmware block transfer writes. + * + * @param[in] obj_inst_id Object instance ID + * @return A registered callback function to receive the block transfer data + */ +lwm2m_engine_set_data_cb_t lwm2m_firmware_get_write_cb_inst(uint16_t obj_inst_id); + #if defined(CONFIG_LWM2M_FIRMWARE_UPDATE_PULL_SUPPORT) /** * @brief Set data callback to handle firmware update execute events. @@ -388,6 +407,25 @@ void lwm2m_firmware_set_update_cb(lwm2m_engine_execute_cb_t cb); * @return A registered callback function to receive the execute event. */ lwm2m_engine_execute_cb_t lwm2m_firmware_get_update_cb(void); + +/** + * @brief Set data callback to handle firmware update execute events. + * + * LwM2M clients use this function to register a callback for receiving the + * update resource "execute" operation on the LwM2M Firmware Update object. + * + * @param[in] obj_inst_id Object instance ID + * @param[in] cb A callback function to receive the execute event. + */ +void lwm2m_firmware_set_update_cb_inst(uint16_t obj_inst_id, lwm2m_engine_execute_cb_t cb); + +/** + * @brief Get the event callback for firmware update execute events. + * + * @param[in] obj_inst_id Object instance ID + * @return A registered callback function to receive the execute event. + */ +lwm2m_engine_execute_cb_t lwm2m_firmware_get_update_cb_inst(uint16_t obj_inst_id); #endif #endif diff --git a/subsys/net/lib/lwm2m/lwm2m_obj_firmware.c b/subsys/net/lib/lwm2m/lwm2m_obj_firmware.c index e0861a6752f..0f689c02cd0 100644 --- a/subsys/net/lib/lwm2m/lwm2m_obj_firmware.c +++ b/subsys/net/lib/lwm2m/lwm2m_obj_firmware.c @@ -77,8 +77,8 @@ static struct lwm2m_engine_obj_inst inst[MAX_INSTANCE_COUNT]; static struct lwm2m_engine_res res[MAX_INSTANCE_COUNT][FIRMWARE_MAX_ID]; static struct lwm2m_engine_res_inst res_inst[MAX_INSTANCE_COUNT][RESOURCE_INSTANCE_COUNT]; -static lwm2m_engine_set_data_cb_t write_cb; -static lwm2m_engine_execute_cb_t update_cb; +static lwm2m_engine_set_data_cb_t write_cb[MAX_INSTANCE_COUNT]; +static lwm2m_engine_execute_cb_t update_cb[MAX_INSTANCE_COUNT]; #ifdef CONFIG_LWM2M_FIRMWARE_UPDATE_PULL_SUPPORT extern int lwm2m_firmware_start_transfer(uint16_t obj_inst_id, char *package_uri); @@ -228,7 +228,8 @@ static int package_write_cb(uint16_t obj_inst_id, uint16_t res_id, bool last_block, size_t total_size) { uint8_t state; - int ret; + int ret = 0; + lwm2m_engine_set_data_cb_t callback; state = lwm2m_firmware_get_update_state_inst(obj_inst_id); if (state == STATE_IDLE) { @@ -247,9 +248,12 @@ static int package_write_cb(uint16_t obj_inst_id, uint16_t res_id, return -EPERM; } - ret = write_cb ? write_cb(obj_inst_id, res_id, res_inst_id, - data, data_len, - last_block, total_size) : 0; + callback = lwm2m_firmware_get_write_cb_inst(obj_inst_id); + if (callback) { + ret = callback(obj_inst_id, res_id, res_inst_id, + data, data_len, last_block, total_size); + } + if (ret >= 0) { if (last_block) { lwm2m_firmware_set_update_state_inst(obj_inst_id, STATE_DOWNLOADED); @@ -302,22 +306,42 @@ static int package_uri_write_cb(uint16_t obj_inst_id, uint16_t res_id, void lwm2m_firmware_set_write_cb(lwm2m_engine_set_data_cb_t cb) { - write_cb = cb; + lwm2m_firmware_set_write_cb_inst(0, cb); } lwm2m_engine_set_data_cb_t lwm2m_firmware_get_write_cb(void) { - return write_cb; + return lwm2m_firmware_get_write_cb_inst(0); } void lwm2m_firmware_set_update_cb(lwm2m_engine_execute_cb_t cb) { - update_cb = cb; + lwm2m_firmware_set_update_cb_inst(0, cb); } lwm2m_engine_execute_cb_t lwm2m_firmware_get_update_cb(void) { - return update_cb; + return lwm2m_firmware_get_update_cb_inst(0); +} + +void lwm2m_firmware_set_write_cb_inst(uint16_t obj_inst_id, lwm2m_engine_set_data_cb_t cb) +{ + write_cb[obj_inst_id] = cb; +} + +lwm2m_engine_set_data_cb_t lwm2m_firmware_get_write_cb_inst(uint16_t obj_inst_id) +{ + return write_cb[obj_inst_id]; +} + +void lwm2m_firmware_set_update_cb_inst(uint16_t obj_inst_id, lwm2m_engine_execute_cb_t cb) +{ + update_cb[obj_inst_id] = cb; +} + +lwm2m_engine_execute_cb_t lwm2m_firmware_get_update_cb_inst(uint16_t obj_inst_id) +{ + return update_cb[obj_inst_id]; } static int firmware_update_cb(uint16_t obj_inst_id, @@ -335,7 +359,7 @@ static int firmware_update_cb(uint16_t obj_inst_id, lwm2m_firmware_set_update_state_inst(obj_inst_id, STATE_UPDATING); - callback = lwm2m_firmware_get_update_cb(); + callback = lwm2m_firmware_get_update_cb_inst(obj_inst_id); if (callback) { ret = callback(obj_inst_id, args, args_len); if (ret < 0) { From 0b95ec897285dd71ee7122ba098fc3a175d3bf0a Mon Sep 17 00:00:00 2001 From: Jarno Lamsa Date: Fri, 28 Jan 2022 08:24:11 +0200 Subject: [PATCH 059/207] [nrf fromtree] net: lib: lwm2m: Add missing function declarations Get-function declarations for fw update state and result were missing from the engine header. Signed-off-by: Jarno Lamsa --- subsys/net/lib/lwm2m/lwm2m_engine.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/subsys/net/lib/lwm2m/lwm2m_engine.h b/subsys/net/lib/lwm2m/lwm2m_engine.h index f01ce3e1ff0..e33b307cb35 100644 --- a/subsys/net/lib/lwm2m/lwm2m_engine.h +++ b/subsys/net/lib/lwm2m/lwm2m_engine.h @@ -132,6 +132,10 @@ void lwm2m_firmware_set_update_state_inst(uint16_t obj_inst_id, uint8_t state); void lwm2m_firmware_set_update_result_inst(uint16_t obj_inst_id, uint8_t result); void lwm2m_firmware_set_update_state(uint8_t state); void lwm2m_firmware_set_update_result(uint8_t result); +uint8_t lwm2m_firmware_get_update_state_inst(uint16_t obj_inst_id); +uint8_t lwm2m_firmware_get_update_state(void); +uint8_t lwm2m_firmware_get_update_result_inst(uint16_t obj_inst_id); +uint8_t lwm2m_firmware_get_update_result(void); #endif /* Attribute handling. */ From b77b23f9a40e7d98c60e86b56595be15d92e56bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20G=C5=82=C4=85bek?= Date: Wed, 12 Jan 2022 08:16:37 +0100 Subject: [PATCH 060/207] [nrf fromtree] drivers: flash: nrf_qspi_nor: Fix setting of the base clock divider MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On nRF53 Series SoCs, the highest SCK frequencies can only be achieved when the HFCLK192M clock divider is changed from the default /4 setting. Such change results in increased power consumption, so the divider needs to be changed only for periods when it is actually necessary. This commit modifies the driver behavior so that it changes the divider only when a QSPI bus operation is performed. However, when XIP accesses to the flash chip are also used, it may be needed to keep the divider changed even when the driver is idle so that the XIP access speed is not reduced, hence a custom API function that allows forcing this is introduced for the driver. Signed-off-by: Andrzej Głąbek (cherry picked from commit aa3b86600db65873cd83a63de873b3414a9a564d) (cherry picked from commit fced0776d8d68e92a550b33be02e23beff4166fe) --- drivers/flash/nrf_qspi_nor.c | 132 ++++++++++++++++++++++++--- include/drivers/flash/nrf_qspi_nor.h | 40 ++++++++ 2 files changed, 157 insertions(+), 15 deletions(-) create mode 100644 include/drivers/flash/nrf_qspi_nor.h diff --git a/drivers/flash/nrf_qspi_nor.c b/drivers/flash/nrf_qspi_nor.c index ea60a5806e0..9ed6dd18ac6 100644 --- a/drivers/flash/nrf_qspi_nor.c +++ b/drivers/flash/nrf_qspi_nor.c @@ -38,6 +38,9 @@ struct qspi_nor_data { */ volatile bool ready; #endif /* CONFIG_MULTITHREADING */ +#if defined(CONFIG_SOC_SERIES_NRF53X) + bool keep_base_clock_div_set; +#endif }; struct qspi_nor_config { @@ -57,10 +60,63 @@ struct qspi_nor_config { /* instance 0 flash size in bytes */ #define INST_0_BYTES (DT_INST_PROP(0, size) / 8) +/* + * Determine a configuration value (INST_0_SCK_CFG) to be used to achieve the + * SCK frequency specified in DT and, if needed, a divider (BASE_CLOCK_DIV) for + * the clock from which the SCK frequency is derived. + */ #define INST_0_SCK_FREQUENCY DT_INST_PROP(0, sck_frequency) BUILD_ASSERT(INST_0_SCK_FREQUENCY >= (NRF_QSPI_BASE_CLOCK_FREQ / 16), "Unsupported SCK frequency."); +#if defined(CONFIG_SOC_SERIES_NRF53X) +/* + * On nRF53 Series SoCs, the highest SCK frequencies can only be achieved + * when the HFCLK192M clock divider is changed from the default /4 setting. + * Such change results in increased power consumption, so the divider needs + * to be changed only for periods when it is actually needed. + */ +#if (INST_0_SCK_FREQUENCY >= NRF_QSPI_BASE_CLOCK_FREQ) +/* Use HFCLK192M / 1 / (2*1) = 96 MHz */ +#define BASE_CLOCK_DIV NRF_CLOCK_HFCLK_DIV_1 +#define INST_0_SCK_CFG NRF_QSPI_FREQ_DIV1 +#elif (INST_0_SCK_FREQUENCY >= (NRF_QSPI_BASE_CLOCK_FREQ / 2)) +/* Use HFCLK192M / 2 / (2*1) = 48 MHz */ +#define BASE_CLOCK_DIV NRF_CLOCK_HFCLK_DIV_2 +#define INST_0_SCK_CFG NRF_QSPI_FREQ_DIV1 +#elif (INST_0_SCK_FREQUENCY >= (NRF_QSPI_BASE_CLOCK_FREQ / 3)) +/* Use HFCLK192M / 1 / (2*3) = 32 MHz */ +#define BASE_CLOCK_DIV NRF_CLOCK_HFCLK_DIV_1 +#define INST_0_SCK_CFG NRF_QSPI_FREQ_DIV3 +#elif (INST_0_SCK_FREQUENCY >= (NRF_QSPI_BASE_CLOCK_FREQ / 4)) +/* Use HFCLK192M / 4 / (2*1) = 24 MHz */ +/* BASE_CLOCK_DIV not defined => the default NRF_CLOCK_HFCLK_DIV_4 is used. */ +#define INST_0_SCK_CFG NRF_QSPI_FREQ_DIV1 +#elif (INST_0_SCK_FREQUENCY >= (NRF_QSPI_BASE_CLOCK_FREQ / 6)) +/* Use HFCLK192M / 2 / (2*3) = 16 MHz */ +#define BASE_CLOCK_DIV NRF_CLOCK_HFCLK_DIV_2 +#define INST_0_SCK_CFG NRF_QSPI_FREQ_DIV3 +#else +/* BASE_CLOCK_DIV not defined => the default NRF_CLOCK_HFCLK_DIV_4 is used. */ +#define INST_0_SCK_CFG (ceiling_fraction(NRF_QSPI_BASE_CLOCK_FREQ / 4, \ + INST_0_SCK_FREQUENCY) - 1) +#endif + +#else +/* + * On nRF52 Series SoCs, the base clock divider is not configurable, + * so BASE_CLOCK_DIV is not defined. + */ +#if (INST_0_SCK_FREQUENCY >= NRF_QSPI_BASE_CLOCK_FREQ) +#define INST_0_SCK_CFG NRF_QSPI_FREQ_DIV1 +#else +#define INST_0_SCK_CFG (ceiling_fraction(NRF_QSPI_BASE_CLOCK_FREQ, \ + INST_0_SCK_FREQUENCY) - 1) + +#endif + +#endif /* defined(CONFIG_SOC_SERIES_NRF53X) */ + /* 0 for MODE0 (CPOL=0, CPHA=0), 1 for MODE3 (CPOL=1, CPHA=1). */ #define INST_0_SPI_MODE DT_INST_PROP(0, cpol) BUILD_ASSERT(DT_INST_PROP(0, cpol) == DT_INST_PROP(0, cpha), @@ -152,24 +208,42 @@ static inline int qspi_get_zephyr_ret_code(nrfx_err_t res) static inline void qspi_lock(const struct device *dev) { -#ifdef CONFIG_MULTITHREADING struct qspi_nor_data *dev_data = dev->data; +#ifdef CONFIG_MULTITHREADING k_sem_take(&dev_data->sem, K_FOREVER); #else /* CONFIG_MULTITHREADING */ - ARG_UNUSED(dev); + ARG_UNUSED(dev_data); #endif /* CONFIG_MULTITHREADING */ + + /* + * If the base clock divider needs to be changed, change it only + * for the time the driver is locked to perform a QSPI operation, + * unless the divider is forced to be kept set permanently. + */ +#if defined(BASE_CLOCK_DIV) + if (!dev_data->keep_base_clock_div_set) { + nrf_clock_hfclk192m_div_set(NRF_CLOCK, BASE_CLOCK_DIV); + } +#endif } static inline void qspi_unlock(const struct device *dev) { -#ifdef CONFIG_MULTITHREADING struct qspi_nor_data *dev_data = dev->data; +#if defined(BASE_CLOCK_DIV) + /* Restore the default base clock divider, unless instructed not to. */ + if (!dev_data->keep_base_clock_div_set) { + nrf_clock_hfclk192m_div_set(NRF_CLOCK, NRF_CLOCK_HFCLK_DIV_4); + } +#endif + +#ifdef CONFIG_MULTITHREADING k_sem_give(&dev_data->sem); -#else /* CONFIG_MULTITHREADING */ - ARG_UNUSED(dev); -#endif /* CONFIG_MULTITHREADING */ +#else + ARG_UNUSED(dev_data); +#endif } static inline void qspi_trans_lock(const struct device *dev) @@ -975,11 +1049,8 @@ static int qspi_nor_configure(const struct device *dev) static int qspi_nor_init(const struct device *dev) { #if defined(CONFIG_SOC_SERIES_NRF53X) - /* Make sure the PCLK192M clock, from which the SCK frequency is - * derived, is not prescaled (the default setting after reset is - * "divide by 4"). - */ - nrf_clock_hfclk192m_div_set(NRF_CLOCK, NRF_CLOCK_HFCLK_DIV_1); + /* Make sure the default /4 divider is set initially. */ + nrf_clock_hfclk192m_div_set(NRF_CLOCK, NRF_CLOCK_HFCLK_DIV_4); #endif IRQ_CONNECT(DT_IRQN(QSPI_NODE), DT_IRQ(QSPI_NODE, priority), @@ -1142,6 +1213,40 @@ static int qspi_nor_pm_action(const struct device *dev, } #endif /* CONFIG_PM_DEVICE */ +void z_impl_nrf_qspi_nor_base_clock_div_force(const struct device *dev, + bool force) +{ +#if defined(BASE_CLOCK_DIV) + struct qspi_nor_data *dev_data = dev->data; + /* + * The divider is normally changed, unless the flag is set, only for + * periods when the driver is locked, so the flag itself also can only + * be modified while the driver is locked. + */ + qspi_lock(dev); + dev_data->keep_base_clock_div_set = force; + qspi_unlock(dev); +#else + ARG_UNUSED(dev); + ARG_UNUSED(force); +#endif +} + +#ifdef CONFIG_USERSPACE +#include + +void z_vrfy_nrf_qspi_nor_base_clock_div_force(const struct device *dev, + bool force) +{ + Z_OOPS(Z_SYSCALL_SPECIFIC_DRIVER(dev, K_OBJ_DRIVER_FLASH, + &qspi_nor_api)); + + z_impl_nrf_qspi_nor_base_clock_div_force(dev, force); +} + +#include +#endif /* CONFIG_USERSPACE */ + static struct qspi_nor_data qspi_nor_dev_data = { #ifdef CONFIG_MULTITHREADING .trans = Z_SEM_INITIALIZER(qspi_nor_dev_data.trans, 1, 1), @@ -1183,10 +1288,7 @@ static const struct qspi_nor_config qspi_nor_dev_config = { : NRF_QSPI_ADDRMODE_24BIT, }, .nrfx_cfg.phy_if = { - .sck_freq = (INST_0_SCK_FREQUENCY > NRF_QSPI_BASE_CLOCK_FREQ) - ? NRF_QSPI_FREQ_DIV1 - : (NRF_QSPI_BASE_CLOCK_FREQ / - INST_0_SCK_FREQUENCY) - 1, + .sck_freq = INST_0_SCK_CFG, .sck_delay = DT_INST_PROP(0, sck_delay), .spi_mode = INST_0_SPI_MODE, }, diff --git a/include/drivers/flash/nrf_qspi_nor.h b/include/drivers/flash/nrf_qspi_nor.h new file mode 100644 index 00000000000..8eb56acfef0 --- /dev/null +++ b/include/drivers/flash/nrf_qspi_nor.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2022 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef __ZEPHYR_INCLUDE_DRIVERS_FLASH_NRF_QSPI_NOR_H__ +#define __ZEPHYR_INCLUDE_DRIVERS_FLASH_NRF_QSPI_NOR_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Specifies whether the QSPI base clock divider should be kept set + * when the driver is idle + * + * On nRF53 Series SoCs, it is necessary to change the default base clock + * divider to achieve the highest possible SCK frequencies. This divider + * should be changed only for periods when it is actually needed, as such + * configuration significantly increases power consumption, so the driver + * normally does this only when it performs an operation on the QSPI bus. + * But when XIP accesses to the flash chip are also used, and the driver + * is not aware of those, it may be necessary for the divider to be kept + * changed also when the driver is idle. This function allows forcing this. + * + * @param dev flash device + * @param force if true, forces the base clock divider to be kept set even + * when the driver is idle + */ +__syscall void nrf_qspi_nor_base_clock_div_force(const struct device *dev, + bool force); + +#ifdef __cplusplus +} +#endif + +#include + +#endif /* __ZEPHYR_INCLUDE_DRIVERS_FLASH_NRF_QSPI_NOR_H__ */ From e73ddb024d059d9437167c3b708f0f9a17c4b4bf Mon Sep 17 00:00:00 2001 From: Maciej Perkowski Date: Fri, 28 Jan 2022 12:02:58 +0100 Subject: [PATCH 061/207] [nrf noup] action: clang: parallel execution Bring back parallel execution to the clang action. In the upstream they went to use a single dedicated powerfull agent to run this. We need to keep this as we have to base on agents available in github's cloud. Signed-off-by: Maciej Perkowski (cherry picked from commit f0876d46f0fc6c48a0e9dbecfe02001d7c5d355f) --- .github/workflows/clang.yaml | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/.github/workflows/clang.yaml b/.github/workflows/clang.yaml index 5732e6f492c..4b7bb7ab7d3 100644 --- a/.github/workflows/clang.yaml +++ b/.github/workflows/clang.yaml @@ -21,12 +21,13 @@ jobs: strategy: fail-fast: false matrix: - platform: ["native_posix"] + subset: [1, 2, 3, 4, 5] env: ZEPHYR_SDK_INSTALL_DIR: /opt/toolchains/zephyr-sdk-0.13.2 CLANG_ROOT_DIR: /usr/lib/llvm-12 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: @@ -81,7 +82,7 @@ jobs: id: cache-ccache uses: nashif/action-s3-cache@master 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/.ccache aws-s3-bucket: ccache.zephyrproject.org aws-access-key-id: ${{ secrets.CCACHE_S3_ACCESS_KEY_ID }} @@ -94,21 +95,29 @@ jobs: test -d github/home/.ccache && rm -rf /github/home/.ccache && mv github/home/.ccache /github/home/.ccache ccache -M 10G -s - - name: Run Tests with Twister + - name: Build test plan with Twister working-directory: ./zephyr - id: 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 --platform ${{ matrix.platform }} -c origin/${BASE_REF}.. + python3 ./scripts/ci/test_plan.py -p native_posix -c origin/${BASE_REF}.. + + + - name: Run Tests with Twister + working-directory: ./zephyr + id: twister + run: | + export ZEPHYR_BASE=${PWD} + export ZEPHYR_TOOLCHAIN_VARIANT=llvm # We can limit scope to just what has changed if [ -s testplan.csv ]; then echo "::set-output name=report_needed::1"; # Full twister but with options based on changes - ./scripts/twister --inline-logs -M -N -v --load-tests testplan.csv --retry-failed 2 + ./scripts/twister --inline-logs -M -N -v --load-tests testplan.csv --retry-failed 2 --subset ${{matrix.subset}}/${MATRIX_SIZE} else # if nothing is run, skip reporting step echo "::set-output name=report_needed::0"; @@ -123,7 +132,7 @@ jobs: if: always() && steps.twister.outputs.report_needed != 0 uses: actions/upload-artifact@v2 with: - name: Unit Test Results (Subset ${{ matrix.platform }}) + name: Unit Test Results (Subset ${{ matrix.subset }}) path: zephyr/twister-out/twister.xml clang-build-results: From fa80b20cd575277669a6bdabe03f9e993df2d6b7 Mon Sep 17 00:00:00 2001 From: Andrzej Kuros Date: Tue, 1 Feb 2022 12:40:37 +0100 Subject: [PATCH 062/207] [nrf fromlist] modules: hal_nordic: nrf_802154_irq ZLI support Parameter `prio` of `nrf_802154_irq_init` is now allowed to have negative value what means use of ZLI priority or highest possible priority if ZLIs are disabled. Zephyr PR: https://github.com/zephyrproject-rtos/zephyr/pull/42355 Signed-off-by: Andrzej Kuros (cherry picked from commit d143ae93cabf2979b4bc3d049145e108a7d7adcf) --- .../sl_opensource/platform/nrf_802154_irq_zephyr.c | 11 +++++++++-- west.yml | 2 +- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/modules/hal_nordic/nrf_802154/sl_opensource/platform/nrf_802154_irq_zephyr.c b/modules/hal_nordic/nrf_802154/sl_opensource/platform/nrf_802154_irq_zephyr.c index 1a3bf443724..9341d3b61ad 100644 --- a/modules/hal_nordic/nrf_802154/sl_opensource/platform/nrf_802154_irq_zephyr.c +++ b/modules/hal_nordic/nrf_802154/sl_opensource/platform/nrf_802154_irq_zephyr.c @@ -9,9 +9,16 @@ #include #include -void nrf_802154_irq_init(uint32_t irqn, uint32_t prio, nrf_802154_isr_t isr) +void nrf_802154_irq_init(uint32_t irqn, int32_t prio, nrf_802154_isr_t isr) { - irq_connect_dynamic(irqn, prio, isr, NULL, 0); + uint32_t flags = 0U; + + if (prio < 0) { + prio = 0; + flags |= IRQ_ZERO_LATENCY; + } + + irq_connect_dynamic(irqn, prio, isr, NULL, flags); } void nrf_802154_irq_enable(uint32_t irqn) diff --git a/west.yml b/west.yml index 0309df68db8..099a5fd4765 100644 --- a/west.yml +++ b/west.yml @@ -88,7 +88,7 @@ manifest: groups: - hal - name: hal_nordic - revision: a42b016d7c7610489f5f8c79773fedc05ba352ee + revision: b1db86f188c3c5864985e1bd18a849d53f1c0a2d path: modules/hal/nordic groups: - hal From 9891c592b6bf2b45a20c1df56d32c873207d5c69 Mon Sep 17 00:00:00 2001 From: Joakim Andersson Date: Mon, 22 Nov 2021 16:46:53 +0100 Subject: [PATCH 063/207] [nrf fromtree] drivers: clock_control: Remove unused header file Remove unused header file nrf_gpio.h which is not used by the clock control driver. Signed-off-by: Joakim Andersson (cherry picked from commit d8dd0ed9121f061279bca50088ff3538a6431683) (cherry picked from commit 23e7d5b75198cfcd79b34fbe92beeee5d5af0d10) --- drivers/clock_control/clock_control_nrf.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/clock_control/clock_control_nrf.c b/drivers/clock_control/clock_control_nrf.c index 2712e8f4393..04dfe1c65c0 100644 --- a/drivers/clock_control/clock_control_nrf.c +++ b/drivers/clock_control/clock_control_nrf.c @@ -14,11 +14,6 @@ #include #include -#if defined(CONFIG_SOC_NRF5340_CPUAPP) && \ - !defined(CONFIG_TRUSTED_EXECUTION_NONSECURE) -#include -#endif - LOG_MODULE_REGISTER(clock_control, CONFIG_CLOCK_CONTROL_LOG_LEVEL); #define DT_DRV_COMPAT nordic_nrf_clock From 0f676ee3304c06fce90b263d755586d1771afbd6 Mon Sep 17 00:00:00 2001 From: Joakim Andersson Date: Mon, 22 Nov 2021 16:53:04 +0100 Subject: [PATCH 064/207] [nrf fromtree] modules: trusted-firmware-m: Use TF-M install headers ... ... as interface Use the set of headers that the TF-M build system places in the install output. Not all public header files are available in the interface/include directory and the TF-M build system uses the install mechanism of cmake to include additional headers based on platform or configuration. Signed-off-by: Joakim Andersson (cherry picked from commit 17f8932f160f80ad5a1ae67bf866dc51c741ca25) (cherry picked from commit 685236c6918c153803d1484885f2a262c9fd2a72) --- modules/trusted-firmware-m/CMakeLists.txt | 2 +- samples/tfm_integration/psa_crypto/CMakeLists.txt | 2 +- .../tfm_integration/psa_protected_storage/CMakeLists.txt | 2 +- samples/tfm_integration/tfm_ipc/CMakeLists.txt | 2 +- samples/tfm_integration/tfm_psa_test/CMakeLists.txt | 2 +- .../tfm_integration/tfm_secure_partition/CMakeLists.txt | 2 +- tests/arch/arm/arm_thread_swap_tz/CMakeLists.txt | 8 +++++--- 7 files changed, 11 insertions(+), 9 deletions(-) diff --git a/modules/trusted-firmware-m/CMakeLists.txt b/modules/trusted-firmware-m/CMakeLists.txt index 8845fa01409..fc38df1f0cd 100644 --- a/modules/trusted-firmware-m/CMakeLists.txt +++ b/modules/trusted-firmware-m/CMakeLists.txt @@ -322,7 +322,7 @@ if (CONFIG_BUILD_WITH_TFM) ) target_include_directories(tfm_api PRIVATE - ${ZEPHYR_TRUSTED_FIRMWARE_M_MODULE_DIR}/interface/include + ${TFM_BINARY_DIR}/install/interface/include ) zephyr_library_link_libraries( diff --git a/samples/tfm_integration/psa_crypto/CMakeLists.txt b/samples/tfm_integration/psa_crypto/CMakeLists.txt index b4461a027de..17339b470b8 100644 --- a/samples/tfm_integration/psa_crypto/CMakeLists.txt +++ b/samples/tfm_integration/psa_crypto/CMakeLists.txt @@ -16,7 +16,7 @@ target_sources(app PRIVATE src/util_app_log.c) target_sources(app PRIVATE src/util_sformat.c) target_include_directories(app PRIVATE - ${ZEPHYR_TRUSTED_FIRMWARE_M_MODULE_DIR}/interface/include + $/install/interface/include ) # In TF-M, default value of CRYPTO_ENGINE_BUF_SIZE is 0x2080. It causes diff --git a/samples/tfm_integration/psa_protected_storage/CMakeLists.txt b/samples/tfm_integration/psa_protected_storage/CMakeLists.txt index 40bfae3263a..bbb8a2041fd 100644 --- a/samples/tfm_integration/psa_protected_storage/CMakeLists.txt +++ b/samples/tfm_integration/psa_protected_storage/CMakeLists.txt @@ -13,5 +13,5 @@ project(protected_storage) target_sources(app PRIVATE src/main.c) target_include_directories(app PRIVATE - ${ZEPHYR_TRUSTED_FIRMWARE_M_MODULE_DIR}/interface/include + $/install/interface/include ) diff --git a/samples/tfm_integration/tfm_ipc/CMakeLists.txt b/samples/tfm_integration/tfm_ipc/CMakeLists.txt index 0ac1e79b48f..f11b67af843 100644 --- a/samples/tfm_integration/tfm_ipc/CMakeLists.txt +++ b/samples/tfm_integration/tfm_ipc/CMakeLists.txt @@ -9,5 +9,5 @@ project(tfm_ipc) target_sources(app PRIVATE src/main.c) target_include_directories(app PRIVATE - ${ZEPHYR_TRUSTED_FIRMWARE_M_MODULE_DIR}/interface/include + $/install/interface/include ) diff --git a/samples/tfm_integration/tfm_psa_test/CMakeLists.txt b/samples/tfm_integration/tfm_psa_test/CMakeLists.txt index 080bfeb0231..9dcbf12ae64 100644 --- a/samples/tfm_integration/tfm_psa_test/CMakeLists.txt +++ b/samples/tfm_integration/tfm_psa_test/CMakeLists.txt @@ -13,5 +13,5 @@ project(tfm_psa_storage_test) target_sources(app PRIVATE src/main.c) target_include_directories(app PRIVATE - ${ZEPHYR_TRUSTED_FIRMWARE_M_MODULE_DIR}/interface/include + $/install/interface/include ) diff --git a/samples/tfm_integration/tfm_secure_partition/CMakeLists.txt b/samples/tfm_integration/tfm_secure_partition/CMakeLists.txt index 636ba5f1c19..262ac042c74 100644 --- a/samples/tfm_integration/tfm_secure_partition/CMakeLists.txt +++ b/samples/tfm_integration/tfm_secure_partition/CMakeLists.txt @@ -28,7 +28,7 @@ target_sources(app PRIVATE ) target_include_directories(app PRIVATE - ${ZEPHYR_TRUSTED_FIRMWARE_M_MODULE_DIR}/interface/include + $/install/interface/include ) target_compile_definitions(app diff --git a/tests/arch/arm/arm_thread_swap_tz/CMakeLists.txt b/tests/arch/arm/arm_thread_swap_tz/CMakeLists.txt index 56231233c97..93e91deafcb 100644 --- a/tests/arch/arm/arm_thread_swap_tz/CMakeLists.txt +++ b/tests/arch/arm/arm_thread_swap_tz/CMakeLists.txt @@ -12,6 +12,8 @@ project(NONE) FILE(GLOB app_sources src/*.c) target_sources(app PRIVATE ${app_sources}) -target_include_directories(app PRIVATE - ${ZEPHYR_TRUSTED_FIRMWARE_M_MODULE_DIR}/interface/include -) +if (CONFIG_BUILD_WITH_TFM) + target_include_directories(app PRIVATE + $/install/interface/include + ) +endif() From 40a059eb047f0eadfad714330a788be1873d0908 Mon Sep 17 00:00:00 2001 From: Joakim Andersson Date: Tue, 23 Nov 2021 15:54:59 +0100 Subject: [PATCH 065/207] [nrf fromtree] soc: nrf53: Add handling of secure-only code in init ... ... with TFM enabled Add handling of secure-only code with TF-M enabled that can only be done from secure processing environment. Signed-off-by: Joakim Andersson (cherry picked from commit aef46a8e5130c81174a2b80d557a48171bffd6d0) (cherry picked from commit eec801b2aa4cd7b94f065d0a70bd247792af73fd) --- soc/arm/nordic_nrf/nrf53/CMakeLists.txt | 6 +++ soc/arm/nordic_nrf/nrf53/Kconfig.soc | 10 +++-- soc/arm/nordic_nrf/nrf53/soc.c | 23 +++++++---- soc/arm/nordic_nrf/nrf53/soc_secure.h | 53 +++++++++++++++++++++++++ west.yml | 2 +- 5 files changed, 83 insertions(+), 11 deletions(-) create mode 100644 soc/arm/nordic_nrf/nrf53/soc_secure.h diff --git a/soc/arm/nordic_nrf/nrf53/CMakeLists.txt b/soc/arm/nordic_nrf/nrf53/CMakeLists.txt index c9799cf9ae6..6d99e1ce016 100644 --- a/soc/arm/nordic_nrf/nrf53/CMakeLists.txt +++ b/soc/arm/nordic_nrf/nrf53/CMakeLists.txt @@ -7,3 +7,9 @@ zephyr_sources( zephyr_library_sources_ifdef(CONFIG_PM power.c ) + +if (CONFIG_BUILD_WITH_TFM) + zephyr_library_include_directories( + $/install/interface/include + ) +endif() diff --git a/soc/arm/nordic_nrf/nrf53/Kconfig.soc b/soc/arm/nordic_nrf/nrf53/Kconfig.soc index f1a2cbf71dc..b25a037aa5c 100644 --- a/soc/arm/nordic_nrf/nrf53/Kconfig.soc +++ b/soc/arm/nordic_nrf/nrf53/Kconfig.soc @@ -146,7 +146,7 @@ config SOC_DCDC_NRF53X_HV help Enable nRF53 series System on Chip High Voltage DC/DC converter. -if !TRUSTED_EXECUTION_NONSECURE +if !TRUSTED_EXECUTION_NONSECURE || BUILD_WITH_TFM config SOC_ENABLE_LFXO bool "Enable LFXO" @@ -208,14 +208,14 @@ config SOC_HFXO_CAP_INT_VALUE_X2 capacitance value for the two capacitors. Set it to 14 to get 7.0 pF for each capacitor, 15 to get 7.5 pF, and so on. -endif # !TRUSTED_EXECUTION_NONSECURE +endif # !TRUSTED_EXECUTION_NONSECURE || BUILD_WITH_TFM endif # SOC_NRF5340_CPUAPP config NRF_ENABLE_CACHE bool "Enable cache" - depends on (SOC_NRF5340_CPUAPP && !TRUSTED_EXECUTION_NONSECURE) \ + depends on (SOC_NRF5340_CPUAPP && (!TRUSTED_EXECUTION_NONSECURE || BUILD_WITH_TFM)) \ || SOC_NRF5340_CPUNET default y help @@ -224,3 +224,7 @@ config NRF_ENABLE_CACHE Instruction cache only (I-Cache) is available in nRF5340 CPUNET (Network MCU). + +config BUILD_WITH_TFM + # TF-M nRF53 platform enables the cache unconditionally. + select NRF_ENABLE_CACHE if SOC_NRF5340_CPUAPP diff --git a/soc/arm/nordic_nrf/nrf53/soc.c b/soc/arm/nordic_nrf/nrf53/soc.c index 7fd1bc9858a..ad01036b6ed 100644 --- a/soc/arm/nordic_nrf/nrf53/soc.c +++ b/soc/arm/nordic_nrf/nrf53/soc.c @@ -26,6 +26,7 @@ #elif defined(CONFIG_SOC_NRF5340_CPUNET) #include #endif +#include #define PIN_XL1 0 #define PIN_XL2 1 @@ -57,14 +58,18 @@ static int nordicsemi_nrf53_init(const struct device *arg) key = irq_lock(); #if defined(CONFIG_SOC_NRF5340_CPUAPP) && defined(CONFIG_NRF_ENABLE_CACHE) - /* Enable the instruction & data cache */ +#if !defined(CONFIG_BUILD_WITH_TFM) + /* Enable the instruction & data cache. + * This can only be done from secure code. + * This is handled by the TF-M platform so we skip it when TF-M is + * enabled. + */ nrf_cache_enable(NRF_CACHE); +#endif #elif defined(CONFIG_SOC_NRF5340_CPUNET) && defined(CONFIG_NRF_ENABLE_CACHE) nrf_nvmc_icache_config_set(NRF_NVMC, NRF_NVMC_ICACHE_ENABLE); #endif -#if defined(CONFIG_SOC_NRF5340_CPUAPP) && \ - !defined(CONFIG_TRUSTED_EXECUTION_NONSECURE) #if defined(CONFIG_SOC_ENABLE_LFXO) nrf_oscillators_lfxo_cap_set(NRF_OSCILLATORS, IS_ENABLED(CONFIG_SOC_LFXO_CAP_INT_6PF) ? @@ -74,13 +79,18 @@ static int nordicsemi_nrf53_init(const struct device *arg) IS_ENABLED(CONFIG_SOC_LFXO_CAP_INT_9PF) ? NRF_OSCILLATORS_LFXO_CAP_9PF : NRF_OSCILLATORS_LFXO_CAP_EXTERNAL); - /* This can only be done from secure code. */ +#if !defined(CONFIG_BUILD_WITH_TFM) + /* This can only be done from secure code. + * This is handled by the TF-M platform so we skip it when TF-M is + * enabled. + */ nrf_gpio_pin_mcu_select(PIN_XL1, NRF_GPIO_PIN_MCUSEL_PERIPHERAL); nrf_gpio_pin_mcu_select(PIN_XL2, NRF_GPIO_PIN_MCUSEL_PERIPHERAL); -#endif +#endif /* !defined(CONFIG_BUILD_WITH_TFM) */ +#endif /* defined(CONFIG_SOC_ENABLE_LFXO) */ #if defined(CONFIG_SOC_HFXO_CAP_INTERNAL) /* This register is only accessible from secure code. */ - uint32_t xosc32mtrim = NRF_FICR->XOSC32MTRIM; + uint32_t xosc32mtrim = soc_secure_read_xosc32mtrim(); /* As specified in the nRF5340 PS: * CAPVALUE = (((FICR->XOSC32MTRIM.SLOPE+56)*(CAPACITANCE*2-14)) * +((FICR->XOSC32MTRIM.OFFSET-8)<<4)+32)>>6; @@ -99,7 +109,6 @@ static int nordicsemi_nrf53_init(const struct device *arg) #elif defined(CONFIG_SOC_HFXO_CAP_EXTERNAL) nrf_oscillators_hfxo_cap_set(NRF_OSCILLATORS, false, 0); #endif -#endif /* defined(CONFIG_SOC_NRF5340_CPUAPP) && ... */ #if defined(CONFIG_SOC_DCDC_NRF53X_APP) nrf_regulators_dcdcen_set(NRF_REGULATORS, true); diff --git a/soc/arm/nordic_nrf/nrf53/soc_secure.h b/soc/arm/nordic_nrf/nrf53/soc_secure.h new file mode 100644 index 00000000000..e6d9bce235b --- /dev/null +++ b/soc/arm/nordic_nrf/nrf53/soc_secure.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2019 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include + +#if defined(CONFIG_SOC_NRF5340_CPUAPP) +#if defined(CONFIG_BUILD_WITH_TFM) +/* Use TF-M platform services */ +#include "tfm_ioctl_api.h" +#include "hal/nrf_gpio.h" + +static inline void soc_secure_gpio_pin_mcu_select(uint32_t pin_number, nrf_gpio_pin_mcusel_t mcu) +{ + uint32_t result; + enum tfm_platform_err_t err; + + err = tfm_platform_gpio_pin_mcu_select(pin_number, mcu, &result); + __ASSERT(err == TFM_PLATFORM_ERR_SUCCESS, "TFM platform error (%d)", err); + __ASSERT(result == 0, "GPIO service error (%d)", result); +} + +#if defined(CONFIG_SOC_HFXO_CAP_INTERNAL) +static inline uint32_t soc_secure_read_xosc32mtrim(void) +{ + uintptr_t ptr = (uintptr_t)&NRF_FICR_S->XOSC32MTRIM; + enum tfm_platform_err_t err; + uint32_t result; + uint32_t xosc32mtrim; + + err = tfm_platform_mem_read(&xosc32mtrim, ptr, 4, &result); + __ASSERT(err == TFM_PLATFORM_ERR_SUCCESS, "TFM platform error (%d)", err); + __ASSERT(result == 0, "Read service error (%d)", result); + + return xosc32mtrim; +} +#endif /* defined(CONFIG_SOC_HFXO_CAP_INTERNAL) */ +#else +#include +/* Do this directly from secure processing environment. */ +static inline void soc_secure_gpio_pin_mcu_select(uint32_t pin_number, nrf_gpio_pin_mcusel_t mcu) +{ + nrf_gpio_pin_mcu_select(pin_number, mcu); +} + +static inline uint32_t soc_secure_read_xosc32mtrim(void) +{ + return NRF_FICR_S->XOSC32MTRIM; +} +#endif /* defined CONFIG_BUILD_WITH_TFM */ +#endif /* defined(CONFIG_SOC_NRF5340_CPUAPP) */ diff --git a/west.yml b/west.yml index 099a5fd4765..dec5d99d0a9 100644 --- a/west.yml +++ b/west.yml @@ -218,7 +218,7 @@ manifest: groups: - debug - name: trusted-firmware-m - revision: c8134809a9439571c54d36ef39210270dbee8f67 + revision: 5d32c3e64b3d589548e881eeeeb37d84944c90af path: modules/tee/tf-m/trusted-firmware-m groups: - tee From d3d3144bde893d28a5b08e03960d72b5f119722d Mon Sep 17 00:00:00 2001 From: Joakim Andersson Date: Tue, 23 Nov 2021 15:56:23 +0100 Subject: [PATCH 066/207] [nrf fromtree] boards: nrf53: Fix board pin MCU selection with TF-M ... ... enabled Fix board pin MCU selection not working with TF-M enabled. This fixed no log output from the network core when TF-M is enabled. Signed-off-by: Joakim Andersson (cherry picked from commit e4260ac03fa6e2f1bc3770826e6dcb54021cab42) (cherry picked from commit 791d4c427b0d6e7726bb94dacb94a2e71fff5791) --- .../arm/bl5340_dvk/bl5340_dvk_cpunet_reset.c | 36 ++++++++----------- .../nrf5340dk_nrf5340/nrf5340_cpunet_reset.c | 31 +++++++--------- 2 files changed, 26 insertions(+), 41 deletions(-) diff --git a/boards/arm/bl5340_dvk/bl5340_dvk_cpunet_reset.c b/boards/arm/bl5340_dvk/bl5340_dvk_cpunet_reset.c index d3e97148878..fb685f1c77a 100644 --- a/boards/arm/bl5340_dvk/bl5340_dvk_cpunet_reset.c +++ b/boards/arm/bl5340_dvk/bl5340_dvk_cpunet_reset.c @@ -10,51 +10,43 @@ #include #include +#include LOG_MODULE_REGISTER(bl5340_dvk_cpuapp, CONFIG_LOG_DEFAULT_LEVEL); -#if !defined(CONFIG_TRUSTED_EXECUTION_NONSECURE) - -/* This should come from DTS, possibly an overlay. */ -#if defined(CONFIG_BOARD_BL5340_DVK_CPUAPP) -#define CPUNET_UARTE_PIN_TX 8 -#define CPUNET_UARTE_PIN_RX 10 -#define CPUNET_UARTE_PORT_TRX NRF_P1 -#define CPUNET_UARTE_PIN_RTS 7 -#define CPUNET_UARTE_PIN_CTS 9 -#define CPUNET_UARTE_PORT_RCTS NRF_P1 -#endif +/* TODO: This should come from DTS, possibly an overlay. */ +#define CPUNET_UARTE_PIN_TX 33 +#define CPUNET_UARTE_PIN_RX 32 +#define CPUNET_UARTE_PIN_RTS 11 +#define CPUNET_UARTE_PIN_CTS 10 static void remoteproc_mgr_config(void) { +#if !defined(CONFIG_TRUSTED_EXECUTION_NONSECURE) || defined(CONFIG_BUILD_WITH_TFM) /* UARTE */ /* Assign specific GPIOs that will be used to get UARTE from * nRF5340 Network MCU. */ - CPUNET_UARTE_PORT_TRX->PIN_CNF[CPUNET_UARTE_PIN_TX] = - GPIO_PIN_CNF_MCUSEL_NetworkMCU << GPIO_PIN_CNF_MCUSEL_Pos; - CPUNET_UARTE_PORT_TRX->PIN_CNF[CPUNET_UARTE_PIN_RX] = - GPIO_PIN_CNF_MCUSEL_NetworkMCU << GPIO_PIN_CNF_MCUSEL_Pos; - CPUNET_UARTE_PORT_RCTS->PIN_CNF[CPUNET_UARTE_PIN_RTS] = - GPIO_PIN_CNF_MCUSEL_NetworkMCU << GPIO_PIN_CNF_MCUSEL_Pos; - CPUNET_UARTE_PORT_RCTS->PIN_CNF[CPUNET_UARTE_PIN_CTS] = - GPIO_PIN_CNF_MCUSEL_NetworkMCU << GPIO_PIN_CNF_MCUSEL_Pos; + soc_secure_gpio_pin_mcu_select(CPUNET_UARTE_PIN_TX, NRF_GPIO_PIN_MCUSEL_NETWORK); + soc_secure_gpio_pin_mcu_select(CPUNET_UARTE_PIN_RX, NRF_GPIO_PIN_MCUSEL_NETWORK); + soc_secure_gpio_pin_mcu_select(CPUNET_UARTE_PIN_RTS, NRF_GPIO_PIN_MCUSEL_NETWORK); + soc_secure_gpio_pin_mcu_select(CPUNET_UARTE_PIN_CTS, NRF_GPIO_PIN_MCUSEL_NETWORK); +#endif /* !defined(CONFIG_TRUSTED_EXECUTION_NONSECURE) || defined(CONFIG_BUILD_WITH_TFM) */ +#if !defined(CONFIG_TRUSTED_EXECUTION_NONSECURE) /* Retain nRF5340 Network MCU in Secure domain (bus * accesses by Network MCU will have Secure attribute set). */ NRF_SPU->EXTDOMAIN[0].PERM = 1 << 4; -} #endif /* !CONFIG_TRUSTED_EXECUTION_NONSECURE */ +} static int remoteproc_mgr_boot(const struct device *dev) { ARG_UNUSED(dev); -#if !defined(CONFIG_TRUSTED_EXECUTION_NONSECURE) /* Secure domain may configure permissions for the Network MCU. */ remoteproc_mgr_config(); -#endif /* !CONFIG_TRUSTED_EXECUTION_NONSECURE */ #if !defined(CONFIG_TRUSTED_EXECUTION_SECURE) /* diff --git a/boards/arm/nrf5340dk_nrf5340/nrf5340_cpunet_reset.c b/boards/arm/nrf5340dk_nrf5340/nrf5340_cpunet_reset.c index d0f5e5eefbf..0223ce8cf1a 100644 --- a/boards/arm/nrf5340dk_nrf5340/nrf5340_cpunet_reset.c +++ b/boards/arm/nrf5340dk_nrf5340/nrf5340_cpunet_reset.c @@ -9,19 +9,15 @@ #include #include +#include LOG_MODULE_REGISTER(nrf5340dk_nrf5340_cpuapp, CONFIG_LOG_DEFAULT_LEVEL); -#if !defined(CONFIG_TRUSTED_EXECUTION_NONSECURE) - -/* This should come from DTS, possibly an overlay. */ -#if defined(CONFIG_BOARD_NRF5340DK_NRF5340_CPUAPP) -#define CPUNET_UARTE_PIN_TX 1 -#define CPUNET_UARTE_PIN_RX 0 -#define CPUNET_UARTE_PORT_TRX NRF_P1 +/* TODO: This should come from DTS, possibly an overlay. */ +#define CPUNET_UARTE_PIN_TX 33 +#define CPUNET_UARTE_PIN_RX 32 #define CPUNET_UARTE_PIN_RTS 11 #define CPUNET_UARTE_PIN_CTS 10 -#endif #if defined(CONFIG_BT_CTLR_DEBUG_PINS_CPUAPP) #include <../subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/debug.h> @@ -31,37 +27,34 @@ LOG_MODULE_REGISTER(nrf5340dk_nrf5340_cpuapp, CONFIG_LOG_DEFAULT_LEVEL); static void remoteproc_mgr_config(void) { +#if !defined(CONFIG_TRUSTED_EXECUTION_NONSECURE) || defined(CONFIG_BUILD_WITH_TFM) /* UARTE */ /* Assign specific GPIOs that will be used to get UARTE from * nRF5340 Network MCU. */ - CPUNET_UARTE_PORT_TRX->PIN_CNF[CPUNET_UARTE_PIN_TX] = - GPIO_PIN_CNF_MCUSEL_NetworkMCU << GPIO_PIN_CNF_MCUSEL_Pos; - CPUNET_UARTE_PORT_TRX->PIN_CNF[CPUNET_UARTE_PIN_RX] = - GPIO_PIN_CNF_MCUSEL_NetworkMCU << GPIO_PIN_CNF_MCUSEL_Pos; - NRF_P0->PIN_CNF[CPUNET_UARTE_PIN_RTS] = - GPIO_PIN_CNF_MCUSEL_NetworkMCU << GPIO_PIN_CNF_MCUSEL_Pos; - NRF_P0->PIN_CNF[CPUNET_UARTE_PIN_CTS] = - GPIO_PIN_CNF_MCUSEL_NetworkMCU << GPIO_PIN_CNF_MCUSEL_Pos; + soc_secure_gpio_pin_mcu_select(CPUNET_UARTE_PIN_TX, NRF_GPIO_PIN_MCUSEL_NETWORK); + soc_secure_gpio_pin_mcu_select(CPUNET_UARTE_PIN_RX, NRF_GPIO_PIN_MCUSEL_NETWORK); + soc_secure_gpio_pin_mcu_select(CPUNET_UARTE_PIN_RTS, NRF_GPIO_PIN_MCUSEL_NETWORK); + soc_secure_gpio_pin_mcu_select(CPUNET_UARTE_PIN_CTS, NRF_GPIO_PIN_MCUSEL_NETWORK); /* Route Bluetooth Controller Debug Pins */ DEBUG_SETUP(); +#endif /* !defined(CONFIG_TRUSTED_EXECUTION_NONSECURE) || defined(CONFIG_BUILD_WITH_TFM) */ +#if !defined(CONFIG_TRUSTED_EXECUTION_NONSECURE) /* Retain nRF5340 Network MCU in Secure domain (bus * accesses by Network MCU will have Secure attribute set). */ NRF_SPU->EXTDOMAIN[0].PERM = 1 << 4; +#endif /* !defined(CONFIG_TRUSTED_EXECUTION_NONSECURE) */ } -#endif /* !CONFIG_TRUSTED_EXECUTION_NONSECURE */ static int remoteproc_mgr_boot(const struct device *dev) { ARG_UNUSED(dev); -#if !defined(CONFIG_TRUSTED_EXECUTION_NONSECURE) /* Secure domain may configure permissions for the Network MCU. */ remoteproc_mgr_config(); -#endif /* !CONFIG_TRUSTED_EXECUTION_NONSECURE */ #if !defined(CONFIG_TRUSTED_EXECUTION_SECURE) /* From de87eb8452fb24aa563cbb24a2302fd7e10a13f3 Mon Sep 17 00:00:00 2001 From: Joakim Andersson Date: Mon, 29 Nov 2021 12:18:15 +0100 Subject: [PATCH 067/207] [nrf fromtree] Bluetooth: controller: Enable debug pins with TF-M ... ... enabled Enable debug pins when TF-M has been enabled for the image. This would otherwise produce an error message as the DEBUG_SETUP would not have been defined for the non-secure image. Signed-off-by: Joakim Andersson (cherry picked from commit 743b0583fcb07dec7a9392e03a5e50cd73ac162b) (cherry picked from commit 84381aa76dbc58cc8b6ae4b11be00bd8cce0179f) --- .../controller/ll_sw/nordic/hal/nrf5/debug.h | 44 ++++++------------- 1 file changed, 13 insertions(+), 31 deletions(-) diff --git a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/debug.h b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/debug.h index 711857ef1ef..72c0f153382 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/debug.h +++ b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/debug.h @@ -8,6 +8,7 @@ #if defined(CONFIG_BT_CTLR_DEBUG_PINS) || \ defined(CONFIG_BT_CTLR_DEBUG_PINS_CPUAPP) #if defined(CONFIG_BOARD_NRF5340DK_NRF5340_CPUAPP) || \ + defined(CONFIG_BOARD_NRF5340DK_NRF5340_CPUAPP_NS) || \ defined(CONFIG_BOARD_NRF5340DK_NRF5340_CPUNET) #define DEBUG_PORT NRF_P1 #define DEBUG_PIN_IDX0 0 @@ -30,39 +31,20 @@ #define DEBUG_PIN7 BIT(DEBUG_PIN_IDX7) #define DEBUG_PIN8 BIT(DEBUG_PIN_IDX8) #define DEBUG_PIN9 BIT(DEBUG_PIN_IDX9) -#if defined(CONFIG_BOARD_NRF5340DK_NRF5340_CPUAPP) +#if defined(CONFIG_BOARD_NRF5340DK_NRF5340_CPUAPP) || \ + (defined(CONFIG_BOARD_NRF5340DK_NRF5340_CPUAPP_NS) && defined(CONFIG_BUILD_WITH_TFM)) #define DEBUG_SETUP() \ do { \ - DEBUG_PORT->PIN_CNF[DEBUG_PIN_IDX0] = \ - (GPIO_PIN_CNF_MCUSEL_NetworkMCU << \ - GPIO_PIN_CNF_MCUSEL_Pos); \ - DEBUG_PORT->PIN_CNF[DEBUG_PIN_IDX1] = \ - (GPIO_PIN_CNF_MCUSEL_NetworkMCU << \ - GPIO_PIN_CNF_MCUSEL_Pos); \ - DEBUG_PORT->PIN_CNF[DEBUG_PIN_IDX2] = \ - (GPIO_PIN_CNF_MCUSEL_NetworkMCU << \ - GPIO_PIN_CNF_MCUSEL_Pos); \ - DEBUG_PORT->PIN_CNF[DEBUG_PIN_IDX3] = \ - (GPIO_PIN_CNF_MCUSEL_NetworkMCU << \ - GPIO_PIN_CNF_MCUSEL_Pos); \ - DEBUG_PORT->PIN_CNF[DEBUG_PIN_IDX4] = \ - (GPIO_PIN_CNF_MCUSEL_NetworkMCU << \ - GPIO_PIN_CNF_MCUSEL_Pos); \ - DEBUG_PORT->PIN_CNF[DEBUG_PIN_IDX5] = \ - (GPIO_PIN_CNF_MCUSEL_NetworkMCU << \ - GPIO_PIN_CNF_MCUSEL_Pos); \ - DEBUG_PORT->PIN_CNF[DEBUG_PIN_IDX6] = \ - (GPIO_PIN_CNF_MCUSEL_NetworkMCU << \ - GPIO_PIN_CNF_MCUSEL_Pos); \ - DEBUG_PORT->PIN_CNF[DEBUG_PIN_IDX7] = \ - (GPIO_PIN_CNF_MCUSEL_NetworkMCU << \ - GPIO_PIN_CNF_MCUSEL_Pos); \ - DEBUG_PORT->PIN_CNF[DEBUG_PIN_IDX8] = \ - (GPIO_PIN_CNF_MCUSEL_NetworkMCU << \ - GPIO_PIN_CNF_MCUSEL_Pos); \ - DEBUG_PORT->PIN_CNF[DEBUG_PIN_IDX9] = \ - (GPIO_PIN_CNF_MCUSEL_NetworkMCU << \ - GPIO_PIN_CNF_MCUSEL_Pos); \ + soc_secure_gpio_pin_mcu_select(32 + DEBUG_PIN_IDX0, NRF_GPIO_PIN_MCUSEL_NETWORK); + soc_secure_gpio_pin_mcu_select(32 + DEBUG_PIN_IDX1, NRF_GPIO_PIN_MCUSEL_NETWORK); + soc_secure_gpio_pin_mcu_select(32 + DEBUG_PIN_IDX2, NRF_GPIO_PIN_MCUSEL_NETWORK); + soc_secure_gpio_pin_mcu_select(32 + DEBUG_PIN_IDX3, NRF_GPIO_PIN_MCUSEL_NETWORK); + soc_secure_gpio_pin_mcu_select(32 + DEBUG_PIN_IDX4, NRF_GPIO_PIN_MCUSEL_NETWORK); + soc_secure_gpio_pin_mcu_select(32 + DEBUG_PIN_IDX5, NRF_GPIO_PIN_MCUSEL_NETWORK); + soc_secure_gpio_pin_mcu_select(32 + DEBUG_PIN_IDX6, NRF_GPIO_PIN_MCUSEL_NETWORK); + soc_secure_gpio_pin_mcu_select(32 + DEBUG_PIN_IDX7, NRF_GPIO_PIN_MCUSEL_NETWORK); + soc_secure_gpio_pin_mcu_select(32 + DEBUG_PIN_IDX8, NRF_GPIO_PIN_MCUSEL_NETWORK); + soc_secure_gpio_pin_mcu_select(32 + DEBUG_PIN_IDX9, NRF_GPIO_PIN_MCUSEL_NETWORK); } while (0) #endif /* CONFIG_BOARD_NRF5340DK_NRF5340_CPUAPP */ #elif defined(CONFIG_BOARD_NRF52840DK_NRF52840) || \ From 7c1b65af1b58ae55773b8db186fbf1b1a4d2670a Mon Sep 17 00:00:00 2001 From: Kamil Piszczek Date: Mon, 24 Jan 2022 12:01:23 +0100 Subject: [PATCH 068/207] [nrf fromlist] bluetooth: gatt: add validation for supervision timeout Added a missing assert statement for validation of the preferred supervision timeout parameter which can be configured by the user via Kconfig. Upstream PR: zephyrproject-rtos/zephyr#42080 Signed-off-by: Kamil Piszczek (cherry picked from commit 6a7993d12e045698f0797f3d45feda51c90c6a48) --- subsys/bluetooth/host/gatt.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/subsys/bluetooth/host/gatt.c b/subsys/bluetooth/host/gatt.c index 448c05885b3..b997a4b7421 100644 --- a/subsys/bluetooth/host/gatt.c +++ b/subsys/bluetooth/host/gatt.c @@ -142,6 +142,9 @@ BUILD_ASSERT(!(CONFIG_BT_PERIPHERAL_PREF_TIMEOUT > 3200 && BUILD_ASSERT((CONFIG_BT_PERIPHERAL_PREF_MIN_INT == 0xffff) || (CONFIG_BT_PERIPHERAL_PREF_MIN_INT <= CONFIG_BT_PERIPHERAL_PREF_MAX_INT)); +BUILD_ASSERT((CONFIG_BT_PERIPHERAL_PREF_TIMEOUT * 4U) > + ((1U + CONFIG_BT_PERIPHERAL_PREF_LATENCY) * + CONFIG_BT_PERIPHERAL_PREF_MAX_INT)); static ssize_t read_ppcp(struct bt_conn *conn, const struct bt_gatt_attr *attr, void *buf, uint16_t len, uint16_t offset) From b9d2bf89fd3db020e99442b14feb5fb495df3108 Mon Sep 17 00:00:00 2001 From: Kamil Piszczek Date: Mon, 20 Dec 2021 12:09:42 +0100 Subject: [PATCH 069/207] [nrf fromlist] mcumgr: bluetooth: use dedicated config of connection params during dfu Extended the connection parameters negotiation procedure used in the SMP BT module. From now on, it is possible to configure a preferable set of all connection parameters to be used during the image transfer. The default values are optimized for transfer throughput. Upstream PR: zephyrproject-rtos/zephyr#41362 Signed-off-by: Kamil Piszczek (cherry picked from commit 9b4e026aa34c3bf96392161ca02a14910b170045) --- subsys/mgmt/mcumgr/Kconfig | 77 ++++++++++-------- subsys/mgmt/mcumgr/smp_bt.c | 152 +++++++++++++++++------------------- 2 files changed, 118 insertions(+), 111 deletions(-) diff --git a/subsys/mgmt/mcumgr/Kconfig b/subsys/mgmt/mcumgr/Kconfig index 98ac7ed7373..9f0de718b53 100644 --- a/subsys/mgmt/mcumgr/Kconfig +++ b/subsys/mgmt/mcumgr/Kconfig @@ -315,51 +315,64 @@ config MCUMGR_SMP_BT_AUTHEN Enables encrypted and authenticated connection requirement to Bluetooth SMP transport. -config MCUMGR_SMP_BT_LATENCY_CONTROL - bool "Request low latency connection when handling SMP commands" +config MCUMGR_SMP_BT_CONN_PARAM_CONTROL + bool "Request specific connection parameters for SMP packet exchange" depends on SYSTEM_WORKQUEUE_PRIORITY < 0 + depends on BT_GAP_PERIPHERAL_PREF_PARAMS help - Enables support for requesting low latency connection parameter when + Enables support for requesting specific connection parameters when SMP commands are handled. This option allows to speed up the command exchange process. Its recommended to enable this if SMP is used for DFU. -config MCUMGR_SMP_BT_LATENCY_CONTROL_DEFAULT_LATENCY - int "Default value for connection latency" - depends on MCUMGR_SMP_BT_LATENCY_CONTROL - default BT_PERIPHERAL_PREF_LATENCY if BT_GAP_PERIPHERAL_PREF_PARAMS - default 99 +if MCUMGR_SMP_BT_CONN_PARAM_CONTROL + +config MCUMGR_SMP_BT_CONN_PARAM_CONTROL_MIN_INT + int "Minimum connection interval for SMP packet exchange" + default 6 + range 6 3200 + help + Minimum connection interval in 1.25ms units used during the exchange of SMP packets. + +config MCUMGR_SMP_BT_CONN_PARAM_CONTROL_MAX_INT + int "Maximum connection interval for SMP packet exchange" + default 9 + range MCUMGR_SMP_BT_CONN_PARAM_CONTROL_MIN_INT 3200 + help + Maximum connection interval in 1.25ms units used during the exchange of SMP packets. + +config MCUMGR_SMP_BT_CONN_PARAM_CONTROL_LATENCY + int "Peripheral latency for SMP packet exchange" + default 0 range 0 499 help - The value is a default connection latency that is used when restoring - from low latency mode. + Peripheral latency in Connection Intervals used during the exchange of SMP packets. -config MCUMGR_SMP_BT_LATENCY_CONTROL_RESTORE_TIME - int "Connection latency restore time in milliseconds" - depends on MCUMGR_SMP_BT_LATENCY_CONTROL +config MCUMGR_SMP_BT_CONN_PARAM_CONTROL_TIMEOUT + int "Supervision timeout for SMP packet exchange" + default 42 + range 10 3200 + help + Supervision timeout in 10ms used during the exchange of SMP packets. + +config MCUMGR_SMP_BT_CONN_PARAM_CONTROL_RESTORE_TIME + int "Connection parameters restore time in milliseconds" default 5000 - range 1 65535 - help - The value is a time after which connection latency is restored - to default value - (:kconfig:`MCUMGR_SMP_BT_LATENCY_CONTROL_DEFAULT_LATENCY`). Latency - restoration time could take up to twice as long as specified time. - This is because of limiting CPU time needed to support this feature. - The implementation periodically checks if the low latency is still - needed every :kconfig:`MCUMGR_SMP_BT_LATENCY_CONTROL_RESTORE_TIME`. - The default latency is restored during check only if there was no SMP - command exchanged in period before the check - -config MCUMGR_SMP_BT_LATENCY_CONTROL_RESTORE_RETRY_TIME - int "Connection latency restore retry time in milliseconds" - depends on MCUMGR_SMP_BT_LATENCY_CONTROL + range 1000 65535 + help + The value is a time of inactivity on the SMP characteristic after which + connection parameters are restored to peripheral preferred values + (:kconfig:`BT_GAP_PERIPHERAL_PREF_PARAMS`). + +config MCUMGR_SMP_BT_CONN_PARAM_CONTROL_RETRY_TIME + int "Connection parameters update retry time in milliseconds" default 1000 range 1 5000 help - In case connection latency restoration fails due to an error, this - option specifies the time after retry to set the default latency - (:kconfig:`MCUMGR_SMP_BT_LATENCY_CONTROL_DEFAULT_LATENCY`) would be - executed. + In case connection parameters update fails due to an error, this + option specifies the time of the next update attempt. + +endif # MCUMGR_SMP_BT_CONN_PARAM_CONTROL endif # MCUMGR_SMP_BT diff --git a/subsys/mgmt/mcumgr/smp_bt.c b/subsys/mgmt/mcumgr/smp_bt.c index 84ff096bc8e..55835eb83f5 100644 --- a/subsys/mgmt/mcumgr/smp_bt.c +++ b/subsys/mgmt/mcumgr/smp_bt.c @@ -21,27 +21,48 @@ #include -#define RESTORE_TIME COND_CODE_1(CONFIG_MCUMGR_SMP_BT_LATENCY_CONTROL, \ - (CONFIG_MCUMGR_SMP_BT_LATENCY_CONTROL_RESTORE_TIME), (0)) -#define RESTORE_RETRY_TIME COND_CODE_1(CONFIG_MCUMGR_SMP_BT_LATENCY_CONTROL, \ - (CONFIG_MCUMGR_SMP_BT_LATENCY_CONTROL_RESTORE_RETRY_TIME), (0)) -#define DEFAULT_LATENCY COND_CODE_1(CONFIG_MCUMGR_SMP_BT_LATENCY_CONTROL, \ - (CONFIG_MCUMGR_SMP_BT_LATENCY_CONTROL_DEFAULT_LATENCY), (0)) - +#define RESTORE_TIME COND_CODE_1(CONFIG_MCUMGR_SMP_BT_CONN_PARAM_CONTROL, \ + (CONFIG_MCUMGR_SMP_BT_CONN_PARAM_CONTROL_RESTORE_TIME), \ + (0)) +#define RETRY_TIME COND_CODE_1(CONFIG_MCUMGR_SMP_BT_CONN_PARAM_CONTROL, \ + (CONFIG_MCUMGR_SMP_BT_CONN_PARAM_CONTROL_RETRY_TIME), \ + (0)) + +#define CONN_PARAM_SMP COND_CODE_1(CONFIG_MCUMGR_SMP_BT_CONN_PARAM_CONTROL, \ + BT_LE_CONN_PARAM( \ + CONFIG_MCUMGR_SMP_BT_CONN_PARAM_CONTROL_MIN_INT, \ + CONFIG_MCUMGR_SMP_BT_CONN_PARAM_CONTROL_MAX_INT, \ + CONFIG_MCUMGR_SMP_BT_CONN_PARAM_CONTROL_LATENCY, \ + CONFIG_MCUMGR_SMP_BT_CONN_PARAM_CONTROL_TIMEOUT), \ + (NULL)) +#define CONN_PARAM_PREF COND_CODE_1(CONFIG_MCUMGR_SMP_BT_CONN_PARAM_CONTROL, \ + BT_LE_CONN_PARAM( \ + CONFIG_BT_PERIPHERAL_PREF_MIN_INT, \ + CONFIG_BT_PERIPHERAL_PREF_MAX_INT, \ + CONFIG_BT_PERIPHERAL_PREF_LATENCY, \ + CONFIG_BT_PERIPHERAL_PREF_TIMEOUT), \ + (NULL)) + +#ifdef CONFIG_MCUMGR_SMP_BT_CONN_PARAM_CONTROL +/* Verification of SMP Connection Parameters configuration that is not possible in the Kconfig. */ +BUILD_ASSERT((CONFIG_MCUMGR_SMP_BT_CONN_PARAM_CONTROL_TIMEOUT * 4U) > + ((1U + CONFIG_MCUMGR_SMP_BT_CONN_PARAM_CONTROL_LATENCY) * + CONFIG_MCUMGR_SMP_BT_CONN_PARAM_CONTROL_MAX_INT)); +#endif struct smp_bt_user_data { struct bt_conn *conn; }; enum { - CONN_LOW_LATENCY_ENABLED = BIT(0), - CONN_LOW_LATENCY_REQUIRED = BIT(1), + CONN_PARAM_SMP_REQUESTED = BIT(0), }; struct conn_param_data { struct bt_conn *conn; struct k_work_delayable dwork; - uint8_t latency_state; + struct k_work_delayable ework; + uint8_t state; }; static struct zephyr_smp_transport smp_bt_transport; @@ -60,7 +81,7 @@ static struct bt_uuid_128 smp_bt_chr_uuid = BT_UUID_INIT_128( BT_UUID_128_ENCODE(0xda2e7828, 0xfbce, 0x4e01, 0xae9e, 0x261174997c48)); /* Helper function that allocates conn_param_data for a conn. */ -static struct conn_param_data *alloc_conn_param_data(struct bt_conn *conn) +static struct conn_param_data *conn_param_data_alloc(struct bt_conn *conn) { for (size_t i = 0; i < ARRAY_SIZE(conn_data); i++) { if (conn_data[i].conn == NULL) { @@ -75,7 +96,7 @@ static struct conn_param_data *alloc_conn_param_data(struct bt_conn *conn) } /* Helper function that returns conn_param_data associated with a conn. */ -static struct conn_param_data *get_conn_param_data(const struct bt_conn *conn) +static struct conn_param_data *conn_param_data_get(const struct bt_conn *conn) { for (size_t i = 0; i < ARRAY_SIZE(conn_data); i++) { if (conn_data[i].conn == conn) { @@ -89,63 +110,51 @@ static struct conn_param_data *get_conn_param_data(const struct bt_conn *conn) } /* Sets connection parameters for a given conn. */ -static void set_conn_latency(struct bt_conn *conn, bool low_latency) +static void conn_param_set(struct bt_conn *conn, struct bt_le_conn_param *param) { - struct bt_le_conn_param params; - struct conn_param_data *cpd; - struct bt_conn_info info; int ret = 0; + struct conn_param_data *cpd = conn_param_data_get(conn); - cpd = get_conn_param_data(conn); - - ret = bt_conn_get_info(conn, &info); - __ASSERT_NO_MSG(!ret); - - if ((low_latency && (info.le.latency == 0)) || - ((!low_latency) && (info.le.latency == DEFAULT_LATENCY))) { - /* Already updated. */ - return; - } - - params.interval_min = info.le.interval; - params.interval_max = info.le.interval; - params.latency = (low_latency) ? (0) : (DEFAULT_LATENCY); - params.timeout = info.le.timeout; - - ret = bt_conn_le_param_update(cpd->conn, ¶ms); + ret = bt_conn_le_param_update(conn, param); if (ret && (ret != -EALREADY)) { - if (!low_latency) { - /* Try again to avoid stucking in low latency. */ - (void)k_work_reschedule(&cpd->dwork, K_MSEC(RESTORE_RETRY_TIME)); - } + /* Try again to avoid being stuck with incorrect connection parameters. */ + (void)k_work_reschedule(&cpd->ework, K_MSEC(RETRY_TIME)); + } else { + (void)k_work_cancel_delayable(&cpd->ework); } } -/* Work handler function for restoring the default latency for the connection. */ -static void restore_default_latency(struct k_work *work) +/* Work handler function for restoring the preferred connection parameters for the connection. */ +static void conn_param_on_pref_restore(struct k_work *work) { - struct conn_param_data *cpd; + struct conn_param_data *cpd = CONTAINER_OF(work, struct conn_param_data, dwork); - cpd = CONTAINER_OF(work, struct conn_param_data, dwork); + conn_param_set(cpd->conn, CONN_PARAM_PREF); + cpd->state &= ~CONN_PARAM_SMP_REQUESTED; +} - if (cpd->latency_state & CONN_LOW_LATENCY_REQUIRED) { - cpd->latency_state &= ~CONN_LOW_LATENCY_REQUIRED; - (void)k_work_reschedule(&cpd->dwork, K_MSEC(RESTORE_TIME)); - } else { - set_conn_latency(cpd->conn, false); - } +/* Work handler function for retrying on conn negotiation API error. */ +static void conn_param_on_error_retry(struct k_work *work) +{ + struct conn_param_data *cpd = CONTAINER_OF(work, struct conn_param_data, ework); + struct bt_le_conn_param *param = (cpd->state & CONN_PARAM_SMP_REQUESTED) ? + CONN_PARAM_SMP : CONN_PARAM_PREF; + + conn_param_set(cpd->conn, param); } -static void enable_low_latency(struct bt_conn *conn) +static void conn_param_smp_enable(struct bt_conn *conn) { - struct conn_param_data *cpd = get_conn_param_data(conn); + struct conn_param_data *cpd = conn_param_data_get(conn); - if (cpd->latency_state & CONN_LOW_LATENCY_ENABLED) { - cpd->latency_state |= CONN_LOW_LATENCY_REQUIRED; - } else { - set_conn_latency(conn, true); + if (!(cpd->state & CONN_PARAM_SMP_REQUESTED)) { + conn_param_set(conn, CONN_PARAM_SMP); + cpd->state |= CONN_PARAM_SMP_REQUESTED; } + + /* SMP characteristic in use; refresh the restore timeout. */ + (void)k_work_reschedule(&cpd->dwork, K_MSEC(RESTORE_TIME)); } /** @@ -168,8 +177,8 @@ static ssize_t smp_bt_chr_write(struct bt_conn *conn, ud = net_buf_user_data(nb); ud->conn = bt_conn_ref(conn); - if (IS_ENABLED(CONFIG_MCUMGR_SMP_BT_LATENCY_CONTROL)) { - enable_low_latency(conn); + if (IS_ENABLED(CONFIG_MCUMGR_SMP_BT_CONN_PARAM_CONTROL)) { + conn_param_smp_enable(conn); } zephyr_smp_rx_req(&smp_bt_transport, nb); @@ -303,51 +312,36 @@ int smp_bt_unregister(void) static void connected(struct bt_conn *conn, uint8_t err) { if (err == 0) { - alloc_conn_param_data(conn); + conn_param_data_alloc(conn); } } /* BT disconnected callback. */ static void disconnected(struct bt_conn *conn, uint8_t reason) { - struct conn_param_data *cpd = get_conn_param_data(conn); + struct conn_param_data *cpd = conn_param_data_get(conn); /* Cancel work if ongoing. */ (void)k_work_cancel_delayable(&cpd->dwork); + (void)k_work_cancel_delayable(&cpd->ework); /* Clear cpd. */ - cpd->latency_state = 0; + cpd->state = 0; cpd->conn = NULL; } -/* BT LE connection parameters updated callback. */ -static void le_param_updated(struct bt_conn *conn, uint16_t interval, - uint16_t latency, uint16_t timeout) -{ - struct conn_param_data *cpd = get_conn_param_data(conn); - - if (latency == 0) { - cpd->latency_state |= CONN_LOW_LATENCY_ENABLED; - cpd->latency_state &= ~CONN_LOW_LATENCY_REQUIRED; - (void)k_work_reschedule(&cpd->dwork, K_MSEC(RESTORE_TIME)); - } else { - cpd->latency_state &= ~CONN_LOW_LATENCY_ENABLED; - (void)k_work_cancel_delayable(&cpd->dwork); - } -} - -static void init_latency_control_support(void) +static void conn_param_control_init(void) { /* Register BT callbacks */ static struct bt_conn_cb conn_callbacks = { .connected = connected, .disconnected = disconnected, - .le_param_updated = le_param_updated, }; bt_conn_cb_register(&conn_callbacks); for (size_t i = 0; i < ARRAY_SIZE(conn_data); i++) { - k_work_init_delayable(&conn_data[i].dwork, restore_default_latency); + k_work_init_delayable(&conn_data[i].dwork, conn_param_on_pref_restore); + k_work_init_delayable(&conn_data[i].ework, conn_param_on_error_retry); } } @@ -355,8 +349,8 @@ static int smp_bt_init(const struct device *dev) { ARG_UNUSED(dev); - if (IS_ENABLED(CONFIG_MCUMGR_SMP_BT_LATENCY_CONTROL)) { - init_latency_control_support(); + if (IS_ENABLED(CONFIG_MCUMGR_SMP_BT_CONN_PARAM_CONTROL)) { + conn_param_control_init(); } zephyr_smp_transport_init(&smp_bt_transport, smp_bt_tx_pkt, From bacbc792bd4f5db19e99c098edce2a412a9018e0 Mon Sep 17 00:00:00 2001 From: Kamil Piszczek Date: Tue, 21 Dec 2021 11:41:43 +0100 Subject: [PATCH 070/207] [nrf fromlist] samples: mgmt: mcumgr: use conn params control config for BT transport By default, the Connection Parameters control feature is enabled for the SMP Server sample with the Bluetooth transport. Upstream PR: zephyrproject-rtos/zephyr#41362 Signed-off-by: Kamil Piszczek (cherry picked from commit 7536362c094f92cfa430d2fe4f53891d8442ba40) --- samples/subsys/mgmt/mcumgr/smp_svr/overlay-bt.conf | 1 + 1 file changed, 1 insertion(+) diff --git a/samples/subsys/mgmt/mcumgr/smp_svr/overlay-bt.conf b/samples/subsys/mgmt/mcumgr/smp_svr/overlay-bt.conf index 401f06fe163..3c228eb5e3b 100644 --- a/samples/subsys/mgmt/mcumgr/smp_svr/overlay-bt.conf +++ b/samples/subsys/mgmt/mcumgr/smp_svr/overlay-bt.conf @@ -5,6 +5,7 @@ CONFIG_BT_BUF_ACL_RX_SIZE=256 # Enable the Bluetooth (unauthenticated) and shell mcumgr transports. CONFIG_MCUMGR_SMP_BT=y CONFIG_MCUMGR_SMP_BT_AUTHEN=n +CONFIG_MCUMGR_SMP_BT_CONN_PARAM_CONTROL=y CONFIG_MCUMGR_SMP_SHELL=y # Enable the LittleFS file system. From 6608ece710ab33cd8c2f35036bc66c14272c9abf 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 071/207] [nrf noup] 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ø (cherry picked from commit f081631c95abb03473b82fa2c8dcd963b5c836bc) --- modules/mbedtls/Kconfig.tls-generic | 35 ++++++++++++++++++++ modules/mbedtls/configs/config-tls-generic.h | 4 +++ 2 files changed, 39 insertions(+) diff --git a/modules/mbedtls/Kconfig.tls-generic b/modules/mbedtls/Kconfig.tls-generic index 7230efbd31c..20bbe735885 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 "Enable support for TLS 1.0" select MBEDTLS_CIPHER @@ -33,6 +35,8 @@ config MBEDTLS_DTLS bool "Enable support for DTLS" depends on MBEDTLS_TLS_VERSION_1_1 || MBEDTLS_TLS_VERSION_1_2 +endif + config MBEDTLS_SSL_EXPORT_KEYS bool "Enable 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 "Enable all available ciphersuite modes" select MBEDTLS_KEY_EXCHANGE_PSK_ENABLED @@ -80,6 +86,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 @@ -87,6 +95,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 "Enable the RSA-only based ciphersuite modes" default y if !NET_L2_OPENTHREAD @@ -119,8 +129,12 @@ if MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED || \ MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED || \ MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED +endif + comment "Supported elliptic curves" +if !(NRF_SECURITY || NORDIC_SECURITY_BACKEND) + config MBEDTLS_ECP_ALL_ENABLED bool "Enable all available elliptic curves" select MBEDTLS_ECP_DP_SECP192R1_ENABLED @@ -182,9 +196,12 @@ config MBEDTLS_ECP_NIST_OPTIM bool "Enable NSIT curves optimization" endif +endif comment "Supported cipher modes" +if !(NRF_SECURITY || NORDIC_SECURITY_BACKEND) + config MBEDTLS_CIPHER_ALL_ENABLED bool "Enable all available ciphers" select MBEDTLS_CIPHER_AES_ENABLED @@ -248,8 +265,12 @@ config MBEDTLS_CHACHAPOLY_AEAD_ENABLED bool "Enable the 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 "Enable all available MAC methods" select MBEDTLS_MAC_MD4_ENABLED @@ -293,10 +314,14 @@ config MBEDTLS_MAC_CMAC_ENABLED bool "Enable the 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 "Enable the CTR_DRBG AES-256-based random generator" depends on MBEDTLS_CIPHER_AES_ENABLED @@ -306,14 +331,20 @@ config MBEDTLS_HMAC_DRBG_ENABLED bool "Enable the HMAC_DRBG random generator" select MBEDTLS_MD +endif + comment "Other configurations" config MBEDTLS_CIPHER bool "Enable the generic cipher layer." +if !(NRF_SECURITY || NORDIC_SECURITY_BACKEND) + config MBEDTLS_MD bool "Enable the generic message digest layer." +endif + config MBEDTLS_GENPRIME_ENABLED bool "Enable the prime-number generation code." @@ -331,10 +362,14 @@ 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 "Enable mbedTLS generic entropy pool" depends on MBEDTLS_MAC_SHA256_ENABLED || MBEDTLS_MAC_SHA512_ENABLED +endif + config MBEDTLS_OPENTHREAD_OPTIMIZATIONS_ENABLED bool "Enable 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 b3b2b3b1f25..f7c1def23c3 100644 --- a/modules/mbedtls/configs/config-tls-generic.h +++ b/modules/mbedtls/configs/config-tls-generic.h @@ -438,6 +438,10 @@ #include CONFIG_MBEDTLS_USER_CONFIG_FILE #endif +#if defined(CONFIG_NRF_CC3XX_PLATFORM) +#define MBEDTLS_PLATFORM_ZEROIZE_ALT +#endif + #include "mbedtls/check_config.h" #endif /* MBEDTLS_CONFIG_H */ From 3c50ceb8184ad3c85e9ef6dcec14843b66bb9c6b Mon Sep 17 00:00:00 2001 From: Lukasz Maciejonczyk Date: Fri, 4 Feb 2022 11:38:04 +0100 Subject: [PATCH 072/207] [nrf fromlist] drivers: ieee802154_nrf5: fix CSL for multicore devices Due to serialization restrictions radio api calls cannot be nested, any violation of this rule leads to a deadlock. This commit fixes the bug by transferring the nested radio api call to ot_radio_workq. Upstream PR: zephyrproject-rtos/zephyr#42484 Signed-off-by: Lukasz Maciejonczyk (cherry picked from commit 12538e3fe4dfa933cdbd1dd10896f9a5fcccfd73) --- drivers/ieee802154/ieee802154_nrf5.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/ieee802154/ieee802154_nrf5.c b/drivers/ieee802154/ieee802154_nrf5.c index 0b61c0fc239..6edb3586be1 100644 --- a/drivers/ieee802154/ieee802154_nrf5.c +++ b/drivers/ieee802154/ieee802154_nrf5.c @@ -962,9 +962,12 @@ void nrf_802154_received_timestamp_raw(uint8_t *data, int8_t power, uint8_t lqi, void nrf_802154_receive_failed(nrf_802154_rx_error_t error, uint32_t id) { + const struct device *dev = net_if_get_device(nrf5_data.iface); + #if defined(CONFIG_IEEE802154_CSL_ENDPOINT) if ((id == DRX_SLOT_PH) || (id == DRX_SLOT_RX)) { - nrf5_stop(net_if_get_device(nrf5_data.iface)); + __ASSERT_NO_MSG(nrf5_data.event_handler); + nrf5_data.event_handler(dev, IEEE802154_EVENT_SLEEP, NULL); return; } #else @@ -994,9 +997,7 @@ void nrf_802154_receive_failed(nrf_802154_rx_error_t error, uint32_t id) nrf5_data.last_frame_ack_fpb = false; if (nrf5_data.event_handler) { - nrf5_data.event_handler(net_if_get_device(nrf5_data.iface), - IEEE802154_EVENT_RX_FAILED, - (void *)&reason); + nrf5_data.event_handler(dev, IEEE802154_EVENT_RX_FAILED, (void *)&reason); } } From f701b25b97583b4d13a89915aaa8a01f0dd2666c Mon Sep 17 00:00:00 2001 From: Robert Lubos Date: Fri, 28 Jan 2022 14:11:25 +0100 Subject: [PATCH 073/207] [nrf fromtree] net: sockets: Report ZSOCK_POLLHUP when socket is in EOF state Report ZSOCK_POLLHUP event if peer closed the connection, and thus the socket is in EOF state. Signed-off-by: Robert Lubos (cherry picked from commit a9cf83154d4c0b172cc12208ebae731129ebe0d1) --- subsys/net/lib/sockets/sockets.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/subsys/net/lib/sockets/sockets.c b/subsys/net/lib/sockets/sockets.c index 0b048fcecd8..238c339e6d5 100644 --- a/subsys/net/lib/sockets/sockets.c +++ b/subsys/net/lib/sockets/sockets.c @@ -1364,6 +1364,10 @@ static int zsock_poll_update_ctx(struct net_context *ctx, (*pev)++; } + if (sock_is_eof(ctx)) { + pfd->revents |= ZSOCK_POLLHUP; + } + return 0; } From 46692dea0c4bfb69e57675cd6725938cabdf41ba Mon Sep 17 00:00:00 2001 From: Robert Lubos Date: Fri, 28 Jan 2022 14:13:11 +0100 Subject: [PATCH 074/207] [nrf fromtree] net: sockets: tls: Fix ZSOCK_POLLHUP detection The previous approach to detect if the underlying transport was closed (by checking the return value of `mbedtls_ssl_read()` was not right, since the function call does not request any data - therefore 0 as a return value is perfectly fine. Instead, rely on the underlying transport ZSOCK_POLLHUP event - if it reports that the connection ended, forward the event to the application. Signed-off-by: Robert Lubos (cherry picked from commit d5a653348eeab5a3bd6305e4f1cd2d6dcf56774a) --- subsys/net/lib/sockets/sockets_tls.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/subsys/net/lib/sockets/sockets_tls.c b/subsys/net/lib/sockets/sockets_tls.c index 2f7370e1425..0bbebfb7f97 100644 --- a/subsys/net/lib/sockets/sockets_tls.c +++ b/subsys/net/lib/sockets/sockets_tls.c @@ -2176,8 +2176,6 @@ static int ztls_socket_data_check(struct tls_context *ctx) /* Treat any other error as fatal. */ return -EIO; - } else if (ret == 0 && ctx->type == SOCK_STREAM) { - return -ENOTCONN; } return mbedtls_ssl_get_bytes_avail(&ctx->ssl); @@ -2206,7 +2204,7 @@ static int ztls_poll_update_pollin(int fd, struct tls_context *ctx, } ret = ztls_socket_data_check(ctx); - if (ret == -ENOTCONN) { + if (ret == -ENOTCONN || (pfd->revents & ZSOCK_POLLHUP)) { /* Datagram does not return 0 on consecutive recv, but an error * code, hence clear POLLIN. */ From dcfec1061238c48a55e81a671c8e64e025e18dc8 Mon Sep 17 00:00:00 2001 From: Piotr Pryga Date: Tue, 4 Jan 2022 07:12:54 +0100 Subject: [PATCH 075/207] [nrf fromtree] Bluetooth: Controller: change def val BT_CTLR_LLCP_PROC_CTX_BUF_NUM Default value for CONFIG_BT_CTLR_LLCP_PROC_CTX_BUF_NUM was set to CONFIG_BT_CTLR_LLCP_CONN, so the value was 1. That caused a problem if a device had started a local control procedure and remote procedure request was received. Ther there were no free context for remote procedure. The commit changes the range of allowed value to start from 2. Also the default value is set to two if CONFIG_BT_CTLR_LLCP_CONN is 1. In other case default value is set to number of CONFIG_BT_- LLCP_CONN. Signed-off-by: Piotr Pryga (cherry picked from commit 429dce40b1532d829b1fde164696cdf440cd122d) --- subsys/bluetooth/controller/Kconfig.ll_sw_split | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/subsys/bluetooth/controller/Kconfig.ll_sw_split b/subsys/bluetooth/controller/Kconfig.ll_sw_split index e762f11d28c..646a4ee2315 100644 --- a/subsys/bluetooth/controller/Kconfig.ll_sw_split +++ b/subsys/bluetooth/controller/Kconfig.ll_sw_split @@ -534,8 +534,9 @@ config BT_CTLR_LLCP_COMMON_TX_CTRL_BUF_NUM config BT_CTLR_LLCP_PROC_CTX_BUF_NUM int "Number of control procedure contexts to be available across all connections" - default BT_CTLR_LLCP_CONN - range 1 255 + default 2 if BT_CTLR_LLCP_CONN = 1 + default BT_CTLR_LLCP_CONN if BT_CTLR_LLCP_CONN > 1 + range 2 255 help Set the number control procedure contexts that is to be available. This defines the size of the pool of control procedure contexts available From 1031598c698eb93c02bab6df370913d52f977dd8 Mon Sep 17 00:00:00 2001 From: Piotr Pryga Date: Wed, 5 Jan 2022 11:16:34 +0100 Subject: [PATCH 076/207] [nrf fromtree] Bluetooth: Controller: llcp: Missing llcp ctx release when disconnect If there were local LLCP pending and connection lost happened there were no release of allocated control procedure context. It caused to exhaustion of available procedures. Signed-off-by: Piotr Pryga (cherry picked from commit 7699b266e5837f0e33d5f9130624d00998bc8569) --- subsys/bluetooth/controller/ll_sw/ull_conn.c | 1 + 1 file changed, 1 insertion(+) diff --git a/subsys/bluetooth/controller/ll_sw/ull_conn.c b/subsys/bluetooth/controller/ll_sw/ull_conn.c index 95eb2aaea14..cb47cdd3d35 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_conn.c +++ b/subsys/bluetooth/controller/ll_sw/ull_conn.c @@ -2303,6 +2303,7 @@ static void conn_cleanup_finalize(struct ll_conn *conn) } #else /* CONFIG_BT_LL_SW_LLCP_LEGACY */ ARG_UNUSED(rx); + ull_cp_state_set(conn, ULL_CP_DISCONNECTED); #endif /* CONFIG_BT_LL_SW_LLCP_LEGACY */ /* flush demux-ed Tx buffer still in ULL context */ From aa913bdfbb16e070a9a48f3b1f746dd26ac825a9 Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Wed, 29 Dec 2021 11:30:19 +0530 Subject: [PATCH 077/207] [nrf fromtree] Bluetooth: Controller: Skip re-init of static initialized PDU fields Skip re-initialization of statically initialized PDU struct fields that are not modified at runtime. When supporting connection oriented CTE, the cp bit and resv field used for CTE info are modified, hence re-initialized these and accordingly reset the values when just-in-time HCI Tx Data fragmentation is performed in the Lower Link Layer. Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit a94e8be627e7666163221377e0cf337e369ba82b) --- .../controller/ll_sw/nordic/lll/lll_conn.c | 15 +++++++++++---- subsys/bluetooth/controller/ll_sw/ull_conn.c | 13 +++++-------- 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_conn.c b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_conn.c index 68eb2d61cb8..5aeb193a9e8 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_conn.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_conn.c @@ -721,6 +721,11 @@ void lll_conn_pdu_tx_prep(struct lll_conn *lll, struct pdu_data **pdu_data_tx) if (lll->packet_tx_head_offset) { p->ll_id = PDU_DATA_LLID_DATA_CONTINUE; + +#if defined(CONFIG_BT_CTLR_DF_CONN_CTE_TX) + p->cp = 0U; + p->resv = 0U; +#endif /* CONFIG_BT_CTLR_DF_CONN_CTE_TX */ } p->len = lll->packet_tx_head_len - lll->packet_tx_head_offset; @@ -738,6 +743,12 @@ void lll_conn_pdu_tx_prep(struct lll_conn *lll, struct pdu_data **pdu_data_tx) } p->rfu = 0U; + +#if !defined(CONFIG_BT_CTLR_DATA_LENGTH_CLEAR) +#if !defined(CONFIG_BT_CTLR_DF_CONN_CTE_TX) + p->resv = 0U; +#endif /* !CONFIG_BT_CTLR_DF_CONN_CTE_TX */ +#endif /* CONFIG_BT_CTLR_DATA_LENGTH_CLEAR */ } *pdu_data_tx = p; @@ -991,10 +1002,6 @@ static void empty_tx_init(void) p = (void *)radio_pkt_empty_get(); p->ll_id = PDU_DATA_LLID_DATA_CONTINUE; - p->cp = false; -#if !defined(CONFIG_BT_CTLR_DATA_LENGTH_CLEAR) - p->resv = 0U; -#endif /* CONFIG_BT_CTLR_DATA_LENGTH_CLEAR */ } #if defined(CONFIG_BT_CTRL_DF_CONN_CTE_RX) diff --git a/subsys/bluetooth/controller/ll_sw/ull_conn.c b/subsys/bluetooth/controller/ll_sw/ull_conn.c index cb47cdd3d35..f6b3a373fd7 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_conn.c +++ b/subsys/bluetooth/controller/ll_sw/ull_conn.c @@ -2052,20 +2052,17 @@ uint16_t ull_conn_lll_max_tx_octets_get(struct lll_conn *lll) /** * @brief Initialize pdu_data members that are read only in lower link layer. + * Fields that are modified after static initialization are only + * re-initialized. * * @param pdu_tx Pointer to pdu_data object to be initialized */ void ull_pdu_data_init(struct pdu_data *pdu_tx) { - LL_ASSERT(pdu_tx); - - pdu_tx->cp = false; - pdu_tx->rfu = 0U; -#if !defined(CONFIG_SOC_OPENISA_RV32M1_RISCV32) -#if !defined(CONFIG_BT_CTLR_DATA_LENGTH_CLEAR) +#if defined(CONFIG_BT_CTLR_DF_CONN_CTE_TX) + pdu_tx->cp = 0U; pdu_tx->resv = 0U; -#endif /* CONFIG_BT_CTLR_DATA_LENGTH_CLEAR */ -#endif /* !CONFIG_SOC_OPENISA_RV32M1_RISCV32 */ +#endif /* CONFIG_BT_CTLR_DF_CONN_CTE_TX */ } static int init_reset(void) From 2e01871d35751d39e89775c1af51f5ade1b5766c Mon Sep 17 00:00:00 2001 From: Piotr Pryga Date: Mon, 27 Dec 2021 11:02:37 +0100 Subject: [PATCH 078/207] [nrf fromtree] include: Bluetooth: Add LE Supported Features type to GAP BT 5.3 Core Spec provides possibility to transmit LE Supported Features in advertising data. The value is prepared as in case of other advertising data by an application. There was missing LE Supported Features advertising data type in macros defined in gap.h. Besides that, the commit provides set of macros that help to encode 64-bit LE Supported Features data into advertising data. There is a set of macros because all 0x0 bytes after last non-zero byte should be ommited. Signed-off-by: Piotr Pryga (cherry picked from commit cd66a35d74aee0ff91cf2dabcb67e7ccc619fc65) --- include/bluetooth/gap.h | 132 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 132 insertions(+) diff --git a/include/bluetooth/gap.h b/include/bluetooth/gap.h index 86b478db8dc..ff8a88b168c 100644 --- a/include/bluetooth/gap.h +++ b/include/bluetooth/gap.h @@ -50,6 +50,7 @@ extern "C" { #define BT_DATA_LE_SC_CONFIRM_VALUE 0x22 /* LE SC Confirmation Value */ #define BT_DATA_LE_SC_RANDOM_VALUE 0x23 /* LE SC Random Value */ #define BT_DATA_URI 0x24 /* URI */ +#define BT_DATA_LE_SUPPORTED_FEATURES 0x27 /* LE Supported Features */ #define BT_DATA_CHANNEL_MAP_UPDATE_IND 0x28 /* Channel Map Update Indication */ #define BT_DATA_MESH_PROV 0x29 /* Mesh Provisioning PDU */ #define BT_DATA_MESH_MESSAGE 0x2a /* Mesh Networking PDU */ @@ -189,6 +190,137 @@ enum { BT_GAP_SCA_0_20 = 7, }; +/** + * @brief Encode 40 least significant bits of 64-bit LE Supported Features into array values + * in little-endian format. + * + * Helper macro to encode 40 least significant bits of 64-bit LE Supported Features value into + * advertising data. The number of bits that are encoded is a number of LE Supported Features + * defined by BT 5.3 Core specification. + * + * Example of how to encode the `0x000000DFF00DF00D` into advertising data. + * + * @code + * BT_DATA_BYTES(BT_DATA_LE_SUPPORTED_FEATURES, BT_LE_SUPP_FEAT_40_ENCODE(0x000000DFF00DF00D)) + * @endcode + * + * @param w64 LE Supported Features value (64-bits) + * + * @return The comma separated values for LE Supported Features value that + * may be used directly as an argument for @ref BT_DATA_BYTES. + */ +#define BT_LE_SUPP_FEAT_40_ENCODE(w64) \ + (((w64) >> 0) & 0xFF), \ + (((w64) >> 8) & 0xFF), \ + (((w64) >> 16) & 0xFF), \ + (((w64) >> 24) & 0xFF), \ + (((w64) >> 32) & 0xFF) + +/** @brief Encode 4 least significant bytes of 64-bit LE Supported Features into + * 4 bytes long array of values in little-endian format. + * + * Helper macro to encode 64-bit LE Supported Features value into advertising + * data. The macro encodes 4 least significant bytes into advertising data. + * Other 4 bytes are not encoded. + * + * Example of how to encode the `0x000000DFF00DF00D` into advertising data. + * + * @code + * BT_DATA_BYTES(BT_DATA_LE_SUPPORTED_FEATURES, BT_LE_SUPP_FEAT_32_ENCODE(0x000000DFF00DF00D)) + * @endcode + * + * @param w64 LE Supported Features value (64-bits) + * + * @return The comma separated values for LE Supported Features value that + * may be used directly as an argument for @ref BT_DATA_BYTES. + */ +#define BT_LE_SUPP_FEAT_32_ENCODE(w64) \ + (((w64) >> 0) & 0xFF), \ + (((w64) >> 8) & 0xFF), \ + (((w64) >> 16) & 0xFF), \ + (((w64) >> 24) & 0xFF) + +/** + * @brief Encode 3 least significant bytes of 64-bit LE Supported Features into + * 3 bytes long array of values in little-endian format. + * + * Helper macro to encode 64-bit LE Supported Features value into advertising + * data. The macro encodes 3 least significant bytes into advertising data. + * Other 5 bytes are not encoded. + * + * Example of how to encode the `0x000000DFF00DF00D` into advertising data. + * + * @code + * BT_DATA_BYTES(BT_DATA_LE_SUPPORTED_FEATURES, BT_LE_SUPP_FEAT_24_ENCODE(0x000000DFF00DF00D)) + * @endcode + * + * @param w64 LE Supported Features value (64-bits) + * + * @return The comma separated values for LE Supported Features value that + * may be used directly as an argument for @ref BT_DATA_BYTES. + */ +#define BT_LE_SUPP_FEAT_24_ENCODE(w64) \ + (((w64) >> 0) & 0xFF), \ + (((w64) >> 8) & 0xFF), \ + (((w64) >> 16) & 0xFF), + +/** + * @brief Encode 2 least significant bytes of 64-bit LE Supported Features into + * 2 bytes long array of values in little-endian format. + * + * Helper macro to encode 64-bit LE Supported Features value into advertising + * data. The macro encodes 3 least significant bytes into advertising data. + * Other 6 bytes are not encoded. + * + * Example of how to encode the `0x000000DFF00DF00D` into advertising data. + * + * @code + * BT_DATA_BYTES(BT_DATA_LE_SUPPORTED_FEATURES, BT_LE_SUPP_FEAT_16_ENCODE(0x000000DFF00DF00D)) + * @endcode + * + * @param w64 LE Supported Features value (64-bits) + * + * @return The comma separated values for LE Supported Features value that + * may be used directly as an argument for @ref BT_DATA_BYTES. + */ +#define BT_LE_SUPP_FEAT_16_ENCODE(w64) \ + (((w64) >> 0) & 0xFF), \ + (((w64) >> 8) & 0xFF), + +/** + * @brief Encode the least significant byte of 64-bit LE Supported Features into + * single byte long array. + * + * Helper macro to encode 64-bit LE Supported Features value into advertising + * data. The macro encodes the least significant byte into advertising data. + * Other 7 bytes are not encoded. + * + * Example of how to encode the `0x000000DFF00DF00D` into advertising data. + * + * @code + * BT_DATA_BYTES(BT_DATA_LE_SUPPORTED_FEATURES, BT_LE_SUPP_FEAT_8_ENCODE(0x000000DFF00DF00D)) + * @endcode + * + * @param w64 LE Supported Features value (64-bits) + * + * @return The value of least significant byte of LE Supported Features value + * that may be used directly as an argument for @ref BT_DATA_BYTES. + */ +#define BT_LE_SUPP_FEAT_8_ENCODE(w64) \ + (((w64) >> 0) & 0xFF) + +/** + * @brief Validate wheather LE Supported Features value does not use bits that are reserved for + * future use. + * + * Helper macro to check if @p w64 has zeros as bits 40-63. The macro is compliant with BT 5.3 + * Core Specifiaction where bits 0-40 has assigned values. In case of invalid value, build time + * error is reported. + */ +#define BT_LE_SUPP_FEAT_VALIDATE(w64) \ + BUILD_ASSERT(!((w64) & (~BIT64_MASK(40))), \ + "RFU bit in LE Supported Features are not zeros.") + /** * @} */ From 33ff369ee380b5d07359ab4188b1b35afe95d894 Mon Sep 17 00:00:00 2001 From: Piotr Pryga Date: Thu, 13 Jan 2022 07:20:00 +0100 Subject: [PATCH 079/207] [nrf fromtree] samples: Bluetooth: df: Fix possible stack overflow issue Host receive thread has small default stack size. Attempt to convert data from binany to string requires large array. Allocation of such array on stack could cause stack overflow. To limit the scope of the array and avoid stack overflow the array is changed to be static local variable in a function. Also the array has been prepared to accept max advertising data sieze of 1650 bytes. Signed-off-by: Piotr Pryga (cherry picked from commit 30b5d03ddd40d1aeed360908bb98f7b763eaa6f2) --- .../bluetooth/direction_finding_connectionless_rx/src/main.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/samples/bluetooth/direction_finding_connectionless_rx/src/main.c b/samples/bluetooth/direction_finding_connectionless_rx/src/main.c index 28a00525fe7..548c1ff4a42 100644 --- a/samples/bluetooth/direction_finding_connectionless_rx/src/main.c +++ b/samples/bluetooth/direction_finding_connectionless_rx/src/main.c @@ -19,6 +19,8 @@ #define DEVICE_NAME_LEN (sizeof(DEVICE_NAME) - 1) #define NAME_LEN 30 #define TIMEOUT_SYNC_CREATE K_SECONDS(10) +/* Maximum length of advertising data represented in hexadecimal format */ +#define ADV_DATA_HEX_STR_LEN_MAX (BT_GAP_ADV_MAX_EXT_ADV_DATA_LEN * 2 + 1) static struct bt_le_per_adv_sync_param sync_create_param; static struct bt_le_per_adv_sync *sync; @@ -147,8 +149,8 @@ static void recv_cb(struct bt_le_per_adv_sync *sync, const struct bt_le_per_adv_sync_recv_info *info, struct net_buf_simple *buf) { + static char data_str[ADV_DATA_HEX_STR_LEN_MAX]; char le_addr[BT_ADDR_LE_STR_LEN]; - char data_str[129]; bt_addr_le_to_str(info->addr, le_addr, sizeof(le_addr)); bin2hex(buf->data, buf->len, data_str, sizeof(data_str)); From da9b5b238cd06bbf3f1b35a3fffca3798c519564 Mon Sep 17 00:00:00 2001 From: Piotr Pryga Date: Thu, 13 Jan 2022 07:15:02 +0100 Subject: [PATCH 080/207] [nrf fromtree] samples: Bluetooth: df: Fix too early per sync create timeout Periodic advertising synchronization create had a timeout set to fixed value of 10 seconds. BT 5.3 Core specification defines synchronization timeout as 6 consecutive periodic advertising events. When advertiser set the periodic interval to be more than 1.6 second it was possible the application timeout is reached before time allowed by BT Core specification. Changed implementation of timeout to depend on the periodic advertising interval. Signed-off-by: Piotr Pryga (cherry picked from commit dbe4294be2844a14fc63723edda9381b6c0f036f) --- include/bluetooth/gap.h | 7 ++++++- .../src/main.c | 17 +++++++++++++++-- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/include/bluetooth/gap.h b/include/bluetooth/gap.h index ff8a88b168c..e9df2941182 100644 --- a/include/bluetooth/gap.h +++ b/include/bluetooth/gap.h @@ -163,6 +163,12 @@ enum { /** Maximum Periodic Advertising Interval (N * 1.25 ms) */ #define BT_GAP_PER_ADV_MAX_INTERVAL 0xFFFF +/** + * @brief Convert periodic advertising interval (N * 1.25 ms) to milliseconds + * + * 5 / 4 represents 1.25 ms unit. + */ +#define BT_GAP_PER_ADV_INTERVAL_TO_MS(interval) ((interval) * 5 / 4) /** Constant Tone Extension (CTE) types */ enum { @@ -176,7 +182,6 @@ enum { BT_GAP_CTE_NONE = 0xFF, }; - /** @brief Peripheral sleep clock accuracy (SCA) in ppm (parts per million) */ enum { BT_GAP_SCA_UNKNOWN = 0, diff --git a/samples/bluetooth/direction_finding_connectionless_rx/src/main.c b/samples/bluetooth/direction_finding_connectionless_rx/src/main.c index 548c1ff4a42..afd1973c758 100644 --- a/samples/bluetooth/direction_finding_connectionless_rx/src/main.c +++ b/samples/bluetooth/direction_finding_connectionless_rx/src/main.c @@ -13,12 +13,18 @@ #include #include +#include #include #define DEVICE_NAME CONFIG_BT_DEVICE_NAME #define DEVICE_NAME_LEN (sizeof(DEVICE_NAME) - 1) #define NAME_LEN 30 -#define TIMEOUT_SYNC_CREATE K_SECONDS(10) +#define PEER_NAME_LEN_MAX 30 +/* BT Core 5.3 Vol 6, Part B section 4.4.5.1 Periodic Advertising Trains allows controller to wait + * 6 periodic advertising events for synchronization establishment, hence timeout must be longer + * than that. + */ +#define SYNC_CREATE_TIMEOUT_INTERVAL_NUM 7 /* Maximum length of advertising data represented in hexadecimal format */ #define ADV_DATA_HEX_STR_LEN_MAX (BT_GAP_ADV_MAX_EXT_ADV_DATA_LEN * 2 + 1) @@ -28,6 +34,7 @@ static bt_addr_le_t per_addr; static bool per_adv_found; static bool scan_enabled; static uint8_t per_sid; +static uint32_t sync_create_timeout_ms; static K_SEM_DEFINE(sem_per_adv, 0, 1); static K_SEM_DEFINE(sem_per_sync, 0, 1); @@ -67,6 +74,11 @@ static struct bt_le_scan_cb scan_callbacks = { .recv = scan_recv, }; +static uint32_t sync_create_timeout_get(uint16_t interval) +{ + return BT_GAP_PER_ADV_INTERVAL_TO_MS(interval) * SYNC_CREATE_TIMEOUT_INTERVAL_NUM; +} + static const char *phy2str(uint8_t phy) { switch (phy) { @@ -196,6 +208,7 @@ static void scan_recv(const struct bt_le_scan_recv_info *info, info->interval, info->interval * 5 / 4, info->sid); if (!per_adv_found && info->interval != 0) { + sync_create_timeout_ms = sync_create_timeout_get(info->interval); per_adv_found = true; per_sid = info->sid; bt_addr_le_copy(&per_addr, info->addr); @@ -346,7 +359,7 @@ void main(void) create_sync(); printk("Waiting for periodic sync...\n"); - err = k_sem_take(&sem_per_sync, TIMEOUT_SYNC_CREATE); + err = k_sem_take(&sem_per_sync, K_MSEC(sync_create_timeout_ms)); if (err != 0) { printk("failed (err %d)\n", err); err = delete_sync(); From 7c194defbe656c8218cb2abef0d3c4ba608ddf0c Mon Sep 17 00:00:00 2001 From: Piotr Pryga Date: Tue, 4 Jan 2022 07:39:13 +0100 Subject: [PATCH 081/207] [nrf fromtree] Bluetooth: Controller: ull: df: use new LLCP structus in conn CTE req The implementation of the ll_df_set_conn_cte_req_enable function was based on former implementation of LLCPs. The CTE request and response control procedures are not implemented in former LLCPs framework. The code has been updated to use data structues from refactored implementation of LLCPs. Signed-off-by: Piotr Pryga (cherry picked from commit c06f6b5874ffed5cba53a157dd4f4ce33abbf4d3) --- subsys/bluetooth/controller/ll_sw/ull_df.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/subsys/bluetooth/controller/ll_sw/ull_df.c b/subsys/bluetooth/controller/ll_sw/ull_df.c index c2675d7bec0..4c6a285d615 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_df.c +++ b/subsys/bluetooth/controller/ll_sw/ull_df.c @@ -36,10 +36,12 @@ #include "ull_sync_types.h" #include "ull_sync_internal.h" #include "ull_adv_types.h" +#include "ull_tx_queue.h" #include "ull_conn_types.h" #include "ull_conn_internal.h" #include "ull_df_types.h" #include "ull_df_internal.h" +#include "ull_llcp.h" #include "ull_adv_internal.h" #include "ull_internal.h" @@ -1189,11 +1191,11 @@ uint8_t ll_df_set_conn_cte_req_enable(uint16_t handle, uint8_t enable, uint8_t c /* If controller is aware of features supported by peer device then check * whether required features are enabled. */ - if (conn->common.fex_valid && - (!(conn->llcp_feature.features_peer & BIT64(BT_LE_FEAT_BIT_CONN_CTE_RESP)) || + if (conn->llcp.fex.valid && + (!(conn->llcp.fex.features_peer & BIT64(BT_LE_FEAT_BIT_CONN_CTE_RESP)) || ((requested_cte_type == BT_HCI_LE_AOD_CTE_1US || requested_cte_type == BT_HCI_LE_AOD_CTE_2US) && - !(conn->llcp_feature.features_peer & + !(conn->llcp.fex.features_peer & BIT64(BT_LE_FEAT_BIT_ANT_SWITCH_TX_AOD))))) { return BT_HCI_ERR_UNSUPP_REMOTE_FEATURE; } From b65d2748b0cb08104254960c43d4ce444c0d634a Mon Sep 17 00:00:00 2001 From: Piotr Pryga Date: Tue, 4 Jan 2022 07:56:02 +0100 Subject: [PATCH 082/207] [nrf fromtree] Bluetooth: Controller: Add Kconfig to enable CTE RX in conn mode The CTE reception and sampling in connected mode was enabled with CONFIG_BT_CTLR_DF_CONN_CTE_REQ. This is a separate fearure tha can be enabled when CTE reqest procedure is disabled. What more the CONFIG_BT_CTLR_DF_CONN_CTE_REQ is dependent on CONFIG_BT_CTLR_DF_CONN_CTE_RX, not other way around. The commit adds separate Kconfig to provide such possibility. Also changes compilation guards for code related with the CTE reception and sampling. Signed-off-by: Piotr Pryga (cherry picked from commit 31209b1be2f6590406a12038cfca23c41844ef86) --- subsys/bluetooth/controller/Kconfig.df | 8 ++--- subsys/bluetooth/controller/hci/hci.c | 16 +++++----- subsys/bluetooth/controller/ll_sw/lll_conn.h | 4 +-- .../controller/ll_sw/nordic/lll/lll_central.c | 8 ++--- .../controller/ll_sw/nordic/lll/lll_conn.c | 32 +++++++++---------- .../controller/ll_sw/nordic/lll/lll_df.c | 8 ++--- .../ll_sw/nordic/lll/lll_peripheral.c | 8 ++--- subsys/bluetooth/controller/ll_sw/ull.c | 12 +++---- subsys/bluetooth/controller/ll_sw/ull_adv.c | 4 +-- .../bluetooth/controller/ll_sw/ull_central.c | 4 +-- subsys/bluetooth/controller/ll_sw/ull_df.c | 20 ++++++------ 11 files changed, 62 insertions(+), 62 deletions(-) diff --git a/subsys/bluetooth/controller/Kconfig.df b/subsys/bluetooth/controller/Kconfig.df index 9033e634737..5dbcfaf863d 100644 --- a/subsys/bluetooth/controller/Kconfig.df +++ b/subsys/bluetooth/controller/Kconfig.df @@ -97,7 +97,7 @@ config BT_CTLR_DF_CTE_RX config BT_CTLR_DF_CONN_CTE_REQ bool "Enable Connection CTE Request feature" - depends on BT_CTLR_DF_CTE_RX && BT_CONN + depends on BT_CTLR_DF_CONN_CTE_RX help Enable support for Bluetooth v5.1 Connection CTE Request feature in controller. @@ -134,13 +134,13 @@ config BT_CTLR_DF_CONN_CTE_TX Enable transmission of Constant Tone Extension in direction finding connected mode. -config BT_CTRL_DF_CONN_CTE_RX +config BT_CTLR_DF_CONN_CTE_RX bool "Enable Connection based CTE Receiver" depends on BT_CTLR_DF_CTE_RX && BT_CONN default y help - Enable reception and sampling of Constant Tone Extension in - direction finding connected mode. + Enable reception and sampling of Constant Tone Extension in direction + finding connected mode. config BT_CTLR_DF_SAMPLE_CTE_FOR_PDU_WITH_BAD_CRC bool "Enable sampling of CTE for PDUs with bad CRC" diff --git a/subsys/bluetooth/controller/hci/hci.c b/subsys/bluetooth/controller/hci/hci.c index a8262c5a06b..998c2106348 100644 --- a/subsys/bluetooth/controller/hci/hci.c +++ b/subsys/bluetooth/controller/hci/hci.c @@ -2878,7 +2878,7 @@ static void le_df_set_conn_cte_tx_params(struct net_buf *buf, } #endif /* CONFIG_BT_CTLR_DF_CONN_CTE_TX */ -#if defined(CONFIG_BT_CTRL_DF_CONN_CTE_RX) +#if defined(CONFIG_BT_CTLR_DF_CONN_CTE_RX) static void le_df_set_conn_cte_rx_params(struct net_buf *buf, struct net_buf **evt) { struct bt_hci_cp_le_set_conn_cte_rx_params *cmd = (void *)buf->data; @@ -2970,7 +2970,7 @@ static void le_df_connection_iq_report(struct node_rx_pdu *node_rx, struct net_b sep->sample_count = samples_cnt; } } -#endif /* CONFIG_BT_CTRL_DF_CONN_CTE_RX */ +#endif /* CONFIG_BT_CTLR_DF_CONN_CTE_RX */ #if defined(CONFIG_BT_CTLR_DF_CONN_CTE_REQ) static void le_df_set_conn_cte_req_enable(struct net_buf *buf, struct net_buf **evt) @@ -4336,11 +4336,11 @@ static int controller_cmd_handle(uint16_t ocf, struct net_buf *cmd, le_df_set_conn_cte_tx_params(cmd, evt); break; #endif /* CONFIG_BT_CTLR_DF_CONN_CTE_TX */ -#if defined(CONFIG_BT_CTRL_DF_CONN_CTE_RX) +#if defined(CONFIG_BT_CTLR_DF_CONN_CTE_RX) case BT_OCF(BT_HCI_OP_LE_SET_CONN_CTE_RX_PARAMS): le_df_set_conn_cte_rx_params(cmd, evt); break; -#endif /* CONFIG_BT_CTRL_DF_CONN_CTE_RX */ +#endif /* CONFIG_BT_CTLR_DF_CONN_CTE_RX */ #if defined(CONFIG_BT_CTLR_DF_CONN_CTE_REQ) case BT_OCF(BT_HCI_OP_LE_CONN_CTE_REQ_ENABLE): le_df_set_conn_cte_req_enable(cmd, evt); @@ -7193,11 +7193,11 @@ static void encode_control(struct node_rx_pdu *node_rx, return; #endif /* CONFIG_BT_CTLR_CONN_ISO */ -#if defined(CONFIG_BT_CTRL_DF_CONN_CTE_RX) +#if defined(CONFIG_BT_CTLR_DF_CONN_CTE_RX) case NODE_RX_TYPE_CONN_IQ_SAMPLE_REPORT: le_df_connection_iq_report(node_rx, buf); return; -#endif /* CONFIG_BT_CTRL_DF_CONN_CTE_RX */ +#endif /* CONFIG_BT_CTLR_DF_CONN_CTE_RX */ #endif /* CONFIG_BT_CONN */ #if defined(CONFIG_BT_CTLR_ADV_INDICATION) @@ -7620,9 +7620,9 @@ uint8_t hci_get_class(struct node_rx_pdu *node_rx) #if defined(CONFIG_BT_CTLR_CONN_ISO) case NODE_RX_TYPE_CIS_ESTABLISHED: #endif /* CONFIG_BT_CTLR_CONN_ISO */ -#if defined(CONFIG_BT_CTRL_DF_CONN_CTE_RX) +#if defined(CONFIG_BT_CTLR_DF_CONN_CTE_RX) case NODE_RX_TYPE_CONN_IQ_SAMPLE_REPORT: -#endif /* CONFIG_BT_CTRL_DF_CONN_CTE_RX */ +#endif /* CONFIG_BT_CTLR_DF_CONN_CTE_RX */ return HCI_CLASS_EVT_REQUIRED; case NODE_RX_TYPE_TERMINATE: diff --git a/subsys/bluetooth/controller/ll_sw/lll_conn.h b/subsys/bluetooth/controller/ll_sw/lll_conn.h index 8b75670e6f8..ef4f9d3b9f3 100644 --- a/subsys/bluetooth/controller/ll_sw/lll_conn.h +++ b/subsys/bluetooth/controller/ll_sw/lll_conn.h @@ -148,9 +148,9 @@ struct lll_conn { int8_t tx_pwr_lvl; #endif -#if defined(CONFIG_BT_CTRL_DF_CONN_CTE_RX) +#if defined(CONFIG_BT_CTLR_DF_CONN_CTE_RX) struct lll_df_conn_rx_cfg df_rx_cfg; -#endif /* CONFIG_BT_CTRL_DF_CONN_CTE_RX */ +#endif /* CONFIG_BT_CTLR_DF_CONN_CTE_RX */ #if defined(CONFIG_BT_CTLR_DF_CONN_CTE_TX) struct lll_df_conn_tx_cfg df_tx_cfg; #endif /* CONFIG_BT_CTLR_DF_CONN_CTE_TX */ diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_central.c b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_central.c index 8ef6ba1315c..03e8fc5c459 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_central.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_central.c @@ -88,10 +88,10 @@ static int init_reset(void) static int prepare_cb(struct lll_prepare_param *p) { -#if defined(CONFIG_BT_CTRL_DF_CONN_CTE_RX) +#if defined(CONFIG_BT_CTLR_DF_CONN_CTE_RX) struct lll_df_conn_rx_params *df_rx_params; struct lll_df_conn_rx_cfg *df_rx_cfg; -#endif /* CONFIG_BT_CTRL_DF_CONN_CTE_RX */ +#endif /* CONFIG_BT_CTLR_DF_CONN_CTE_RX */ struct pdu_data *pdu_data_tx; uint32_t ticks_at_event; uint32_t ticks_at_start; @@ -184,7 +184,7 @@ static int prepare_cb(struct lll_prepare_param *p) radio_tmr_tifs_set(EVENT_IFS_US); -#if defined(CONFIG_BT_CTRL_DF_CONN_CTE_RX) +#if defined(CONFIG_BT_CTLR_DF_CONN_CTE_RX) /* If CTE RX is enabled and the PHY is not CODED, store channel used for * the connection event to report it with collected IQ samples. * The configuration of the CTE receive may not change during the event, @@ -198,7 +198,7 @@ static int prepare_cb(struct lll_prepare_param *p) lll->df_rx_cfg.chan = data_chan_use; } } -#endif /* CONFIG_BT_CTRL_DF_CONN_CTE_RX */ +#endif /* CONFIG_BT_CTLR_DF_CONN_CTE_RX */ #if defined(CONFIG_BT_CTLR_PHY) radio_switch_complete_and_rx(lll->phy_rx); diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_conn.c b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_conn.c index 5aeb193a9e8..a595b9015bf 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_conn.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_conn.c @@ -48,10 +48,10 @@ static inline int isr_rx_pdu(struct lll_conn *lll, struct pdu_data *pdu_data_rx, uint8_t *is_rx_enqueue, struct node_tx **tx_release, uint8_t *is_done); static void empty_tx_init(void); -#if defined(CONFIG_BT_CTRL_DF_CONN_CTE_RX) +#if defined(CONFIG_BT_CTLR_DF_CONN_CTE_RX) static inline bool create_iq_report(struct lll_conn *lll, uint8_t rssi_ready, uint8_t packet_status); -#endif /* CONFIG_BT_CTRL_DF_CONN_CTE_RX */ +#endif /* CONFIG_BT_CTLR_DF_CONN_CTE_RX */ #if defined(CONFIG_BT_CTLR_DF_CONN_CTE_TX) static struct pdu_data *get_last_tx_pdu(struct lll_conn *lll); #endif /* CONFIG_BT_CTLR_DF_CONN_CTE_TX */ @@ -195,9 +195,9 @@ void lll_conn_isr_rx(void *param) uint8_t is_done; uint8_t cte_len; uint8_t crc_ok; -#if defined(CONFIG_BT_CTRL_DF_CONN_CTE_RX) +#if defined(CONFIG_BT_CTLR_DF_CONN_CTE_RX) bool cte_ready; -#endif /* CONFIG_BT_CTRL_DF_CONN_CTE_RX */ +#endif /* CONFIG_BT_CTLR_DF_CONN_CTE_RX */ if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) { lll_prof_latency_capture(); @@ -208,15 +208,15 @@ void lll_conn_isr_rx(void *param) if (trx_done) { crc_ok = radio_crc_is_valid(); rssi_ready = radio_rssi_is_ready(); -#if defined(CONFIG_BT_CTRL_DF_CONN_CTE_RX) +#if defined(CONFIG_BT_CTLR_DF_CONN_CTE_RX) cte_ready = radio_df_cte_ready(); -#endif /* CONFIG_BT_CTRL_DF_CONN_CTE_RX */ +#endif /* CONFIG_BT_CTLR_DF_CONN_CTE_RX */ } else { crc_ok = rssi_ready = 0U; -#if defined(CONFIG_BT_CTRL_DF_CONN_CTE_RX) +#if defined(CONFIG_BT_CTLR_DF_CONN_CTE_RX) cte_ready = 0U; -#endif /* CONFIG_BT_CTRL_DF_CONN_CTE_RX */ +#endif /* CONFIG_BT_CTLR_DF_CONN_CTE_RX */ } /* Clear radio rx status and events */ @@ -406,7 +406,7 @@ void lll_conn_isr_rx(void *param) is_ull_rx = 1U; } -#if defined(CONFIG_BT_CTRL_DF_CONN_CTE_RX) +#if defined(CONFIG_BT_CTLR_DF_CONN_CTE_RX) if (cte_ready) { is_iq_report = create_iq_report(lll, rssi_ready, @@ -415,7 +415,7 @@ void lll_conn_isr_rx(void *param) } else { #else if (1) { -#endif /* CONFIG_BT_CTRL_DF_CONN_CTE_RX */ +#endif /* CONFIG_BT_CTLR_DF_CONN_CTE_RX */ is_iq_report = false; } @@ -467,7 +467,7 @@ void lll_conn_isr_tx(void *param) lll = param; -#if defined(CONFIG_BT_CTRL_DF_CONN_CTE_RX) +#if defined(CONFIG_BT_CTLR_DF_CONN_CTE_RX) #if defined(CONFIG_BT_CTLR_DF_PHYEND_OFFSET_COMPENSATION_ENABLE) enum radio_end_evt_delay_state end_evt_delay; #endif /* CONFIG_BT_CTLR_DF_PHYEND_OFFSET_COMPENSATION_ENABLE */ @@ -506,7 +506,7 @@ void lll_conn_isr_tx(void *param) #endif /* !CONFIG_BT_CTLR_PHY */ #endif /* CONFIG_BT_CTLR_DF_PHYEND_OFFSET_COMPENSATION_ENABLE */ -#endif /* CONFIG_BT_CTRL_DF_CONN_CTE_RX */ +#endif /* CONFIG_BT_CTLR_DF_CONN_CTE_RX */ /* Use regular API for cases when: * - CTE RX is not enabled, @@ -554,13 +554,13 @@ void lll_conn_isr_tx(void *param) radio_tmr_hcto_configure(hcto); -#if defined(CONFIG_BT_CTRL_DF_CONN_CTE_RX) +#if defined(CONFIG_BT_CTLR_DF_CONN_CTE_RX) if (true) { #elif defined(CONFIG_BT_CENTRAL) && defined(CONFIG_BT_CTLR_CONN_RSSI) if (!trx_cnt && !lll->role) { #else if (false) { -#endif /* CONFIG_BT_CTRL_DF_CONN_CTE_RX */ +#endif /* CONFIG_BT_CTLR_DF_CONN_CTE_RX */ radio_rssi_measure(); } @@ -1004,7 +1004,7 @@ static void empty_tx_init(void) p->ll_id = PDU_DATA_LLID_DATA_CONTINUE; } -#if defined(CONFIG_BT_CTRL_DF_CONN_CTE_RX) +#if defined(CONFIG_BT_CTLR_DF_CONN_CTE_RX) static inline bool create_iq_report(struct lll_conn *lll, uint8_t rssi_ready, uint8_t packet_status) { struct lll_df_conn_rx_params *rx_params; @@ -1047,7 +1047,7 @@ static inline bool create_iq_report(struct lll_conn *lll, uint8_t rssi_ready, ui return false; } -#endif /* CONFIG_BT_CTRL_DF_CONN_CTE_RX */ +#endif /* CONFIG_BT_CTLR_DF_CONN_CTE_RX */ #if defined(CONFIG_BT_CTLR_DF_CONN_CTE_TX) /** diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_df.c b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_df.c index 8e58773e5d3..657bdc6105c 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_df.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_df.c @@ -225,7 +225,7 @@ struct lll_df_sync_cfg *lll_df_sync_cfg_latest_get(struct lll_df_sync *df_cfg, } #endif /* CONFIG_BT_CTLR_DF_SCAN_CTE_RX */ -#if defined(CONFIG_BT_CTLR_DF_SCAN_CTE_RX) || defined(CONFIG_BT_CTRL_DF_CONN_CTE_RX) +#if defined(CONFIG_BT_CTLR_DF_SCAN_CTE_RX) || defined(CONFIG_BT_CTLR_DF_CONN_CTE_RX) /* @brief Function initializes reception of Constant Tone Extension. * * @param slot_duration Switching and sampling slots duration (1us or 2us). @@ -264,9 +264,9 @@ void lll_df_conf_cte_rx_enable(uint8_t slot_duration, uint8_t ant_num, const uin radio_df_iq_data_packet_set(node_rx->pdu, IQ_SAMPLE_TOTAL_CNT); node_rx->chan_idx = chan_idx; } -#endif /* CONFIG_BT_CTLR_DF_SCAN_CTE_RX || CONFIG_BT_CTRL_DF_CONN_CTE_RX */ +#endif /* CONFIG_BT_CTLR_DF_SCAN_CTE_RX || CONFIG_BT_CTLR_DF_CONN_CTE_RX */ -#if defined(CONFIG_BT_CTRL_DF_CONN_CTE_RX) +#if defined(CONFIG_BT_CTLR_DF_CONN_CTE_RX) /** * @brief Function initializes parsing of received PDU for CTEInfo. * @@ -293,7 +293,7 @@ void lll_df_conf_cte_info_parsing_enable(void) /* Do not set storage for IQ samples, it is irrelevant for parsing of a PDU for CTEInfo. */ radio_df_iq_data_packet_set(NULL, 0); } -#endif /* CONFIG_BT_CTRL_DF_CONN_CTE_RX */ +#endif /* CONFIG_BT_CTLR_DF_CONN_CTE_RX */ /* @brief Function performs common steps for initialization and reset * of Direction Finding LLL module. diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_peripheral.c b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_peripheral.c index 7587ff17d6c..761bf1ed8c6 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_peripheral.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_peripheral.c @@ -101,10 +101,10 @@ static int init_reset(void) static int prepare_cb(struct lll_prepare_param *p) { -#if defined(CONFIG_BT_CTRL_DF_CONN_CTE_RX) +#if defined(CONFIG_BT_CTLR_DF_CONN_CTE_RX) struct lll_df_conn_rx_params *df_rx_params; struct lll_df_conn_rx_cfg *df_rx_cfg; -#endif /* CONFIG_BT_CTRL_DF_CONN_CTE_RX */ +#endif /* CONFIG_BT_CTLR_DF_CONN_CTE_RX */ uint32_t ticks_at_event; uint32_t ticks_at_start; uint16_t event_counter; @@ -213,7 +213,7 @@ static int prepare_cb(struct lll_prepare_param *p) radio_tmr_tifs_set(EVENT_IFS_US); -#if defined(CONFIG_BT_CTRL_DF_CONN_CTE_RX) +#if defined(CONFIG_BT_CTLR_DF_CONN_CTE_RX) #if defined(CONFIG_BT_CTLR_DF_PHYEND_OFFSET_COMPENSATION_ENABLE) enum radio_end_evt_delay_state end_evt_delay; #endif /* CONFIG_BT_CTLR_DF_PHYEND_OFFSET_COMPENSATION_ENABLE */ @@ -247,7 +247,7 @@ static int prepare_cb(struct lll_prepare_param *p) #endif /* !CONFIG_BT_CTLR_PHY */ #endif /* CONFIG_BT_CTLR_DF_PHYEND_OFFSET_COMPENSATION_ENABLE */ -#endif /* CONFIG_BT_CTRL_DF_CONN_CTE_RX */ +#endif /* CONFIG_BT_CTLR_DF_CONN_CTE_RX */ /* Use regular API for cases when: * - CTE RX is not enabled, diff --git a/subsys/bluetooth/controller/ll_sw/ull.c b/subsys/bluetooth/controller/ll_sw/ull.c index 60b991c47bf..017496dc906 100644 --- a/subsys/bluetooth/controller/ll_sw/ull.c +++ b/subsys/bluetooth/controller/ll_sw/ull.c @@ -1206,9 +1206,9 @@ void ll_rx_dequeue(void) case NODE_RX_TYPE_SYNC_IQ_SAMPLE_REPORT: #endif /* CONFIG_BT_CTLR_DF_SCAN_CTE_RX */ -#if defined(CONFIG_BT_CTRL_DF_CONN_CTE_RX) +#if defined(CONFIG_BT_CTLR_DF_CONN_CTE_RX) case NODE_RX_TYPE_CONN_IQ_SAMPLE_REPORT: -#endif /* CONFIG_BT_CTRL_DF_CONN_CTE_RX */ +#endif /* CONFIG_BT_CTLR_DF_CONN_CTE_RX */ /* Ensure that at least one 'case' statement is present for this * code block. @@ -1483,7 +1483,7 @@ void ll_rx_mem_release(void **node_rx) #endif /* CONFIG_BT_CTLR_SYNC_ISO */ #endif /* CONFIG_BT_CTLR_SYNC_PERIODIC */ -#if defined(CONFIG_BT_CTLR_DF_SCAN_CTE_RX) || defined(CONFIG_BT_CTRL_DF_CONN_CTE_RX) +#if defined(CONFIG_BT_CTLR_DF_SCAN_CTE_RX) || defined(CONFIG_BT_CTLR_DF_CONN_CTE_RX) case NODE_RX_TYPE_SYNC_IQ_SAMPLE_REPORT: case NODE_RX_TYPE_CONN_IQ_SAMPLE_REPORT: { @@ -1494,7 +1494,7 @@ void ll_rx_mem_release(void **node_rx) ull_df_rx_iq_report_alloc(report_cnt); } break; -#endif /* CONFIG_BT_CTLR_DF_SCAN_CTE_RX || CONFIG_BT_CTRL_DF_CONN_CTE_RX */ +#endif /* CONFIG_BT_CTLR_DF_SCAN_CTE_RX || CONFIG_BT_CTLR_DF_CONN_CTE_RX */ #if defined(CONFIG_BT_CONN) || defined(CONFIG_BT_CTLR_CONN_ISO) case NODE_RX_TYPE_TERMINATE: @@ -2445,7 +2445,7 @@ static inline int rx_demux_rx(memq_link_t *link, struct node_rx_hdr *rx) #endif /* CONFIG_BT_CTLR_ADV_EXT */ #endif /* CONFIG_BT_OBSERVER */ -#if defined(CONFIG_BT_CTLR_DF_SCAN_CTE_RX) || defined(CONFIG_BT_CTRL_DF_CONN_CTE_RX) +#if defined(CONFIG_BT_CTLR_DF_SCAN_CTE_RX) || defined(CONFIG_BT_CTLR_DF_CONN_CTE_RX) case NODE_RX_TYPE_SYNC_IQ_SAMPLE_REPORT: case NODE_RX_TYPE_CONN_IQ_SAMPLE_REPORT: { @@ -2454,7 +2454,7 @@ static inline int rx_demux_rx(memq_link_t *link, struct node_rx_hdr *rx) ll_rx_sched(); } break; -#endif /* CONFIG_BT_CTLR_DF_SCAN_CTE_RX || CONFIG_BT_CTRL_DF_CONN_CTE_RX */ +#endif /* CONFIG_BT_CTLR_DF_SCAN_CTE_RX || CONFIG_BT_CTLR_DF_CONN_CTE_RX */ #if defined(CONFIG_BT_CONN) case NODE_RX_TYPE_CONNECTION: diff --git a/subsys/bluetooth/controller/ll_sw/ull_adv.c b/subsys/bluetooth/controller/ll_sw/ull_adv.c index 88c31505f63..a42b98c6f83 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_adv.c +++ b/subsys/bluetooth/controller/ll_sw/ull_adv.c @@ -1025,9 +1025,9 @@ uint8_t ll_adv_enable(uint8_t enable) #if defined(CONFIG_BT_CTLR_CONN_META) memset(&conn_lll->conn_meta, 0, sizeof(conn_lll->conn_meta)); #endif /* CONFIG_BT_CTLR_CONN_META */ -#if defined(CONFIG_BT_CTRL_DF_CONN_CTE_RX) +#if defined(CONFIG_BT_CTLR_DF_CONN_CTE_RX) conn_lll->df_rx_cfg.hdr.elem_size = sizeof(struct lll_df_conn_rx_params); -#endif /* CONFIG_BT_CTRL_DF_CONN_CTE_RX */ +#endif /* CONFIG_BT_CTLR_DF_CONN_CTE_RX */ conn->connect_expire = 6; conn->supervision_expire = 0; diff --git a/subsys/bluetooth/controller/ll_sw/ull_central.c b/subsys/bluetooth/controller/ll_sw/ull_central.c index c5a3b590dd2..14978610fd0 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_central.c +++ b/subsys/bluetooth/controller/ll_sw/ull_central.c @@ -270,10 +270,10 @@ uint8_t ll_create_connection(uint16_t scan_interval, uint16_t scan_window, memset(&conn_lll->conn_meta, 0, sizeof(conn_lll->conn_meta)); #endif /* CONFIG_BT_CTLR_CONN_META */ -#if defined(CONFIG_BT_CTRL_DF_CONN_CTE_RX) +#if defined(CONFIG_BT_CTLR_DF_CONN_CTE_RX) conn_lll->df_rx_cfg.is_initialized = false; conn_lll->df_rx_cfg.hdr.elem_size = sizeof(struct lll_df_conn_rx_params); -#endif /* CONFIG_BT_CTRL_DF_CONN_CTE_RX */ +#endif /* CONFIG_BT_CTLR_DF_CONN_CTE_RX */ conn->connect_expire = CONN_ESTAB_COUNTDOWN; conn->supervision_expire = 0U; diff --git a/subsys/bluetooth/controller/ll_sw/ull_df.c b/subsys/bluetooth/controller/ll_sw/ull_df.c index 4c6a285d615..f8647f72aad 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_df.c +++ b/subsys/bluetooth/controller/ll_sw/ull_df.c @@ -53,7 +53,7 @@ #include "common/log.h" #include "hal/debug.h" -#if defined(CONFIG_BT_CTLR_DF_SCAN_CTE_RX) || defined(CONFIG_BT_CTRL_DF_CONN_CTE_RX) +#if defined(CONFIG_BT_CTLR_DF_SCAN_CTE_RX) || defined(CONFIG_BT_CTLR_DF_CONN_CTE_RX) #define CTE_LEN_MAX_US 160U @@ -76,7 +76,7 @@ static MFIFO_DEFINE(iq_report_free, sizeof(void *), IQ_REPORT_CNT); /* Number of available instance of linked list to be used for node_rx_iq_reports. */ static uint8_t mem_link_iq_report_quota_pdu; -#endif /* CONFIG_BT_CTLR_DF_SCAN_CTE_RX || CONFIG_BT_CTRL_DF_CONN_CTE_RX*/ +#endif /* CONFIG_BT_CTLR_DF_SCAN_CTE_RX || CONFIG_BT_CTLR_DF_CONN_CTE_RX*/ /* ToDo: * - Add release of df_adv_cfg when adv_sync is released. @@ -168,7 +168,7 @@ static int init_reset(void) &df_adv_cfg_free); #endif /* CONFIG_BT_CTLR_DF_ADV_CTE_TX */ -#if defined(CONFIG_BT_CTLR_DF_SCAN_CTE_RX) || defined(CONFIG_BT_CTRL_DF_CONN_CTE_RX) +#if defined(CONFIG_BT_CTLR_DF_SCAN_CTE_RX) || defined(CONFIG_BT_CTLR_DF_CONN_CTE_RX) /* Re-initialize the free IQ report mfifo */ MFIFO_INIT(iq_report_free); @@ -180,7 +180,7 @@ static int init_reset(void) /* Allocate free IQ report node rx */ mem_link_iq_report_quota_pdu = IQ_REPORT_CNT; ull_df_rx_iq_report_alloc(UINT8_MAX); -#endif /* CONFIG_BT_CTLR_DF_SCAN_CTE_RX || CONFIG_BT_CTRL_DF_CONN_CTE_RX */ +#endif /* CONFIG_BT_CTLR_DF_SCAN_CTE_RX || CONFIG_BT_CTLR_DF_CONN_CTE_RX */ return 0; } @@ -499,7 +499,7 @@ bool ull_df_sync_cfg_is_not_enabled(struct lll_df_sync *df_cfg) } #endif /* CONFIG_BT_CTLR_DF_SCAN_CTE_RX */ -#if defined(CONFIG_BT_CTLR_DF_SCAN_CTE_RX) || defined(CONFIG_BT_CTRL_DF_CONN_CTE_RX) +#if defined(CONFIG_BT_CTLR_DF_SCAN_CTE_RX) || defined(CONFIG_BT_CTLR_DF_CONN_CTE_RX) void *ull_df_iq_report_alloc_peek(uint8_t count) { if (count > MFIFO_AVAIL_COUNT_GET(iq_report_free)) { @@ -560,9 +560,9 @@ void ull_df_rx_iq_report_alloc(uint8_t max) ull_iq_report_link_inc_quota(-1); } } -#endif /* CONFIG_BT_CTLR_DF_SCAN_CTE_RX || CONFIG_BT_CTRL_DF_CONN_CTE_RX */ +#endif /* CONFIG_BT_CTLR_DF_SCAN_CTE_RX || CONFIG_BT_CTLR_DF_CONN_CTE_RX */ -#if defined(CONFIG_BT_CTRL_DF_CONN_CTE_RX) +#if defined(CONFIG_BT_CTLR_DF_CONN_CTE_RX) bool ull_df_conn_cfg_is_not_enabled(struct lll_df_conn_rx_cfg *rx_cfg) { struct lll_df_conn_rx_params *rx_params; @@ -582,7 +582,7 @@ bool ull_df_conn_cfg_is_not_enabled(struct lll_df_conn_rx_cfg *rx_cfg) return !rx_params->is_enabled; } -#endif /* CONFIG_BT_CTRL_DF_CONN_CTE_RX */ +#endif /* CONFIG_BT_CTLR_DF_CONN_CTE_RX */ #if defined(CONFIG_BT_CTLR_DF_ADV_CTE_TX) /* @brief Function releases unused memory for DF advertising configuration. @@ -1049,7 +1049,7 @@ uint8_t ll_df_set_conn_cte_tx_params(uint16_t handle, uint8_t cte_types, uint8_t } #endif /* CONFIG_BT_CTLR_DF_CONN_CTE_TX */ -#if defined(CONFIG_BT_CTRL_DF_CONN_CTE_RX) +#if defined(CONFIG_BT_CTLR_DF_CONN_CTE_RX) /** * @brief Function sets CTE reception parameters for a connection. * @@ -1118,7 +1118,7 @@ uint8_t ll_df_set_conn_cte_rx_params(uint16_t handle, uint8_t sampling_enable, return BT_HCI_ERR_SUCCESS; } -#endif /* CONFIG_BT_CTRL_DF_CONN_CTE_RX */ +#endif /* CONFIG_BT_CTLR_DF_CONN_CTE_RX */ #if defined(CONFIG_BT_CTLR_DF_CONN_CTE_REQ) /* @brief Function enables or disables CTE request control procedure for a connection. From ea808562f9f049f3ae3c3c9f96c7c5d16bda0625 Mon Sep 17 00:00:00 2001 From: Piotr Pryga Date: Tue, 4 Jan 2022 09:01:17 +0100 Subject: [PATCH 083/207] [nrf fromtree] BLuetooth: Controller: llcp: Fix wrong conditions in remote CTE req There were wrong conditions in rp_comm_tx function for CTE request that vefiry if: - PHY is allowed one, - CTE length is within allowed value. The commit fixes it. Signed-off-by: Piotr Pryga (cherry picked from commit 55e73ec3659910564231fadc861600c2bf1a1d61) --- subsys/bluetooth/controller/ll_sw/ull_llcp_common.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/subsys/bluetooth/controller/ll_sw/ull_llcp_common.c b/subsys/bluetooth/controller/ll_sw/ull_llcp_common.c index 619c2045f02..eacfefccf67 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_llcp_common.c +++ b/subsys/bluetooth/controller/ll_sw/ull_llcp_common.c @@ -748,12 +748,12 @@ static void rp_comm_tx(struct ll_conn *conn, struct proc_ctx *ctx) /* If the PHY update is not possible, then PHY1M is used. * CTE is supported for PHY1M. */ - if (conn->lll.phy_tx != PHY_CODED) { + if (conn->lll.phy_tx == PHY_CODED) { err_code = BT_HCI_ERR_INVALID_LL_PARAM; } #endif /* CONFIG_BT_PHY_UPDATE */ if (!(conn->llcp.cte_rsp.cte_types & BIT(conn->llcp.cte_req.cte_type)) && - conn->llcp.cte_rsp.max_cte_len >= conn->llcp.cte_req.min_cte_len) { + conn->llcp.cte_rsp.max_cte_len < conn->llcp.cte_req.min_cte_len) { err_code = BT_HCI_ERR_UNSUPP_LL_PARAM_VAL; } From d0feb86b3f59b952590ffe6a3d7b63e0848874e0 Mon Sep 17 00:00:00 2001 From: Piotr Pryga Date: Tue, 4 Jan 2022 09:18:14 +0100 Subject: [PATCH 084/207] [nrf fromtree] Bluetooth: Controller: llcp: setting of CTE related content in pdu_data The llcp_pdu_encode_cte_rsp functio didn't set pdu_data fields related with CTE transmission. The commit fixes that. Signed-off-by: Piotr Pryga (cherry picked from commit 576d06e0a7c093592c5c598c0232da96d2846cef) --- subsys/bluetooth/controller/ll_sw/ull_llcp_common.c | 2 +- subsys/bluetooth/controller/ll_sw/ull_llcp_internal.h | 2 +- subsys/bluetooth/controller/ll_sw/ull_llcp_pdu.c | 11 +++++++++-- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/subsys/bluetooth/controller/ll_sw/ull_llcp_common.c b/subsys/bluetooth/controller/ll_sw/ull_llcp_common.c index eacfefccf67..1961f549a46 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_llcp_common.c +++ b/subsys/bluetooth/controller/ll_sw/ull_llcp_common.c @@ -758,7 +758,7 @@ static void rp_comm_tx(struct ll_conn *conn, struct proc_ctx *ctx) } if (!err_code) { - llcp_pdu_encode_cte_rsp(pdu); + llcp_pdu_encode_cte_rsp(conn, pdu); ctx->rx_opcode = PDU_DATA_LLCTRL_TYPE_CTE_RSP; } else { llcp_pdu_encode_reject_ext_ind(pdu, PDU_DATA_LLCTRL_TYPE_CTE_REQ, err_code); diff --git a/subsys/bluetooth/controller/ll_sw/ull_llcp_internal.h b/subsys/bluetooth/controller/ll_sw/ull_llcp_internal.h index 10cf74c3b34..4cda2262a5c 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_llcp_internal.h +++ b/subsys/bluetooth/controller/ll_sw/ull_llcp_internal.h @@ -580,7 +580,7 @@ void llcp_ntf_encode_length_change(struct ll_conn *conn, void llcp_pdu_encode_cte_req(struct proc_ctx *ctx, struct pdu_data *pdu); void llcp_ntf_encode_cte_req(struct ll_conn *conn, struct pdu_data *pdu); void llcp_pdu_decode_cte_req(struct ll_conn *conn, struct pdu_data *pdu); -void llcp_pdu_encode_cte_rsp(struct pdu_data *pdu); +void llcp_pdu_encode_cte_rsp(struct ll_conn *conn, struct pdu_data *pdu); #endif /* CONFIG_BT_CTLR_DF_CONN_CTE_REQ */ #ifdef ZTEST_UNITTEST diff --git a/subsys/bluetooth/controller/ll_sw/ull_llcp_pdu.c b/subsys/bluetooth/controller/ll_sw/ull_llcp_pdu.c index 60f0a0e7328..6864e8e538c 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_llcp_pdu.c +++ b/subsys/bluetooth/controller/ll_sw/ull_llcp_pdu.c @@ -743,11 +743,18 @@ void llcp_pdu_decode_cte_req(struct ll_conn *conn, struct pdu_data *pdu) conn->llcp.cte_req.cte_type = pdu->llctrl.cte_req.cte_type_req; } -void llcp_pdu_encode_cte_rsp(struct pdu_data *pdu) +void llcp_pdu_encode_cte_rsp(struct ll_conn *conn, struct pdu_data *pdu) { pdu->ll_id = PDU_DATA_LLID_CTRL; pdu->len = - offsetof(struct pdu_data_llctrl, cte_rsp) + sizeof(struct pdu_data_llctrl_cte_rsp); + offsetof(struct pdu_data_llctrl, cte_rsp) + sizeof(struct pdu_data_llctrl_cte_rsp); pdu->llctrl.opcode = PDU_DATA_LLCTRL_TYPE_CTE_RSP; + + /* Set content of a PDU header first byte, that is not changed by LLL */ + pdu->cp = 1U; + pdu->rfu = 0U; + + pdu->cte_info.time = conn->llcp.cte_req.min_cte_len; + pdu->cte_info.type = conn->llcp.cte_req.cte_type; } #endif /* CONFIG_BT_CTLR_DF_CONN_CTE_REQ */ From a45e51149bf816118c7beee1b9aa7739bf84d38d Mon Sep 17 00:00:00 2001 From: Piotr Pryga Date: Tue, 4 Jan 2022 11:29:01 +0100 Subject: [PATCH 085/207] [nrf fromtree] Bluetooth: Controller: df: Use PDUs CTEInfo to config radio TX CTE type and length parameters in connected mode are dependent on remote CTE request procedure. These parameters are required to setup radio to correctly transmit CTE. The same parameters are also included in CTEInfo byte of data channel PDU header. The parameters were provided to LLL with PDU to be transmitted and by lll_conn::df_tx_cfg, hence it was redundant. The PDUs CTEInfo has to be set before transmission anyway. The contents of the PDU are set in ULL by CTE RSP control procedure. To remove redundancy CTE length and type from lll_df_- conn_tx_cfg were removed from ll_df_conn_tx_cfg. It was better option becuse it saves instructions in LLL. Radio in connected mode was configured by lll_df_conn_cte_tx_enable. The function just unpacked the lll_df_conn_tx_cfg mebmers and called static function df_cte_tx_configure. Instead of extending parameters list of lll_df_conn_cte_tx_enable, the function was removed and df_cte_tx_configure was changed to be global function - lll_df_cte_tx_configure. Now LLL directly passes all parameters from pdu_data::cte_info and ll_df_conn_tx_cfg to lll_df_cte_tx_configure. Signed-off-by: Piotr Pryga (cherry picked from commit 01a130da708e98f2ca8bdf1e97810c3a7913fe17) --- .../controller/ll_sw/nordic/lll/lll_central.c | 5 ++- .../controller/ll_sw/nordic/lll/lll_conn.c | 5 ++- .../controller/ll_sw/nordic/lll/lll_df.c | 39 ++++++------------- .../ll_sw/nordic/lll/lll_df_internal.h | 5 ++- .../ll_sw/nordic/lll/lll_df_types.h | 2 - 5 files changed, 20 insertions(+), 36 deletions(-) diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_central.c b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_central.c index 03e8fc5c459..0caf0d62487 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_central.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_central.c @@ -158,9 +158,10 @@ static int prepare_cb(struct lll_prepare_param *p) #if defined(CONFIG_BT_CTLR_DF_CONN_CTE_TX) if (pdu_data_tx->cp) { - lll_df_conn_cte_tx_enable(&lll->df_tx_cfg); - cte_len = CTE_LEN_US(pdu_data_tx->cte_info.time); + + lll_df_cte_tx_configure(pdu_data_tx->cte_info.type, pdu_data_tx->cte_info.time, + lll->df_tx_cfg.ant_sw_len, lll->df_tx_cfg.ant_ids); } else #endif /* CONFIG_BT_CTLR_DF_CONN_CTE_TX */ { diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_conn.c b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_conn.c index a595b9015bf..0435159cb73 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_conn.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_conn.c @@ -274,9 +274,10 @@ void lll_conn_isr_rx(void *param) #if defined(CONFIG_BT_CTLR_DF_CONN_CTE_TX) if (pdu_data_tx->cp) { - lll_df_conn_cte_tx_enable(&lll->df_tx_cfg); - cte_len = CTE_LEN_US(pdu_data_tx->cte_info.time); + + lll_df_cte_tx_configure(pdu_data_tx->cte_info.type, pdu_data_tx->cte_info.time, + lll->df_tx_cfg.ant_sw_len, lll->df_tx_cfg.ant_ids); } else #endif /* CONFIG_BT_CTLR_DF_CONN_CTE_TX */ { diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_df.c b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_df.c index 657bdc6105c..ca8afcf8522 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_df.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_df.c @@ -43,10 +43,7 @@ #define DF_MIN_ANT_NUM_REQUIRED 2 static int init_reset(void); -#if defined(CONFIG_BT_CTLR_DF_ADV_CTE_TX) || defined(CONFIG_BT_CTLR_DF_CONN_CTE_TX) -static void df_cte_tx_configure(uint8_t cte_type, uint8_t cte_length, uint8_t ant_ids_len, - const uint8_t *ant_ids); -#endif /* CONFIG_BT_CTLR_DF_ADV_CTE_TX || CONFIG_BT_CTLR_DF_CONN_CTE_TX */ + /* @brief Function performs Direction Finding initialization * * @return Zero in case of success, other value in case of failure. @@ -79,20 +76,6 @@ uint8_t lll_df_ant_num_get(void) return radio_df_ant_num_get(); } -#if defined(CONFIG_BT_CTLR_DF_CONN_CTE_TX) -/** - * @brief Function enables transmission of Constant Tone Extension by radio peripheral in connected - * mode. - * - * @param df_cfg Pointer to configuration of the CTE. - */ -void lll_df_conn_cte_tx_enable(const struct lll_df_conn_tx_cfg *df_cfg) -{ - df_cte_tx_configure(df_cfg->cte_type, df_cfg->cte_length, df_cfg->ant_sw_len, - df_cfg->ant_ids); -} -#endif /* CONFIG_BT_CTLR_DF_CONN_CTE_TX */ - #if defined(CONFIG_BT_CTLR_DF_ADV_CTE_TX) /* @brief Function enables transmission of Constant Tone Extension. * @@ -121,8 +104,8 @@ void lll_df_cte_tx_enable(struct lll_adv_sync *lll_sync, const struct pdu_adv *p df_cfg = lll_adv_sync_extra_data_curr_get(lll_sync); LL_ASSERT(df_cfg); - df_cte_tx_configure(df_cfg->cte_type, df_cfg->cte_length, - df_cfg->ant_sw_len, df_cfg->ant_ids); + lll_df_cte_tx_configure(df_cfg->cte_type, df_cfg->cte_length, + df_cfg->ant_sw_len, df_cfg->ant_ids); lll_sync->cte_started = 1U; *cte_len_us = CTE_LEN_US(df_cfg->cte_length); @@ -307,17 +290,17 @@ static int init_reset(void) #if defined(CONFIG_BT_CTLR_DF_ADV_CTE_TX) || defined(CONFIG_BT_CTLR_DF_CONN_CTE_TX) /** - * @brief Function initializes transmission of Constant Tone Extension. + * @brief Function configures transmission of Constant Tone Extension. * - * @param cte_type Type of the CTE - * @param cte_length Length of CTE in units of 8 us - * @param ant_ids_len Length of antenna identifiers array - * @param ant_ids Pointer to antenna identifiers array + * @param cte_type Type of the CTE + * @param cte_length Length of CTE in units of 8 us + * @param num_ant_ids Length of @p ant_ids + * @param ant_ids Pointer to antenna identifiers array * * In case of AoA mode ant_sw_len and ant_ids members are not used. */ -static void df_cte_tx_configure(uint8_t cte_type, uint8_t cte_length, uint8_t ant_ids_len, - const uint8_t *ant_ids) +void lll_df_cte_tx_configure(uint8_t cte_type, uint8_t cte_length, uint8_t num_ant_ids, + const uint8_t *ant_ids) { if (cte_type == BT_HCI_LE_AOA_CTE) { radio_df_mode_set_aoa(); @@ -335,7 +318,7 @@ static void df_cte_tx_configure(uint8_t cte_type, uint8_t cte_length, uint8_t an radio_df_ant_switching_pin_sel_cfg(); radio_df_ant_switch_pattern_clear(); - radio_df_ant_switch_pattern_set(ant_ids, ant_ids_len); + radio_df_ant_switch_pattern_set(ant_ids, num_ant_ids); } #endif /* CONFIG_BT_CTLR_DF_ANT_SWITCH_TX */ } diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_df_internal.h b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_df_internal.h index 83889ea31ce..7c7f0730c29 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_df_internal.h +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_df_internal.h @@ -59,8 +59,9 @@ static inline uint8_t lll_df_sync_cfg_is_modified(struct lll_df_sync *df_cfg) void lll_df_conf_cte_rx_enable(uint8_t slot_duration, uint8_t ant_num, const uint8_t *ant_ids, uint8_t chan_idx, bool cte_info_in_s1); -/* Enable CTE transmission according to provided configuration */ -void lll_df_conn_cte_tx_enable(const struct lll_df_conn_tx_cfg *df_cfg); +/* Configure CTE transmission */ +void lll_df_cte_tx_configure(uint8_t cte_type, uint8_t cte_length, uint8_t num_ant_ids, + const uint8_t *ant_ids); /* Enabled parsing of a PDU for CTEInfo */ void lll_df_conf_cte_info_parsing_enable(void); diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_df_types.h b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_df_types.h index b19d3b19788..44e0f70a647 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_df_types.h +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_df_types.h @@ -156,8 +156,6 @@ struct cte_conn_iq_report { struct lll_df_conn_tx_cfg { uint8_t state:1; uint8_t ant_sw_len:7; - uint8_t cte_type:2; - uint8_t cte_length:6; /* Length of CTE in 8us units */ uint8_t cte_rsp_en:1; /* CTE response is enabled */ uint8_t cte_types_allowed:3; /* Bitfield with allowed CTE types */ uint8_t ant_ids[BT_CTLR_DF_MAX_ANT_SW_PATTERN_LEN]; From 54a2231373454fe3120cb9233570293ca877e359 Mon Sep 17 00:00:00 2001 From: Piotr Pryga Date: Sat, 8 Jan 2022 09:31:26 +0100 Subject: [PATCH 086/207] [nrf fromtree] Bluetooth: hci: Fix wrong CTE request interval type Request interval is a number of connection events that is used to periodically run CTE request control procedure. BT 5.3 Core Specification defines it as 2 octets long. It had wrong type uint8_t. Changed to correct one uint16_t. The commit also changes type of cte_rsp_en field of lll_df_conn_tx_cfg to state that it is a boolean flag. Signed-off-by: Piotr Pryga (cherry picked from commit 2ac5f7574b87885f3baf432b1559698000ec8517) --- include/bluetooth/direction.h | 2 +- include/bluetooth/hci.h | 2 +- subsys/bluetooth/controller/hci/hci.c | 3 +- subsys/bluetooth/controller/include/ll.h | 7 ++- .../ll_sw/nordic/lll/lll_df_types.h | 11 ++-- .../bluetooth/controller/ll_sw/ull_central.c | 2 +- subsys/bluetooth/controller/ll_sw/ull_df.c | 54 +++++++++++++++++-- subsys/bluetooth/host/direction.c | 2 +- 8 files changed, 66 insertions(+), 17 deletions(-) diff --git a/include/bluetooth/direction.h b/include/bluetooth/direction.h index f080d2d4310..09b5f85cb46 100644 --- a/include/bluetooth/direction.h +++ b/include/bluetooth/direction.h @@ -179,7 +179,7 @@ struct bt_df_conn_cte_req_params { * Value 0x0 means, run the procedure once. Other values are intervals in number of * connection events, to run the command periodically. */ - uint8_t interval; + uint16_t interval; /** Requested length of the CTE in 8 us units. */ uint8_t cte_length; /** diff --git a/include/bluetooth/hci.h b/include/bluetooth/hci.h index 001e5f79993..95160e0aa35 100644 --- a/include/bluetooth/hci.h +++ b/include/bluetooth/hci.h @@ -1607,7 +1607,7 @@ struct bt_hci_rp_le_set_conn_cte_tx_params { struct bt_hci_cp_le_conn_cte_req_enable { uint16_t handle; uint8_t enable; - uint8_t cte_request_interval; + uint16_t cte_request_interval; uint8_t requested_cte_length; uint8_t requested_cte_type; } __packed; diff --git a/subsys/bluetooth/controller/hci/hci.c b/subsys/bluetooth/controller/hci/hci.c index 998c2106348..35c75a43b05 100644 --- a/subsys/bluetooth/controller/hci/hci.c +++ b/subsys/bluetooth/controller/hci/hci.c @@ -2983,7 +2983,8 @@ static void le_df_set_conn_cte_req_enable(struct net_buf *buf, struct net_buf ** handle_le16 = cmd->handle; handle = sys_le16_to_cpu(handle_le16); - status = ll_df_set_conn_cte_req_enable(handle, cmd->enable, cmd->cte_request_interval, + status = ll_df_set_conn_cte_req_enable(handle, cmd->enable, + sys_le16_to_cpu(cmd->cte_request_interval), cmd->requested_cte_length, cmd->requested_cte_type); rp = hci_cmd_complete(evt, sizeof(*rp)); diff --git a/subsys/bluetooth/controller/include/ll.h b/subsys/bluetooth/controller/include/ll.h index 36baeb2b987..fa69bf70907 100644 --- a/subsys/bluetooth/controller/include/ll.h +++ b/subsys/bluetooth/controller/include/ll.h @@ -303,8 +303,11 @@ uint8_t ll_df_set_conn_cte_rx_params(uint16_t handle, uint8_t sampling_enable, uint8_t slot_durations, uint8_t switch_pattern_len, const uint8_t *ant_ids); /* Enables or disables CTE request control procedure in direction fingin connected mode. */ -uint8_t ll_df_set_conn_cte_req_enable(uint16_t handle, uint8_t enable, uint8_t cte_request_interval, - uint8_t requested_cte_length, uint8_t requested_cte_type); +uint8_t ll_df_set_conn_cte_req_enable(uint16_t handle, uint8_t enable, + uint16_t cte_request_interval, uint8_t requested_cte_length, + uint8_t requested_cte_type); +/* Enables or disables CTE response control procedure in direction fingin connected mode. */ +uint8_t ll_df_set_conn_cte_rsp_enable(uint16_t handle, uint8_t enable); /* Enables or disables CTE sampling in periodic advertising scan */ uint8_t ll_df_set_cl_iq_sampling_enable(uint16_t handle, uint8_t sampling_enable, diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_df_types.h b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_df_types.h index 44e0f70a647..2916709d51b 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_df_types.h +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_df_types.h @@ -108,11 +108,6 @@ struct lll_df_sync { struct lll_df_sync_cfg cfg[DOUBLE_BUFFER_SIZE]; }; -/* Names for allowed states for CTE transmit parameters in connected mode */ -enum df_cte_tx_state { - DF_CTE_CONN_TX_PARAMS_UNINITIALIZED, - DF_CTE_CONN_TX_PARAMS_SET, -}; /* Parameters for reception of Constant Tone Extension in connected mode */ struct lll_df_conn_rx_params { uint8_t is_enabled:1; @@ -154,7 +149,11 @@ struct cte_conn_iq_report { /* Configuration for transmission of Constant Tone Extension in connected mode */ struct lll_df_conn_tx_cfg { - uint8_t state:1; + /* Stores information if the TX configuration was set at least once. + * It is required for handling HCI_LE_Connection_CTE_Response_Enable HCI command. + * See BT 5.3 Core specification Vol 4, Part E, sec. 7.8.86. + */ + uint8_t is_initialized:1; uint8_t ant_sw_len:7; uint8_t cte_rsp_en:1; /* CTE response is enabled */ uint8_t cte_types_allowed:3; /* Bitfield with allowed CTE types */ diff --git a/subsys/bluetooth/controller/ll_sw/ull_central.c b/subsys/bluetooth/controller/ll_sw/ull_central.c index 14978610fd0..e63e351b143 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_central.c +++ b/subsys/bluetooth/controller/ll_sw/ull_central.c @@ -271,7 +271,7 @@ uint8_t ll_create_connection(uint16_t scan_interval, uint16_t scan_window, #endif /* CONFIG_BT_CTLR_CONN_META */ #if defined(CONFIG_BT_CTLR_DF_CONN_CTE_RX) - conn_lll->df_rx_cfg.is_initialized = false; + conn_lll->df_rx_cfg.is_initialized = 0U; conn_lll->df_rx_cfg.hdr.elem_size = sizeof(struct lll_df_conn_rx_params); #endif /* CONFIG_BT_CTLR_DF_CONN_CTE_RX */ diff --git a/subsys/bluetooth/controller/ll_sw/ull_df.c b/subsys/bluetooth/controller/ll_sw/ull_df.c index f8647f72aad..0bcf0902b77 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_df.c +++ b/subsys/bluetooth/controller/ll_sw/ull_df.c @@ -1043,7 +1043,7 @@ uint8_t ll_df_set_conn_cte_tx_params(uint16_t handle, uint8_t cte_types, uint8_t df_tx_cfg->ant_sw_len = switch_pattern_len; df_tx_cfg->cte_types_allowed = cte_types; - df_tx_cfg->state = DF_CTE_CONN_TX_PARAMS_SET; + df_tx_cfg->is_initialized = 1U; return BT_HCI_ERR_SUCCESS; } @@ -1087,7 +1087,7 @@ uint8_t ll_df_set_conn_cte_rx_params(uint16_t handle, uint8_t sampling_enable, /* This is an information for HCI_LE_Connection_CTE_Request_Enable that * HCI_LE_Set_Connection_CTE_Receive_Parameters was called at least once. */ - cfg_rx->is_initialized = true; + cfg_rx->is_initialized = 1U; params_buf_hdr = &cfg_rx->hdr; params_rx = dbuf_alloc(params_buf_hdr, ¶ms_idx); @@ -1141,8 +1141,9 @@ uint8_t ll_df_set_conn_cte_rx_params(uint16_t handle, uint8_t sampling_enable, * * @return HCI Status of command completion. */ -uint8_t ll_df_set_conn_cte_req_enable(uint16_t handle, uint8_t enable, uint8_t cte_request_interval, - uint8_t requested_cte_length, uint8_t requested_cte_type) +uint8_t ll_df_set_conn_cte_req_enable(uint16_t handle, uint8_t enable, + uint16_t cte_request_interval, uint8_t requested_cte_length, + uint8_t requested_cte_type) { struct ll_conn *conn; @@ -1207,6 +1208,51 @@ uint8_t ll_df_set_conn_cte_req_enable(uint16_t handle, uint8_t enable, uint8_t c } #endif /* CONFIG_BT_CTLR_DF_CONN_CTE_REQ */ +#if defined(CONFIG_BT_CTLR_DF_CONN_CTE_RSP) +/** + * @brief Function enables or disables CTE response control procedure for a connection. + * + * @param handle Connection handle. + * @param enable Enable or disable CTE response. + * + * @return HCI Status of command completion. + */ +uint8_t ll_df_set_conn_cte_rsp_enable(uint16_t handle, uint8_t enable) +{ + struct ll_conn *conn; + + conn = ll_connected_get(handle); + if (!conn) { + return BT_HCI_ERR_UNKNOWN_CONN_ID; + } + + if (enable) { + if (!conn->lll.df_tx_cfg.is_initialized) { + return BT_HCI_ERR_CMD_DISALLOWED; + } + +#if defined(CONFIG_BT_CTLR_PHY) + /* CTE may not be send over CODED PHY */ + if (conn->lll.phy_tx == PHY_CODED) { + return BT_HCI_ERR_CMD_DISALLOWED; + } +#endif /* CONFIG_BT_CTLR_PHY */ + conn->lll.df_tx_cfg.cte_rsp_en = 1U; + + ull_cp_cte_rsp_enable(conn, enable, LLL_DF_MAX_CTE_LEN, + conn->lll.df_tx_cfg.cte_types_allowed); + } else { + /* There is no parameter validation for disable operation. */ + + /* TODO: Add missing implementation of disable CTE request. + * Requires refactored LLCPs. + */ + } + + return BT_HCI_ERR_SUCCESS; +} +#endif /* CONFIG_BT_CTLR_DF_CONN_CTE_RSP */ + /* @brief Function provides information about Direction Finding * antennas switching and sampling related settings. * diff --git a/subsys/bluetooth/host/direction.c b/subsys/bluetooth/host/direction.c index bb02cee70cc..6331f0896e8 100644 --- a/subsys/bluetooth/host/direction.c +++ b/subsys/bluetooth/host/direction.c @@ -669,7 +669,7 @@ static void prepare_conn_cte_req_enable_cmd_params(struct net_buf *buf, const st if (enable) { cp->cte_request_interval = params->interval; - cp->requested_cte_length = params->cte_length; + cp->requested_cte_length = sys_cpu_to_le16(params->cte_length); cp->requested_cte_type = get_hci_cte_type(params->cte_type); } } From d832ca022b29d4d9cd644afd3599d3d66460cfb1 Mon Sep 17 00:00:00 2001 From: Piotr Pryga Date: Sat, 8 Jan 2022 10:23:44 +0100 Subject: [PATCH 087/207] [nrf fromtree] Bluetooth: Controller: Add init CTE REQ and RSP variables on conn create There were missing initialization for CTX request and response conotrol procedure related variables. The variables were zeored on system startup but not initialized when a connection is established. In case of re-use of connection instance for new connection it was not possible to setup procedures again. Signed-off-by: Piotr Pryga (cherry picked from commit 9e523d98997c9acfe54d7e7a020da0a5941ecfc9) --- subsys/bluetooth/controller/ll_sw/ull_adv.c | 6 +++++- subsys/bluetooth/controller/ll_sw/ull_central.c | 4 ++++ subsys/bluetooth/controller/ll_sw/ull_llcp.c | 8 ++++++++ 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/subsys/bluetooth/controller/ll_sw/ull_adv.c b/subsys/bluetooth/controller/ll_sw/ull_adv.c index a42b98c6f83..5a7f0fb9644 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_adv.c +++ b/subsys/bluetooth/controller/ll_sw/ull_adv.c @@ -1026,9 +1026,13 @@ uint8_t ll_adv_enable(uint8_t enable) memset(&conn_lll->conn_meta, 0, sizeof(conn_lll->conn_meta)); #endif /* CONFIG_BT_CTLR_CONN_META */ #if defined(CONFIG_BT_CTLR_DF_CONN_CTE_RX) + conn_lll->df_rx_cfg.is_initialized = 0U; conn_lll->df_rx_cfg.hdr.elem_size = sizeof(struct lll_df_conn_rx_params); #endif /* CONFIG_BT_CTLR_DF_CONN_CTE_RX */ - +#if defined(CONFIG_BT_CTLR_DF_CONN_CTE_TX) + conn_lll->df_tx_cfg.is_initialized = 0U; + conn_lll->df_tx_cfg.cte_rsp_en = 0U; +#endif /* CONFIG_BT_CTLR_DF_CONN_CTE_TX */ conn->connect_expire = 6; conn->supervision_expire = 0; conn->procedure_expire = 0; diff --git a/subsys/bluetooth/controller/ll_sw/ull_central.c b/subsys/bluetooth/controller/ll_sw/ull_central.c index e63e351b143..1f98a6e6d57 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_central.c +++ b/subsys/bluetooth/controller/ll_sw/ull_central.c @@ -274,6 +274,10 @@ uint8_t ll_create_connection(uint16_t scan_interval, uint16_t scan_window, conn_lll->df_rx_cfg.is_initialized = 0U; conn_lll->df_rx_cfg.hdr.elem_size = sizeof(struct lll_df_conn_rx_params); #endif /* CONFIG_BT_CTLR_DF_CONN_CTE_RX */ +#if defined(CONFIG_BT_CTLR_DF_CONN_CTE_TX) + conn_lll->df_tx_cfg.is_initialized = 0U; + conn_lll->df_tx_cfg.cte_rsp_en = 0U; +#endif /* CONFIG_BT_CTLR_DF_CONN_CTE_TX */ conn->connect_expire = CONN_ESTAB_COUNTDOWN; conn->supervision_expire = 0U; diff --git a/subsys/bluetooth/controller/ll_sw/ull_llcp.c b/subsys/bluetooth/controller/ll_sw/ull_llcp.c index 2b1a133a6ad..5d024dd70b8 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_llcp.c +++ b/subsys/bluetooth/controller/ll_sw/ull_llcp.c @@ -452,6 +452,14 @@ void ull_llcp_init(struct ll_conn *conn) conn->lll.enc_rx = 0U; #endif /* CONFIG_BT_CTLR_LE_ENC */ +#if defined(CONFIG_BT_CTLR_DF_CONN_CTE_REQ) + conn->llcp.cte_req.is_enabled = 0U; + conn->llcp.cte_req.req_expire = 0U; +#endif /* CONFIG_BT_CTLR_DF_CONN_CTE_REQ */ +#if defined(CONFIG_BT_CTLR_DF_CONN_CTE_RSP) + conn->llcp.cte_rsp.is_enabled = 0U; +#endif /* CONFIG_BT_CTLR_DF_CONN_CTE_RSP */ + #if defined(LLCP_TX_CTRL_BUF_QUEUE_ENABLE) #if (CONFIG_BT_CTLR_LLCP_PER_CONN_TX_CTRL_BUF_NUM > 0) conn->llcp.tx_buffer_alloc = 0; From e758a36f95d4830e6e41dcf39d4292c05db1fbe5 Mon Sep 17 00:00:00 2001 From: Piotr Pryga Date: Sat, 8 Jan 2022 11:01:24 +0100 Subject: [PATCH 088/207] [nrf fromtree] Bluetooth: Controller: llcp: Make remote CTE REQ to compile with CTE RSP Part of the CTE request procdure that is related with handling of remote request should be compiled when CTE RSP is enabled. Withouth it CTE response will not work. Local CTE request does not need code reponsible for handling of remote reques. The commit changes conditional compilation guards. Signed-off-by: Piotr Pryga (cherry picked from commit 88ec18de5ec74625cd7d47b8d2a3d3202d66e79e) --- subsys/bluetooth/controller/ll_sw/ull_llcp.c | 2 +- subsys/bluetooth/controller/ll_sw/ull_llcp_common.c | 13 +++++++------ .../bluetooth/controller/ll_sw/ull_llcp_internal.h | 8 +++++++- subsys/bluetooth/controller/ll_sw/ull_llcp_pdu.c | 4 +++- subsys/bluetooth/controller/ll_sw/ull_llcp_remote.c | 8 ++++---- 5 files changed, 22 insertions(+), 13 deletions(-) diff --git a/subsys/bluetooth/controller/ll_sw/ull_llcp.c b/subsys/bluetooth/controller/ll_sw/ull_llcp.c index 5d024dd70b8..fc3f57a87a1 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_llcp.c +++ b/subsys/bluetooth/controller/ll_sw/ull_llcp.c @@ -391,7 +391,7 @@ struct proc_ctx *llcp_create_remote_procedure(enum llcp_proc proc) llcp_rp_comm_init_proc(ctx); break; #endif /* CONFIG_BT_CTLR_DATA_LENGTH */ -#if defined(CONFIG_BT_CTLR_DF_CONN_CTE_REQ) +#if defined(CONFIG_BT_CTLR_DF_CONN_CTE_RSP) case PROC_CTE_REQ: llcp_rp_comm_init_proc(ctx); break; diff --git a/subsys/bluetooth/controller/ll_sw/ull_llcp_common.c b/subsys/bluetooth/controller/ll_sw/ull_llcp_common.c index 1961f549a46..74e38b089f8 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_llcp_common.c +++ b/subsys/bluetooth/controller/ll_sw/ull_llcp_common.c @@ -692,11 +692,11 @@ static void rp_comm_rx_decode(struct ll_conn *conn, struct proc_ctx *ctx, struct llcp_tx_pause_data(conn); break; #endif /* CONFIG_BT_CTLR_DATA_LENGTH */ -#if defined(CONFIG_BT_CTLR_DF_CONN_CTE_REQ) +#if defined(CONFIG_BT_CTLR_DF_CONN_CTE_RSP) case PDU_DATA_LLCTRL_TYPE_CTE_REQ: llcp_pdu_decode_cte_req(conn, pdu); break; -#endif /* CONFIG_BT_CTLR_DF_CONN_CTE_REQ */ +#endif /* CONFIG_BT_CTLR_DF_CONN_CTE_RSP */ default: /* Unknown opcode */ LL_ASSERT(0); @@ -737,13 +737,14 @@ static void rp_comm_tx(struct ll_conn *conn, struct proc_ctx *ctx) ctx->rx_opcode = PDU_DATA_LLCTRL_TYPE_LENGTH_RSP; break; #endif /* CONFIG_BT_CTLR_DATA_LENGTH */ -#if defined(CONFIG_BT_CTLR_DF_CONN_CTE_REQ) +#if defined(CONFIG_BT_CTLR_DF_CONN_CTE_RSP) case PROC_CTE_REQ: { uint8_t err_code = 0; if (conn->llcp.cte_rsp.is_enabled == 0) { err_code = BT_HCI_ERR_UNSUPP_LL_PARAM_VAL; } + #if defined(CONFIG_BT_PHY_UPDATE) /* If the PHY update is not possible, then PHY1M is used. * CTE is supported for PHY1M. @@ -766,7 +767,7 @@ static void rp_comm_tx(struct ll_conn *conn, struct proc_ctx *ctx) } break; } -#endif /* CONFIG_BT_CTLR_DF_CONN_CTE_REQ */ +#endif /* CONFIG_BT_CTLR_DF_CONN_CTE_RSP */ default: /* Unknown procedure */ LL_ASSERT(0); @@ -920,7 +921,7 @@ static void rp_comm_send_rsp(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t } break; #endif /* CONFIG_BT_CTLR_DATA_LENGTH */ -#if defined(CONFIG_BT_CTLR_DF_CONN_CTE_REQ) +#if defined(CONFIG_BT_CTLR_DF_CONN_CTE_RSP) case PROC_CTE_REQ: if (ctx->pause || !llcp_tx_alloc_peek(conn, ctx)) { ctx->state = RP_COMMON_STATE_WAIT_TX; @@ -930,7 +931,7 @@ static void rp_comm_send_rsp(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t ctx->state = RP_COMMON_STATE_IDLE; } break; -#endif /* CONFIG_BT_CTLR_DF_CONN_CTE_REQ */ +#endif /* CONFIG_BT_CTLR_DF_CONN_CTE_RSP */ default: /* Unknown procedure */ LL_ASSERT(0); diff --git a/subsys/bluetooth/controller/ll_sw/ull_llcp_internal.h b/subsys/bluetooth/controller/ll_sw/ull_llcp_internal.h index 4cda2262a5c..ebe563f1785 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_llcp_internal.h +++ b/subsys/bluetooth/controller/ll_sw/ull_llcp_internal.h @@ -579,9 +579,15 @@ void llcp_ntf_encode_length_change(struct ll_conn *conn, */ void llcp_pdu_encode_cte_req(struct proc_ctx *ctx, struct pdu_data *pdu); void llcp_ntf_encode_cte_req(struct ll_conn *conn, struct pdu_data *pdu); +#endif /* CONFIG_BT_CTLR_DF_CONN_CTE_REQ */ + +#if defined(CONFIG_BT_CTLR_DF_CONN_CTE_RSP) +/* + * Constant Tone Response Procedure Helper + */ void llcp_pdu_decode_cte_req(struct ll_conn *conn, struct pdu_data *pdu); void llcp_pdu_encode_cte_rsp(struct ll_conn *conn, struct pdu_data *pdu); -#endif /* CONFIG_BT_CTLR_DF_CONN_CTE_REQ */ +#endif /* CONFIG_BT_CTLR_DF_CONN_CTE_RSP */ #ifdef ZTEST_UNITTEST bool lr_is_disconnected(struct ll_conn *conn); diff --git a/subsys/bluetooth/controller/ll_sw/ull_llcp_pdu.c b/subsys/bluetooth/controller/ll_sw/ull_llcp_pdu.c index 6864e8e538c..1d6be39cd8d 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_llcp_pdu.c +++ b/subsys/bluetooth/controller/ll_sw/ull_llcp_pdu.c @@ -736,7 +736,9 @@ void llcp_ntf_encode_cte_req(struct ll_conn *conn, struct pdu_data *pdu) /* TODO add handling of IQ samples forwarding */ } +#endif /* CONFIG_BT_CTLR_DF_CONN_CTE_REQ */ +#if defined(CONFIG_BT_CTLR_DF_CONN_CTE_RSP) void llcp_pdu_decode_cte_req(struct ll_conn *conn, struct pdu_data *pdu) { conn->llcp.cte_req.min_cte_len = pdu->llctrl.cte_req.min_cte_len_req; @@ -757,4 +759,4 @@ void llcp_pdu_encode_cte_rsp(struct ll_conn *conn, struct pdu_data *pdu) pdu->cte_info.time = conn->llcp.cte_req.min_cte_len; pdu->cte_info.type = conn->llcp.cte_req.cte_type; } -#endif /* CONFIG_BT_CTLR_DF_CONN_CTE_REQ */ +#endif /* CONFIG_BT_CTLR_DF_CONN_CTE_RSP */ diff --git a/subsys/bluetooth/controller/ll_sw/ull_llcp_remote.c b/subsys/bluetooth/controller/ll_sw/ull_llcp_remote.c index 9f2ea5e3bea..897c4205b74 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_llcp_remote.c +++ b/subsys/bluetooth/controller/ll_sw/ull_llcp_remote.c @@ -219,11 +219,11 @@ void llcp_rr_rx(struct ll_conn *conn, struct proc_ctx *ctx, struct node_rx_pdu * llcp_rp_comm_rx(conn, ctx, rx); break; #endif /* CONFIG_BT_CTLR_DATA_LENGTH */ -#if defined(CONFIG_BT_CTLR_DF_CONN_CTE_REQ) +#if defined(CONFIG_BT_CTLR_DF_CONN_CTE_RSP) case PROC_CTE_REQ: llcp_rp_comm_rx(conn, ctx, rx); break; -#endif /* CONFIG_BT_CTLR_DF_CONN_CTE_REQ */ +#endif /* CONFIG_BT_CTLR_DF_CONN_CTE_RSP */ default: /* Unknown procedure */ LL_ASSERT(0); @@ -304,11 +304,11 @@ static void rr_act_run(struct ll_conn *conn) llcp_rp_comm_run(conn, ctx, NULL); break; #endif /* CONFIG_BT_CTLR_DATA_LENGTH */ -#if defined(CONFIG_BT_CTLR_DF_CONN_CTE_REQ) +#if defined(CONFIG_BT_CTLR_DF_CONN_CTE_RSP) case PROC_CTE_REQ: llcp_rp_comm_run(conn, ctx, NULL); break; -#endif /* CONFIG_BT_CTLR_DF_CONN_CTE_REQ */ +#endif /* CONFIG_BT_CTLR_DF_CONN_CTE_RSP */ default: /* Unknown procedure */ LL_ASSERT(0); From fe22c163ff7f0e0619bce898b23ca74bbf43d35d Mon Sep 17 00:00:00 2001 From: Piotr Pryga Date: Sat, 8 Jan 2022 11:37:23 +0100 Subject: [PATCH 089/207] [nrf fromtree] Bluetooth: Controller: Remove unused members from llcp_df_rsp_cfg ant_sw_len and ant_ids members of the structure llcp_df_rsp_cfg were not used. These data are stored in lll_df_conn_tx_cfg that is member of lll_conn. Unused members are removed. Signed-off-by: Piotr Pryga (cherry picked from commit a937f4eccb3d154782734a05d9558ee71f1dc8d2) --- subsys/bluetooth/controller/ll_sw/ull_conn_types.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/subsys/bluetooth/controller/ll_sw/ull_conn_types.h b/subsys/bluetooth/controller/ll_sw/ull_conn_types.h index 62f7da3c625..680d17f14e3 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_conn_types.h +++ b/subsys/bluetooth/controller/ll_sw/ull_conn_types.h @@ -432,9 +432,6 @@ struct llcp_struct { uint8_t is_enabled; uint8_t cte_types; uint8_t max_cte_len; - uint8_t ant_sw_len; - /* TODO (ppryga): Update to use the same macro as in lll_df_types.h */ - uint8_t ant_ids[CONFIG_BT_CTLR_DF_MAX_ANT_SW_PATTERN_LEN]; } cte_rsp; #endif /* CONFIG_BT_CTLR_DF_CONN_CTE_RSP */ #if (CONFIG_BT_CTLR_LLCP_PER_CONN_TX_CTRL_BUF_NUM > 0) &&\ From f15bd6dc59b86ee26e790d4d10258d214fad06ea Mon Sep 17 00:00:00 2001 From: Piotr Pryga Date: Sat, 8 Jan 2022 11:42:06 +0100 Subject: [PATCH 090/207] [nrf fromtree] Bluetooth: Controller: Add storage for remote CTE request data There are data received from peer device with CTE request. These data are not part of local CTE request procedure and they don't belong to CTE response configuration, hence separate storage was provided. Signed-off-by: Piotr Pryga (cherry picked from commit 16b754afb94fd7c239e4c778ac8ba86bd0829048) --- subsys/bluetooth/controller/ll_sw/ull_conn_types.h | 3 --- subsys/bluetooth/controller/ll_sw/ull_llcp_common.c | 8 ++++---- .../bluetooth/controller/ll_sw/ull_llcp_internal.h | 13 +++++++++++-- subsys/bluetooth/controller/ll_sw/ull_llcp_pdu.c | 12 ++++++------ 4 files changed, 21 insertions(+), 15 deletions(-) diff --git a/subsys/bluetooth/controller/ll_sw/ull_conn_types.h b/subsys/bluetooth/controller/ll_sw/ull_conn_types.h index 680d17f14e3..99e62fd04e3 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_conn_types.h +++ b/subsys/bluetooth/controller/ll_sw/ull_conn_types.h @@ -425,9 +425,6 @@ struct llcp_struct { } cte_req; #endif /* CONFIG_BT_CTLR_DF_CONN_CTE_REQ */ #if defined(CONFIG_BT_CTLR_DF_CONN_CTE_RSP) - /* TODO (ppryga): Consided move of the type of structure to ull_df_types.h or - * lll_df_types.h. To have single definition of the type and share it wish LLL. - */ struct llcp_df_rsp_cfg { uint8_t is_enabled; uint8_t cte_types; diff --git a/subsys/bluetooth/controller/ll_sw/ull_llcp_common.c b/subsys/bluetooth/controller/ll_sw/ull_llcp_common.c index 74e38b089f8..be227f121fc 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_llcp_common.c +++ b/subsys/bluetooth/controller/ll_sw/ull_llcp_common.c @@ -694,7 +694,7 @@ static void rp_comm_rx_decode(struct ll_conn *conn, struct proc_ctx *ctx, struct #endif /* CONFIG_BT_CTLR_DATA_LENGTH */ #if defined(CONFIG_BT_CTLR_DF_CONN_CTE_RSP) case PDU_DATA_LLCTRL_TYPE_CTE_REQ: - llcp_pdu_decode_cte_req(conn, pdu); + llcp_pdu_decode_cte_req(ctx, pdu); break; #endif /* CONFIG_BT_CTLR_DF_CONN_CTE_RSP */ default: @@ -753,13 +753,13 @@ static void rp_comm_tx(struct ll_conn *conn, struct proc_ctx *ctx) err_code = BT_HCI_ERR_INVALID_LL_PARAM; } #endif /* CONFIG_BT_PHY_UPDATE */ - if (!(conn->llcp.cte_rsp.cte_types & BIT(conn->llcp.cte_req.cte_type)) && - conn->llcp.cte_rsp.max_cte_len < conn->llcp.cte_req.min_cte_len) { + if (!(conn->llcp.cte_rsp.cte_types & BIT(ctx->data.cte_remote_req.cte_type)) || + conn->llcp.cte_rsp.max_cte_len < ctx->data.cte_remote_req.min_cte_len) { err_code = BT_HCI_ERR_UNSUPP_LL_PARAM_VAL; } if (!err_code) { - llcp_pdu_encode_cte_rsp(conn, pdu); + llcp_pdu_encode_cte_rsp(ctx, pdu); ctx->rx_opcode = PDU_DATA_LLCTRL_TYPE_CTE_RSP; } else { llcp_pdu_encode_reject_ext_ind(pdu, PDU_DATA_LLCTRL_TYPE_CTE_REQ, err_code); diff --git a/subsys/bluetooth/controller/ll_sw/ull_llcp_internal.h b/subsys/bluetooth/controller/ll_sw/ull_llcp_internal.h index ebe563f1785..039225930a7 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_llcp_internal.h +++ b/subsys/bluetooth/controller/ll_sw/ull_llcp_internal.h @@ -221,6 +221,15 @@ struct proc_ctx { uint8_t min_len:5; } cte_req; #endif /* CONFIG_BT_CTLR_DF_CONN_CTE_REQ */ + +#if defined(CONFIG_BT_CTLR_DF_CONN_CTE_RSP) + /* Use by CTE Response Procedure */ + struct llcp_df_cte_remote_req { + uint8_t cte_type; + uint8_t min_cte_len; + } cte_remote_req; +#endif /* CONFIG_BT_CTLR_DF_CONN_CTE_RSP */ + } data; struct { @@ -585,8 +594,8 @@ void llcp_ntf_encode_cte_req(struct ll_conn *conn, struct pdu_data *pdu); /* * Constant Tone Response Procedure Helper */ -void llcp_pdu_decode_cte_req(struct ll_conn *conn, struct pdu_data *pdu); -void llcp_pdu_encode_cte_rsp(struct ll_conn *conn, struct pdu_data *pdu); +void llcp_pdu_decode_cte_req(struct proc_ctx *ctx, struct pdu_data *pdu); +void llcp_pdu_encode_cte_rsp(const struct proc_ctx *ctx, struct pdu_data *pdu); #endif /* CONFIG_BT_CTLR_DF_CONN_CTE_RSP */ #ifdef ZTEST_UNITTEST diff --git a/subsys/bluetooth/controller/ll_sw/ull_llcp_pdu.c b/subsys/bluetooth/controller/ll_sw/ull_llcp_pdu.c index 1d6be39cd8d..224c4ae9b4d 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_llcp_pdu.c +++ b/subsys/bluetooth/controller/ll_sw/ull_llcp_pdu.c @@ -739,13 +739,13 @@ void llcp_ntf_encode_cte_req(struct ll_conn *conn, struct pdu_data *pdu) #endif /* CONFIG_BT_CTLR_DF_CONN_CTE_REQ */ #if defined(CONFIG_BT_CTLR_DF_CONN_CTE_RSP) -void llcp_pdu_decode_cte_req(struct ll_conn *conn, struct pdu_data *pdu) +void llcp_pdu_decode_cte_req(struct proc_ctx *ctx, struct pdu_data *pdu) { - conn->llcp.cte_req.min_cte_len = pdu->llctrl.cte_req.min_cte_len_req; - conn->llcp.cte_req.cte_type = pdu->llctrl.cte_req.cte_type_req; + ctx->data.cte_remote_req.min_cte_len = pdu->llctrl.cte_req.min_cte_len_req; + ctx->data.cte_remote_req.cte_type = pdu->llctrl.cte_req.cte_type_req; } -void llcp_pdu_encode_cte_rsp(struct ll_conn *conn, struct pdu_data *pdu) +void llcp_pdu_encode_cte_rsp(const struct proc_ctx *ctx, struct pdu_data *pdu) { pdu->ll_id = PDU_DATA_LLID_CTRL; pdu->len = @@ -756,7 +756,7 @@ void llcp_pdu_encode_cte_rsp(struct ll_conn *conn, struct pdu_data *pdu) pdu->cp = 1U; pdu->rfu = 0U; - pdu->cte_info.time = conn->llcp.cte_req.min_cte_len; - pdu->cte_info.type = conn->llcp.cte_req.cte_type; + pdu->cte_info.time = ctx->data.cte_remote_req.min_cte_len; + pdu->cte_info.type = ctx->data.cte_remote_req.cte_type; } #endif /* CONFIG_BT_CTLR_DF_CONN_CTE_RSP */ From 548843904c184e088a11b555afe683fccf11e268 Mon Sep 17 00:00:00 2001 From: Piotr Pryga Date: Sat, 8 Jan 2022 12:51:23 +0100 Subject: [PATCH 091/207] [nrf fromtree] Bluetooth: Controller: Integrate CTE req in ULL with refactored LLCPs Integrate existing CTE request control procedure code in ULL with implementation of refactor LLCPs. The commit includes code responsible for: - enabling CTE request and scheduling its execution by refactored LLCPs framework, - running CTE request periodically - disabling CTE reqest in case it is running periodic Signed-off-by: Piotr Pryga (cherry picked from commit 3aa0b3ef0b6fdbc9d4f399172b29661a53381127) --- subsys/bluetooth/controller/ll_sw/ull_conn.c | 12 ++++++++++ .../controller/ll_sw/ull_conn_types.h | 1 + subsys/bluetooth/controller/ll_sw/ull_df.c | 24 ++++++++++++------- .../bluetooth/controller/ll_sw/ull_df_types.h | 2 +- .../controller/ll_sw/ull_llcp_common.c | 24 +++++++++++-------- 5 files changed, 44 insertions(+), 19 deletions(-) diff --git a/subsys/bluetooth/controller/ll_sw/ull_conn.c b/subsys/bluetooth/controller/ll_sw/ull_conn.c index f6b3a373fd7..74a9a19c626 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_conn.c +++ b/subsys/bluetooth/controller/ll_sw/ull_conn.c @@ -1649,6 +1649,18 @@ void ull_conn_done(struct node_rx_event_done *done) } #endif /* CONFIG_BT_CTLR_LE_PING */ +#if defined(CONFIG_BT_CTLR_DF_CONN_CTE_REQ) + if (conn->llcp.cte_req.req_expire != 0U) { + if (conn->llcp.cte_req.req_expire > elapsed_event) { + conn->llcp.cte_req.req_expire -= elapsed_event; + } else { + conn->llcp.cte_req.req_expire = 0U; + ull_cp_cte_req(conn, conn->llcp.cte_req.min_cte_len, + conn->llcp.cte_req.cte_type); + } + } +#endif /* CONFIG_BT_CTLR_DF_CONN_CTE_REQ */ + #if defined(CONFIG_BT_CTLR_CONN_RSSI_EVENT) /* generate RSSI event */ if (lll->rssi_sample_count == 0U) { diff --git a/subsys/bluetooth/controller/ll_sw/ull_conn_types.h b/subsys/bluetooth/controller/ll_sw/ull_conn_types.h index 99e62fd04e3..87ce4ac679f 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_conn_types.h +++ b/subsys/bluetooth/controller/ll_sw/ull_conn_types.h @@ -422,6 +422,7 @@ struct llcp_struct { /* Minimum requested CTE length in 8us units */ uint8_t min_cte_len; uint16_t req_interval; + uint16_t req_expire; } cte_req; #endif /* CONFIG_BT_CTLR_DF_CONN_CTE_REQ */ #if defined(CONFIG_BT_CTLR_DF_CONN_CTE_RSP) diff --git a/subsys/bluetooth/controller/ll_sw/ull_df.c b/subsys/bluetooth/controller/ll_sw/ull_df.c index 0bcf0902b77..9767cbbd55e 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_df.c +++ b/subsys/bluetooth/controller/ll_sw/ull_df.c @@ -1153,17 +1153,22 @@ uint8_t ll_df_set_conn_cte_req_enable(uint16_t handle, uint8_t enable, } if (!enable) { - /* There is no parameter validation for disable operation. */ + conn->llcp.cte_req.is_enabled = false; + conn->llcp.cte_req.req_interval = 0U; - /* TODO: Add missing implementation of disable CTE reques. - * Requires refactored LLCPs. + /* There is no verification if the command is pending. If it is already disabled + * there is no change to the state. */ + /* TODO: How handle command pending in LLL? */ + return BT_HCI_ERR_SUCCESS; } else { - if (!conn->df_rx_params.is_enabled) { + if (!conn->lll.df_rx_cfg.is_initialized) { return BT_HCI_ERR_CMD_DISALLOWED; } - /* TODO: check if CTE_REQ LLCP is active. Add when merged with refactored LLCPs */ + if (conn->llcp.cte_req.is_enabled) { + return BT_HCI_ERR_CMD_DISALLOWED; + } #if defined(CONFIG_BT_CTLR_PHY) /* Phy may be changed to CODED only if PHY update procedure is supproted. In other @@ -1200,11 +1205,14 @@ uint8_t ll_df_set_conn_cte_req_enable(uint16_t handle, uint8_t enable, BIT64(BT_LE_FEAT_BIT_ANT_SWITCH_TX_AOD))))) { return BT_HCI_ERR_UNSUPP_REMOTE_FEATURE; } - } - /* TODO: implement disable of the CTE if PHY is changed to coded */ + conn->llcp.cte_req.is_enabled = true; + conn->llcp.cte_req.req_interval = cte_request_interval; + conn->llcp.cte_req.cte_type = requested_cte_type; + conn->llcp.cte_req.min_cte_len = requested_cte_length; + } - return BT_HCI_ERR_CMD_DISALLOWED; + return ull_cp_cte_req(conn, requested_cte_length, requested_cte_type); } #endif /* CONFIG_BT_CTLR_DF_CONN_CTE_REQ */ diff --git a/subsys/bluetooth/controller/ll_sw/ull_df_types.h b/subsys/bluetooth/controller/ll_sw/ull_df_types.h index 42f669daf20..d7a38eda5a1 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_df_types.h +++ b/subsys/bluetooth/controller/ll_sw/ull_df_types.h @@ -33,7 +33,7 @@ enum df_switch_sample_support { #define SYNC_IQ_REPORT_CNT 0U #endif -#if defined(CONFIG_BT_MAX_CONN) && defined(CONFIG_BT_CTRL_DF_CONN_CTE_RX) +#if defined(CONFIG_BT_MAX_CONN) && defined(CONFIG_BT_CTLR_DF_CONN_CTE_RX) #define CONN_IQ_REPORT_CNT (CONFIG_BT_MAX_CONN * 2) #else #define CONN_IQ_REPORT_CNT 0U diff --git a/subsys/bluetooth/controller/ll_sw/ull_llcp_common.c b/subsys/bluetooth/controller/ll_sw/ull_llcp_common.c index be227f121fc..4601cf26323 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_llcp_common.c +++ b/subsys/bluetooth/controller/ll_sw/ull_llcp_common.c @@ -210,15 +210,9 @@ static void lp_comm_ntf_length_change(struct ll_conn *conn, struct proc_ctx *ctx #if defined(CONFIG_BT_CTLR_DF_CONN_CTE_REQ) static void lp_comm_ntf_cte_req(struct ll_conn *conn, struct proc_ctx *ctx, struct pdu_data *pdu) { - /* TODO (ppryga): pack IQ samples and send them to host */ - /* TODO (ppryga): procedure may be re-triggered periodically by controller itself. - * Add periodicy handling code. It should be executed after receive - * notification about end of current procedure run. - */ /* TODO (ppryga): Add handling of rejections in HCI: HCI_LE_CTE_Request_Failed. */ switch (ctx->response_opcode) { case PDU_DATA_LLCTRL_TYPE_CTE_RSP: - llcp_ntf_encode_cte_req(conn, pdu); break; case PDU_DATA_LLCTRL_TYPE_REJECT_EXT_IND: llcp_ntf_encode_reject_ext_ind(ctx, pdu); @@ -351,13 +345,23 @@ static void lp_comm_complete(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t #endif /* CONFIG_BT_CTLR_DATA_LENGTH */ #if defined(CONFIG_BT_CTLR_DF_CONN_CTE_REQ) case PROC_CTE_REQ: - if (ctx->response_opcode == PDU_DATA_LLCTRL_TYPE_CTE_RSP || - (ctx->response_opcode == PDU_DATA_LLCTRL_TYPE_REJECT_EXT_IND && - ctx->reject_ext_ind.reject_opcode == PDU_DATA_LLCTRL_TYPE_CTE_REQ)) { + if (ctx->response_opcode == PDU_DATA_LLCTRL_TYPE_CTE_RSP) { + if (conn->llcp.cte_req.req_interval != 0U) { + conn->llcp.cte_req.req_expire = conn->llcp.cte_req.req_interval; + } else { + conn->llcp.cte_req.is_enabled = 0U; + } + ctx->state = LP_COMMON_STATE_IDLE; + } else if (ctx->response_opcode == PDU_DATA_LLCTRL_TYPE_REJECT_EXT_IND && + ctx->reject_ext_ind.reject_opcode == PDU_DATA_LLCTRL_TYPE_CTE_REQ) { lp_comm_ntf(conn, ctx); - llcp_lr_complete(conn); + conn->llcp.cte_req.is_enabled = 0U; ctx->state = LP_COMMON_STATE_IDLE; } + + if (ctx->state == LP_COMMON_STATE_IDLE) { + llcp_lr_complete(conn); + } break; #endif /* CONFIG_BT_CTLR_DF_CONN_CTE_REQ */ default: From 0b3c1c3e216e250dbc781ec7c13cc9a1844355fe Mon Sep 17 00:00:00 2001 From: Piotr Pryga Date: Sat, 8 Jan 2022 13:55:24 +0100 Subject: [PATCH 092/207] [nrf fromtree] Bluetooth: controller: Add handling of CTE request failed CTE request control procedure may failed due to rejection by peer device or due to receive of LL_CTE_RSP PDU without CTE. These events has to be reported to host by HCI_LE_CTE_Request_Failed. The commit adds missing functionalit. Signed-off-by: Piotr Pryga (cherry picked from commit 8e81fce6ccee6a05c9ceee37d7064aef9957826f) --- include/bluetooth/hci.h | 7 +++ subsys/bluetooth/controller/hci/hci.c | 62 +++++++++++++++++++ .../controller/ll_sw/ull_conn_types.h | 1 + .../controller/ll_sw/ull_llcp_common.c | 13 +++- .../controller/ll_sw/ull_llcp_internal.h | 8 ++- .../bluetooth/controller/ll_sw/ull_llcp_pdu.c | 14 ++++- 6 files changed, 99 insertions(+), 6 deletions(-) diff --git a/include/bluetooth/hci.h b/include/bluetooth/hci.h index 95160e0aa35..d324e0c68ac 100644 --- a/include/bluetooth/hci.h +++ b/include/bluetooth/hci.h @@ -2495,8 +2495,15 @@ struct bt_hci_evt_le_connection_iq_report { struct bt_hci_le_iq_sample sample[0]; } __packed; +#define BT_HCI_CTE_REQ_STATUS_RSP_WITHOUT_CTE 0x0 + #define BT_HCI_EVT_LE_CTE_REQUEST_FAILED 0x17 struct bt_hci_evt_le_cte_req_failed { + /* According to BT 5.3 Core Spec the status field may have following + * values: + * - BT_HCI_CTE_REQ_STATUS_RSP_WIHOUT_CTE when received LL_CTE_RSP_PDU without CTE. + * - Other Controller error code for peer rejected request. + */ uint8_t status; uint16_t conn_handle; } __packed; diff --git a/subsys/bluetooth/controller/hci/hci.c b/subsys/bluetooth/controller/hci/hci.c index 35c75a43b05..4cad95c2bc1 100644 --- a/subsys/bluetooth/controller/hci/hci.c +++ b/subsys/bluetooth/controller/hci/hci.c @@ -2991,6 +2991,40 @@ static void le_df_set_conn_cte_req_enable(struct net_buf *buf, struct net_buf ** rp->status = status; rp->handle = handle_le16; } + +static void le_df_cte_req_failed(uint8_t error_code, uint16_t handle, struct net_buf *buf) +{ + struct bt_hci_evt_le_cte_req_failed *sep; + + if (!(event_mask & BT_EVT_MASK_LE_META_EVENT) || + !(le_event_mask & BT_EVT_MASK_LE_CTE_REQUEST_FAILED)) { + return; + } + + sep = meta_evt(buf, BT_HCI_EVT_LE_CTE_REQUEST_FAILED, sizeof(*sep)); + + sep->status = error_code; + sep->conn_handle = sys_cpu_to_le16(handle); +} +#endif /* CONFIG_BT_CTLR_DF_CONN_CTE_REQ */ + +#if defined(CONFIG_BT_CTLR_DF_CONN_CTE_RSP) +static void le_df_set_conn_cte_rsp_enable(struct net_buf *buf, struct net_buf **evt) +{ + struct bt_hci_cp_le_conn_cte_rsp_enable *cmd = (void *)buf->data; + struct bt_hci_rp_le_conn_cte_rsp_enable *rp; + uint16_t handle, handle_le16; + uint8_t status; + + handle_le16 = cmd->handle; + handle = sys_le16_to_cpu(handle_le16); + + status = ll_df_set_conn_cte_rsp_enable(handle, cmd->enable); + rp = hci_cmd_complete(evt, sizeof(*rp)); + + rp->status = status; + rp->handle = handle_le16; +} #endif /* CONFIG_BT_CTLR_DF_CONN_CTE_RSP */ static void le_df_read_ant_inf(struct net_buf *buf, struct net_buf **evt) @@ -4347,6 +4381,11 @@ static int controller_cmd_handle(uint16_t ocf, struct net_buf *cmd, le_df_set_conn_cte_req_enable(cmd, evt); break; #endif /* CONFIG_BT_CTLR_DF_CONN_CTE_REQ */ +#if defined(CONFIG_BT_CTLR_DF_CONN_CTE_RSP) + case BT_OCF(BT_HCI_OP_LE_CONN_CTE_RSP_ENABLE): + le_df_set_conn_cte_rsp_enable(cmd, evt); + break; +#endif /* CONFIG_BT_CTLR_DF_CONN_CTE_RSP */ #endif /* CONFIG_BT_CTLR_DF */ #if defined(CONFIG_BT_CTLR_DTM_HCI) @@ -7326,6 +7365,19 @@ static void le_unknown_rsp(struct pdu_data *pdu_data, uint16_t handle, } } +static void le_reject_ext_ind(struct pdu_data *pdu, uint16_t handle, struct net_buf *buf) +{ + switch (pdu->llctrl.reject_ext_ind.reject_opcode) { +#if defined(CONFIG_BT_CTLR_DF_CONN_CTE_REQ) + case PDU_DATA_LLCTRL_TYPE_CTE_REQ: + le_df_cte_req_failed(pdu->llctrl.reject_ext_ind.error_code, handle, buf); + break; +#endif /* CONFIG_BT_CTLR_DF_CONN_CTE_REQ */ + default: + BT_WARN("reject opcode: 0x%02x", pdu->llctrl.reject_ext_ind.reject_opcode); + break; + } +} #if defined(CONFIG_BT_CTLR_CONN_PARAM_REQ) static void le_conn_param_req(struct pdu_data *pdu_data, uint16_t handle, struct net_buf *buf) @@ -7442,10 +7494,20 @@ static void encode_data_ctrl(struct node_rx_pdu *node_rx, break; #endif /* CONFIG_BT_CTLR_DATA_LENGTH */ +#if defined(CONFIG_BT_CTLR_DF_CONN_CTE_REQ) + case PDU_DATA_LLCTRL_TYPE_CTE_REQ: + le_df_cte_req_failed(BT_HCI_CTE_REQ_STATUS_RSP_WITHOUT_CTE, handle, buf); + break; +#endif /* CONFIG_BT_CTLR_DF_CONN_CTE_REQ */ + case PDU_DATA_LLCTRL_TYPE_UNKNOWN_RSP: le_unknown_rsp(pdu_data, handle, buf); break; + case PDU_DATA_LLCTRL_TYPE_REJECT_EXT_IND: + le_reject_ext_ind(pdu_data, handle, buf); + break; + default: LL_ASSERT(0); return; diff --git a/subsys/bluetooth/controller/ll_sw/ull_conn_types.h b/subsys/bluetooth/controller/ll_sw/ull_conn_types.h index 87ce4ac679f..32b50585530 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_conn_types.h +++ b/subsys/bluetooth/controller/ll_sw/ull_conn_types.h @@ -424,6 +424,7 @@ struct llcp_struct { uint16_t req_interval; uint16_t req_expire; } cte_req; + #endif /* CONFIG_BT_CTLR_DF_CONN_CTE_REQ */ #if defined(CONFIG_BT_CTLR_DF_CONN_CTE_RSP) struct llcp_df_rsp_cfg { diff --git a/subsys/bluetooth/controller/ll_sw/ull_llcp_common.c b/subsys/bluetooth/controller/ll_sw/ull_llcp_common.c index 4601cf26323..f614bb118f7 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_llcp_common.c +++ b/subsys/bluetooth/controller/ll_sw/ull_llcp_common.c @@ -210,9 +210,12 @@ static void lp_comm_ntf_length_change(struct ll_conn *conn, struct proc_ctx *ctx #if defined(CONFIG_BT_CTLR_DF_CONN_CTE_REQ) static void lp_comm_ntf_cte_req(struct ll_conn *conn, struct proc_ctx *ctx, struct pdu_data *pdu) { - /* TODO (ppryga): Add handling of rejections in HCI: HCI_LE_CTE_Request_Failed. */ switch (ctx->response_opcode) { case PDU_DATA_LLCTRL_TYPE_CTE_RSP: + /* Notify host that received LL_CTE_RSP does not have CTE */ + if (!ctx->data.cte_remote_rsp.has_cte) { + llcp_ntf_encode_cte_req(pdu); + } break; case PDU_DATA_LLCTRL_TYPE_REJECT_EXT_IND: llcp_ntf_encode_reject_ext_ind(ctx, pdu); @@ -346,10 +349,12 @@ static void lp_comm_complete(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t #if defined(CONFIG_BT_CTLR_DF_CONN_CTE_REQ) case PROC_CTE_REQ: if (ctx->response_opcode == PDU_DATA_LLCTRL_TYPE_CTE_RSP) { - if (conn->llcp.cte_req.req_interval != 0U) { + if (ctx->data.cte_remote_rsp.has_cte && + conn->llcp.cte_req.req_interval != 0U) { conn->llcp.cte_req.req_expire = conn->llcp.cte_req.req_interval; } else { conn->llcp.cte_req.is_enabled = 0U; + lp_comm_ntf(conn, ctx); } ctx->state = LP_COMMON_STATE_IDLE; } else if (ctx->response_opcode == PDU_DATA_LLCTRL_TYPE_REJECT_EXT_IND && @@ -556,9 +561,11 @@ static void lp_comm_rx_decode(struct ll_conn *conn, struct proc_ctx *ctx, struct llcp_pdu_decode_length_rsp(conn, pdu); break; #endif /* CONFIG_BT_CTLR_DATA_LENGTH */ +#if defined(CONFIG_BT_CTLR_DF_CONN_CTE_REQ) case PDU_DATA_LLCTRL_TYPE_CTE_RSP: - /* CTE Response PDU had no data */ + llcp_pdu_decode_cte_rsp(ctx, pdu); break; +#endif /* CONFIG_BT_CTLR_DF_CONN_CTE_REQ */ case PDU_DATA_LLCTRL_TYPE_REJECT_EXT_IND: llcp_pdu_decode_reject_ext_ind(ctx, pdu); break; diff --git a/subsys/bluetooth/controller/ll_sw/ull_llcp_internal.h b/subsys/bluetooth/controller/ll_sw/ull_llcp_internal.h index 039225930a7..1b26fc5d6aa 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_llcp_internal.h +++ b/subsys/bluetooth/controller/ll_sw/ull_llcp_internal.h @@ -220,6 +220,11 @@ struct proc_ctx { uint8_t type:2; uint8_t min_len:5; } cte_req; + + struct llcp_df_cte_remote_rsp { + /* Storage for information that received LL_CTE_RSP PDU includes CTE */ + uint8_t has_cte; + } cte_remote_rsp; #endif /* CONFIG_BT_CTLR_DF_CONN_CTE_REQ */ #if defined(CONFIG_BT_CTLR_DF_CONN_CTE_RSP) @@ -587,7 +592,8 @@ void llcp_ntf_encode_length_change(struct ll_conn *conn, * Constant Tone Request Procedure Helper */ void llcp_pdu_encode_cte_req(struct proc_ctx *ctx, struct pdu_data *pdu); -void llcp_ntf_encode_cte_req(struct ll_conn *conn, struct pdu_data *pdu); +void llcp_pdu_decode_cte_rsp(struct proc_ctx *ctx, const struct pdu_data *pdu); +void llcp_ntf_encode_cte_req(struct pdu_data *pdu); #endif /* CONFIG_BT_CTLR_DF_CONN_CTE_REQ */ #if defined(CONFIG_BT_CTLR_DF_CONN_CTE_RSP) diff --git a/subsys/bluetooth/controller/ll_sw/ull_llcp_pdu.c b/subsys/bluetooth/controller/ll_sw/ull_llcp_pdu.c index 224c4ae9b4d..54c56a713e5 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_llcp_pdu.c +++ b/subsys/bluetooth/controller/ll_sw/ull_llcp_pdu.c @@ -727,14 +727,24 @@ void llcp_pdu_encode_cte_req(struct proc_ctx *ctx, struct pdu_data *pdu) p->cte_type_req = ctx->data.cte_req.type; } -void llcp_ntf_encode_cte_req(struct ll_conn *conn, struct pdu_data *pdu) +void llcp_pdu_decode_cte_rsp(struct proc_ctx *ctx, const struct pdu_data *pdu) +{ + if (pdu->cp == 0U || pdu->cte_info.time == 0U) { + ctx->data.cte_remote_rsp.has_cte = false; + } else { + ctx->data.cte_remote_rsp.has_cte = true; + } +} + +void llcp_ntf_encode_cte_req(struct pdu_data *pdu) { pdu->ll_id = PDU_DATA_LLID_CTRL; pdu->len = offsetof(struct pdu_data_llctrl, cte_rsp) + sizeof(struct pdu_data_llctrl_cte_rsp); pdu->llctrl.opcode = PDU_DATA_LLCTRL_TYPE_CTE_RSP; - /* TODO add handling of IQ samples forwarding */ + /* Received LL_CTE_RSP PDU didn't have CTE */ + pdu->cp = 0U; } #endif /* CONFIG_BT_CTLR_DF_CONN_CTE_REQ */ From 54428ee07610546d1d18ff9caf0e3cd27c69a8e4 Mon Sep 17 00:00:00 2001 From: Piotr Pryga Date: Sat, 8 Jan 2022 14:01:03 +0100 Subject: [PATCH 093/207] [nrf fromtree] Bluetooth: host: df: Fix to wrong variable passed to net_buf_add Wrong variable was passed to net_buff_add call. In could lead to memory overwrite. Signed-off-by: Piotr Pryga (cherry picked from commit e4b7fecfdc4ea22ca719bc542dedbdf8567d148b) --- subsys/bluetooth/host/direction.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subsys/bluetooth/host/direction.c b/subsys/bluetooth/host/direction.c index 6331f0896e8..ee4a64e7352 100644 --- a/subsys/bluetooth/host/direction.c +++ b/subsys/bluetooth/host/direction.c @@ -534,7 +534,7 @@ static void prepare_conn_cte_rx_enable_cmd_params(struct net_buf *buf, struct bt ant_ids = &df_dummy_switch_pattern[0]; } - dest_ant_ids = net_buf_add(buf, params->num_ant_ids); + dest_ant_ids = net_buf_add(buf, cp->switch_pattern_len); (void)memcpy(dest_ant_ids, ant_ids, cp->switch_pattern_len); } } From ecf8c431f95236b1d4430ade3164feeb331e47cb Mon Sep 17 00:00:00 2001 From: Piotr Pryga Date: Sat, 8 Jan 2022 14:03:31 +0100 Subject: [PATCH 094/207] [nrf fromtree] Bluetooth: host: df: Fix wrong arguments order Function valid_cte_req_params was called with cte_length and cte_type in wrong order. Signed-off-by: Piotr Pryga (cherry picked from commit becd9a97d819a0e62604def5c78825da3c6ca399) --- subsys/bluetooth/host/direction.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subsys/bluetooth/host/direction.c b/subsys/bluetooth/host/direction.c index ee4a64e7352..e395caffca9 100644 --- a/subsys/bluetooth/host/direction.c +++ b/subsys/bluetooth/host/direction.c @@ -682,7 +682,7 @@ static int hci_df_set_conn_cte_req_enable(struct bt_conn *conn, bool enable, struct net_buf *buf, *rsp; int err; - if (enable && !valid_cte_req_params(conn, params->cte_length, params->cte_type)) { + if (enable && !valid_cte_req_params(conn, params->cte_type, params->cte_length)) { return -EINVAL; } From 79dab9cf69786034d07ecf8a73a64719bbaf86c2 Mon Sep 17 00:00:00 2001 From: Piotr Pryga Date: Sat, 8 Jan 2022 14:06:49 +0100 Subject: [PATCH 095/207] [nrf fromtree] Bluetooth: host: df: Add handling of HCI_LE_CTE_Request_Failed There were no handling of HCI_LE_CTE_Request_Failed event. The commit adds missing implementation. An application will be notified about failed request by cte_report_cb. It is the same callback that is used for reporting collected CTE IQ samples. The same callback was used to avoid creation new callback. To give an application possibility to distinguish between regular IQ samples report and request failed additional member err was added to bf_df_conn_iq_samples_report structure. Signed-off-by: Piotr Pryga (cherry picked from commit 4ddee30b024ad947949b4c98e1259685319a8435) --- include/bluetooth/direction.h | 11 ++++++ subsys/bluetooth/host/conn.c | 31 ++++++++++++++++ subsys/bluetooth/host/direction.c | 41 +++++++++++++++++++++- subsys/bluetooth/host/direction_internal.h | 3 ++ subsys/bluetooth/host/hci_core.c | 5 +++ subsys/bluetooth/host/hci_core.h | 1 + 6 files changed, 91 insertions(+), 1 deletion(-) diff --git a/include/bluetooth/direction.h b/include/bluetooth/direction.h index 09b5f85cb46..c5cb2f1bf1e 100644 --- a/include/bluetooth/direction.h +++ b/include/bluetooth/direction.h @@ -137,7 +137,18 @@ struct bt_df_conn_cte_rx_param { const uint8_t *ant_ids; }; +enum bt_df_conn_iq_report_err { + /** IQ samples report received successfully. */ + BT_DF_IQ_REPORT_ERR_SUCCESS, + /** Received PDU without CTE. No valid data in report. */ + BT_DF_IQ_REPORT_ERR_NO_CTE, + /** Peer rejected CTE request. No valid data in report. */ + BT_DF_IQ_REPORT_ERR_PEER_REJECTED, +}; + struct bt_df_conn_iq_samples_report { + /** Report receive failed reason. */ + enum bt_df_conn_iq_report_err err; /** PHY that was used to receive PDU with CTE that was sampled. */ uint8_t rx_phy; /** Channel index used to receive PDU with CTE that was sampled. */ diff --git a/subsys/bluetooth/host/conn.c b/subsys/bluetooth/host/conn.c index a27ef52d74e..6d8a8b38316 100644 --- a/subsys/bluetooth/host/conn.c +++ b/subsys/bluetooth/host/conn.c @@ -2952,4 +2952,35 @@ void bt_hci_le_df_connection_iq_report(struct net_buf *buf) } #endif /* CONFIG_BT_DF_CONNECTION_CTE_RX */ +#if defined(CONFIG_BT_DF_CONNECTION_CTE_REQ) +void bt_hci_le_df_cte_req_failed(struct net_buf *buf) +{ + struct bt_df_conn_iq_samples_report iq_report; + struct bt_conn *conn; + struct bt_conn_cb *cb; + int err; + + err = hci_df_prepare_conn_cte_req_failed(buf, &iq_report, &conn); + if (err) { + BT_ERR("Prepare CTE REQ failed IQ report failed %d", err); + return; + } + + for (cb = callback_list; cb; cb = cb->_next) { + if (cb->cte_report_cb) { + cb->cte_report_cb(conn, &iq_report); + } + } + + STRUCT_SECTION_FOREACH(bt_conn_cb, cb) + { + if (cb->cte_report_cb) { + cb->cte_report_cb(conn, &iq_report); + } + } + + bt_conn_unref(conn); +} +#endif /* CONFIG_BT_DF_CONNECTION_CTE_REQ */ + #endif /* CONFIG_BT_CONN */ diff --git a/subsys/bluetooth/host/direction.c b/subsys/bluetooth/host/direction.c index e395caffca9..89612d10c13 100644 --- a/subsys/bluetooth/host/direction.c +++ b/subsys/bluetooth/host/direction.c @@ -605,7 +605,6 @@ int hci_df_prepare_connection_iq_report(struct net_buf *buf, evt = net_buf_pull_mem(buf, sizeof(*evt)); conn = bt_conn_lookup_handle(sys_le16_to_cpu(evt->conn_handle)); - if (!conn) { BT_ERR("Unknown conn handle 0x%04X for iq samples report", sys_le16_to_cpu(evt->conn_handle)); @@ -622,6 +621,7 @@ int hci_df_prepare_connection_iq_report(struct net_buf *buf, return -EINVAL; } + report->err = BT_DF_IQ_REPORT_ERR_SUCCESS; report->chan_idx = evt->data_chan_idx; report->rx_phy = evt->rx_phy; report->chan_idx = evt->data_chan_idx; @@ -710,6 +710,45 @@ static int hci_df_set_conn_cte_req_enable(struct bt_conn *conn, bool enable, return err; } + +int hci_df_prepare_conn_cte_req_failed(struct net_buf *buf, + struct bt_df_conn_iq_samples_report *report, + struct bt_conn **conn_to_report) +{ + struct bt_hci_evt_le_cte_req_failed *evt; + struct bt_conn *conn; + + if (buf->len < sizeof(*evt)) { + BT_ERR("Unexpected end of buffer"); + return -EINVAL; + } + + evt = net_buf_pull_mem(buf, sizeof(*evt)); + + conn = bt_conn_lookup_handle(sys_le16_to_cpu(evt->conn_handle)); + if (!conn) { + BT_ERR("Unknown conn handle 0x%04X for iq samples report", + sys_le16_to_cpu(evt->conn_handle)); + return -EINVAL; + } + + if (!atomic_test_bit(conn->flags, BT_CONN_CTE_REQ_ENABLED)) { + BT_ERR("Received conn CTE request notification when CTE REQ disabled"); + return -EINVAL; + } + + (void)memset(report, 0U, sizeof(*report)); + + if (evt->status == BT_HCI_CTE_REQ_STATUS_RSP_WITHOUT_CTE) { + report->err = BT_DF_IQ_REPORT_ERR_NO_CTE; + } else { + report->err = BT_DF_IQ_REPORT_ERR_PEER_REJECTED; + } + + *conn_to_report = conn; + + return 0; +} #endif /* CONFIG_BT_DF_CONNECTION_CTE_REQ */ #if defined(CONFIG_BT_DF_CONNECTION_CTE_RSP) diff --git a/subsys/bluetooth/host/direction_internal.h b/subsys/bluetooth/host/direction_internal.h index 424bc536df6..0fb8d89ab3d 100644 --- a/subsys/bluetooth/host/direction_internal.h +++ b/subsys/bluetooth/host/direction_internal.h @@ -13,3 +13,6 @@ void hci_df_prepare_connectionless_iq_report(struct net_buf *buf, int hci_df_prepare_connection_iq_report(struct net_buf *buf, struct bt_df_conn_iq_samples_report *report, struct bt_conn **conn_to_report); +int hci_df_prepare_conn_cte_req_failed(struct net_buf *buf, + struct bt_df_conn_iq_samples_report *report, + struct bt_conn **conn_to_report); diff --git a/subsys/bluetooth/host/hci_core.c b/subsys/bluetooth/host/hci_core.c index 617ba3cc38b..033f695ae22 100644 --- a/subsys/bluetooth/host/hci_core.c +++ b/subsys/bluetooth/host/hci_core.c @@ -2229,6 +2229,11 @@ static const struct event_handler meta_events[] = { EVENT_HANDLER(BT_HCI_EVT_LE_CONNECTION_IQ_REPORT, bt_hci_le_df_connection_iq_report, sizeof(struct bt_hci_evt_le_connection_iq_report)), #endif /* CONFIG_BT_DF_CONNECTION_CTE_RX */ +#if defined(CONFIG_BT_DF_CONNECTION_CTE_REQ) + EVENT_HANDLER(BT_HCI_EVT_LE_CTE_REQUEST_FAILED, bt_hci_le_df_cte_req_failed, + sizeof(struct bt_hci_evt_le_cte_req_failed)), +#endif /* CONFIG_BT_DF_CONNECTION_CTE_REQ */ + }; static void hci_le_meta_event(struct net_buf *buf) diff --git a/subsys/bluetooth/host/hci_core.h b/subsys/bluetooth/host/hci_core.h index 412da9c2639..c265eec1078 100644 --- a/subsys/bluetooth/host/hci_core.h +++ b/subsys/bluetooth/host/hci_core.h @@ -469,3 +469,4 @@ void bt_hci_role_change(struct net_buf *buf); void bt_hci_synchronous_conn_complete(struct net_buf *buf); void bt_hci_le_df_connection_iq_report(struct net_buf *buf); +void bt_hci_le_df_cte_req_failed(struct net_buf *buf); From 98b91f0aa6aa41f214a0446c438a64dc264f0655 Mon Sep 17 00:00:00 2001 From: Piotr Pryga Date: Sat, 8 Jan 2022 14:13:20 +0100 Subject: [PATCH 096/207] [nrf fromtree] Bluetooth: host: df: Add missing bt_conn_unref There were missing bt_conn_unref after reporting IQ samples to an application. Signed-off-by: Piotr Pryga (cherry picked from commit 92be4412c0195818802ae98a827c60946187b51a) --- subsys/bluetooth/host/conn.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/subsys/bluetooth/host/conn.c b/subsys/bluetooth/host/conn.c index 6d8a8b38316..6ead16ad0db 100644 --- a/subsys/bluetooth/host/conn.c +++ b/subsys/bluetooth/host/conn.c @@ -2949,6 +2949,8 @@ void bt_hci_le_df_connection_iq_report(struct net_buf *buf) cb->cte_report_cb(conn, &iq_report); } } + + bt_conn_unref(conn); } #endif /* CONFIG_BT_DF_CONNECTION_CTE_RX */ From 9920c111340ab4d1e15dd08b93a58fe50b00792e Mon Sep 17 00:00:00 2001 From: Piotr Pryga Date: Fri, 14 Jan 2022 11:51:06 +0100 Subject: [PATCH 097/207] [nrf fromtree] Bluetooth: Controller: radio: Fix error in pkt conf macros Macros responsible for preparation of packet configuration flags in regard of PHY and CTE were wrong. PHY flags are not used as regular integer values but bits in a bitfield, hence size of the field in packet configuration flags is three instead of two. In such case CTE presen filed should be moved to bit 4th. The problem was spot when testing implementation with CODED PHY enabled. When device was sending PDUs that had attached CTE the radio was configured to use CODED PHY due to wrong bit set in packet configuration flags variable (overlapping of CTE bit with CODED PHY bit). Signed-off-by: Piotr Pryga (cherry picked from commit 9cc14c371bfc6f6c40eab897516a3ddbd471f25e) --- .../controller/ll_sw/nordic/hal/nrf5/radio/radio.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) 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 9776dd195f8..844bc7aefda 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 @@ -11,16 +11,16 @@ #define RADIO_PKT_CONF_PDU_TYPE_MSK BIT(RADIO_PKT_CONF_PDU_TYPE_POS) #define RADIO_PKT_CONF_PDU_TYPE_AC (0U) #define RADIO_PKT_CONF_PDU_TYPE_DC (1U) -/* PHY type, two bit field */ +/* PHY type, three bit field */ #define RADIO_PKT_CONF_PHY_POS (1U) -#define RADIO_PKT_CONF_PHY_MSK (BIT_MASK(2U) << RADIO_PKT_CONF_PHY_POS) +#define RADIO_PKT_CONF_PHY_MSK (BIT_MASK(3U)) #define RADIO_PKT_CONF_PHY_LEGACY (0U) -#define RADIO_PKT_CONF_PHY_1M (1U) -#define RADIO_PKT_CONF_PHY_2M (2U) -#define RADIO_PKT_CONF_PHY_CODED (3U) +#define RADIO_PKT_CONF_PHY_1M (BIT(0U)) +#define RADIO_PKT_CONF_PHY_2M (BIT(1U)) +#define RADIO_PKT_CONF_PHY_CODED (BIT(2U)) /* CTE enabled, 1 bit field */ -#define RADIO_PKT_CONF_CTE_POS (3U) -#define RADIO_PKT_CONF_CTE_MSK BIT(RADIO_PKT_CONF_PDU_TYPE_POS) +#define RADIO_PKT_CONF_CTE_POS (4U) +#define RADIO_PKT_CONF_CTE_MSK BIT(0) #define RADIO_PKT_CONF_CTE_DISABLED (0U) #define RADIO_PKT_CONF_CTE_ENABLED (1U) From e622f476e49fe756f39764954a1e1348c6ced9ba Mon Sep 17 00:00:00 2001 From: Piotr Pryga Date: Fri, 14 Jan 2022 12:39:13 +0100 Subject: [PATCH 098/207] [nrf fromtree] Bluetooth: Controller: llcp: Fix PHY update FSM stale after instant In peripheral role when: - data length update is enabled - the CONFIG_BT_MAX_CONN is set to 1 the PHY update control procedure after reaching instant sends two notifications to host. It notifies host about PHY update and data length change. Both notifications are send one after another, so two free node rx are required. The number of available node rx in provided conditions is one. The PHY update FSM is stalled in waiting state for enough empty node rx. At the same time remote device is allowed to send new remote control procedures. Received request are handled by PHY update FSM that asserts due to unknown procedure opcode. The commit changes number of allocated nodes to be two times a number of LLCP connections. This is a workaround for the issue. The best solution seems to be sharing nodsx between connections. Though this solution requires buffering remote control procedures until host notification is done. Signed-off-by: Piotr Pryga (cherry picked from commit 8ef642be82892e444cefd6d614e1910408c8777e) --- subsys/bluetooth/controller/ll_sw/ull.c | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/subsys/bluetooth/controller/ll_sw/ull.c b/subsys/bluetooth/controller/ll_sw/ull.c index 017496dc906..c76a4ab1890 100644 --- a/subsys/bluetooth/controller/ll_sw/ull.c +++ b/subsys/bluetooth/controller/ll_sw/ull.c @@ -353,15 +353,21 @@ static RXFIFO_DEFINE(done, sizeof(struct node_rx_event_done), * Increasing this by times the max. simultaneous connection count will permit * simultaneous parallel PHY update or Connection Update procedures amongst * active connections. - * Minimum node rx of 2 that can be reserved happens when local central - * initiated PHY Update reserves 2 node rx, one for PHY update complete and - * another for Data Length Update complete notification. Otherwise, a - * peripheral only needs 1 additional node rx to generate Data Length Update - * complete when PHY Update completes; node rx for PHY update complete is - * reserved as the received PHY Update Ind PDU. + * Minimum node rx of 2 that can be reserved happens when: + * - for legacy LLCPs: + * Local central initiated PHY Update reserves 2 node rx, + * one for PHY update complete and another for Data Length Update complete + * notification. Otherwise, a peripheral only needs 1 additional node rx to + * generate Data Length Update complete when PHY Update completes; node rx for + * PHY update complete is reserved as the received PHY Update Ind PDU. + * - for new LLCPs: + * Central and peripheral always use two new nodes for handling completion + * notification one for PHY update complete and another for Data Length Update + * complete. */ -#if defined(CONFIG_BT_CENTRAL) && defined(CONFIG_BT_CTLR_PHY) && \ - defined(CONFIG_BT_CTLR_DATA_LENGTH) +#if defined(CONFIG_BT_CTLR_DATA_LENGTH) && defined(CONFIG_BT_CTLR_PHY) && \ + (defined(CONFIG_BT_LL_SW_LLCP_LEGACY) && defined(CONFIG_BT_CENTRAL) || \ + !defined(CONFIG_BT_LL_SW_LLCP_LEGACY)) #define LL_PDU_RX_CNT (2 * (CONFIG_BT_CTLR_LLCP_CONN)) #elif defined(CONFIG_BT_CONN) #define LL_PDU_RX_CNT (CONFIG_BT_CTLR_LLCP_CONN) From 61613610c1a70aaa9db06451d4643547e2fed151 Mon Sep 17 00:00:00 2001 From: Piotr Pryga Date: Tue, 18 Jan 2022 11:42:30 +0100 Subject: [PATCH 099/207] [nrf fromtree] Bluetooth: Controller: Add packet TX restrictions for CTE REQ/RSP PDUs There are packet restrictions imposed by PHY update procedure for PDU that includes CTE (BT Core 5.3 : - central/peripheral can't send PDU with CTE after receive or send LLPHY_UPDATE_IND until instant if the PHY after instant is CODED - peripheral can't send PDU including CTE after it sends LL_PHY_REQ PDU until receive LL_PHY_UPDATE_IND, LL_UNKNOWN_RSP, LL_REJECTED_EXT_- IND_PDU if there is a CODE PHY in TX_PHYS - peripheral can't send PDU including CTE after it sends LL_PHY_RSP PDU until receive LL_PHY_UPDATE_IND if there is a CODED PHY in TX_PHYS of LL_PHY_RSP PDU or RX_PHYS of LL_PHY_REQ PDU. The BT 5.3 Core spec defines only one PDU that may include CTE, that is LL_CTE_RSP PDU. To avoid a situation that there is such PDU enqueued for transmission in LLL when packet transmission restrictions should be applied, both procedures in almost all cases will not be executed in parallel. Current implementation always handles remote procedurerequest first. There are possible three scenarios: 1. Remotely requested PHY update. Locally initiated CTE REQ. In this case there is no problem with LL_CTE_RSP waiting in a TX queue in LLL. Both procedures may be executed one after another. 2. Remotely requested CTE REQ. Locally initiated PHY update. In this case the CTE REQ is handled first and it will pause the PHY update procedure until LL_CTE_RSP PDU is acknowledged by remote. Then the CTE REQ procedure will be completed and PHY update continued. 3. Locally initiated PHY update is pending. Arrives remote CTE REQ. In this case the CTE REQ will be paused until localy initiated PHY update is completed. Then the CTE REQ will be continued. Thanks to that there should be no PDU including CTE in LLL TX quueue. That releases us from a situation there is a LL_CTE_RSP PDU in the LLL TX qeueue that must be changed into LL_REJECT_EXT_IND PDU due to change of PHY to CODED PHY after PHY update procedure completes. Signed-off-by: Piotr Pryga (cherry picked from commit b96e5a00385efaca891bfd17a8fbcc311d66fae0) --- .../controller/ll_sw/ull_conn_types.h | 3 ++ subsys/bluetooth/controller/ll_sw/ull_llcp.c | 3 ++ .../controller/ll_sw/ull_llcp_common.c | 28 +++++++++++++++---- .../controller/ll_sw/ull_llcp_internal.h | 4 +++ .../bluetooth/controller/ll_sw/ull_llcp_phy.c | 14 +++++++--- .../controller/ll_sw/ull_llcp_remote.c | 21 ++++++++++++++ 6 files changed, 63 insertions(+), 10 deletions(-) diff --git a/subsys/bluetooth/controller/ll_sw/ull_conn_types.h b/subsys/bluetooth/controller/ll_sw/ull_conn_types.h index 32b50585530..bac7866798e 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_conn_types.h +++ b/subsys/bluetooth/controller/ll_sw/ull_conn_types.h @@ -367,6 +367,9 @@ struct llcp_struct { uint8_t collision; uint8_t incompat; uint8_t reject_opcode; +#if defined(CONFIG_BT_CTLR_DF_CONN_CTE_RSP) || defined(CONFIG_BT_CTLR_DF_CONN_CTE_REQ) + uint8_t paused_cmd; +#endif /* CONFIG_BT_CTLR_DF_CONN_CTE_RSP || CONFIG_BT_CTLR_DF_CONN_CTE_REQ */ } remote; /* Prepare parameters */ diff --git a/subsys/bluetooth/controller/ll_sw/ull_llcp.c b/subsys/bluetooth/controller/ll_sw/ull_llcp.c index fc3f57a87a1..d65ef4b09f5 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_llcp.c +++ b/subsys/bluetooth/controller/ll_sw/ull_llcp.c @@ -433,6 +433,9 @@ void ull_llcp_init(struct ll_conn *conn) sys_slist_init(&conn->llcp.remote.pend_proc_list); conn->llcp.remote.incompat = INCOMPAT_NO_COLLISION; conn->llcp.remote.collision = 0U; +#if defined(CONFIG_BT_CTLR_DF_CONN_CTE_RSP) + conn->llcp.remote.paused_cmd = PROC_NONE; +#endif /* CONFIG_BT_CTLR_DF_CONN_CTE_RSP */ /* Reset the cached version Information (PROC_VERSION_EXCHANGE) */ memset(&conn->llcp.vex, 0, sizeof(conn->llcp.vex)); diff --git a/subsys/bluetooth/controller/ll_sw/ull_llcp_common.c b/subsys/bluetooth/controller/ll_sw/ull_llcp_common.c index f614bb118f7..e2271b1c8af 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_llcp_common.c +++ b/subsys/bluetooth/controller/ll_sw/ull_llcp_common.c @@ -365,6 +365,7 @@ static void lp_comm_complete(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t } if (ctx->state == LP_COMMON_STATE_IDLE) { + llcp_rr_set_paused_cmd(conn, PROC_NONE); llcp_lr_complete(conn); } break; @@ -458,7 +459,8 @@ static void lp_comm_send_req(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t #endif /* CONFIG_BT_CTLR_DATA_LENGTH */ #if defined(CONFIG_BT_CTLR_DF_CONN_CTE_REQ) case PROC_CTE_REQ: - if (ctx->pause || !llcp_tx_alloc_peek(conn, ctx)) { + if (ctx->pause || !llcp_tx_alloc_peek(conn, ctx) || + (llcp_rr_get_paused_cmd(conn) == PROC_CTE_REQ)) { ctx->state = LP_COMMON_STATE_WAIT_TX; } else { lp_comm_tx(conn, ctx); @@ -776,6 +778,9 @@ static void rp_comm_tx(struct ll_conn *conn, struct proc_ctx *ctx) llcp_pdu_encode_reject_ext_ind(pdu, PDU_DATA_LLCTRL_TYPE_CTE_REQ, err_code); ctx->rx_opcode = PDU_DATA_LLCTRL_TYPE_REJECT_EXT_IND; } + + ctx->tx_ack = tx; + break; } #endif /* CONFIG_BT_CTLR_DF_CONN_CTE_RSP */ @@ -934,12 +939,13 @@ static void rp_comm_send_rsp(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t #endif /* CONFIG_BT_CTLR_DATA_LENGTH */ #if defined(CONFIG_BT_CTLR_DF_CONN_CTE_RSP) case PROC_CTE_REQ: - if (ctx->pause || !llcp_tx_alloc_peek(conn, ctx)) { + if (ctx->pause || !llcp_tx_alloc_peek(conn, ctx) || + (llcp_rr_get_paused_cmd(conn) == PROC_CTE_REQ)) { ctx->state = RP_COMMON_STATE_WAIT_TX; } else { + llcp_rr_set_paused_cmd(conn, PROC_PHY_UPDATE); rp_comm_tx(conn, ctx); - llcp_rr_complete(conn); - ctx->state = RP_COMMON_STATE_IDLE; + ctx->state = RP_COMMON_STATE_WAIT_TX_ACK; } break; #endif /* CONFIG_BT_CTLR_DF_CONN_CTE_RSP */ @@ -974,13 +980,13 @@ static void rp_comm_st_wait_tx(struct ll_conn *conn, struct proc_ctx *ctx, uint8 } } -#if defined(CONFIG_BT_CTLR_DATA_LENGTH) static void rp_comm_st_wait_tx_ack(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t evt, void *param) { switch (evt) { case RP_COMMON_EVT_ACK: switch (ctx->proc) { +#if defined(CONFIG_BT_CTLR_DATA_LENGTH) case PROC_DATA_LENGTH_UPDATE: { /* Apply changes in data lengths/times */ uint8_t dle_changed = ull_dle_update_eff(conn); @@ -998,6 +1004,15 @@ static void rp_comm_st_wait_tx_ack(struct ll_conn *conn, struct proc_ctx *ctx, u } break; } +#endif /* CONFIG_BT_CTLR_DATA_LENGTH */ +#if defined(CONFIG_BT_CTLR_DF_CONN_CTE_RSP) + case PROC_CTE_REQ: { + /* add PHY update pause = false here */ + llcp_rr_set_paused_cmd(conn, PROC_NONE); + llcp_rr_complete(conn); + ctx->state = RP_COMMON_STATE_IDLE; + } +#endif /* CONFIG_BT_CTLR_DF_CONN_CTE_RSP */ default: /* Ignore other procedures */ break; @@ -1009,6 +1024,7 @@ static void rp_comm_st_wait_tx_ack(struct ll_conn *conn, struct proc_ctx *ctx, u } } +#if defined(CONFIG_BT_CTLR_DATA_LENGTH) static void rp_comm_st_wait_ntf(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t evt, void *param) { @@ -1033,10 +1049,10 @@ static void rp_comm_execute_fsm(struct ll_conn *conn, struct proc_ctx *ctx, uint case RP_COMMON_STATE_WAIT_TX: rp_comm_st_wait_tx(conn, ctx, evt, param); break; -#if defined(CONFIG_BT_CTLR_DATA_LENGTH) case RP_COMMON_STATE_WAIT_TX_ACK: rp_comm_st_wait_tx_ack(conn, ctx, evt, param); break; +#if defined(CONFIG_BT_CTLR_DATA_LENGTH) case RP_COMMON_STATE_WAIT_NTF: rp_comm_st_wait_ntf(conn, ctx, evt, param); break; diff --git a/subsys/bluetooth/controller/ll_sw/ull_llcp_internal.h b/subsys/bluetooth/controller/ll_sw/ull_llcp_internal.h index 1b26fc5d6aa..0c1390f395e 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_llcp_internal.h +++ b/subsys/bluetooth/controller/ll_sw/ull_llcp_internal.h @@ -20,6 +20,8 @@ enum llcp_proc { PROC_CHAN_MAP_UPDATE, PROC_DATA_LENGTH_UPDATE, PROC_CTE_REQ, + /* A helper enum entry, to use in pause prcedure context */ + PROC_NONE = 0x0, }; #if ((CONFIG_BT_CTLR_LLCP_COMMON_TX_CTRL_BUF_NUM <\ (CONFIG_BT_CTLR_LLCP_TX_PER_CONN_TX_CTRL_BUF_NUM_MAX *\ @@ -444,6 +446,8 @@ void llcp_lr_abort(struct ll_conn *conn); */ void llcp_rr_set_incompat(struct ll_conn *conn, enum proc_incompat incompat); bool llcp_rr_get_collision(struct ll_conn *conn); +void llcp_rr_set_paused_cmd(struct ll_conn *conn, enum llcp_proc); +enum llcp_proc llcp_rr_get_paused_cmd(struct ll_conn *conn); struct proc_ctx *llcp_rr_peek(struct ll_conn *conn); void llcp_rr_tx_ack(struct ll_conn *conn, struct proc_ctx *ctx, struct node_tx *tx); void llcp_rr_rx(struct ll_conn *conn, struct proc_ctx *ctx, struct node_rx_pdu *rx); diff --git a/subsys/bluetooth/controller/ll_sw/ull_llcp_phy.c b/subsys/bluetooth/controller/ll_sw/ull_llcp_phy.c index 021b2a35cc3..bd006d03959 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_llcp_phy.c +++ b/subsys/bluetooth/controller/ll_sw/ull_llcp_phy.c @@ -435,15 +435,18 @@ static void lp_pu_complete(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t e #endif llcp_lr_complete(conn); ctx->state = LP_PU_STATE_IDLE; + llcp_rr_set_paused_cmd(conn, PROC_NONE); } } static void lp_pu_send_phy_req(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t evt, void *param) { - if (llcp_rr_get_collision(conn) || !llcp_tx_alloc_peek(conn, ctx)) { + if (ctx->pause || llcp_rr_get_collision(conn) || !llcp_tx_alloc_peek(conn, ctx) || + (llcp_rr_get_paused_cmd(conn) == PROC_PHY_UPDATE)) { ctx->state = LP_PU_STATE_WAIT_TX_PHY_REQ; } else { llcp_rr_set_incompat(conn, INCOMPAT_RESOLVABLE); + llcp_rr_set_paused_cmd(conn, PROC_CTE_REQ); lp_pu_tx(conn, ctx, PDU_DATA_LLCTRL_TYPE_PHY_REQ); llcp_tx_pause_data(conn); ctx->state = LP_PU_STATE_WAIT_TX_ACK_PHY_REQ; @@ -454,7 +457,7 @@ static void lp_pu_send_phy_req(struct ll_conn *conn, struct proc_ctx *ctx, uint8 static void lp_pu_send_phy_update_ind(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t evt, void *param) { - if (!llcp_tx_alloc_peek(conn, ctx)) { + if (ctx->pause || !llcp_tx_alloc_peek(conn, ctx)) { ctx->state = LP_PU_STATE_WAIT_TX_PHY_UPDATE_IND; } else { ctx->data.pu.instant = pu_event_counter(conn) + PHY_UPDATE_INSTANT_DELTA; @@ -832,6 +835,7 @@ static void rp_pu_complete(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t e pu_dle_ntf(conn, ctx); } #endif + llcp_rr_set_paused_cmd(conn, PROC_NONE); llcp_rr_complete(conn); ctx->state = RP_PU_STATE_IDLE; } @@ -841,7 +845,7 @@ static void rp_pu_complete(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t e static void rp_pu_send_phy_update_ind(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t evt, void *param) { - if (!llcp_tx_alloc_peek(conn, ctx)) { + if (ctx->pause || !llcp_tx_alloc_peek(conn, ctx)) { ctx->state = RP_PU_STATE_WAIT_TX_PHY_UPDATE_IND; } else { ctx->data.pu.instant = pu_event_counter(conn) + PHY_UPDATE_INSTANT_DELTA; @@ -855,9 +859,11 @@ static void rp_pu_send_phy_update_ind(struct ll_conn *conn, struct proc_ctx *ctx #if defined(CONFIG_BT_PERIPHERAL) static void rp_pu_send_phy_rsp(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t evt, void *param) { - if (!llcp_tx_alloc_peek(conn, ctx)) { + if (ctx->pause || !llcp_tx_alloc_peek(conn, ctx) || + (llcp_rr_get_paused_cmd(conn) == PROC_PHY_UPDATE)) { ctx->state = RP_PU_STATE_WAIT_TX_PHY_RSP; } else { + llcp_rr_set_paused_cmd(conn, PROC_CTE_REQ); rp_pu_tx(conn, ctx, PDU_DATA_LLCTRL_TYPE_PHY_RSP); ctx->rx_opcode = PDU_DATA_LLCTRL_TYPE_PHY_UPD_IND; ctx->state = RP_PU_STATE_WAIT_TX_ACK_PHY_RSP; diff --git a/subsys/bluetooth/controller/ll_sw/ull_llcp_remote.c b/subsys/bluetooth/controller/ll_sw/ull_llcp_remote.c index 897c4205b74..453bf833c97 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_llcp_remote.c +++ b/subsys/bluetooth/controller/ll_sw/ull_llcp_remote.c @@ -136,6 +136,22 @@ void llcp_rr_set_incompat(struct ll_conn *conn, enum proc_incompat incompat) conn->llcp.remote.incompat = incompat; } +void llcp_rr_set_paused_cmd(struct ll_conn *conn, enum llcp_proc proc) +{ +#if defined(CONFIG_BT_CTLR_DF_CONN_CTE_RSP) || defined(CONFIG_BT_CTLR_DF_CONN_CTE_REQ) + conn->llcp.remote.paused_cmd = proc; +#endif /* CONFIG_BT_CTLR_DF_CONN_CTE_RSP || CONFIG_BT_CTLR_DF_CONN_CTE_REQ */ +} + +enum llcp_proc llcp_rr_get_paused_cmd(struct ll_conn *conn) +{ +#if defined(CONFIG_BT_CTLR_DF_CONN_CTE_RSP) || defined(CONFIG_BT_CTLR_DF_CONN_CTE_REQ) + return conn->llcp.remote.paused_cmd; +#else + return PROC_NONE; +#endif /* CONFIG_BT_CTLR_DF_CONN_CTE_RSP || CONFIG_BT_CTLR_DF_CONN_CTE_REQ */ +} + static enum proc_incompat rr_get_incompat(struct ll_conn *conn) { return conn->llcp.remote.incompat; @@ -245,6 +261,11 @@ void llcp_rr_tx_ack(struct ll_conn *conn, struct proc_ctx *ctx, struct node_tx * llcp_rp_pu_tx_ack(conn, ctx, tx); break; #endif /* CONFIG_BT_CTLR_PHY */ +#if defined(CONFIG_BT_CTLR_DF_CONN_CTE_RSP) + case PROC_CTE_REQ: + llcp_rp_comm_tx_ack(conn, ctx, tx); + break; +#endif /* CONFIG_BT_CTLR_DF_CONN_CTE_RSP */ default: /* Ignore tx_ack */ break; From 856c2ab8bee58a4998033565ad645491a1d3690d Mon Sep 17 00:00:00 2001 From: Piotr Pryga Date: Tue, 18 Jan 2022 12:01:42 +0100 Subject: [PATCH 100/207] [nrf fromtree] Bluetooth: Controller: Add missing LLCP collision resolve When there is pending local control procedure that has instant it should be possible to run remote control procedure without instant because there is no collision. There were missing code to run this case in rr_st_idle() of refactored LLCPs. Signed-off-by: Piotr Pryga (cherry picked from commit 2006083c48885722ddcfeccffd7c4218973b8fb1) --- subsys/bluetooth/controller/ll_sw/ull_llcp_remote.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/subsys/bluetooth/controller/ll_sw/ull_llcp_remote.c b/subsys/bluetooth/controller/ll_sw/ull_llcp_remote.c index 453bf833c97..802c5f19591 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_llcp_remote.c +++ b/subsys/bluetooth/controller/ll_sw/ull_llcp_remote.c @@ -486,6 +486,12 @@ static void rr_st_idle(struct ll_conn *conn, uint8_t evt, void *param) conn->llcp.remote.reject_opcode = pdu->llctrl.opcode; rr_act_reject(conn); + } else if (!with_instant && central && incompat == INCOMPAT_RESOLVABLE) { + /* No collision with procedure without instant + * => Run procedure + */ + rr_act_run(conn); + rr_set_state(conn, RR_STATE_ACTIVE); } else if (with_instant && incompat == INCOMPAT_RESERVED) { /* Protocol violation. * => Disconnect From 0ea4b98e7a57c68661bfab2b6d80493daf6a3772 Mon Sep 17 00:00:00 2001 From: Piotr Pryga Date: Tue, 18 Jan 2022 18:14:47 +0100 Subject: [PATCH 101/207] [nrf fromtree] tests: Bluetooth: Fix failing tests related with direction finding Fixes build issues for tests in related with CTE REQ and hci commands. Fixes issues in unit tests for CTE REQ/RSP control proedures. Signed-off-by: Piotr Pryga (cherry picked from commit 239c1a07660ac7a7bc111a1ae3a78ea0df65c516) --- tests/bluetooth/controller/ctrl_cte_req/src/main.c | 14 +++++++++++++- tests/bluetooth/df/connection_cte_req/prj.conf | 6 ++++-- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/tests/bluetooth/controller/ctrl_cte_req/src/main.c b/tests/bluetooth/controller/ctrl_cte_req/src/main.c index 66911c49392..21cd87061ae 100644 --- a/tests/bluetooth/controller/ctrl_cte_req/src/main.c +++ b/tests/bluetooth/controller/ctrl_cte_req/src/main.c @@ -237,6 +237,9 @@ void test_cte_req_central_remote(void) lt_rx(LL_CTE_RSP, &conn, &tx, &remote_cte_rsp); lt_rx_q_is_empty(&conn); + /* TX Ack */ + event_tx_ack(&conn, tx); + /* Done */ event_done(&conn); @@ -303,6 +306,9 @@ void test_cte_req_peripheral_remote(void) lt_rx(LL_CTE_RSP, &conn, &tx, &remote_cte_rsp); lt_rx_q_is_empty(&conn); + /* TX Ack */ + event_tx_ack(&conn, tx); + /* Done */ event_done(&conn); @@ -504,7 +510,7 @@ void test_cte_req_reject_inv_ll_param_central_remote(void) /* Enable response for CTE request */ ull_cp_cte_rsp_enable(&conn, true, BT_HCI_LE_CTE_LEN_MAX, - (BT_HCI_LE_AOA_CTE | BT_HCI_LE_AOD_CTE_1US)); + (BT_HCI_LE_AOA_CTE_RSP | BT_HCI_LE_AOD_CTE_RSP_1US)); /* Prepare */ event_prepare(&conn); @@ -522,6 +528,9 @@ void test_cte_req_reject_inv_ll_param_central_remote(void) lt_rx(LL_REJECT_EXT_IND, &conn, &tx, &remote_reject_ext_ind); lt_rx_q_is_empty(&conn); + /* TX Ack */ + event_tx_ack(&conn, tx); + /* Done */ event_done(&conn); @@ -591,6 +600,9 @@ void test_cte_req_reject_inv_ll_param_peripheral_remote(void) lt_rx(LL_REJECT_EXT_IND, &conn, &tx, &remote_reject_ext_ind); lt_rx_q_is_empty(&conn); + /* TX Ack */ + event_tx_ack(&conn, tx); + /* Done */ event_done(&conn); diff --git a/tests/bluetooth/df/connection_cte_req/prj.conf b/tests/bluetooth/df/connection_cte_req/prj.conf index 6a3efb55fb1..36c48049ce7 100644 --- a/tests/bluetooth/df/connection_cte_req/prj.conf +++ b/tests/bluetooth/df/connection_cte_req/prj.conf @@ -15,8 +15,10 @@ CONFIG_BT_DF=y CONFIG_BT_DF_CONNECTION_CTE_RX=y CONFIG_BT_CTLR_DF=y -CONFIG_BT_CTLR_DF_CONN_CTE_REQ=y - +CONFIG_BT_DF_CONNECTION_CTE_TX=y +CONFIG_BT_DF_CONNECTION_CTE_RX=y +CONFIG_BT_DF_CONNECTION_CTE_RSP=y +CONFIG_BT_DF_CONNECTION_CTE_REQ=y # set antenna switch pattern to max allowed value CONFIG_BT_CTLR_DF_MAX_ANT_SW_PATTERN_LEN=39 From a34f95121697ea9c0cec61d3005757eb3fe739ff Mon Sep 17 00:00:00 2001 From: Piotr Pryga Date: Wed, 19 Jan 2022 22:29:02 +0100 Subject: [PATCH 102/207] [nrf fromtree] Bluetooth: Controller: df: Add disable support for CTE REQ and RSP proc Add missing implementation for disabling CTE request and resposne control procedures. If any of these commands is active in LLL then ULL context has to wait before return. The wait mechanism is based on semaphore. The semaphore is initialized in ULL context and given by code responsible for command completion. Signed-off-by: Piotr Pryga (cherry picked from commit 3ba1d20378288a6f3230de30d9698162e054cba9) --- .../controller/ll_sw/ull_conn_types.h | 13 ++++-- subsys/bluetooth/controller/ll_sw/ull_df.c | 41 +++++++++++++++---- subsys/bluetooth/controller/ll_sw/ull_llcp.c | 9 ++++ .../controller/ll_sw/ull_llcp_common.c | 11 ++++- 4 files changed, 60 insertions(+), 14 deletions(-) diff --git a/subsys/bluetooth/controller/ll_sw/ull_conn_types.h b/subsys/bluetooth/controller/ll_sw/ull_conn_types.h index bac7866798e..fc028e7ebf8 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_conn_types.h +++ b/subsys/bluetooth/controller/ll_sw/ull_conn_types.h @@ -420,22 +420,29 @@ struct llcp_struct { /* Procedure may be active periodically, active state must be stored. * If procedure is active, request parameters update may not be issued. */ - uint8_t is_enabled; + uint8_t is_enabled:1; + uint8_t is_active:1; uint8_t cte_type; /* Minimum requested CTE length in 8us units */ uint8_t min_cte_len; uint16_t req_interval; uint16_t req_expire; + void *disable_param; + void (*disable_cb)(void *param); } cte_req; - #endif /* CONFIG_BT_CTLR_DF_CONN_CTE_REQ */ + #if defined(CONFIG_BT_CTLR_DF_CONN_CTE_RSP) struct llcp_df_rsp_cfg { - uint8_t is_enabled; + uint8_t is_enabled:1; + uint8_t is_active:1; uint8_t cte_types; uint8_t max_cte_len; + void *disable_param; + void (*disable_cb)(void *param); } cte_rsp; #endif /* CONFIG_BT_CTLR_DF_CONN_CTE_RSP */ + #if (CONFIG_BT_CTLR_LLCP_PER_CONN_TX_CTRL_BUF_NUM > 0) &&\ (CONFIG_BT_CTLR_LLCP_PER_CONN_TX_CTRL_BUF_NUM <\ CONFIG_BT_CTLR_LLCP_TX_PER_CONN_TX_CTRL_BUF_NUM_MAX) diff --git a/subsys/bluetooth/controller/ll_sw/ull_df.c b/subsys/bluetooth/controller/ll_sw/ull_df.c index 9767cbbd55e..4fcb6e17aa4 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_df.c +++ b/subsys/bluetooth/controller/ll_sw/ull_df.c @@ -1120,6 +1120,13 @@ uint8_t ll_df_set_conn_cte_rx_params(uint16_t handle, uint8_t sampling_enable, } #endif /* CONFIG_BT_CTLR_DF_CONN_CTE_RX */ +#if defined(CONFIG_BT_CTLR_DF_CONN_CTE_REQ) || defined(CONFIG_BT_CTLR_DF_CONN_CTE_RSP) +static void df_conn_cte_req_disable(void *param) +{ + k_sem_give(param); +} +#endif /* CONFIG_BT_CTLR_DF_CONN_CTE_REQ || CONFIG_BT_CTLR_DF_CONN_CTE_RSP */ + #if defined(CONFIG_BT_CTLR_DF_CONN_CTE_REQ) /* @brief Function enables or disables CTE request control procedure for a connection. * @@ -1156,10 +1163,18 @@ uint8_t ll_df_set_conn_cte_req_enable(uint16_t handle, uint8_t enable, conn->llcp.cte_req.is_enabled = false; conn->llcp.cte_req.req_interval = 0U; - /* There is no verification if the command is pending. If it is already disabled - * there is no change to the state. - */ - /* TODO: How handle command pending in LLL? */ + if (conn->llcp.cte_req.is_active) { + struct k_sem sem; + + k_sem_init(&sem, 0U, 1U); + conn->llcp.cte_req.disable_param = &sem; + conn->llcp.cte_req.disable_cb = df_conn_cte_req_disable; + + if (!conn->llcp.cte_req.is_active) { + k_sem_take(&sem, K_FOREVER); + } + } + return BT_HCI_ERR_SUCCESS; } else { if (!conn->lll.df_rx_cfg.is_initialized) { @@ -1206,7 +1221,7 @@ uint8_t ll_df_set_conn_cte_req_enable(uint16_t handle, uint8_t enable, return BT_HCI_ERR_UNSUPP_REMOTE_FEATURE; } - conn->llcp.cte_req.is_enabled = true; + conn->llcp.cte_req.is_enabled = 0U; conn->llcp.cte_req.req_interval = cte_request_interval; conn->llcp.cte_req.cte_type = requested_cte_type; conn->llcp.cte_req.min_cte_len = requested_cte_length; @@ -1250,11 +1265,19 @@ uint8_t ll_df_set_conn_cte_rsp_enable(uint16_t handle, uint8_t enable) ull_cp_cte_rsp_enable(conn, enable, LLL_DF_MAX_CTE_LEN, conn->lll.df_tx_cfg.cte_types_allowed); } else { - /* There is no parameter validation for disable operation. */ + conn->lll.df_tx_cfg.cte_rsp_en = false; - /* TODO: Add missing implementation of disable CTE request. - * Requires refactored LLCPs. - */ + if (conn->llcp.cte_rsp.is_active) { + struct k_sem sem; + + k_sem_init(&sem, 0U, 1U); + conn->llcp.cte_rsp.disable_param = &sem; + conn->llcp.cte_rsp.disable_cb = df_conn_cte_req_disable; + + if (!conn->llcp.cte_rsp.is_active) { + k_sem_take(&sem, K_FOREVER); + } + } } return BT_HCI_ERR_SUCCESS; diff --git a/subsys/bluetooth/controller/ll_sw/ull_llcp.c b/subsys/bluetooth/controller/ll_sw/ull_llcp.c index d65ef4b09f5..2a5810a5711 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_llcp.c +++ b/subsys/bluetooth/controller/ll_sw/ull_llcp.c @@ -458,9 +458,15 @@ void ull_llcp_init(struct ll_conn *conn) #if defined(CONFIG_BT_CTLR_DF_CONN_CTE_REQ) conn->llcp.cte_req.is_enabled = 0U; conn->llcp.cte_req.req_expire = 0U; + conn->llcp.cte_req.is_active = 0U; + conn->llcp.cte_req.disable_param = NULL; + conn->llcp.cte_req.disable_cb = NULL; #endif /* CONFIG_BT_CTLR_DF_CONN_CTE_REQ */ #if defined(CONFIG_BT_CTLR_DF_CONN_CTE_RSP) conn->llcp.cte_rsp.is_enabled = 0U; + conn->llcp.cte_rsp.is_active = 0U; + conn->llcp.cte_rsp.disable_param = NULL; + conn->llcp.cte_rsp.disable_cb = NULL; #endif /* CONFIG_BT_CTLR_DF_CONN_CTE_RSP */ #if defined(LLCP_TX_CTRL_BUF_QUEUE_ENABLE) @@ -904,6 +910,9 @@ uint8_t ull_cp_cte_req(struct ll_conn *conn, uint8_t min_cte_len, uint8_t cte_ty ctx->data.cte_req.min_len = min_cte_len; ctx->data.cte_req.type = cte_type; + + conn->llcp.cte_req.is_active = 1U; + llcp_lr_enqueue(conn, ctx); return BT_HCI_ERR_SUCCESS; diff --git a/subsys/bluetooth/controller/ll_sw/ull_llcp_common.c b/subsys/bluetooth/controller/ll_sw/ull_llcp_common.c index e2271b1c8af..a38423b3822 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_llcp_common.c +++ b/subsys/bluetooth/controller/ll_sw/ull_llcp_common.c @@ -356,18 +356,24 @@ static void lp_comm_complete(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t conn->llcp.cte_req.is_enabled = 0U; lp_comm_ntf(conn, ctx); } - ctx->state = LP_COMMON_STATE_IDLE; } else if (ctx->response_opcode == PDU_DATA_LLCTRL_TYPE_REJECT_EXT_IND && ctx->reject_ext_ind.reject_opcode == PDU_DATA_LLCTRL_TYPE_CTE_REQ) { lp_comm_ntf(conn, ctx); conn->llcp.cte_req.is_enabled = 0U; - ctx->state = LP_COMMON_STATE_IDLE; } + ctx->state = LP_COMMON_STATE_IDLE; + if (ctx->state == LP_COMMON_STATE_IDLE) { llcp_rr_set_paused_cmd(conn, PROC_NONE); llcp_lr_complete(conn); } + + conn->llcp.cte_req.is_active = 0U; + if (conn->llcp.cte_req.disable_cb) { + conn->llcp.cte_req.disable_cb(conn->llcp.cte_req.disable_param); + } + break; #endif /* CONFIG_BT_CTLR_DF_CONN_CTE_REQ */ default: @@ -1008,6 +1014,7 @@ static void rp_comm_st_wait_tx_ack(struct ll_conn *conn, struct proc_ctx *ctx, u #if defined(CONFIG_BT_CTLR_DF_CONN_CTE_RSP) case PROC_CTE_REQ: { /* add PHY update pause = false here */ + ctx->tx_ack = NULL; llcp_rr_set_paused_cmd(conn, PROC_NONE); llcp_rr_complete(conn); ctx->state = RP_COMMON_STATE_IDLE; From 501947b3fa651f89eacfeadb4f52867bd9d59980 Mon Sep 17 00:00:00 2001 From: Piotr Pryga Date: Fri, 21 Jan 2022 01:06:44 +0100 Subject: [PATCH 103/207] [nrf fromtree] Bluetooth: Controller: Enable PDU CP bit when CTE RX is enabled The CP bit is read in DF connected mode while interpreting LL_CTE_RSP PDU, hence it must be available in struct pdu_data type. There were missing two Kconfig options in new LLCP tests. They were reponsbile for disable of CP bit instruct pdu_data. That caused tests to fail during compilation. Signed-off-by: Piotr Pryga (cherry picked from commit 69a6ae3b3a7a0a22a70c62cee2c66538698057bd) --- subsys/bluetooth/controller/ll_sw/pdu.h | 8 ++++++++ tests/bluetooth/controller/mock_ctrl/include/kconfig.h | 8 ++++++++ 2 files changed, 16 insertions(+) diff --git a/subsys/bluetooth/controller/ll_sw/pdu.h b/subsys/bluetooth/controller/ll_sw/pdu.h index 6bdb35053d5..8f16b26c3ba 100644 --- a/subsys/bluetooth/controller/ll_sw/pdu.h +++ b/subsys/bluetooth/controller/ll_sw/pdu.h @@ -809,11 +809,19 @@ struct pdu_data { uint8_t nesn:1; uint8_t sn:1; uint8_t md:1; +#if defined(CONFIG_BT_CTLR_DF_CONN_CTE_TX) || defined(CONFIG_BT_CTLR_DF_CONN_CTE_RX) uint8_t cp:1; uint8_t rfu:2; +#else + uint8_t rfu:3; +#endif #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ +#if defined(CONFIG_BT_CTLR_DF_CONN_CTE_TX) || defined(CONFIG_BT_CTLR_DF_CONN_CTE_RX) uint8_t rfu:2; uint8_t cp:1; +#else + uint8_t rfu:3; +#endif uint8_t md:1; uint8_t sn:1; uint8_t nesn:1; diff --git a/tests/bluetooth/controller/mock_ctrl/include/kconfig.h b/tests/bluetooth/controller/mock_ctrl/include/kconfig.h index 2c24b121b34..f5222e7e29a 100644 --- a/tests/bluetooth/controller/mock_ctrl/include/kconfig.h +++ b/tests/bluetooth/controller/mock_ctrl/include/kconfig.h @@ -119,6 +119,14 @@ #endif /* Direction finding LE Features configs */ +#ifndef CONFIG_BT_CTLR_DF_CONN_CTE_RX +#define CONFIG_BT_CTLR_DF_CONN_CTE_RX y +#endif + +#ifndef CONFIG_BT_CTLR_DF_CONN_CTE_TX +#define CONFIG_BT_CTLR_DF_CONN_CTE_TX y +#endif + #ifndef CONFIG_BT_CTLR_DF_CONN_CTE_REQ #define CONFIG_BT_CTLR_DF_CONN_CTE_REQ y #endif From b2736e35b3efdae614f95e434c4bc9ee2704d4b3 Mon Sep 17 00:00:00 2001 From: Piotr Pryga Date: Thu, 20 Jan 2022 15:04:04 +0100 Subject: [PATCH 104/207] [nrf fromtree] samples: Bluetooth: df: Add DF central sample Add new sample application for direction finding to show how the functionality works in connected mode for central role. Signed-off-by: Piotr Pryga (cherry picked from commit e17c4485bf4ee35d44ad475cc15275b699d58eee) --- .../direction_finding_central/CMakeLists.txt | 14 + .../direction_finding_central/README.rst | 73 +++++ .../boards/nrf52833dk_nrf52820.conf | 23 ++ .../boards/nrf52833dk_nrf52820.overlay | 26 ++ .../boards/nrf52833dk_nrf52833.conf | 23 ++ .../boards/nrf52833dk_nrf52833.overlay | 28 ++ .../overlay-aod.conf | 8 + .../direction_finding_central/prj.conf | 18 ++ .../direction_finding_central/sample.yaml | 17 ++ .../direction_finding_central/src/main.c | 269 ++++++++++++++++++ 10 files changed, 499 insertions(+) create mode 100644 samples/bluetooth/direction_finding_central/CMakeLists.txt create mode 100644 samples/bluetooth/direction_finding_central/README.rst create mode 100644 samples/bluetooth/direction_finding_central/boards/nrf52833dk_nrf52820.conf create mode 100644 samples/bluetooth/direction_finding_central/boards/nrf52833dk_nrf52820.overlay create mode 100644 samples/bluetooth/direction_finding_central/boards/nrf52833dk_nrf52833.conf create mode 100644 samples/bluetooth/direction_finding_central/boards/nrf52833dk_nrf52833.overlay create mode 100644 samples/bluetooth/direction_finding_central/overlay-aod.conf create mode 100644 samples/bluetooth/direction_finding_central/prj.conf create mode 100644 samples/bluetooth/direction_finding_central/sample.yaml create mode 100644 samples/bluetooth/direction_finding_central/src/main.c diff --git a/samples/bluetooth/direction_finding_central/CMakeLists.txt b/samples/bluetooth/direction_finding_central/CMakeLists.txt new file mode 100644 index 00000000000..a3f5cb8d0bf --- /dev/null +++ b/samples/bluetooth/direction_finding_central/CMakeLists.txt @@ -0,0 +1,14 @@ +# +# Copyright (c) 2022 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) + +project(direction_finding_central) + +target_sources(app PRIVATE + src/main.c +) diff --git a/samples/bluetooth/direction_finding_central/README.rst b/samples/bluetooth/direction_finding_central/README.rst new file mode 100644 index 00000000000..7c070ec2746 --- /dev/null +++ b/samples/bluetooth/direction_finding_central/README.rst @@ -0,0 +1,73 @@ +.. _bluetooth_direction_finding_central: + +Bluetooth: Direction Finding Central +#################################### + +Overview +******** + +A simple application demonstrating the BLE Direction Finding CTE reception in +connected mode by requesting transmission of a packet containing Constant +Tone Extension by connected peer device. + +Requirements +************ + +* Nordic nRF SoC based board with Direction Finding support (example boards: + :ref:`nrf52833dk_nrf52833`, :ref:`nrf52833dk_nrf52820`, :ref:`nrf5340dk_nrf5340`) +* Antenna matrix for AoA (optional) + +Check your SoC's product specification for Direction Finding support if you are +unsure. + +Building and Running +******************** + +By default the application supports Angle of Arrival and Angle of Departure mode. + +To use Angle of Departure mode only, build this application as follows, +changing ``nrf52833dk_nrf52833`` as needed for your board: + +.. zephyr-app-commands:: + :zephyr-app: samples/bluetooth/direction_finding_central + :host-os: unix + :board: nrf52833dk_nrf52833 + :gen-args: -DOVERLAY_CONFIG=overlay-aod.conf + :goals: build flash + :compact: + +To run the application on nRF5340DK, a Bluetooth controller application must +also run on the network core. The :ref:`bluetooth-hci-rpmsg-sample` sample +application may be used. To build this sample with direction finding support +enabled: + +* Copy + :zephyr_file:`samples/bluetooth/direction_finding_central/boards/nrf52833dk_nrf52833.overlay` + to a new file, + :file:`samples/bluetooth/hci_rpmsg/boards/nrf5340dk_nrf5340_cpunet.overlay`. +* Copy + :zephyr_file:`samples/bluetooth/direction_finding_central/boards/nrf52833dk_nrf52833.conf` + to a new file, + :file:`samples/bluetooth/hci_rpmsg/boards/nrf5340dk_nrf5340_cpunet.conf`. + +Antenna matrix configuration +**************************** + +To use this sample with Angle of Arrival enabled on Nordic SoCs, additional +configuration must be provided via :ref:`devicetree ` to enable +control of the antenna array. + +An example devicetree overlay is in +:zephyr_file:`samples/bluetooth/direction_finding_central/boards/nrf52833dk_nrf52833.overlay`. +You can customize this overlay when building for the same board, or create your +own board-specific overlay in the same directory for a different board. See +:dtcompatible:`nordic,nrf-radio` for documentation on the properties used in +this overlay. See :ref:`set-devicetree-overlays` for information on setting up +and using overlays. + +Note that antenna matrix configuration for the nRF5340 SoC is part of the +network core application. When :ref:`bluetooth-hci-rpmsg-sample` is used as the +network core application, the antenna matrix configuration should be stored in +the file +:file:`samples/bluetooth/hci_rpmsg/boards/nrf5340dk_nrf5340_cpunet.overlay` +instead. diff --git a/samples/bluetooth/direction_finding_central/boards/nrf52833dk_nrf52820.conf b/samples/bluetooth/direction_finding_central/boards/nrf52833dk_nrf52820.conf new file mode 100644 index 00000000000..93bd2a71c6d --- /dev/null +++ b/samples/bluetooth/direction_finding_central/boards/nrf52833dk_nrf52820.conf @@ -0,0 +1,23 @@ +# +# Copyright (c) 2022 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: Apache-2.0 +# + +CONFIG_BT_CTLR=y +CONFIG_BT_LL_SW_SPLIT=y + +# Enable new implementation of LLCPs +CONFIG_BT_LL_SW_LLCP=y + +# Enable Direction Finding Feature including AoA and AoD +CONFIG_BT_CTLR_DF=y + +CONFIG_BT_CTLR_DF_CTE_RX=y +CONFIG_BT_CTLR_DF_CONN_CTE_RX=y +CONFIG_BT_CTLR_DF_ANT_SWITCH_RX=y +CONFIG_BT_CTLR_DF_CONN_CTE_REQ=y + +# Ensure that there is enough control prcedure contexts to queue and execute all procedures +CONFIG_BT_CTLR_LLCP_PROC_CTX_BUF_NUM=6 +CONFIG_BT_CTLR_ADVANCED_FEATURES=y diff --git a/samples/bluetooth/direction_finding_central/boards/nrf52833dk_nrf52820.overlay b/samples/bluetooth/direction_finding_central/boards/nrf52833dk_nrf52820.overlay new file mode 100644 index 00000000000..918803762e9 --- /dev/null +++ b/samples/bluetooth/direction_finding_central/boards/nrf52833dk_nrf52820.overlay @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2022 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&radio { + status = "okay"; + /* This is an example number of antennas that may be available + * on antenna matrix board. + */ + dfe-antenna-num = <10>; + /* This is an example switch pattern that will be used to set an + * antenna for Tx PDU (period before start of Tx CTE). + */ + dfe-pdu-antenna = <0x1>; + + /* These are example GPIO pin numbers that are provided to + * Radio peripheral. The pins will be acquired by Radio to + * drive antenna switching when AoD is enabled. + */ + dfegpio0-gpios = <&gpio0 1 0>; + dfegpio1-gpios = <&gpio0 2 0>; + dfegpio2-gpios = <&gpio0 3 0>; + dfegpio3-gpios = <&gpio0 4 0>; +}; diff --git a/samples/bluetooth/direction_finding_central/boards/nrf52833dk_nrf52833.conf b/samples/bluetooth/direction_finding_central/boards/nrf52833dk_nrf52833.conf new file mode 100644 index 00000000000..93bd2a71c6d --- /dev/null +++ b/samples/bluetooth/direction_finding_central/boards/nrf52833dk_nrf52833.conf @@ -0,0 +1,23 @@ +# +# Copyright (c) 2022 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: Apache-2.0 +# + +CONFIG_BT_CTLR=y +CONFIG_BT_LL_SW_SPLIT=y + +# Enable new implementation of LLCPs +CONFIG_BT_LL_SW_LLCP=y + +# Enable Direction Finding Feature including AoA and AoD +CONFIG_BT_CTLR_DF=y + +CONFIG_BT_CTLR_DF_CTE_RX=y +CONFIG_BT_CTLR_DF_CONN_CTE_RX=y +CONFIG_BT_CTLR_DF_ANT_SWITCH_RX=y +CONFIG_BT_CTLR_DF_CONN_CTE_REQ=y + +# Ensure that there is enough control prcedure contexts to queue and execute all procedures +CONFIG_BT_CTLR_LLCP_PROC_CTX_BUF_NUM=6 +CONFIG_BT_CTLR_ADVANCED_FEATURES=y diff --git a/samples/bluetooth/direction_finding_central/boards/nrf52833dk_nrf52833.overlay b/samples/bluetooth/direction_finding_central/boards/nrf52833dk_nrf52833.overlay new file mode 100644 index 00000000000..8df796c6bbc --- /dev/null +++ b/samples/bluetooth/direction_finding_central/boards/nrf52833dk_nrf52833.overlay @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2022 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&radio { + status = "okay"; + /* This is a number of antennas that are available on antenna matrix + * designed by Nordic. For more information see README.rst. + */ + dfe-antenna-num = <12>; + /* This is a setting that enables antenna 12 (in antenna matrix designed + * by Nordic) for Rx PDU. For more information see README.rst. + */ + dfe-pdu-antenna = <0x0>; + + /* These are GPIO pin numbers that are provided to + * Radio peripheral. The pins will be acquired by Radio to + * drive antenna switching when AoA is enabled. + * Pin numbers are selected to drive switches on antenna matrix + * desinged by Nordic. For more information see README.rst. + */ + dfegpio0-gpios = <&gpio0 3 0>; + dfegpio1-gpios = <&gpio0 4 0>; + dfegpio2-gpios = <&gpio0 28 0>; + dfegpio3-gpios = <&gpio0 29 0>; +}; diff --git a/samples/bluetooth/direction_finding_central/overlay-aod.conf b/samples/bluetooth/direction_finding_central/overlay-aod.conf new file mode 100644 index 00000000000..7a78fdf6828 --- /dev/null +++ b/samples/bluetooth/direction_finding_central/overlay-aod.conf @@ -0,0 +1,8 @@ +# +# Copyright (c) 2022 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: Apache-2.0 +# + +# Disable AoA Feature (antenna switching) in Rx mode +CONFIG_BT_CTLR_DF_ANT_SWITCH_RX=n diff --git a/samples/bluetooth/direction_finding_central/prj.conf b/samples/bluetooth/direction_finding_central/prj.conf new file mode 100644 index 00000000000..03ef424c1b8 --- /dev/null +++ b/samples/bluetooth/direction_finding_central/prj.conf @@ -0,0 +1,18 @@ +# +# Copyright (c) 2022 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: Apache-2.0 +# + +CONFIG_BT=y +CONFIG_BT_DEBUG_LOG=y +CONFIG_BT_DEVICE_NAME="Direction Finding Central" + +CONFIG_BT_CENTRAL=y +CONFIG_BT_SMP=y +CONFIG_BT_GATT_CLIENT=y + +# Enable Direction Finding Feature RX in connected mode +CONFIG_BT_DF=y +CONFIG_BT_DF_CONNECTION_CTE_RX=y +CONFIG_BT_DF_CONNECTION_CTE_REQ=y diff --git a/samples/bluetooth/direction_finding_central/sample.yaml b/samples/bluetooth/direction_finding_central/sample.yaml new file mode 100644 index 00000000000..dcedc108958 --- /dev/null +++ b/samples/bluetooth/direction_finding_central/sample.yaml @@ -0,0 +1,17 @@ +sample: + name: Direction Finding Central + description: Sample application showing central role of Direction Finding in connected mode +tests: + sample.bluetooth.direction_finding_connectionless_rx: + harness: bluetooth + platform_allow: nrf52833dk_nrf52833 + tags: bluetooth + integration_platforms: + - nrf52833dk_nrf52833 + sample.bluetooth.direction_finding_connectionless_rx.aod: + extra_args: OVERLAY_CONFIG="overlay-aod.conf" + harness: bluetooth + platform_allow: nrf52833dk_nrf52833 + tags: bluetooth + integration_platforms: + - nrf52833dk_nrf52833 diff --git a/samples/bluetooth/direction_finding_central/src/main.c b/samples/bluetooth/direction_finding_central/src/main.c new file mode 100644 index 00000000000..060b336ae7f --- /dev/null +++ b/samples/bluetooth/direction_finding_central/src/main.c @@ -0,0 +1,269 @@ +/* + * Copyright (c) 2022 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +/* Latency set to zero, to enforce PDU exchange every connection event */ +#define CONN_LATENCY 0U +/* Arbitrary selected timeout value */ +#define CONN_TIMEOUT 400U +/* Inteval used to run CTE request procedure periodically. + * Value is a number of connection events. + */ +#define CTE_REQ_INTERVAL (CONN_LATENCY + 10U) +/* Length of CTE in unit of 8 us */ +#define CTE_LEN (0x14U) + +#define DF_FEAT_ENABLED BIT64(BT_LE_FEAT_BIT_CONN_CTE_RESP) + +static struct bt_conn *default_conn; +static const struct bt_le_conn_param conn_params = BT_LE_CONN_PARAM_INIT( + BT_GAP_INIT_CONN_INT_MIN, BT_GAP_INIT_CONN_INT_MAX, CONN_LATENCY, CONN_TIMEOUT); + +#if defined(CONFIG_BT_CTLR_DF_ANT_SWITCH_RX) +static const uint8_t ant_patterns[] = { 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA }; +#endif /* CONFIG_BT_CTLR_DF_ANT_SWITCH_RX */ + +static void start_scan(void); + +static const char *cte_type2str(uint8_t type) +{ + switch (type) { + case BT_DF_CTE_TYPE_AOA: + return "AOA"; + case BT_DF_CTE_TYPE_AOD_1US: + return "AOD 1 [us]"; + case BT_DF_CTE_TYPE_AOD_2US: + return "AOD 2 [us]"; + default: + return "Unknown"; + } +} + +static const char *packet_status2str(uint8_t status) +{ + switch (status) { + case BT_DF_CTE_CRC_OK: + return "CRC OK"; + case BT_DF_CTE_CRC_ERR_CTE_BASED_TIME: + return "CRC not OK, CTE Info OK"; + case BT_DF_CTE_CRC_ERR_CTE_BASED_OTHER: + return "CRC not OK, Sampled other way"; + case BT_DF_CTE_INSUFFICIENT_RESOURCES: + return "No resources"; + default: + return "Unknown"; + } +} + +static bool eir_found(struct bt_data *data, void *user_data) +{ + bt_addr_le_t *addr = user_data; + uint64_t u64 = 0U; + int err; + + printk("[AD]: %u data_len %u\n", data->type, data->data_len); + + switch (data->type) { + case BT_DATA_LE_SUPPORTED_FEATURES: + if (data->data_len > sizeof(u64)) { + return true; + } + + (void)memcpy(&u64, data->data, data->data_len); + + u64 = sys_le64_to_cpu(u64); + + if (!(u64 & DF_FEAT_ENABLED)) { + return true; + } + + err = bt_le_scan_stop(); + if (err) { + printk("Stop LE scan failed (err %d)\n", err); + return true; + } + + err = bt_conn_le_create(addr, BT_CONN_LE_CREATE_CONN, &conn_params, &default_conn); + if (err) { + printk("Create conn failed (err %d)\n", err); + start_scan(); + } + return false; + } + + return true; +} + +static void device_found(const bt_addr_le_t *addr, int8_t rssi, uint8_t type, + struct net_buf_simple *ad) +{ + char dev[BT_ADDR_LE_STR_LEN]; + + bt_addr_le_to_str(addr, dev, sizeof(dev)); + printk("[DEVICE]: %s, AD evt type %u, AD data len %u, RSSI %i\n", dev, type, ad->len, rssi); + + /* We're only interested in connectable events */ + if (type == BT_GAP_ADV_TYPE_ADV_IND || type == BT_GAP_ADV_TYPE_ADV_DIRECT_IND) { + bt_data_parse(ad, eir_found, (void *)addr); + } +} + +static void enable_cte_reqest(void) +{ + int err; + + const struct bt_df_conn_cte_rx_param cte_rx_params = { +#if defined(CONFIG_BT_CTLR_DF_ANT_SWITCH_RX) + .cte_types = BT_DF_CTE_TYPE_ALL, + .slot_durations = 0x2, + .num_ant_ids = ARRAY_SIZE(ant_patterns), + .ant_ids = ant_patterns, +#else + .cte_types = BT_DF_CTE_TYPE_AOD_1US | BT_DF_CTE_TYPE_AOD_2US, +#endif /* CONFIG_BT_CTLR_DF_ANT_SWITCH_RX */ + }; + + const struct bt_df_conn_cte_req_params cte_req_params = { + .interval = CTE_REQ_INTERVAL, + .cte_length = CTE_LEN, +#if defined(CONFIG_BT_CTLR_DF_ANT_SWITCH_RX) + .cte_type = BT_DF_CTE_TYPE_AOA, +#else + .cte_type = BT_DF_CTE_TYPE_AOD_2US, +#endif /* CONFIG_BT_CTLR_DF_ANT_SWITCH_TX */ + }; + + printk("Enable receiving of CTE...\n"); + err = bt_df_conn_cte_rx_enable(default_conn, &cte_rx_params); + if (err) { + printk("failed (err %d)\n", err); + return; + } + printk("success. CTE receive enabled.\n"); + + printk("Request CTE from peer device...\n"); + err = bt_df_conn_cte_req_enable(default_conn, &cte_req_params); + if (err) { + printk("failed (err %d)\n", err); + return; + } + printk("success. CTE request enabled.\n"); +} + +static void start_scan(void) +{ + int err; + + /* Use active scanning and disable duplicate filtering to handle any + * devices that might update their advertising data at runtime. + */ + struct bt_le_scan_param scan_param = { + .type = BT_LE_SCAN_TYPE_ACTIVE, + .options = BT_LE_SCAN_OPT_NONE, + .interval = BT_GAP_SCAN_FAST_INTERVAL, + .window = BT_GAP_SCAN_FAST_WINDOW, + }; + + err = bt_le_scan_start(&scan_param, device_found); + if (err) { + printk("Scanning failed to start (err %d)\n", err); + return; + } + + printk("Scanning successfully started\n"); +} + +static void connected(struct bt_conn *conn, uint8_t conn_err) +{ + char addr[BT_ADDR_LE_STR_LEN]; + + bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr)); + + if (conn_err) { + printk("Failed to connect to %s (%u)\n", addr, conn_err); + + bt_conn_unref(default_conn); + default_conn = NULL; + + start_scan(); + return; + } + + printk("Connected: %s\n", addr); + + if (conn == default_conn) { + enable_cte_reqest(); + } +} + +static void disconnected(struct bt_conn *conn, uint8_t reason) +{ + char addr[BT_ADDR_LE_STR_LEN]; + + bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr)); + + printk("Disconnected: %s (reason 0x%02x)\n", addr, reason); + + if (default_conn != conn) { + return; + } + + bt_conn_unref(default_conn); + default_conn = NULL; + + start_scan(); +} + +static void cte_recv_cb(struct bt_conn *conn, struct bt_df_conn_iq_samples_report const *report) +{ + char addr[BT_ADDR_LE_STR_LEN]; + + bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr)); + + if (report->err == BT_DF_IQ_REPORT_ERR_SUCCESS) { + printk("CTE[%s]: samples count %d, cte type %s, slot durations: %u [us], " + "packet status %s, RSSI %i\n", + addr, report->sample_count, cte_type2str(report->cte_type), + report->slot_durations, packet_status2str(report->packet_status), + report->rssi); + } else { + printk("CTE[%s]: request failed, err %u\n", addr, report->err); + } +} + +BT_CONN_CB_DEFINE(conn_callbacks) = { + .connected = connected, + .disconnected = disconnected, + .cte_report_cb = cte_recv_cb, +}; + +void main(void) +{ + int err; + + err = bt_enable(NULL); + if (err) { + printk("Bluetooth init failed (err %d)\n", err); + return; + } + + printk("Bluetooth initialized\n"); + + start_scan(); +} From b9063834d84948837fdb4a12f3dcc13391e8b57e Mon Sep 17 00:00:00 2001 From: Piotr Pryga Date: Thu, 20 Jan 2022 21:50:09 +0100 Subject: [PATCH 105/207] [nrf fromtree] samples: Bluetooth: df: Add DF peripheral sample Add new sample application for direction finding to show how the functionality works in connected mode for peripheral role. Signed-off-by: Piotr Pryga (cherry picked from commit 56b33c378c60e29f36cbc1d7f59ccd30848a5109) --- .../CMakeLists.txt | 14 ++ .../direction_finding_peripheral/README.rst | 72 +++++++++++ .../boards/nrf52833dk_nrf52820.conf | 23 ++++ .../boards/nrf52833dk_nrf52820.overlay | 26 ++++ .../boards/nrf52833dk_nrf52833.conf | 23 ++++ .../boards/nrf52833dk_nrf52833.overlay | 28 ++++ .../overlay-aoa.conf | 8 ++ .../direction_finding_peripheral/prj.conf | 18 +++ .../direction_finding_peripheral/sample.yaml | 17 +++ .../direction_finding_peripheral/src/main.c | 122 ++++++++++++++++++ 10 files changed, 351 insertions(+) create mode 100644 samples/bluetooth/direction_finding_peripheral/CMakeLists.txt create mode 100644 samples/bluetooth/direction_finding_peripheral/README.rst create mode 100644 samples/bluetooth/direction_finding_peripheral/boards/nrf52833dk_nrf52820.conf create mode 100644 samples/bluetooth/direction_finding_peripheral/boards/nrf52833dk_nrf52820.overlay create mode 100644 samples/bluetooth/direction_finding_peripheral/boards/nrf52833dk_nrf52833.conf create mode 100644 samples/bluetooth/direction_finding_peripheral/boards/nrf52833dk_nrf52833.overlay create mode 100644 samples/bluetooth/direction_finding_peripheral/overlay-aoa.conf create mode 100644 samples/bluetooth/direction_finding_peripheral/prj.conf create mode 100644 samples/bluetooth/direction_finding_peripheral/sample.yaml create mode 100644 samples/bluetooth/direction_finding_peripheral/src/main.c diff --git a/samples/bluetooth/direction_finding_peripheral/CMakeLists.txt b/samples/bluetooth/direction_finding_peripheral/CMakeLists.txt new file mode 100644 index 00000000000..57c340187f9 --- /dev/null +++ b/samples/bluetooth/direction_finding_peripheral/CMakeLists.txt @@ -0,0 +1,14 @@ +# +# Copyright (c) 2022 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) + +project(direction_finding_peripheral) + +target_sources(app PRIVATE + src/main.c +) diff --git a/samples/bluetooth/direction_finding_peripheral/README.rst b/samples/bluetooth/direction_finding_peripheral/README.rst new file mode 100644 index 00000000000..1a6c58fb258 --- /dev/null +++ b/samples/bluetooth/direction_finding_peripheral/README.rst @@ -0,0 +1,72 @@ +.. _bluetooth_direction_finding_peripheral: + +Bluetooth: Direction Finding Peripheral +####################################### + +Overview +******** + +A simple application demonstrating the BLE Direction Finding CTE transmission in +connected mode by response to a request received from connected peer device. + +Requirements +************ + +* Nordic nRF SoC based board with Direction Finding support (example boards: + :ref:`nrf52833dk_nrf52833`, :ref:`nrf52833dk_nrf52820`, :ref:`nrf5340dk_nrf5340`) +* Antenna matrix for AoA (optional) + +Check your SoC's product specification for Direction Finding support if you are +unsure. + +Building and Running +******************** + +By default the application supports Angle of Arrival and Angle of Departure mode. + +To use Angle of Arrival mode only, build this application as follows, +changing ``nrf52833dk_nrf52833`` as needed for your board: + +.. zephyr-app-commands:: + :zephyr-app: samples/bluetooth/direction_finding_peripheral + :host-os: unix + :board: nrf52833dk_nrf52833 + :gen-args: -DOVERLAY_CONFIG=overlay-aoa.conf + :goals: build flash + :compact: + +To run the application on nRF5340DK, a Bluetooth controller application must +also run on the network core. The :ref:`bluetooth-hci-rpmsg-sample` sample +application may be used. To build this sample with direction finding support +enabled: + +* Copy + :zephyr_file:`samples/bluetooth/direction_finding_peripheral/boards/nrf52833dk_nrf52833.overlay` + to a new file, + :file:`samples/bluetooth/hci_rpmsg/boards/nrf5340dk_nrf5340_cpunet.overlay`. +* Copy + :zephyr_file:`samples/bluetooth/direction_finding_peripheral/boards/nrf52833dk_nrf52833.conf` + to a new file, + :file:`samples/bluetooth/hci_rpmsg/boards/nrf5340dk_nrf5340_cpunet.conf`. + +Antenna matrix configuration +**************************** + +To use this sample with Angle of Departure enabled on Nordic SoCs, additional +configuration must be provided via :ref:`devicetree ` to enable +control of the antenna array. + +An example devicetree overlay is in +:zephyr_file:`samples/bluetooth/direction_finding_peripheral/boards/nrf52833dk_nrf52833.overlay`. +You can customize this overlay when building for the same board, or create your +own board-specific overlay in the same directory for a different board. See +:dtcompatible:`nordic,nrf-radio` for documentation on the properties used in +this overlay. See :ref:`set-devicetree-overlays` for information on setting up +and using overlays. + +Note that antenna matrix configuration for the nRF5340 SoC is part of the +network core application. When :ref:`bluetooth-hci-rpmsg-sample` is used as the +network core application, the antenna matrix configuration should be stored in +the file +:file:`samples/bluetooth/hci_rpmsg/boards/nrf5340dk_nrf5340_cpunet.overlay` +instead. diff --git a/samples/bluetooth/direction_finding_peripheral/boards/nrf52833dk_nrf52820.conf b/samples/bluetooth/direction_finding_peripheral/boards/nrf52833dk_nrf52820.conf new file mode 100644 index 00000000000..bb4952ac87f --- /dev/null +++ b/samples/bluetooth/direction_finding_peripheral/boards/nrf52833dk_nrf52820.conf @@ -0,0 +1,23 @@ +# +# Copyright (c) 2022 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: Apache-2.0 +# + +CONFIG_BT_CTLR=y +CONFIG_BT_LL_SW_SPLIT=y + +# Enable new implementation of LLCPs +CONFIG_BT_LL_SW_LLCP=y + +# Enable Direction Finding Feature including AoA and AoD +CONFIG_BT_CTLR_DF=y + +CONFIG_BT_CTLR_DF_CTE_TX=y +CONFIG_BT_CTLR_DF_CONN_CTE_TX=y +CONFIG_BT_CTLR_DF_ANT_SWITCH_TX=y +CONFIG_BT_CTLR_DF_CONN_CTE_RSP=y + +# Ensure that there is enough control prcedure contexts to queue and execute all procedures +CONFIG_BT_CTLR_ADVANCED_FEATURES=y +CONFIG_BT_CTLR_LLCP_PROC_CTX_BUF_NUM=6 diff --git a/samples/bluetooth/direction_finding_peripheral/boards/nrf52833dk_nrf52820.overlay b/samples/bluetooth/direction_finding_peripheral/boards/nrf52833dk_nrf52820.overlay new file mode 100644 index 00000000000..918803762e9 --- /dev/null +++ b/samples/bluetooth/direction_finding_peripheral/boards/nrf52833dk_nrf52820.overlay @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2022 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&radio { + status = "okay"; + /* This is an example number of antennas that may be available + * on antenna matrix board. + */ + dfe-antenna-num = <10>; + /* This is an example switch pattern that will be used to set an + * antenna for Tx PDU (period before start of Tx CTE). + */ + dfe-pdu-antenna = <0x1>; + + /* These are example GPIO pin numbers that are provided to + * Radio peripheral. The pins will be acquired by Radio to + * drive antenna switching when AoD is enabled. + */ + dfegpio0-gpios = <&gpio0 1 0>; + dfegpio1-gpios = <&gpio0 2 0>; + dfegpio2-gpios = <&gpio0 3 0>; + dfegpio3-gpios = <&gpio0 4 0>; +}; diff --git a/samples/bluetooth/direction_finding_peripheral/boards/nrf52833dk_nrf52833.conf b/samples/bluetooth/direction_finding_peripheral/boards/nrf52833dk_nrf52833.conf new file mode 100644 index 00000000000..bb4952ac87f --- /dev/null +++ b/samples/bluetooth/direction_finding_peripheral/boards/nrf52833dk_nrf52833.conf @@ -0,0 +1,23 @@ +# +# Copyright (c) 2022 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: Apache-2.0 +# + +CONFIG_BT_CTLR=y +CONFIG_BT_LL_SW_SPLIT=y + +# Enable new implementation of LLCPs +CONFIG_BT_LL_SW_LLCP=y + +# Enable Direction Finding Feature including AoA and AoD +CONFIG_BT_CTLR_DF=y + +CONFIG_BT_CTLR_DF_CTE_TX=y +CONFIG_BT_CTLR_DF_CONN_CTE_TX=y +CONFIG_BT_CTLR_DF_ANT_SWITCH_TX=y +CONFIG_BT_CTLR_DF_CONN_CTE_RSP=y + +# Ensure that there is enough control prcedure contexts to queue and execute all procedures +CONFIG_BT_CTLR_ADVANCED_FEATURES=y +CONFIG_BT_CTLR_LLCP_PROC_CTX_BUF_NUM=6 diff --git a/samples/bluetooth/direction_finding_peripheral/boards/nrf52833dk_nrf52833.overlay b/samples/bluetooth/direction_finding_peripheral/boards/nrf52833dk_nrf52833.overlay new file mode 100644 index 00000000000..8df796c6bbc --- /dev/null +++ b/samples/bluetooth/direction_finding_peripheral/boards/nrf52833dk_nrf52833.overlay @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2022 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&radio { + status = "okay"; + /* This is a number of antennas that are available on antenna matrix + * designed by Nordic. For more information see README.rst. + */ + dfe-antenna-num = <12>; + /* This is a setting that enables antenna 12 (in antenna matrix designed + * by Nordic) for Rx PDU. For more information see README.rst. + */ + dfe-pdu-antenna = <0x0>; + + /* These are GPIO pin numbers that are provided to + * Radio peripheral. The pins will be acquired by Radio to + * drive antenna switching when AoA is enabled. + * Pin numbers are selected to drive switches on antenna matrix + * desinged by Nordic. For more information see README.rst. + */ + dfegpio0-gpios = <&gpio0 3 0>; + dfegpio1-gpios = <&gpio0 4 0>; + dfegpio2-gpios = <&gpio0 28 0>; + dfegpio3-gpios = <&gpio0 29 0>; +}; diff --git a/samples/bluetooth/direction_finding_peripheral/overlay-aoa.conf b/samples/bluetooth/direction_finding_peripheral/overlay-aoa.conf new file mode 100644 index 00000000000..d13e82d3581 --- /dev/null +++ b/samples/bluetooth/direction_finding_peripheral/overlay-aoa.conf @@ -0,0 +1,8 @@ +# +# Copyright (c) 2022 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: Apache-2.0 +# + +# Disable AoD Feature (antenna switching) in Tx mode +CONFIG_BT_CTLR_DF_ANT_SWITCH_TX=n diff --git a/samples/bluetooth/direction_finding_peripheral/prj.conf b/samples/bluetooth/direction_finding_peripheral/prj.conf new file mode 100644 index 00000000000..b94ff0a4732 --- /dev/null +++ b/samples/bluetooth/direction_finding_peripheral/prj.conf @@ -0,0 +1,18 @@ +# +# Copyright (c) 2022 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: Apache-2.0 +# + +CONFIG_BT=y +CONFIG_BT_DEBUG_LOG=y +CONFIG_BT_DEVICE_NAME="DF Conn App" +CONFIG_BT_SMP=y + +CONFIG_BT_PERIPHERAL=y +CONFIG_BT_DEVICE_APPEARANCE=833 + +# Enable Direction Finding Feature RX in connected mode +CONFIG_BT_DF=y +CONFIG_BT_DF_CONNECTION_CTE_TX=y +CONFIG_BT_DF_CONNECTION_CTE_RSP=y diff --git a/samples/bluetooth/direction_finding_peripheral/sample.yaml b/samples/bluetooth/direction_finding_peripheral/sample.yaml new file mode 100644 index 00000000000..208036b8964 --- /dev/null +++ b/samples/bluetooth/direction_finding_peripheral/sample.yaml @@ -0,0 +1,17 @@ +sample: + name: Direction Finding Peripheral + description: Sample application showing peripheral role of Direction Finding in connected mode +tests: + sample.bluetooth.direction_finding_connectionless_rx: + harness: bluetooth + platform_allow: nrf52833dk_nrf52833 + tags: bluetooth + integration_platforms: + - nrf52833dk_nrf52833 + sample.bluetooth.direction_finding_connectionless_rx.aod: + extra_args: OVERLAY_CONFIG="overlay-aoa.conf" + harness: bluetooth + platform_allow: nrf52833dk_nrf52833 + tags: bluetooth + integration_platforms: + - nrf52833dk_nrf52833 diff --git a/samples/bluetooth/direction_finding_peripheral/src/main.c b/samples/bluetooth/direction_finding_peripheral/src/main.c new file mode 100644 index 00000000000..8de8aa117d2 --- /dev/null +++ b/samples/bluetooth/direction_finding_peripheral/src/main.c @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2022 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#define DF_FEAT_ENABLED BIT64(BT_LE_FEAT_BIT_CONN_CTE_RESP) + +static const struct bt_data ad[] = { + BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)), + BT_DATA_BYTES(BT_DATA_LE_SUPPORTED_FEATURES, BT_LE_SUPP_FEAT_24_ENCODE(DF_FEAT_ENABLED)), +}; + +/* Latency set to zero, to enforce PDU exchange every connection event */ +#define CONN_LATENCY 0U +/* Inteval used to run CTE request procedure periodically. + * Value is a number of connection events. + */ +#define CTE_REQ_INTERVAL (CONN_LATENCY + 10U) +/* Length of CTE in unit of 8 us */ +#define CTE_LEN (0x14U) + +#if defined(CONFIG_BT_CTLR_DF_ANT_SWITCH_TX) +static const uint8_t ant_patterns[] = { 0x2, 0x0, 0x5, 0x6, 0x1, 0x4, 0xC, 0x9, 0xE, 0xD, 0x8 }; +#endif /* CONFIG_BT_CTLR_DF_ANT_SWITCH_TX */ + +static void enable_cte_response(struct bt_conn *conn) +{ + int err; + + const struct bt_df_conn_cte_tx_param cte_tx_params = { +#if defined(CONFIG_BT_CTLR_DF_ANT_SWITCH_TX) + .cte_types = BT_DF_CTE_TYPE_ALL, + .num_ant_ids = ARRAY_SIZE(ant_patterns), + .ant_ids = ant_patterns, +#else + .cte_types = BT_DF_CTE_TYPE_AOA, +#endif /* CONFIG_BT_CTLR_DF_ANT_SWITCH_TX */ + }; + + printk("Set CTE transmission params..."); + err = bt_df_set_conn_cte_tx_param(conn, &cte_tx_params); + if (err) { + printk("failed (err %d)\n", err); + return; + } + printk("success.\n"); + + printk("Set CTE response enable..."); + err = bt_df_conn_cte_rsp_enable(conn); + if (err) { + printk("failed (err %d).\n", err); + return; + } + printk("success.\n"); +} + +static void connected(struct bt_conn *conn, uint8_t err) +{ + if (err) { + printk("Connection failed (err 0x%02x)\n", err); + } else { + printk("Connected\n"); + } + + enable_cte_response(conn); +} + +static void disconnected(struct bt_conn *conn, uint8_t reason) +{ + printk("Disconnected (reason 0x%02x)\n", reason); +} + +BT_CONN_CB_DEFINE(conn_callbacks) = { + .connected = connected, + .disconnected = disconnected, +}; + +static void bt_ready(void) +{ + int err; + + printk("Bluetooth initialized\n"); + + err = bt_le_adv_start(BT_LE_ADV_CONN_NAME, ad, ARRAY_SIZE(ad), NULL, 0); + if (err) { + printk("Advertising failed to start (err %d)\n", err); + return; + } + + printk("Advertising successfully started\n"); +} + +void main(void) +{ + int err; + + err = bt_enable(NULL); + if (err) { + printk("Bluetooth init failed (err %d)\n", err); + return; + } + + bt_ready(); +} From 7065446f75a3c4852dc7d39f1c1c26184cff6fa0 Mon Sep 17 00:00:00 2001 From: Piotr Pryga Date: Fri, 28 Jan 2022 21:38:41 +0100 Subject: [PATCH 106/207] [nrf fromtree] Bluetooth: Controller: df: refactor CTE REQ set disable Add a function that is responsible for set CTE request disabled. It is a refactoring, to have a single place where CTE request is_enabled and req_interval are zeroed. Signed-off-by: Piotr Pryga (cherry picked from commit d2e9bc352ca8d67d8ae4188a8e86530304bd82b4) --- subsys/bluetooth/controller/ll_sw/ull_df.c | 3 +-- subsys/bluetooth/controller/ll_sw/ull_llcp.c | 6 ++++++ subsys/bluetooth/controller/ll_sw/ull_llcp.h | 5 +++++ subsys/bluetooth/controller/ll_sw/ull_llcp_common.c | 1 + 4 files changed, 13 insertions(+), 2 deletions(-) diff --git a/subsys/bluetooth/controller/ll_sw/ull_df.c b/subsys/bluetooth/controller/ll_sw/ull_df.c index 4fcb6e17aa4..5aee08b1dd0 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_df.c +++ b/subsys/bluetooth/controller/ll_sw/ull_df.c @@ -1160,8 +1160,7 @@ uint8_t ll_df_set_conn_cte_req_enable(uint16_t handle, uint8_t enable, } if (!enable) { - conn->llcp.cte_req.is_enabled = false; - conn->llcp.cte_req.req_interval = 0U; + ull_cp_cte_req_set_disable(conn); if (conn->llcp.cte_req.is_active) { struct k_sem sem; diff --git a/subsys/bluetooth/controller/ll_sw/ull_llcp.c b/subsys/bluetooth/controller/ll_sw/ull_llcp.c index 2a5810a5711..923e70fd2cf 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_llcp.c +++ b/subsys/bluetooth/controller/ll_sw/ull_llcp.c @@ -917,6 +917,12 @@ uint8_t ull_cp_cte_req(struct ll_conn *conn, uint8_t min_cte_len, uint8_t cte_ty return BT_HCI_ERR_SUCCESS; } + +void ull_cp_cte_req_set_disable(struct ll_conn *conn) +{ + conn->llcp.cte_req.is_enabled = 0U; + conn->llcp.cte_req.req_interval = 0U; +} #endif /* CONFIG_BT_CTLR_DF_CONN_CTE_REQ */ static bool pdu_is_expected(struct pdu_data *pdu, struct proc_ctx *ctx) diff --git a/subsys/bluetooth/controller/ll_sw/ull_llcp.h b/subsys/bluetooth/controller/ll_sw/ull_llcp.h index c7cf75ee514..2842d1b1fe4 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_llcp.h +++ b/subsys/bluetooth/controller/ll_sw/ull_llcp.h @@ -153,6 +153,11 @@ uint8_t ull_cp_data_length_update(struct ll_conn *conn, uint16_t max_tx_octets, */ uint8_t ull_cp_cte_req(struct ll_conn *conn, uint8_t min_cte_len, uint8_t cte_type); +/** + * @brief Set a CTE Request Procedure disabled. + */ +void ull_cp_cte_req_set_disable(struct ll_conn *conn); + /** * @brief Enable or disable response to CTE Request Procedure. */ diff --git a/subsys/bluetooth/controller/ll_sw/ull_llcp_common.c b/subsys/bluetooth/controller/ll_sw/ull_llcp_common.c index a38423b3822..5aaf395b76b 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_llcp_common.c +++ b/subsys/bluetooth/controller/ll_sw/ull_llcp_common.c @@ -355,6 +355,7 @@ static void lp_comm_complete(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t } else { conn->llcp.cte_req.is_enabled = 0U; lp_comm_ntf(conn, ctx); + ull_cp_cte_req_set_disable(conn); } } else if (ctx->response_opcode == PDU_DATA_LLCTRL_TYPE_REJECT_EXT_IND && ctx->reject_ext_ind.reject_opcode == PDU_DATA_LLCTRL_TYPE_CTE_REQ) { From aca8c2d21430d871d81c0e2c8a990cacb841c0c5 Mon Sep 17 00:00:00 2001 From: Piotr Pryga Date: Fri, 28 Jan 2022 21:45:48 +0100 Subject: [PATCH 107/207] [nrf fromtree] Bluetooth: Controller: df: Fix wrong PHY type check in CTE req enable CTE request may not be enabled when actual PHY does not support transmission of constant tone extension. In case a connection is asymetric, receive PHY is required to support transmission of CTE. Receive PHY will be used by a device to get PDU with CTE. In ll_df_set_conn_cte_req_enable was checking TX PHY type. It should check RX PHY type. Signed-off-by: Piotr Pryga (cherry picked from commit fa78cfa19bb6c667c1d4e9fc628033fd94d151ee) --- subsys/bluetooth/controller/ll_sw/ull_df.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/subsys/bluetooth/controller/ll_sw/ull_df.c b/subsys/bluetooth/controller/ll_sw/ull_df.c index 5aee08b1dd0..21b3a2f7f79 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_df.c +++ b/subsys/bluetooth/controller/ll_sw/ull_df.c @@ -1185,10 +1185,8 @@ uint8_t ll_df_set_conn_cte_req_enable(uint16_t handle, uint8_t enable, } #if defined(CONFIG_BT_CTLR_PHY) - /* Phy may be changed to CODED only if PHY update procedure is supproted. In other - * case the mandatory PHY1M is used (that supports CTE). - */ - if (conn->lll.phy_tx == PHY_CODED) { + /* CTE request may be enabled only in case the receiver PHY is not CODED */ + if (conn->lll.phy_rx == PHY_CODED) { return BT_HCI_ERR_CMD_DISALLOWED; } #endif /* CONFIG_BT_CTLR_PHY */ From 5db8c91f6188730d84762aed4a0e8a2d7684728f Mon Sep 17 00:00:00 2001 From: Piotr Pryga Date: Fri, 28 Jan 2022 22:01:12 +0100 Subject: [PATCH 108/207] [nrf fromtree] Bluetooth: Controller: llcp: add complete evt handling in idle state Add handling of complete event in idle state of localy innitiated control procedures. The transition will be used by CTE request disable if PHY changes to CODED while the procedure is waiting in the waiting queue. Signed-off-by: Piotr Pryga (cherry picked from commit 45057fdb2e5aa3ce6fe4a63abf3ea212436977fc) --- subsys/bluetooth/controller/ll_sw/ull_llcp_local.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/subsys/bluetooth/controller/ll_sw/ull_llcp_local.c b/subsys/bluetooth/controller/ll_sw/ull_llcp_local.c index e142dd192e6..b9323e9ef69 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_llcp_local.c +++ b/subsys/bluetooth/controller/ll_sw/ull_llcp_local.c @@ -326,6 +326,12 @@ static void lr_st_idle(struct ll_conn *conn, uint8_t evt, void *param) lr_act_disconnect(conn); lr_set_state(conn, LR_STATE_DISCONNECT); break; + case LR_EVT_COMPLETE: + /* Some procedures like CTE request may be completed without actual run due to + * change in conditions while the procedure was waiting in a queue. + */ + lr_act_complete(conn); + break; default: /* Ignore other evts */ break; From de71e6c4043081e2a5f60dd04dfd039bc3e46715 Mon Sep 17 00:00:00 2001 From: Piotr Pryga Date: Fri, 28 Jan 2022 22:36:56 +0100 Subject: [PATCH 109/207] [nrf fromtree] Bluetooth: Controller: df: Remove not needed if statement Removes a if statement that was always true. Signed-off-by: Piotr Pryga (cherry picked from commit 60e643477fda5c93876106a53a5e670ea2be6072) --- subsys/bluetooth/controller/ll_sw/ull_llcp_common.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/subsys/bluetooth/controller/ll_sw/ull_llcp_common.c b/subsys/bluetooth/controller/ll_sw/ull_llcp_common.c index 5aaf395b76b..f905c8a7cc2 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_llcp_common.c +++ b/subsys/bluetooth/controller/ll_sw/ull_llcp_common.c @@ -363,13 +363,10 @@ static void lp_comm_complete(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t conn->llcp.cte_req.is_enabled = 0U; } + llcp_rr_set_paused_cmd(conn, PROC_NONE); + llcp_lr_complete(conn); ctx->state = LP_COMMON_STATE_IDLE; - if (ctx->state == LP_COMMON_STATE_IDLE) { - llcp_rr_set_paused_cmd(conn, PROC_NONE); - llcp_lr_complete(conn); - } - conn->llcp.cte_req.is_active = 0U; if (conn->llcp.cte_req.disable_cb) { conn->llcp.cte_req.disable_cb(conn->llcp.cte_req.disable_param); From 9170b9b4835a8152dedd08f4c29570f643dfb627 Mon Sep 17 00:00:00 2001 From: Piotr Pryga Date: Fri, 28 Jan 2022 22:38:01 +0100 Subject: [PATCH 110/207] [nrf fromtree] Bluetooth: Controller: df: Add clarifying comment Add comment to clarify what is a disable_cb callback purpose and when it is set. Signed-off-by: Piotr Pryga (cherry picked from commit 5a1a6c7ffb846c1407f1e379d576521400ad887c) --- subsys/bluetooth/controller/ll_sw/ull_llcp_common.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/subsys/bluetooth/controller/ll_sw/ull_llcp_common.c b/subsys/bluetooth/controller/ll_sw/ull_llcp_common.c index f905c8a7cc2..5aeeafed4c4 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_llcp_common.c +++ b/subsys/bluetooth/controller/ll_sw/ull_llcp_common.c @@ -368,6 +368,10 @@ static void lp_comm_complete(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t ctx->state = LP_COMMON_STATE_IDLE; conn->llcp.cte_req.is_active = 0U; + /* If disable_cb is not NULL then there is waiting CTE REQ disable request from + * host. Execute the callback to notify waiting thread that the procedure is + * inactive. + */ if (conn->llcp.cte_req.disable_cb) { conn->llcp.cte_req.disable_cb(conn->llcp.cte_req.disable_param); } From 96a67e301d0f94d209d05d7af83bf66af210b9c3 Mon Sep 17 00:00:00 2001 From: Piotr Pryga Date: Fri, 28 Jan 2022 22:50:51 +0100 Subject: [PATCH 111/207] [nrf fromtree] Bluetooth: Controller: llcp: Add missing CTE pause in remote PHY change There were missing pause of CTE request in case remote PHY change was handled. That may end in violation of BT 5.3 Core Vol 6, Part B section 5.1.10.1 Packet transmission restrictions. Without the change there was a possibility to transmitt CTE when PHY is about to change to PHY CODED. Signed-off-by: Piotr Pryga (cherry picked from commit d4a93b51b757b0752acafb05557462a31a993ab3) --- subsys/bluetooth/controller/ll_sw/ull_llcp_phy.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/subsys/bluetooth/controller/ll_sw/ull_llcp_phy.c b/subsys/bluetooth/controller/ll_sw/ull_llcp_phy.c index bd006d03959..46f90c732c2 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_llcp_phy.c +++ b/subsys/bluetooth/controller/ll_sw/ull_llcp_phy.c @@ -845,9 +845,11 @@ static void rp_pu_complete(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t e static void rp_pu_send_phy_update_ind(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t evt, void *param) { - if (ctx->pause || !llcp_tx_alloc_peek(conn, ctx)) { + if (ctx->pause || !llcp_tx_alloc_peek(conn, ctx) || + (llcp_rr_get_paused_cmd(conn) == PROC_PHY_UPDATE)) { ctx->state = RP_PU_STATE_WAIT_TX_PHY_UPDATE_IND; } else { + llcp_rr_set_paused_cmd(conn, PROC_CTE_REQ); ctx->data.pu.instant = pu_event_counter(conn) + PHY_UPDATE_INSTANT_DELTA; rp_pu_tx(conn, ctx, PDU_DATA_LLCTRL_TYPE_PHY_UPD_IND); ctx->rx_opcode = PDU_DATA_LLCTRL_TYPE_UNUSED; From 505c2ab25caefb9119463d94cd327a3a69bd5e5f Mon Sep 17 00:00:00 2001 From: Piotr Pryga Date: Fri, 28 Jan 2022 22:58:34 +0100 Subject: [PATCH 112/207] [nrf fromtree] Bluetooth: Controller: Add CTE REQ disable when change PHY to CODED Accodring to BT 5.3 Core Vol 4, Part E section 7.8.85 the CTE request procedure has to be disabled as if Host issued the HCI_LE_Connection- CTE_Request_Enable with enable property set to 0. It means a Controller should automaticall disable the procedure. There were no handling of this part of specification. Signed-off-by: Piotr Pryga (cherry picked from commit ceca46ca1e0457313bac899408fb10b6bb736618) --- subsys/bluetooth/controller/ll_sw/ull_conn.c | 19 ++++++++- subsys/bluetooth/controller/ll_sw/ull_llcp.c | 29 +++++++++----- .../controller/ll_sw/ull_llcp_common.c | 40 +++++++++++++++---- 3 files changed, 70 insertions(+), 18 deletions(-) diff --git a/subsys/bluetooth/controller/ll_sw/ull_conn.c b/subsys/bluetooth/controller/ll_sw/ull_conn.c index 74a9a19c626..1d55dcebc84 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_conn.c +++ b/subsys/bluetooth/controller/ll_sw/ull_conn.c @@ -1654,9 +1654,24 @@ void ull_conn_done(struct node_rx_event_done *done) if (conn->llcp.cte_req.req_expire > elapsed_event) { conn->llcp.cte_req.req_expire -= elapsed_event; } else { + uint8_t err; + conn->llcp.cte_req.req_expire = 0U; - ull_cp_cte_req(conn, conn->llcp.cte_req.min_cte_len, - conn->llcp.cte_req.cte_type); + + err = ull_cp_cte_req(conn, conn->llcp.cte_req.min_cte_len, + conn->llcp.cte_req.cte_type); + + if (err == BT_HCI_ERR_CMD_DISALLOWED) { + /* Conditions has changed e.g. PHY was changed to CODED. + * New CTE REQ is not possible. Disable the periodic requests. + * + * If the CTE REQ is in active state, let it complete and disable + * in regular control procedure way. + */ + if (!conn->llcp.cte_req.is_active) { + ull_cp_cte_req_set_disable(conn); + } + } } } #endif /* CONFIG_BT_CTLR_DF_CONN_CTE_REQ */ diff --git a/subsys/bluetooth/controller/ll_sw/ull_llcp.c b/subsys/bluetooth/controller/ll_sw/ull_llcp.c index 923e70fd2cf..0a39d9b038f 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_llcp.c +++ b/subsys/bluetooth/controller/ll_sw/ull_llcp.c @@ -903,19 +903,30 @@ uint8_t ull_cp_cte_req(struct ll_conn *conn, uint8_t min_cte_len, uint8_t cte_ty { struct proc_ctx *ctx; - ctx = llcp_create_local_procedure(PROC_CTE_REQ); - if (!ctx) { - return BT_HCI_ERR_CMD_DISALLOWED; - } + /* The request may be started by periodic CTE request procedure, so it skips earlier + * verification of PHY. In case the PHY has changed to CODE the request should be stopped. + */ +#if defined(CONFIG_BT_CTLR_PHY) + if (conn->lll.phy_rx != PHY_CODED) { +#else + if (1) { +#endif /* CONFIG_BT_CTLR_PHY */ + ctx = llcp_create_local_procedure(PROC_CTE_REQ); + if (!ctx) { + return BT_HCI_ERR_CMD_DISALLOWED; + } - ctx->data.cte_req.min_len = min_cte_len; - ctx->data.cte_req.type = cte_type; + ctx->data.cte_req.min_len = min_cte_len; + ctx->data.cte_req.type = cte_type; - conn->llcp.cte_req.is_active = 1U; + conn->llcp.cte_req.is_active = 1U; - llcp_lr_enqueue(conn, ctx); + llcp_lr_enqueue(conn, ctx); - return BT_HCI_ERR_SUCCESS; + return BT_HCI_ERR_SUCCESS; + } + + return BT_HCI_ERR_CMD_DISALLOWED; } void ull_cp_cte_req_set_disable(struct ll_conn *conn) diff --git a/subsys/bluetooth/controller/ll_sw/ull_llcp_common.c b/subsys/bluetooth/controller/ll_sw/ull_llcp_common.c index 5aeeafed4c4..95126e294d8 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_llcp_common.c +++ b/subsys/bluetooth/controller/ll_sw/ull_llcp_common.c @@ -353,14 +353,22 @@ static void lp_comm_complete(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t conn->llcp.cte_req.req_interval != 0U) { conn->llcp.cte_req.req_expire = conn->llcp.cte_req.req_interval; } else { - conn->llcp.cte_req.is_enabled = 0U; + /* TODO: add wait for notification buffer */ lp_comm_ntf(conn, ctx); ull_cp_cte_req_set_disable(conn); } } else if (ctx->response_opcode == PDU_DATA_LLCTRL_TYPE_REJECT_EXT_IND && ctx->reject_ext_ind.reject_opcode == PDU_DATA_LLCTRL_TYPE_CTE_REQ) { + /* TODO: add wait for notification buffer */ lp_comm_ntf(conn, ctx); - conn->llcp.cte_req.is_enabled = 0U; + ull_cp_cte_req_set_disable(conn); + } else if (ctx->response_opcode == PDU_DATA_LLCTRL_TYPE_UNUSED) { + /* This path is related with handling disable the CTE REQ when PHY + * has been changed to CODED PHY. BT 5.3 Core Vol 4 Part E 7.8.85 + * says CTE REQ has to be automatically disabled as if it had been requested + * by Host. There is no notification send to Host. + */ + ull_cp_cte_req_set_disable(conn); } llcp_rr_set_paused_cmd(conn, PROC_NONE); @@ -467,12 +475,30 @@ static void lp_comm_send_req(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t #endif /* CONFIG_BT_CTLR_DATA_LENGTH */ #if defined(CONFIG_BT_CTLR_DF_CONN_CTE_REQ) case PROC_CTE_REQ: - if (ctx->pause || !llcp_tx_alloc_peek(conn, ctx) || - (llcp_rr_get_paused_cmd(conn) == PROC_CTE_REQ)) { - ctx->state = LP_COMMON_STATE_WAIT_TX; +#if defined(CONFIG_BT_CTLR_PHY) + if (conn->lll.phy_rx != PHY_CODED) { +#else + if (1) { +#endif /* CONFIG_BT_CTLR_PHY */ + if (ctx->pause || !llcp_tx_alloc_peek(conn, ctx) || + (llcp_rr_get_paused_cmd(conn) == PROC_CTE_REQ)) { + ctx->state = LP_COMMON_STATE_WAIT_TX; + } else { + lp_comm_tx(conn, ctx); + ctx->state = LP_COMMON_STATE_WAIT_RX; + } } else { - lp_comm_tx(conn, ctx); - ctx->state = LP_COMMON_STATE_WAIT_RX; + /* The PHY was changed to CODED when the request was waiting in a local + * request queue. + * + * Use of pair: proc PROC_CTE_REQ and rx_opcode PDU_DATA_LLCTRL_TYPE_UNUSED + * to complete the procedure before sending a request to peer. + * This is a special complete execution path to disable the procedure + * due to change of RX PHY to CODED. + */ + ctx->rx_opcode = PDU_DATA_LLCTRL_TYPE_UNUSED; + ctx->state = LP_COMMON_STATE_IDLE; + llcp_lr_complete(conn); } break; #endif /* CONFIG_BT_CTLR_DF_CONN_CTE_REQ */ From 22d37818e257a93332b4a67a19a268c3a25a1731 Mon Sep 17 00:00:00 2001 From: Piotr Pryga Date: Fri, 28 Jan 2022 23:05:16 +0100 Subject: [PATCH 113/207] [nrf fromtree] tests: Bluetooth: llcp: Add CTE REQ and PHY change collision tests To avoid violation of BT 5.3 Core Vol 6, Part B section 5.1.10.1 there was added a command pause mechanism that allows to postpone handling of CTE REQ if there is pending PHY change procedure or PHY change if there is pending CTE REQ procedure. The commit adds unit tests for the functionality. Signed-off-by: Piotr Pryga (cherry picked from commit 6d52a890167d36c147375da8d9efba117fd2ba66) --- .../controller/ctrl_cte_req/src/main.c | 782 +++++++++++++++++- 1 file changed, 780 insertions(+), 2 deletions(-) diff --git a/tests/bluetooth/controller/ctrl_cte_req/src/main.c b/tests/bluetooth/controller/ctrl_cte_req/src/main.c index 21cd87061ae..653bd8c71ff 100644 --- a/tests/bluetooth/controller/ctrl_cte_req/src/main.c +++ b/tests/bluetooth/controller/ctrl_cte_req/src/main.c @@ -616,6 +616,749 @@ void test_cte_req_reject_inv_ll_param_peripheral_remote(void) "Free CTX buffers %d", ctx_buffers_free()); } +/* Tests related with PHY update procedure and CTE request procedure "collision" */ + +#define PREFER_S2_CODING 0U +#define HOST_INITIATED 1U +#define PHY_UPDATE_INSTANT_DELTA 6U +#define PHY_PREFER_ANY (PHY_1M | PHY_2M | PHY_CODED) +/* Arbitrary value used for setting effective maximum number of TX/RX octets */ +#define PDU_PDU_MAX_OCTETS (PDU_DC_PAYLOAD_SIZE_MIN * 3) + +static void check_pref_phy_state(const struct ll_conn *conn, uint8_t phy_tx, uint8_t phy_rx) +{ + zassert_equal(conn->phy_pref_rx, phy_rx, + "Preferred RX PHY mismatch %d (actual) != %d (expected)", conn->phy_pref_rx, + phy_rx); + zassert_equal(conn->phy_pref_tx, phy_tx, + "Preferred TX PHY mismatch %d (actual) != %d (expected)", conn->phy_pref_tx, + phy_tx); +} + +static void check_current_phy_state(const struct ll_conn *conn, uint8_t phy_tx, uint8_t flags, + uint8_t phy_rx) +{ + zassert_equal(conn->lll.phy_rx, phy_rx, + "Current RX PHY mismatch %d (actual) != %d (expected)", conn->lll.phy_rx, + phy_rx); + zassert_equal(conn->lll.phy_tx, phy_tx, + "Current TX PHY mismatch %d (actual) != %d (expected)", conn->lll.phy_tx, + phy_tx); + zassert_equal(conn->lll.phy_flags, flags, + "Current Flags mismatch %d (actual) != %d (expected)", conn->lll.phy_flags, + flags); +} + +static bool is_instant_reached(struct ll_conn *conn, uint16_t instant) +{ + /* Check if instant is in the past. + * + * NOTE: If conn_event > instant then subtract operation will result in value greather than + * 0x7FFF for uint16_t type. This is based on modulo 65536 math. The 0x7FFF is + * maximum positive difference between actual value of connection event counter and + * instant. + */ + return (uint16_t)(event_counter(conn) - instant) <= (uint16_t)0x7FFF; +} + +static uint16_t pu_event_counter(struct ll_conn *conn) +{ + struct lll_conn *lll; + uint16_t event_counter; + + lll = &conn->lll; + + /* Calculate current event counter */ + event_counter = lll->event_counter + lll->latency_prepare; + + return event_counter; +} + +static void phy_update_setup(void) +{ + test_setup(&conn); + + /* Emulate initial conn state */ + conn.phy_pref_rx = PHY_PREFER_ANY; + conn.phy_pref_tx = PHY_PREFER_ANY; + conn.lll.phy_flags = PREFER_S2_CODING; + conn.lll.phy_tx_time = PHY_1M; + conn.lll.phy_rx = PHY_1M; + conn.lll.phy_tx = PHY_1M; + + /* Init DLE data */ + ull_conn_default_tx_octets_set(251); + ull_conn_default_tx_time_set(2120); + ull_dle_init(&conn, PHY_1M); + /* Emulate different remote numbers to trigger update of effective max TX octets and time. + * Numbers are taken arbitrary. + */ + conn.lll.dle.remote.max_tx_octets = PDU_PDU_MAX_OCTETS; + conn.lll.dle.remote.max_rx_octets = PDU_PDU_MAX_OCTETS; + conn.lll.dle.remote.max_tx_time = PDU_DC_MAX_US(conn.lll.dle.remote.max_tx_octets, PHY_1M); + conn.lll.dle.remote.max_rx_time = PDU_DC_MAX_US(conn.lll.dle.remote.max_rx_octets, PHY_1M); + ull_dle_update_eff(&conn); +} + +static void run_local_cte_req(struct pdu_data_llctrl_cte_req *cte_req) +{ + struct pdu_data_llctrl_cte_rsp remote_cte_rsp = {}; + struct node_tx *tx = NULL; + struct node_rx_pdu *ntf; + + /* The CTE request should already be in local control procedures queue */ + + /* Prepare */ + event_prepare(&conn); + + /* Tx Queue should have one LL Control PDU */ + lt_rx(LL_CTE_REQ, &conn, &tx, cte_req); + lt_rx_q_is_empty(&conn); + + /* Rx */ + lt_tx(LL_CTE_RSP, &conn, &remote_cte_rsp); + + /* Done */ + event_done(&conn); + + /* Receive notification of sampled CTE response */ + ut_rx_pdu(LL_CTE_RSP, &ntf, &remote_cte_rsp); + + /* There should not be a host notifications */ + ut_rx_q_is_empty(); + + /* Release tx node */ + ull_cp_release_tx(&conn, tx); +} + +void wait_for_phy_update_instant(uint8_t instant) +{ + /* */ + while (!is_instant_reached(&conn, instant)) { + /* Prepare */ + event_prepare(&conn); + + /* Tx Queue should NOT have a LL Control PDU */ + lt_rx_q_is_empty(&conn); + + /* Done */ + event_done(&conn); + + check_current_phy_state(&conn, PHY_1M, PREFER_S2_CODING, PHY_1M); + + /* There should NOT be a host notification */ + ut_rx_q_is_empty(); + } +} + +void check_phy_update_and_cte_req_complete(bool is_local, struct pdu_data_llctrl_cte_req *cte_req, + struct pdu_data_llctrl_phy_req *phy_req, + uint8_t ctx_num_at_end) +{ + struct pdu_data_llctrl_length_rsp length_ntf = { + PDU_PDU_MAX_OCTETS, PDU_DC_MAX_US(PDU_PDU_MAX_OCTETS, phy_req->tx_phys), + PDU_PDU_MAX_OCTETS, PDU_DC_MAX_US(PDU_PDU_MAX_OCTETS, phy_req->rx_phys) + }; + struct node_rx_pu pu = { .status = BT_HCI_ERR_SUCCESS }; + struct pdu_data_llctrl_cte_rsp remote_cte_rsp = {}; + struct node_tx *tx = NULL; + struct node_rx_pdu *ntf; + + /* Prepare */ + event_prepare(&conn); + + if (!is_local && cte_req != NULL) { + /* Handle remote PHY update request completion and local CTE reques in the same + * event. + */ + + /* Tx Queue should have one LL Control PDU */ + lt_rx(LL_CTE_REQ, &conn, &tx, cte_req); + lt_rx_q_is_empty(&conn); + + /* Rx */ + lt_tx(LL_CTE_RSP, &conn, &remote_cte_rsp); + } else { + /* Tx Queue should NOT have a LL Control PDU */ + lt_rx_q_is_empty(&conn); + } + + /* Done */ + event_done(&conn); + + /* There should be two host notifications, one pu and one dle */ + ut_rx_node(NODE_PHY_UPDATE, &ntf, &pu); + ut_rx_pdu(LL_LENGTH_RSP, &ntf, &length_ntf); + + /* Release Ntf */ + ull_cp_release_ntf(ntf); + + if (!is_local && cte_req != NULL) { + /* Receive notification of sampled CTE response */ + ut_rx_pdu(LL_CTE_RSP, &ntf, &remote_cte_rsp); + + /* Release Ntf */ + ull_cp_release_ntf(ntf); + + /* Release tx node */ + ull_cp_release_tx(&conn, tx); + } + + /* There should not be a host notifications */ + ut_rx_q_is_empty(); + + check_current_phy_state(&conn, phy_req->tx_phys, PREFER_S2_CODING, phy_req->tx_phys); + if (is_local) { + check_pref_phy_state(&conn, phy_req->rx_phys, phy_req->tx_phys); + } else { + check_pref_phy_state(&conn, PHY_PREFER_ANY, PHY_PREFER_ANY); + } + + /* There is still queued CTE REQ so number of contexts is smaller by 1 than max */ + zassert_equal(ctx_buffers_free(), ctx_num_at_end, "Free CTX buffers %d", + ctx_buffers_free()); +} + +/** + * @brief The function executes PHY update procedure in central role. + * + * The main goal for the function is to run and evaluate the PHY update control procedure. + * In case the PHY request is remote request and there is a local CTE request then + * after PHY update completion CTE request is executed in the same event. + * In this situation the function processes verification of CTE request completion also. + * + * @param is_local Flag informing if PHY request is local or remote. + * @param cte_req Parameters of CTE request procedure. If it is NULL there were no CTE + * request. + * @param phy_req Parameters of PHY update reques. + * @param events_at_start Number of connection events at function start. + * @param ctx_num_at_end Expected number of free procedure contexts at function end. + */ +static void run_phy_update_central(bool is_local, struct pdu_data_llctrl_cte_req *cte_req, + struct pdu_data_llctrl_phy_req *phy_req, uint8_t events_at_start, + uint8_t ctx_num_at_end) +{ + struct pdu_data_llctrl_phy_req rsp = { .rx_phys = PHY_PREFER_ANY, + .tx_phys = PHY_PREFER_ANY }; + struct pdu_data_llctrl_phy_upd_ind ind = { .instant = events_at_start + + PHY_UPDATE_INSTANT_DELTA, + .c_to_p_phy = phy_req->tx_phys, + .p_to_c_phy = phy_req->rx_phys }; + struct node_tx *tx = NULL; + struct pdu_data *pdu; + uint16_t instant; + + /* Prepare */ + event_prepare(&conn); + + if (is_local) { + /* Tx Queue should have one LL Control PDU */ + lt_rx(LL_PHY_REQ, &conn, &tx, phy_req); + lt_rx_q_is_empty(&conn); + + /* TX Ack */ + event_tx_ack(&conn, tx); + + /* Rx */ + lt_tx(LL_PHY_RSP, &conn, &rsp); + + ind.instant += 1; + } + + /* Done */ + event_done(&conn); + + /* Check that data tx was paused */ + zassert_equal(conn.tx_q.pause_data, 1U, "Data tx is not paused"); + + if (tx != NULL) { + /* Release Tx */ + ull_cp_release_tx(&conn, tx); + } + /* Prepare */ + event_prepare(&conn); + + /* Tx Queue should have one LL Control PDU */ + lt_rx(LL_PHY_UPDATE_IND, &conn, &tx, &ind); + lt_rx_q_is_empty(&conn); + + /* TX Ack */ + event_tx_ack(&conn, tx); + + /* Check that data tx is no lonnger paused */ + zassert_equal(conn.tx_q.pause_data, 0U, "Data tx is paused"); + + /* Done */ + event_done(&conn); + + /* Save Instant */ + pdu = (struct pdu_data *)tx->pdu; + instant = sys_le16_to_cpu(pdu->llctrl.phy_upd_ind.instant); + + /* Release Tx */ + ull_cp_release_tx(&conn, tx); + + wait_for_phy_update_instant(instant); + + check_phy_update_and_cte_req_complete(is_local, cte_req, phy_req, ctx_num_at_end); +} + +/** + * @brief The function executes PHY update procedure in peripheral role. + * + * The main goal for the function is to run and evaluate the PHY update control procedure. + * In case the PHY request is remote request and there is a local CTE request then + * after PHY update completion CTE request is executed in the same event. + * In this situation the function processes verification of CTE request completion also. + * + * @param is_local Flag informing if PHY request is local or remote. + * @param cte_req Parameters of CTE request procedure. If it is NULL there were no CTE + * request. + * @param phy_req Parameters of PHY update reques. + * @param events_at_start Number of connection events at function start. + * @param ctx_num_at_end Expected number of free procedure contexts at function end. + */ +static void run_phy_update_peripheral(bool is_local, struct pdu_data_llctrl_cte_req *cte_req, + struct pdu_data_llctrl_phy_req *phy_req, + uint8_t events_at_start, uint8_t ctx_num_at_end) +{ + struct pdu_data_llctrl_phy_req rsp = { .rx_phys = PHY_PREFER_ANY, + .tx_phys = PHY_PREFER_ANY }; + struct pdu_data_llctrl_phy_upd_ind ind = { .c_to_p_phy = phy_req->rx_phys, + .p_to_c_phy = phy_req->tx_phys }; + struct node_tx *tx; + uint16_t instant; + + /* Prepare */ + event_prepare(&conn); + + if (is_local) { + /* Tx Queue should have one LL Control PDU */ + lt_rx(LL_PHY_REQ, &conn, &tx, phy_req); + lt_rx_q_is_empty(&conn); + + /* TX Ack */ + event_tx_ack(&conn, tx); + } + + /* Done */ + event_done(&conn); + + if (is_local) { + /* Release Tx */ + ull_cp_release_tx(&conn, tx); + } else { + /* Check that data tx was paused */ + zassert_equal(conn.tx_q.pause_data, 1U, "Data tx is not paused"); + } + + /* Prepare */ + event_prepare(&conn); + + instant = event_counter(&conn) + PHY_UPDATE_INSTANT_DELTA; + ind.instant = instant; + + if (is_local) { + /* Tx Queue should NOT have a LL Control PDU */ + lt_rx_q_is_empty(&conn); + + /* Tx Queue should have one LL Control PDU */ + lt_tx(LL_PHY_UPDATE_IND, &conn, &ind); + } else { + /* Tx Queue should have one LL Control PDU */ + lt_rx(LL_PHY_RSP, &conn, &tx, &rsp); + lt_rx_q_is_empty(&conn); + + /* Rx */ + lt_tx(LL_PHY_UPDATE_IND, &conn, &ind); + + /* We are sending RSP, so data tx should be paused until after tx ack */ + zassert_equal(conn.tx_q.pause_data, 1U, "Data tx is not paused"); + + /* TX Ack */ + event_tx_ack(&conn, tx); + + /* Check that data tx is no longer paused */ + zassert_equal(conn.tx_q.pause_data, 0U, "Data tx is paused"); + } + + /* Done */ + event_done(&conn); + + if (!is_local) { + /* Release Tx */ + ull_cp_release_tx(&conn, tx); + } + + wait_for_phy_update_instant(instant); + + check_phy_update_and_cte_req_complete(is_local, cte_req, phy_req, ctx_num_at_end); +} + +static void test_local_cte_req_wait_for_phy_update_complete_and_disable(uint8_t role) +{ + uint8_t err; + + struct pdu_data_llctrl_cte_req local_cte_req = { + .cte_type_req = BT_HCI_LE_AOA_CTE, + .min_cte_len_req = BT_HCI_LE_CTE_LEN_MIN, + }; + struct pdu_data_llctrl_phy_req phy_req = { .rx_phys = PHY_CODED, .tx_phys = PHY_CODED }; + + phy_update_setup(); + + /* Role */ + test_set_role(&conn, role); + + /* Connect */ + ull_cp_state_set(&conn, ULL_CP_CONNECTED); + + /* Initiate an PHY Update Procedure */ + err = ull_cp_phy_update(&conn, PHY_CODED, PREFER_S2_CODING, PHY_CODED, HOST_INITIATED); + zassert_equal(err, BT_HCI_ERR_SUCCESS, NULL); + + /* Initiate an CTE Request Procedure */ + err = ull_cp_cte_req(&conn, local_cte_req.min_cte_len_req, local_cte_req.cte_type_req); + zassert_equal(err, BT_HCI_ERR_SUCCESS, NULL); + + if (role == BT_HCI_ROLE_CENTRAL) { + run_phy_update_central(true, NULL, &phy_req, pu_event_counter(&conn), + CONFIG_BT_CTLR_LLCP_PROC_CTX_BUF_NUM - 1); + } else { + run_phy_update_peripheral(true, NULL, &phy_req, pu_event_counter(&conn), + CONFIG_BT_CTLR_LLCP_PROC_CTX_BUF_NUM - 1); + } + + /* In this test CTE request is local procedure. Local procedures are handled after remote + * procedures, hence PHY update will be handled one event after completion of CTE request. + */ + + /* Prepare */ + event_prepare(&conn); + + /* Tx Queue should not have any LL Control PDU */ + lt_rx_q_is_empty(&conn); + + /* Done */ + event_done(&conn); + + /* There should not be a host notifications */ + ut_rx_q_is_empty(); + + zassert_equal(ctx_buffers_free(), CONFIG_BT_CTLR_LLCP_PROC_CTX_BUF_NUM, + "Free CTX buffers %d", ctx_buffers_free()); +} + +void test_central_local_cte_req_wait_for_phy_update_complete_and_disable(void) +{ + test_local_cte_req_wait_for_phy_update_complete_and_disable(BT_HCI_ROLE_CENTRAL); +} + +void test_peripheral_local_cte_req_wait_for_phy_update_complete_and_disable(void) +{ + test_local_cte_req_wait_for_phy_update_complete_and_disable(BT_HCI_ROLE_PERIPHERAL); +} + +static void test_local_cte_req_wait_for_phy_update_complete(uint8_t role) +{ + struct pdu_data_llctrl_cte_req local_cte_req = { + .cte_type_req = BT_HCI_LE_AOA_CTE, + .min_cte_len_req = BT_HCI_LE_CTE_LEN_MIN, + }; + struct pdu_data_llctrl_phy_req phy_req = { .rx_phys = PHY_2M, .tx_phys = PHY_2M }; + + uint8_t err; + + phy_update_setup(); + + /* Role */ + test_set_role(&conn, role); + + /* Connect */ + ull_cp_state_set(&conn, ULL_CP_CONNECTED); + + /* Initiate an PHY Update Procedure */ + err = ull_cp_phy_update(&conn, phy_req.rx_phys, PREFER_S2_CODING, phy_req.tx_phys, + HOST_INITIATED); + zassert_equal(err, BT_HCI_ERR_SUCCESS, NULL); + + /* Initiate an CTE Request Procedure */ + err = ull_cp_cte_req(&conn, local_cte_req.min_cte_len_req, local_cte_req.cte_type_req); + zassert_equal(err, BT_HCI_ERR_SUCCESS, NULL); + + if (role == BT_HCI_ROLE_CENTRAL) { + run_phy_update_central(true, &local_cte_req, &phy_req, pu_event_counter(&conn), + CONFIG_BT_CTLR_LLCP_PROC_CTX_BUF_NUM - 1); + } else { + run_phy_update_peripheral(true, &local_cte_req, &phy_req, pu_event_counter(&conn), + CONFIG_BT_CTLR_LLCP_PROC_CTX_BUF_NUM - 1); + } + + /* PHY update was completed. Handle CTE request */ + run_local_cte_req(&local_cte_req); + + zassert_equal(ctx_buffers_free(), CONFIG_BT_CTLR_LLCP_PROC_CTX_BUF_NUM, + "Free CTX buffers %d", ctx_buffers_free()); +} + +void test_central_local_cte_req_wait_for_phy_update_complete(void) +{ + test_local_cte_req_wait_for_phy_update_complete(BT_HCI_ROLE_CENTRAL); +} + +void test_peripheral_local_cte_req_wait_for_phy_update_complete(void) +{ + test_local_cte_req_wait_for_phy_update_complete(BT_HCI_ROLE_PERIPHERAL); +} + +static void test_local_phy_update_wait_for_cte_req_complete(uint8_t role) +{ + struct pdu_data_llctrl_phy_req phy_req = { .rx_phys = PHY_CODED, .tx_phys = PHY_CODED }; + struct pdu_data_llctrl_cte_req local_cte_req = { + .cte_type_req = BT_HCI_LE_AOA_CTE, + .min_cte_len_req = BT_HCI_LE_CTE_LEN_MIN, + }; + uint8_t err; + + phy_update_setup(); + + /* Role */ + test_set_role(&conn, role); + + /* Connect */ + ull_cp_state_set(&conn, ULL_CP_CONNECTED); + + /* Initiate an CTE Request Procedure */ + err = ull_cp_cte_req(&conn, local_cte_req.min_cte_len_req, local_cte_req.cte_type_req); + zassert_equal(err, BT_HCI_ERR_SUCCESS, NULL); + + /* Initiate an PHY Update Procedure */ + err = ull_cp_phy_update(&conn, PHY_CODED, PREFER_S2_CODING, PHY_CODED, HOST_INITIATED); + zassert_equal(err, BT_HCI_ERR_SUCCESS, NULL); + + /* Handle CTE request */ + run_local_cte_req(&local_cte_req); + + zassert_equal(ctx_buffers_free(), CONFIG_BT_CTLR_LLCP_PROC_CTX_BUF_NUM - 1, + "Free CTX buffers %d", ctx_buffers_free()); + + if (role == BT_HCI_ROLE_CENTRAL) { + run_phy_update_central(true, NULL, &phy_req, pu_event_counter(&conn), + CONFIG_BT_CTLR_LLCP_PROC_CTX_BUF_NUM); + } else { + run_phy_update_peripheral(true, NULL, &phy_req, pu_event_counter(&conn), + CONFIG_BT_CTLR_LLCP_PROC_CTX_BUF_NUM); + } +} + +void test_central_local_phy_update_wait_for_cte_req_complete(void) +{ + test_local_phy_update_wait_for_cte_req_complete(BT_HCI_ROLE_CENTRAL); +} + +void test_peripheral_local_phy_update_wait_for_cte_req_complete(void) +{ + test_local_phy_update_wait_for_cte_req_complete(BT_HCI_ROLE_PERIPHERAL); +} + +static void run_remote_cte_req(struct pdu_data_llctrl_cte_req *cte_req) +{ + struct pdu_data_llctrl_cte_rsp remote_cte_rsp = {}; + struct node_tx *tx; + + /* The CTE response should already be enabled and request PDU should already be + * received. + */ + + /* Prepare */ + event_prepare(&conn); + + /* Tx Queue should have one LL Control PDU */ + lt_rx(LL_CTE_RSP, &conn, &tx, &remote_cte_rsp); + lt_rx_q_is_empty(&conn); + + /* TX Ack */ + event_tx_ack(&conn, tx); + + /* Done */ + event_done(&conn); + + /* Release tx node */ + ull_cp_release_tx(&conn, tx); + + /* There should not be a host notifications */ + ut_rx_q_is_empty(); +} + +static void test_phy_update_wait_for_remote_cte_req_complete(uint8_t role) +{ + struct pdu_data_llctrl_cte_req local_cte_req = { + .cte_type_req = BT_HCI_LE_AOA_CTE, + .min_cte_len_req = BT_HCI_LE_CTE_LEN_MIN, + }; + struct pdu_data_llctrl_phy_req phy_req = { .rx_phys = PHY_CODED, .tx_phys = PHY_CODED }; + uint8_t err; + + phy_update_setup(); + + /* Role */ + test_set_role(&conn, role); + + /* Connect */ + ull_cp_state_set(&conn, ULL_CP_CONNECTED); + + /* Enable response for CTE request */ + ull_cp_cte_rsp_enable(&conn, true, BT_HCI_LE_CTE_LEN_MAX, + (BT_HCI_LE_AOA_CTE | BT_HCI_LE_AOD_CTE_1US | BT_HCI_LE_AOD_CTE_2US)); + + /* Prepare */ + event_prepare(&conn); + + /* Tx */ + lt_tx(LL_CTE_REQ, &conn, &local_cte_req); + + /* Done */ + event_done(&conn); + + /* Initiate an PHY Update Procedure */ + err = ull_cp_phy_update(&conn, PHY_CODED, PREFER_S2_CODING, PHY_CODED, HOST_INITIATED); + zassert_equal(err, BT_HCI_ERR_SUCCESS, NULL); + + run_remote_cte_req(&local_cte_req); + + /* There should not be a host notifications */ + ut_rx_q_is_empty(); + + zassert_equal(ctx_buffers_free(), CONFIG_BT_CTLR_LLCP_PROC_CTX_BUF_NUM - 1, + "Free CTX buffers %d", ctx_buffers_free()); + + if (role == BT_HCI_ROLE_CENTRAL) { + run_phy_update_central(true, NULL, &phy_req, pu_event_counter(&conn), + CONFIG_BT_CTLR_LLCP_PROC_CTX_BUF_NUM); + } else { + run_phy_update_peripheral(true, NULL, &phy_req, pu_event_counter(&conn), + CONFIG_BT_CTLR_LLCP_PROC_CTX_BUF_NUM); + } +} + +void test_central_phy_update_wait_for_remote_cte_req_complete(void) +{ + test_phy_update_wait_for_remote_cte_req_complete(BT_HCI_ROLE_CENTRAL); +} + +void test_peripheral_phy_update_wait_for_remote_cte_req_complete(void) +{ + test_phy_update_wait_for_remote_cte_req_complete(BT_HCI_ROLE_PERIPHERAL); +} + +static void test_cte_req_wait_for_remote_phy_update_complete_and_disable(uint8_t role) +{ + uint8_t err; + + struct pdu_data_llctrl_cte_req local_cte_req = { + .cte_type_req = BT_HCI_LE_AOA_CTE, + .min_cte_len_req = BT_HCI_LE_CTE_LEN_MIN, + }; + struct pdu_data_llctrl_phy_req phy_req = { .rx_phys = PHY_CODED, .tx_phys = PHY_CODED }; + + phy_update_setup(); + + /* Role */ + test_set_role(&conn, role); + + /* Connect */ + ull_cp_state_set(&conn, ULL_CP_CONNECTED); + + /* Prepare */ + event_prepare(&conn); + + /* Tx */ + lt_tx(LL_PHY_REQ, &conn, &phy_req); + + /* Done */ + event_done(&conn); + + /* Initiate an CTE Request Procedure */ + err = ull_cp_cte_req(&conn, local_cte_req.min_cte_len_req, local_cte_req.cte_type_req); + zassert_equal(err, BT_HCI_ERR_SUCCESS, NULL); + + if (role == BT_HCI_ROLE_CENTRAL) { + run_phy_update_central(false, NULL, &phy_req, pu_event_counter(&conn), + CONFIG_BT_CTLR_LLCP_PROC_CTX_BUF_NUM); + } else { + run_phy_update_peripheral(false, NULL, &phy_req, pu_event_counter(&conn), + CONFIG_BT_CTLR_LLCP_PROC_CTX_BUF_NUM); + } + + /* There is no special handling of CTE REQ completion. It is done when instant happens just + * after remote PHY update completes. + */ +} + +void test_central_cte_req_wait_for_remote_phy_update_complete_and_disable(void) +{ + test_cte_req_wait_for_remote_phy_update_complete_and_disable(BT_HCI_ROLE_CENTRAL); +} + +void test_peripheral_cte_req_wait_for_remote_phy_update_complete_and_disable(void) +{ + test_cte_req_wait_for_remote_phy_update_complete_and_disable(BT_HCI_ROLE_PERIPHERAL); +} + +static void test_cte_req_wait_for_remote_phy_update_complete(uint8_t role) +{ + uint8_t err; + + struct pdu_data_llctrl_cte_req local_cte_req = { + .cte_type_req = BT_HCI_LE_AOA_CTE, + .min_cte_len_req = BT_HCI_LE_CTE_LEN_MIN, + }; + struct pdu_data_llctrl_phy_req phy_req = { .rx_phys = PHY_2M, .tx_phys = PHY_2M }; + + phy_update_setup(); + + /* Role */ + test_set_role(&conn, role); + + /* Connect */ + ull_cp_state_set(&conn, ULL_CP_CONNECTED); + + /* Prepare */ + event_prepare(&conn); + + /* Tx */ + lt_tx(LL_PHY_REQ, &conn, &phy_req); + + /* Done */ + event_done(&conn); + + /* Initiate an CTE Request Procedure */ + err = ull_cp_cte_req(&conn, local_cte_req.min_cte_len_req, local_cte_req.cte_type_req); + zassert_equal(err, BT_HCI_ERR_SUCCESS, NULL); + + if (role == BT_HCI_ROLE_CENTRAL) { + run_phy_update_central(false, &local_cte_req, &phy_req, pu_event_counter(&conn), + CONFIG_BT_CTLR_LLCP_PROC_CTX_BUF_NUM); + } else { + run_phy_update_peripheral(false, &local_cte_req, &phy_req, pu_event_counter(&conn), + CONFIG_BT_CTLR_LLCP_PROC_CTX_BUF_NUM); + } + + /* There is no special handling of CTE REQ completion here. It is done when instant happens + * just after remote PHY update completes. + */ +} + +void test_central_cte_req_wait_for_remote_phy_update_complete(void) +{ + test_cte_req_wait_for_remote_phy_update_complete(BT_HCI_ROLE_CENTRAL); +} + +void test_peripheral_cte_req_wait_for_remote_phy_update_complete(void) +{ + test_cte_req_wait_for_remote_phy_update_complete(BT_HCI_ROLE_PERIPHERAL); +} + void test_main(void) { ztest_test_suite( @@ -633,7 +1376,42 @@ void test_main(void) ztest_unit_test_setup_teardown(test_cte_req_reject_inv_ll_param_central_remote, setup, unit_test_noop), ztest_unit_test_setup_teardown(test_cte_req_reject_inv_ll_param_peripheral_remote, - setup, unit_test_noop)); - + setup, unit_test_noop), + ztest_unit_test_setup_teardown( + test_central_local_cte_req_wait_for_phy_update_complete_and_disable, setup, + unit_test_noop), + ztest_unit_test_setup_teardown( + test_central_local_cte_req_wait_for_phy_update_complete_and_disable, setup, + unit_test_noop), + ztest_unit_test_setup_teardown( + test_peripheral_local_cte_req_wait_for_phy_update_complete, setup, + unit_test_noop), + ztest_unit_test_setup_teardown( + test_central_local_phy_update_wait_for_cte_req_complete, setup, + unit_test_noop), + ztest_unit_test_setup_teardown( + test_peripheral_local_phy_update_wait_for_cte_req_complete, setup, + unit_test_noop), + ztest_unit_test_setup_teardown( + test_peripheral_local_cte_req_wait_for_phy_update_complete, setup, + unit_test_noop), + ztest_unit_test_setup_teardown( + test_central_phy_update_wait_for_remote_cte_req_complete, setup, + unit_test_noop), + ztest_unit_test_setup_teardown( + test_peripheral_phy_update_wait_for_remote_cte_req_complete, setup, + unit_test_noop), + ztest_unit_test_setup_teardown( + test_central_cte_req_wait_for_remote_phy_update_complete_and_disable, setup, + unit_test_noop), + ztest_unit_test_setup_teardown( + test_peripheral_cte_req_wait_for_remote_phy_update_complete_and_disable, + setup, unit_test_noop), + ztest_unit_test_setup_teardown( + test_central_cte_req_wait_for_remote_phy_update_complete, setup, + unit_test_noop), + ztest_unit_test_setup_teardown( + test_peripheral_cte_req_wait_for_remote_phy_update_complete, setup, + unit_test_noop)); ztest_run_test_suite(cte_req); } From 7a21d06373d9cc2ada56465b9351d9950bce9d46 Mon Sep 17 00:00:00 2001 From: Piotr Pryga Date: Sat, 29 Jan 2022 14:54:28 +0100 Subject: [PATCH 114/207] [nrf fromtree] Bluetooth: Controller: llcp: Add wait for nrf state in CTE REQ There were no wait for free notification buffer (pdu object used to send notifications to Host). That may cause assertion in lp_comm_ntf function. Signed-off-by: Piotr Pryga (cherry picked from commit 092f697ceeb2a79973213982d855298fa75ed3e0) --- .../controller/ll_sw/ull_llcp_common.c | 58 +++++++++++++------ 1 file changed, 41 insertions(+), 17 deletions(-) diff --git a/subsys/bluetooth/controller/ll_sw/ull_llcp_common.c b/subsys/bluetooth/controller/ll_sw/ull_llcp_common.c index 95126e294d8..ea1715e60a2 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_llcp_common.c +++ b/subsys/bluetooth/controller/ll_sw/ull_llcp_common.c @@ -208,6 +208,23 @@ static void lp_comm_ntf_length_change(struct ll_conn *conn, struct proc_ctx *ctx #endif /* CONFIG_BT_CTLR_DATA_LENGTH */ #if defined(CONFIG_BT_CTLR_DF_CONN_CTE_REQ) + +static void lp_comm_complete_cte_req_finalize(struct ll_conn *conn) +{ + llcp_rr_set_paused_cmd(conn, PROC_NONE); + llcp_lr_complete(conn); + + conn->llcp.cte_req.is_active = 0U; + + /* If disable_cb is not NULL then there is waiting CTE REQ disable request + * from host. Execute the callback to notify waiting thread that the + * procedure is inactive. + */ + if (conn->llcp.cte_req.disable_cb) { + conn->llcp.cte_req.disable_cb(conn->llcp.cte_req.disable_param); + } +} + static void lp_comm_ntf_cte_req(struct ll_conn *conn, struct proc_ctx *ctx, struct pdu_data *pdu) { switch (ctx->response_opcode) { @@ -352,16 +369,23 @@ static void lp_comm_complete(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t if (ctx->data.cte_remote_rsp.has_cte && conn->llcp.cte_req.req_interval != 0U) { conn->llcp.cte_req.req_expire = conn->llcp.cte_req.req_interval; - } else { - /* TODO: add wait for notification buffer */ + ctx->state = LP_COMMON_STATE_IDLE; + } else if (llcp_ntf_alloc_is_available()) { lp_comm_ntf(conn, ctx); ull_cp_cte_req_set_disable(conn); + ctx->state = LP_COMMON_STATE_IDLE; + } else { + ctx->state = LP_COMMON_STATE_WAIT_NTF; } } else if (ctx->response_opcode == PDU_DATA_LLCTRL_TYPE_REJECT_EXT_IND && ctx->reject_ext_ind.reject_opcode == PDU_DATA_LLCTRL_TYPE_CTE_REQ) { - /* TODO: add wait for notification buffer */ - lp_comm_ntf(conn, ctx); - ull_cp_cte_req_set_disable(conn); + if (llcp_ntf_alloc_is_available()) { + lp_comm_ntf(conn, ctx); + ull_cp_cte_req_set_disable(conn); + ctx->state = LP_COMMON_STATE_IDLE; + } else { + ctx->state = LP_COMMON_STATE_WAIT_NTF; + } } else if (ctx->response_opcode == PDU_DATA_LLCTRL_TYPE_UNUSED) { /* This path is related with handling disable the CTE REQ when PHY * has been changed to CODED PHY. BT 5.3 Core Vol 4 Part E 7.8.85 @@ -369,21 +393,12 @@ static void lp_comm_complete(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t * by Host. There is no notification send to Host. */ ull_cp_cte_req_set_disable(conn); + ctx->state = LP_COMMON_STATE_IDLE; } - llcp_rr_set_paused_cmd(conn, PROC_NONE); - llcp_lr_complete(conn); - ctx->state = LP_COMMON_STATE_IDLE; - - conn->llcp.cte_req.is_active = 0U; - /* If disable_cb is not NULL then there is waiting CTE REQ disable request from - * host. Execute the callback to notify waiting thread that the procedure is - * inactive. - */ - if (conn->llcp.cte_req.disable_cb) { - conn->llcp.cte_req.disable_cb(conn->llcp.cte_req.disable_param); + if (ctx->state == LP_COMMON_STATE_IDLE) { + lp_comm_complete_cte_req_finalize(conn); } - break; #endif /* CONFIG_BT_CTLR_DF_CONN_CTE_REQ */ default: @@ -642,6 +657,15 @@ static void lp_comm_st_wait_ntf(struct ll_conn *conn, struct proc_ctx *ctx, uint ctx->state = LP_COMMON_STATE_IDLE; } break; +#if defined(CONFIG_BT_CTLR_DF_CONN_CTE_REQ) + case PROC_CTE_REQ: + if (llcp_ntf_alloc_is_available()) { + lp_comm_ntf(conn, ctx); + ctx->state = LP_COMMON_STATE_IDLE; + lp_comm_complete_cte_req_finalize(conn); + } + break; +#endif /* CONFIG_BT_CTLR_DF_CONN_CTE_REQ */ default: break; } From 4d4d735430eb58a06840f067d9f488f94d2d163f Mon Sep 17 00:00:00 2001 From: Piotr Pryga Date: Sun, 30 Jan 2022 00:55:27 +0100 Subject: [PATCH 115/207] [nrf fromtree] tests: Bluetooth: df: Fix not building connection CTE req tests The tests for direction finding connected mode were not building correclty. There were missing Kconfig options that enable missing functionality to be tested. Tests were not failing because there were no expected positive behavior tests added. Added changes allow to validate all implemented test cases. Signed-off-by: Piotr Pryga (cherry picked from commit 95174fe48f3cf3f90a3533eb9039161c357a87f8) --- tests/bluetooth/df/common/src/bt_conn_common.c | 5 +++-- tests/bluetooth/df/connection_cte_req/prj.conf | 11 +++++++++-- .../df/connection_cte_req/src/test_cte_req_enable.c | 2 +- 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/tests/bluetooth/df/common/src/bt_conn_common.c b/tests/bluetooth/df/common/src/bt_conn_common.c index 02e31ad5432..3750d2b98f0 100644 --- a/tests/bluetooth/df/common/src/bt_conn_common.c +++ b/tests/bluetooth/df/common/src/bt_conn_common.c @@ -19,6 +19,7 @@ #include #include +#include #include #include @@ -54,8 +55,8 @@ void ut_bt_set_peer_features(uint16_t conn_handle, uint64_t features) conn = ll_conn_get(conn_handle); zassert_not_equal(conn, NULL, "Failed ll_conn instance for given handle"); - conn->common.fex_valid = PEER_FEATURES_ARE_VALID; - conn->llcp_feature.features_peer = features; + conn->llcp.fex.valid = PEER_FEATURES_ARE_VALID; + conn->llcp.fex.features_peer = features; } void ut_bt_set_periph_latency(uint16_t conn_handle, uint16_t periph_latency) diff --git a/tests/bluetooth/df/connection_cte_req/prj.conf b/tests/bluetooth/df/connection_cte_req/prj.conf index 36c48049ce7..6280ed8e699 100644 --- a/tests/bluetooth/df/connection_cte_req/prj.conf +++ b/tests/bluetooth/df/connection_cte_req/prj.conf @@ -10,15 +10,22 @@ CONFIG_BT_GATT_CLIENT=y CONFIG_BT_CTLR=y CONFIG_BT_LL_SW_SPLIT=y +# Enable new implementation of LLCP +CONFIG_BT_LL_SW_LLCP=y + # Enable Direction Finding Feature including AoA and AoD CONFIG_BT_DF=y -CONFIG_BT_DF_CONNECTION_CTE_RX=y +CONFIG_BT_CTLR_DF_CTE_RX=y +CONFIG_BT_DF_CONNECTION_CTE_REQ=y CONFIG_BT_CTLR_DF=y +CONFIG_BT_CTLR_DF_CONN_CTE_REQ=y +CONFIG_BT_CTLR_DF_CONN_CTE_REQ=y + CONFIG_BT_DF_CONNECTION_CTE_TX=y CONFIG_BT_DF_CONNECTION_CTE_RX=y CONFIG_BT_DF_CONNECTION_CTE_RSP=y CONFIG_BT_DF_CONNECTION_CTE_REQ=y -# set antenna switch pattern to max allowed value +# Set antenna switch pattern to max allowed value CONFIG_BT_CTLR_DF_MAX_ANT_SW_PATTERN_LEN=39 diff --git a/tests/bluetooth/df/connection_cte_req/src/test_cte_req_enable.c b/tests/bluetooth/df/connection_cte_req/src/test_cte_req_enable.c index 1b0839d31df..ca27eabc4be 100644 --- a/tests/bluetooth/df/connection_cte_req/src/test_cte_req_enable.c +++ b/tests/bluetooth/df/connection_cte_req/src/test_cte_req_enable.c @@ -173,7 +173,7 @@ static void cte_rx_param_setup(void) }; ut_bt_create_connection(); - ut_bt_set_periph_latency(g_conn_handle, REQUEST_INTERVAL_TOO_LOW); + ut_bt_set_periph_latency(g_conn_handle, CONN_PERIPH_LATENCY); send_set_conn_cte_rx_params(g_conn_handle, &cte_rx_params, true); } From 3546d850ead5ae885b029a6f03d74e1091c1da58 Mon Sep 17 00:00:00 2001 From: Piotr Pryga Date: Sun, 30 Jan 2022 00:59:23 +0100 Subject: [PATCH 116/207] [nrf fromtree] tests: Bluetooth: df: Add CTE REQ expected positive behavior tests Add expected positive behavior tests for direction fingin in connected mode. Signed-off-by: Piotr Pryga (cherry picked from commit 16054c247b4db997e79706b62c679ba8f8b72477) --- .../bluetooth/df/common/src/bt_conn_common.c | 8 +++ .../src/test_cte_req_enable.c | 54 ++++++++++++++++--- 2 files changed, 55 insertions(+), 7 deletions(-) diff --git a/tests/bluetooth/df/common/src/bt_conn_common.c b/tests/bluetooth/df/common/src/bt_conn_common.c index 3750d2b98f0..46955669a12 100644 --- a/tests/bluetooth/df/common/src/bt_conn_common.c +++ b/tests/bluetooth/df/common/src/bt_conn_common.c @@ -35,6 +35,14 @@ uint16_t ut_bt_create_connection(void) conn->lll.latency = 0; conn->lll.handle = ll_conn_handle_get(conn); +#if defined(CONFIG_BT_CTLR_DF_CONN_CTE_RX) + conn->lll.df_rx_cfg.is_initialized = 0U; +#endif /* CONFIG_BT_CTLR_DF_CONN_CTE_RX */ + +#if defined(CONFIG_BT_CTLR_DF_CONN_CTE_REQ) + conn->llcp.cte_req.is_enabled = 0U; +#endif /* CONFIG_BT_CTLR_DF_CONN_CTE_REQ */ + return conn->lll.handle; } diff --git a/tests/bluetooth/df/connection_cte_req/src/test_cte_req_enable.c b/tests/bluetooth/df/connection_cte_req/src/test_cte_req_enable.c index ca27eabc4be..3db45d573ba 100644 --- a/tests/bluetooth/df/connection_cte_req/src/test_cte_req_enable.c +++ b/tests/bluetooth/df/connection_cte_req/src/test_cte_req_enable.c @@ -63,8 +63,6 @@ int send_conn_cte_req_enable(uint16_t conn_handle, struct bt_hci_cp_le_conn_cte_req_enable *cp; struct net_buf *buf; - zassert_not_equal(data, NULL, "Unexpected data pointer with null value."); - buf = bt_hci_cmd_create(BT_HCI_OP_LE_CONN_CTE_REQ_ENABLE, sizeof(*cp)); if (!buf) { return -ENOBUFS; @@ -74,9 +72,11 @@ int send_conn_cte_req_enable(uint16_t conn_handle, (void)memset(cp, 0, sizeof(*cp)); cp->handle = sys_cpu_to_le16(conn_handle); cp->enable = enable ? 1 : 0; - cp->cte_request_interval = data->cte_request_interval; - cp->requested_cte_length = data->requested_cte_length; - cp->requested_cte_type = data->requested_cte_type; + if (data != NULL) { + cp->cte_request_interval = data->cte_request_interval; + cp->requested_cte_length = data->requested_cte_length; + cp->requested_cte_type = data->requested_cte_type; + } return bt_hci_cmd_send_sync(BT_HCI_OP_LE_CONN_CTE_REQ_ENABLE, buf, NULL); } @@ -146,11 +146,31 @@ void test_set_conn_cte_req_enable_with_invalid_cte_type(void) "Unexpected error value for CTE request enable with invalid CTE type"); } -static void connection_setup(void) +void test_set_conn_cte_req_enable(void) +{ + int err; + + err = send_conn_cte_req_enable(g_conn_handle, &g_data, true); + zassert_equal(err, 0, "Unexpected error value for CTE request enable"); +} + +void test_set_conn_cte_req_disable(void) +{ + int err; + + err = send_conn_cte_req_enable(g_conn_handle, NULL, false); + zassert_equal(err, 0, "Unexpected error value for CTE request disable"); +} +static void cte_req_params_set(void) { g_data.cte_request_interval = REQUEST_INTERVAL_OK; g_data.requested_cte_length = BT_HCI_LE_CTE_LEN_MAX; g_data.requested_cte_type = BT_HCI_LE_AOD_CTE_2US; +} + +static void connection_setup(void) +{ + cte_req_params_set(); g_conn_handle = ut_bt_create_connection(); } @@ -172,12 +192,21 @@ static void cte_rx_param_setup(void) .ant_ids = ant_ids }; + cte_req_params_set(); + ut_bt_create_connection(); ut_bt_set_periph_latency(g_conn_handle, CONN_PERIPH_LATENCY); send_set_conn_cte_rx_params(g_conn_handle, &cte_rx_params, true); } +static void cte_req_setup(void) +{ + cte_rx_param_setup(); + + send_conn_cte_req_enable(g_conn_handle, &g_data, true); +} + static void cte_rx_param_teardown(void) { connection_teardown(); @@ -185,6 +214,13 @@ static void cte_rx_param_teardown(void) send_set_conn_cte_rx_params(g_conn_handle, NULL, false); } +static void cte_req_teardown(void) +{ + send_conn_cte_req_enable(g_conn_handle, NULL, false); + + cte_rx_param_teardown(); +} + void run_cte_request_enable_tests(void) { ztest_test_suite( @@ -199,7 +235,11 @@ void run_cte_request_enable_tests(void) cte_rx_param_setup, cte_rx_param_teardown), ztest_unit_test_setup_teardown( test_set_conn_cte_req_enable_with_too_long_requested_length, - cte_rx_param_setup, cte_rx_param_teardown)); + cte_rx_param_setup, cte_rx_param_teardown), + ztest_unit_test_setup_teardown(test_set_conn_cte_req_enable, cte_rx_param_setup, + cte_rx_param_teardown), + ztest_unit_test_setup_teardown(test_set_conn_cte_req_disable, cte_req_setup, + cte_req_teardown)); ztest_run_test_suite(test_hci_set_conn_cte_rx_params); /* TODO: Add tests cases that verify positive behavior of the function From 7022f0899d849ff23886c4da1c8466795be6b8cb Mon Sep 17 00:00:00 2001 From: Piotr Pryga Date: Mon, 31 Jan 2022 12:44:27 +0100 Subject: [PATCH 117/207] [nrf fromtree] Bluetooth: Controller: llcp: Fix failing UT for version exchange Test that verifies correct handling of Version exchanged procedure called twice on the same connection failed. The reason was wrong number of expected free procedure context objects. It was expected that there will be one context not released. That was wrong because the context is released just after the procedure completes in idle state. The second and following calls to the procedure do not start any PDU exchange, so the procedure ends immediately. Signed-off-by: Piotr Pryga (cherry picked from commit 1dd832fcc095d2bd26063db0a993a3a773c99de7) --- tests/bluetooth/controller/ctrl_version/src/main.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/bluetooth/controller/ctrl_version/src/main.c b/tests/bluetooth/controller/ctrl_version/src/main.c index 2925649cbbd..6aa488ef460 100644 --- a/tests/bluetooth/controller/ctrl_version/src/main.c +++ b/tests/bluetooth/controller/ctrl_version/src/main.c @@ -346,8 +346,10 @@ void test_version_exchange_mas_loc_twice(void) ut_rx_pdu(LL_VERSION_IND, &ntf, &remote_version_ind); ut_rx_q_is_empty(); - /* Note that one context buffer is not freed for this test */ - zassert_equal(ctx_buffers_free(), CONFIG_BT_CTLR_LLCP_PROC_CTX_BUF_NUM - 1, + /* Second attempt to run the version exchange completes immediately in idle state. + * The context is released just after that. + */ + zassert_equal(ctx_buffers_free(), CONFIG_BT_CTLR_LLCP_PROC_CTX_BUF_NUM, "Free CTX buffers %d", ctx_buffers_free()); } From 719c6e3df2f1554cbb7fc9b003a92016b789ce45 Mon Sep 17 00:00:00 2001 From: Piotr Pryga Date: Wed, 2 Feb 2022 22:59:58 +0100 Subject: [PATCH 118/207] [nrf fromtree] samples: Bluetooth: df: Remove dep on CTLR Kconf in sample sources Direction finding samples had dependency on KConfig option defined in Controller. That caused a problem for split builds where an application and host are not part of the same binary as controller. The code dependend on the Kconfig option was always disabled. To fix that issue new Kconfig options were introduced to Host. The dependency is removed. Unwanted features may stil be disabled and samples binaier will be smaller. The commit aligns all direction finding samples code. Signed-off-by: Piotr Pryga (cherry picked from commit fe827647dfb8ba2021c57368567379330cf3705f) --- .../direction_finding_central/src/main.c | 12 +++++----- .../src/main.c | 8 +++---- .../prj.conf | 1 + .../src/main.c | 8 +++---- .../direction_finding_peripheral/src/main.c | 8 +++---- subsys/bluetooth/host/Kconfig | 22 +++++++++++++++++++ 6 files changed, 41 insertions(+), 18 deletions(-) diff --git a/samples/bluetooth/direction_finding_central/src/main.c b/samples/bluetooth/direction_finding_central/src/main.c index 060b336ae7f..bae4b73f4cf 100644 --- a/samples/bluetooth/direction_finding_central/src/main.c +++ b/samples/bluetooth/direction_finding_central/src/main.c @@ -35,9 +35,9 @@ static struct bt_conn *default_conn; static const struct bt_le_conn_param conn_params = BT_LE_CONN_PARAM_INIT( BT_GAP_INIT_CONN_INT_MIN, BT_GAP_INIT_CONN_INT_MAX, CONN_LATENCY, CONN_TIMEOUT); -#if defined(CONFIG_BT_CTLR_DF_ANT_SWITCH_RX) +#if defined(CONFIG_BT_DF_CTE_RX_AOA) static const uint8_t ant_patterns[] = { 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA }; -#endif /* CONFIG_BT_CTLR_DF_ANT_SWITCH_RX */ +#endif /* CONFIG_BT_DF_CTE_RX_AOA */ static void start_scan(void); @@ -129,24 +129,24 @@ static void enable_cte_reqest(void) int err; const struct bt_df_conn_cte_rx_param cte_rx_params = { -#if defined(CONFIG_BT_CTLR_DF_ANT_SWITCH_RX) +#if defined(CONFIG_BT_DF_CTE_RX_AOA) .cte_types = BT_DF_CTE_TYPE_ALL, .slot_durations = 0x2, .num_ant_ids = ARRAY_SIZE(ant_patterns), .ant_ids = ant_patterns, #else .cte_types = BT_DF_CTE_TYPE_AOD_1US | BT_DF_CTE_TYPE_AOD_2US, -#endif /* CONFIG_BT_CTLR_DF_ANT_SWITCH_RX */ +#endif /* CONFIG_BT_DF_CTE_RX_AOA */ }; const struct bt_df_conn_cte_req_params cte_req_params = { .interval = CTE_REQ_INTERVAL, .cte_length = CTE_LEN, -#if defined(CONFIG_BT_CTLR_DF_ANT_SWITCH_RX) +#if defined(CONFIG_BT_DF_CTE_RX_AOA) .cte_type = BT_DF_CTE_TYPE_AOA, #else .cte_type = BT_DF_CTE_TYPE_AOD_2US, -#endif /* CONFIG_BT_CTLR_DF_ANT_SWITCH_TX */ +#endif /* CONFIG_BT_DF_CTE_RX_AOA */ }; printk("Enable receiving of CTE...\n"); diff --git a/samples/bluetooth/direction_finding_connectionless_rx/src/main.c b/samples/bluetooth/direction_finding_connectionless_rx/src/main.c index afd1973c758..8c5c50ca4ac 100644 --- a/samples/bluetooth/direction_finding_connectionless_rx/src/main.c +++ b/samples/bluetooth/direction_finding_connectionless_rx/src/main.c @@ -40,10 +40,10 @@ static K_SEM_DEFINE(sem_per_adv, 0, 1); static K_SEM_DEFINE(sem_per_sync, 0, 1); static K_SEM_DEFINE(sem_per_sync_lost, 0, 1); -#if defined(CONFIG_BT_CTLR_DF_ANT_SWITCH_RX) +#if defined(CONFIG_BT_DF_CTE_RX_AOA) const static uint8_t ant_patterns[] = { 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA }; -#endif /* CONFIG_BT_CTLR_DF_ANT_SWITCH_RX */ +#endif /* CONFIG_BT_DF_CTE_RX_AOA */ static bool data_cb(struct bt_data *data, void *user_data); static void create_sync(void); @@ -257,14 +257,14 @@ static void enable_cte_rx(void) const struct bt_df_per_adv_sync_cte_rx_param cte_rx_params = { .max_cte_count = 5, -#if defined(CONFIG_BT_CTLR_DF_ANT_SWITCH_RX) +#if defined(CONFIG_BT_DF_CTE_RX_AOA) .cte_types = BT_DF_CTE_TYPE_ALL, .slot_durations = 0x2, .num_ant_ids = ARRAY_SIZE(ant_patterns), .ant_ids = ant_patterns, #else .cte_types = BT_DF_CTE_TYPE_AOD_1US | BT_DF_CTE_TYPE_AOD_2US, -#endif /* CONFIG_BT_CTLR_DF_ANT_SWITCH_RX */ +#endif /* CONFIG_BT_DF_CTE_RX_AOA */ }; printk("Enable receiving of CTE...\n"); diff --git a/samples/bluetooth/direction_finding_connectionless_tx/prj.conf b/samples/bluetooth/direction_finding_connectionless_tx/prj.conf index a006af0993f..437ffbc4334 100644 --- a/samples/bluetooth/direction_finding_connectionless_tx/prj.conf +++ b/samples/bluetooth/direction_finding_connectionless_tx/prj.conf @@ -7,3 +7,4 @@ CONFIG_BT_BROADCASTER=y # Enable Direction Finding Feature including AoA and AoD CONFIG_BT_DF=y +CONFIG_BT_DF_CONNECTIONLESS_CTE_TX=y diff --git a/samples/bluetooth/direction_finding_connectionless_tx/src/main.c b/samples/bluetooth/direction_finding_connectionless_tx/src/main.c index 0f072d08834..5545c760afc 100644 --- a/samples/bluetooth/direction_finding_connectionless_tx/src/main.c +++ b/samples/bluetooth/direction_finding_connectionless_tx/src/main.c @@ -47,13 +47,13 @@ static struct bt_le_per_adv_param per_adv_param = { .options = BT_LE_ADV_OPT_USE_TX_POWER, }; -#if defined(CONFIG_BT_CTLR_DF_ANT_SWITCH_TX) +#if defined(CONFIG_BT_DF_CTE_TX_AOD) static uint8_t ant_patterns[] = {0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA }; -#endif /* CONFIG_BT_CTLR_DF_ANT_SWITCH_TX */ +#endif /* CONFIG_BT_DF_CTE_TX_AOD */ struct bt_df_adv_cte_tx_param cte_params = { .cte_len = CTE_LEN, .cte_count = PER_ADV_EVENT_CTE_COUNT, -#if defined(CONFIG_BT_CTLR_DF_ANT_SWITCH_TX) +#if defined(CONFIG_BT_DF_CTE_TX_AOD) .cte_type = BT_DF_CTE_TYPE_AOD_2US, .num_ant_ids = ARRAY_SIZE(ant_patterns), .ant_ids = ant_patterns @@ -61,7 +61,7 @@ struct bt_df_adv_cte_tx_param cte_params = { .cte_len = CTE_LEN, .cte_type = BT_DF_CTE_TYPE_AOA, .num_ant_ids = 0, .ant_ids = NULL -#endif /* CONFIG_BT_CTLR_DF_ANT_SWITCH_TX */ +#endif /* CONFIG_BT_DF_CTE_TX_AOD */ }; static void adv_sent_cb(struct bt_le_ext_adv *adv, diff --git a/samples/bluetooth/direction_finding_peripheral/src/main.c b/samples/bluetooth/direction_finding_peripheral/src/main.c index 8de8aa117d2..e28f9e53782 100644 --- a/samples/bluetooth/direction_finding_peripheral/src/main.c +++ b/samples/bluetooth/direction_finding_peripheral/src/main.c @@ -37,22 +37,22 @@ static const struct bt_data ad[] = { /* Length of CTE in unit of 8 us */ #define CTE_LEN (0x14U) -#if defined(CONFIG_BT_CTLR_DF_ANT_SWITCH_TX) +#if defined(CONFIG_BT_DF_CTE_TX_AOD) static const uint8_t ant_patterns[] = { 0x2, 0x0, 0x5, 0x6, 0x1, 0x4, 0xC, 0x9, 0xE, 0xD, 0x8 }; -#endif /* CONFIG_BT_CTLR_DF_ANT_SWITCH_TX */ +#endif /* CONFIG_BT_DF_CTE_TX_AOD */ static void enable_cte_response(struct bt_conn *conn) { int err; const struct bt_df_conn_cte_tx_param cte_tx_params = { -#if defined(CONFIG_BT_CTLR_DF_ANT_SWITCH_TX) +#if defined(CONFIG_BT_DF_CTE_TX_AOD) .cte_types = BT_DF_CTE_TYPE_ALL, .num_ant_ids = ARRAY_SIZE(ant_patterns), .ant_ids = ant_patterns, #else .cte_types = BT_DF_CTE_TYPE_AOA, -#endif /* CONFIG_BT_CTLR_DF_ANT_SWITCH_TX */ +#endif /* CONFIG_BT_DF_CTE_TX_AOD */ }; printk("Set CTE transmission params..."); diff --git a/subsys/bluetooth/host/Kconfig b/subsys/bluetooth/host/Kconfig index d9ba7824064..63048586b8d 100644 --- a/subsys/bluetooth/host/Kconfig +++ b/subsys/bluetooth/host/Kconfig @@ -565,6 +565,12 @@ config BT_DF_CONNECTIONLESS_CTE_RX Enable support for reception and sampling of Constant Tone Extension in connectionless mode. +config BT_DF_CONNECTIONLESS_CTE_TX + bool "Enable support for transmission of CTE in connectionless mode" + help + Enable support for transmission of Constant Tone Extension in + connectionless mode. + config BT_DF_CONNECTION_CTE_RX bool "Enable support for receive of CTE in connection mode" help @@ -591,6 +597,22 @@ config BT_DF_CONNECTION_CTE_RSP Enable support for request of Constant Tone Extension in connection mode. +config BT_DF_CTE_RX_AOA + bool "Enable antenna switching during CTE reception (AoA) feature" + depends on BT_DF_CONNECTIONLESS_CTE_RX || BT_DF_CONNECTION_CTE_RX + default y + help + Enable support for antenna switching during CTE reception. + Also known as Angle of Arrival mode. + +config BT_DF_CTE_TX_AOD + bool "Enable antenna switching during CTE transmission (AoD) feature" + depends on BT_DF_CONNECTIONLESS_CTE_TX || BT_DF_CONNECTION_CTE_TX + default y + help + Enable support for antenna switching during CTE transmission. + Also known as Angle of Departure mode. + config BT_DEBUG_DF bool "Bluetooth Direction Finding debug" help From 8274cb3a54b753ffaa8159de3891c9ce94ec05b1 Mon Sep 17 00:00:00 2001 From: Piotr Pryga Date: Wed, 2 Feb 2022 23:06:37 +0100 Subject: [PATCH 119/207] [nrf fromtree] Bluetooth: common: Kconfig: Extend EVT buf size to store IQ samples BT_BUF_EVT_RX_SIZE size by default was set to 68 bytes. In case of build with direction finding connected mode receiver enabled the size of event buffer was not enough to store all IQ samples. In such situation IQ samples reports were not delivered to Host. The commit changes default size of event RX buffer to 255 in case the BT_DF_CONNECTION_CTE_RX is enabled. Signed-off-by: Piotr Pryga (cherry picked from commit c673fccd250f2f7e35c83c9a86ab167a57452e60) --- subsys/bluetooth/common/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subsys/bluetooth/common/Kconfig b/subsys/bluetooth/common/Kconfig index 6e8a8b3f405..aaa9362ebe3 100644 --- a/subsys/bluetooth/common/Kconfig +++ b/subsys/bluetooth/common/Kconfig @@ -109,7 +109,7 @@ config BT_BUF_ACL_RX_COUNT config BT_BUF_EVT_RX_SIZE int "Maximum supported HCI Event buffer length" - default 255 if (BT_EXT_ADV && BT_OBSERVER) || BT_PER_ADV_SYNC + default 255 if (BT_EXT_ADV && BT_OBSERVER) || BT_PER_ADV_SYNC || BT_DF_CONNECTION_CTE_RX # LE Read Supported Commands command complete event. default 68 range 68 255 From 361c4d7bfa12b0db9ae5889016bb5175ac6d5406 Mon Sep 17 00:00:00 2001 From: Piotr Pryga Date: Wed, 2 Feb 2022 23:11:28 +0100 Subject: [PATCH 120/207] [nrf fromtree] Bluetooth: host: df: Fix wrong HCI cmd buf size for RX params sety In case the direction finding RX is enabled but without Angle of Arrival functionality enabled, there HCI command buffer had wrong command length assigned. It didn't take into account two dummy antenna IDs provided to fulfil requirement from BT 5.3 Core Vol 4, Part E sections: 7.7.82, 7.7.85. HCI driver when received such command buffer, didn't handle it due to wrong command length. The commit fixes the problem. Signed-off-by: Piotr Pryga (cherry picked from commit 54983eeedaac5228a43565284e9378ffa74245ca) --- subsys/bluetooth/host/direction.c | 104 ++++++++++++++++++------------ 1 file changed, 64 insertions(+), 40 deletions(-) diff --git a/subsys/bluetooth/host/direction.c b/subsys/bluetooth/host/direction.c index 89612d10c13..8bfcba36d29 100644 --- a/subsys/bluetooth/host/direction.c +++ b/subsys/bluetooth/host/direction.c @@ -53,8 +53,8 @@ static bool valid_cte_rx_common_params(uint8_t cte_types, uint8_t slot_durations #if defined(CONFIG_BT_DF_CONNECTIONLESS_CTE_RX) static bool valid_cl_cte_rx_params(const struct bt_df_per_adv_sync_cte_rx_param *params); -static void -prepare_cl_cte_rx_enable_cmd_params(struct net_buf *buf, struct bt_le_per_adv_sync *sync, +static int +prepare_cl_cte_rx_enable_cmd_params(struct net_buf **buf, struct bt_le_per_adv_sync *sync, const struct bt_df_per_adv_sync_cte_rx_param *params, bool enable); static int hci_df_set_cl_cte_rx_enable(struct bt_le_per_adv_sync *sync, bool enable, @@ -62,9 +62,9 @@ static int hci_df_set_cl_cte_rx_enable(struct bt_le_per_adv_sync *sync, bool ena #endif /* CONFIG_BT_DF_CONNECTIONLESS_CTE_RX */ #if defined(CONFIG_BT_DF_CONNECTION_CTE_RX) -static void prepare_conn_cte_rx_enable_cmd_params(struct net_buf *buf, struct bt_conn *conn, - const struct bt_df_conn_cte_rx_param *params, - bool enable); +static int prepare_conn_cte_rx_enable_cmd_params(struct net_buf **buf, struct bt_conn *conn, + const struct bt_df_conn_cte_rx_param *params, + bool enable); static int hci_df_set_conn_cte_rx_enable(struct bt_conn *conn, bool enable, const struct bt_df_conn_cte_rx_param *params); #endif /* CONFIG_BT_DF_CONNECTION_CTE_RX */ @@ -273,28 +273,44 @@ static bool valid_cl_cte_rx_params(const struct bt_df_per_adv_sync_cte_rx_param return true; } -static void -prepare_cl_cte_rx_enable_cmd_params(struct net_buf *buf, struct bt_le_per_adv_sync *sync, +static int +prepare_cl_cte_rx_enable_cmd_params(struct net_buf **buf, struct bt_le_per_adv_sync *sync, const struct bt_df_per_adv_sync_cte_rx_param *params, bool enable) { struct bt_hci_cp_le_set_cl_cte_sampling_enable *cp; - const uint8_t *ant_ids; + uint8_t switch_pattern_len; - cp = net_buf_add(buf, sizeof(*cp)); + if (params->cte_types & BT_DF_CTE_TYPE_AOA) { + switch_pattern_len = cp->switch_pattern_len; + } else { + switch_pattern_len = ARRAY_SIZE(df_dummy_switch_pattern); + } + + /* If CTE Rx is enabled, command parameters total length must include + * antenna ids, so command size if extended by num_and_ids. + */ + *buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_CL_CTE_SAMPLING_ENABLE, + (sizeof(struct bt_hci_cp_le_set_cl_cte_sampling_enable) + + (enable ? switch_pattern_len : 0))); + if (!(*buf)) { + return -ENOBUFS; + } + + cp = net_buf_add(*buf, sizeof(*cp)); (void)memset(cp, 0, sizeof(*cp)); cp->sync_handle = sys_cpu_to_le16(sync->handle); cp->sampling_enable = enable ? 1 : 0; if (enable) { + const uint8_t *ant_ids; uint8_t *dest_ant_ids; cp->max_sampled_cte = params->max_cte_count; if (params->cte_types & BT_DF_CTE_TYPE_AOA) { cp->slot_durations = params->slot_durations; - cp->switch_pattern_len = params->num_ant_ids; ant_ids = params->ant_ids; } else { /* Those values are put here due to constraints from HCI command @@ -303,13 +319,15 @@ prepare_cl_cte_rx_enable_cmd_params(struct net_buf *buf, struct bt_le_per_adv_sy * receive for AoD mode (e.g. device equipped with single antenna). */ cp->slot_durations = BT_HCI_LE_ANTENNA_SWITCHING_SLOT_2US; - cp->switch_pattern_len = ARRAY_SIZE(df_dummy_switch_pattern); ant_ids = &df_dummy_switch_pattern[0]; } - dest_ant_ids = net_buf_add(buf, params->num_ant_ids); + cp->switch_pattern_len = switch_pattern_len; + dest_ant_ids = net_buf_add(*buf, params->num_ant_ids); memcpy(dest_ant_ids, ant_ids, cp->switch_pattern_len); } + + return 0; } static int hci_df_set_cl_cte_rx_enable(struct bt_le_per_adv_sync *sync, bool enable, @@ -326,18 +344,11 @@ static int hci_df_set_cl_cte_rx_enable(struct bt_le_per_adv_sync *sync, bool ena } } - /* If CTE Rx is enabled, command parameters total length must include - * antenna ids, so command size if extended by num_and_ids. - */ - buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_CL_CTE_SAMPLING_ENABLE, - (sizeof(struct bt_hci_cp_le_set_cl_cte_sampling_enable) + - (enable ? params->num_ant_ids : 0))); - if (!buf) { - return -ENOBUFS; + err = prepare_cl_cte_rx_enable_cmd_params(&buf, sync, params, enable); + if (err) { + return err; } - prepare_cl_cte_rx_enable_cmd_params(buf, sync, params, enable); - bt_hci_cmd_state_set_init(buf, &state, sync->flags, BT_PER_ADV_SYNC_CTE_ENABLED, enable); err = bt_hci_cmd_send_sync(BT_HCI_OP_LE_SET_CL_CTE_SAMPLING_ENABLE, buf, &rsp); @@ -503,40 +514,60 @@ static int hci_df_set_conn_cte_tx_param(struct bt_conn *conn, #endif /* CONFIG_BT_DF_CONNECTION_CTE_TX */ #if defined(CONFIG_BT_DF_CONNECTION_CTE_RX) -static void prepare_conn_cte_rx_enable_cmd_params(struct net_buf *buf, struct bt_conn *conn, - const struct bt_df_conn_cte_rx_param *params, - bool enable) +static int prepare_conn_cte_rx_enable_cmd_params(struct net_buf **buf, struct bt_conn *conn, + const struct bt_df_conn_cte_rx_param *params, + bool enable) { struct bt_hci_cp_le_set_conn_cte_rx_params *cp; - const uint8_t *ant_ids; + uint8_t switch_pattern_len; - cp = net_buf_add(buf, sizeof(*cp)); + if (params->cte_types & BT_DF_CTE_TYPE_AOA) { + switch_pattern_len = cp->switch_pattern_len; + } else { + switch_pattern_len = ARRAY_SIZE(df_dummy_switch_pattern); + } + + /* If CTE Rx is enabled, command parameters total length must include + * antenna ids, so command size if extended by num_and_ids. + */ + *buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_CONN_CTE_RX_PARAMS, + (sizeof(struct bt_hci_cp_le_set_conn_cte_rx_params) + + (enable ? switch_pattern_len : 0))); + if (!(*buf)) { + return -ENOBUFS; + } + + cp = net_buf_add(*buf, sizeof(*cp)); (void)memset(cp, 0, sizeof(*cp)); cp->handle = sys_cpu_to_le16(conn->handle); cp->sampling_enable = enable ? 1 : 0; if (enable) { + const uint8_t *ant_ids; uint8_t *dest_ant_ids; if (params->cte_types & BT_DF_CTE_TYPE_AOA) { cp->slot_durations = params->slot_durations; - cp->switch_pattern_len = params->num_ant_ids; ant_ids = params->ant_ids; } else { /* Those values are put here due to constraints from HCI command * specification: Bluetooth Core Spec. 5.3 Vol 4,Part E, sec 7.8.85. * There is no right way to successfully send the command to enable CTE * receive for AoD mode (e.g. device equipped with single antenna). + * There is no CTE type in the parameters list, so controller is forced + * to check correctness of all parameters always. */ cp->slot_durations = BT_HCI_LE_ANTENNA_SWITCHING_SLOT_2US; - cp->switch_pattern_len = ARRAY_SIZE(df_dummy_switch_pattern); ant_ids = &df_dummy_switch_pattern[0]; } - dest_ant_ids = net_buf_add(buf, cp->switch_pattern_len); + cp->switch_pattern_len = switch_pattern_len; + dest_ant_ids = net_buf_add(*buf, cp->switch_pattern_len); (void)memcpy(dest_ant_ids, ant_ids, cp->switch_pattern_len); } + + return 0; } static int hci_df_set_conn_cte_rx_enable(struct bt_conn *conn, bool enable, @@ -554,18 +585,11 @@ static int hci_df_set_conn_cte_rx_enable(struct bt_conn *conn, bool enable, } } - /* If CTE Rx is enabled, command parameters total length must include - * antenna ids, so command size if extended by num_and_ids. - */ - buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_CONN_CTE_RX_PARAMS, - (sizeof(struct bt_hci_rp_le_set_conn_cte_rx_params) + - (enable ? params->num_ant_ids : 0))); - if (!buf) { - return -ENOBUFS; + err = prepare_conn_cte_rx_enable_cmd_params(&buf, conn, params, enable); + if (err) { + return err; } - prepare_conn_cte_rx_enable_cmd_params(buf, conn, params, enable); - bt_hci_cmd_state_set_init(buf, &state, conn->flags, BT_CONN_CTE_RX_ENABLED, enable); err = bt_hci_cmd_send_sync(BT_HCI_OP_LE_SET_CONN_CTE_RX_PARAMS, buf, &rsp); From 4f6ee30522e7b39d0eb739c2017e94ce715ba463 Mon Sep 17 00:00:00 2001 From: Piotr Pryga Date: Thu, 3 Feb 2022 00:04:52 +0100 Subject: [PATCH 121/207] [nrf fromtree] Bluetooth: Controller: Make PHY check in conn mode Kconf dependent Constant Tone Extension may not be transmittied with PHY CODED. There were check to avoid situation that controller tries to transmit or receive CTE when PHY is set to CODED. These check were not conditionally compilated, hence when PHY Update feature is disabled code did build. The commit fixes the issue. Signed-off-by: Piotr Pryga (cherry picked from commit f506d621bf49ec427cf437e64ce56227d73fcbd3) --- subsys/bluetooth/controller/hci/hci.c | 5 +++++ subsys/bluetooth/controller/ll_sw/nordic/lll/lll_conn.c | 6 ++++++ .../bluetooth/controller/ll_sw/nordic/lll/lll_peripheral.c | 4 ++++ 3 files changed, 15 insertions(+) diff --git a/subsys/bluetooth/controller/hci/hci.c b/subsys/bluetooth/controller/hci/hci.c index 4cad95c2bc1..0d6f40fec2b 100644 --- a/subsys/bluetooth/controller/hci/hci.c +++ b/subsys/bluetooth/controller/hci/hci.c @@ -2916,9 +2916,14 @@ static void le_df_connection_iq_report(struct node_rx_pdu *node_rx, struct net_b lll = iq_report->hdr.rx_ftr.param; +#if defined(CONFIG_BT_CTLR_PHY) phy_rx = lll->phy_rx; + /* Make sure the report is generated for connection on PHY UNCODED */ LL_ASSERT(phy_rx != PHY_CODED); +#else + phy_rx = PHY_1M; +#endif /* CONFIG_BT_CTLR_PHY */ /* TX LL thread has higher priority than RX thread. It may happen that host succefully * disables CTE sampling in the meantime. It should be verified here, to avoid reporing diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_conn.c b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_conn.c index 0435159cb73..3f9e68bdafd 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_conn.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_conn.c @@ -473,7 +473,11 @@ void lll_conn_isr_tx(void *param) enum radio_end_evt_delay_state end_evt_delay; #endif /* CONFIG_BT_CTLR_DF_PHYEND_OFFSET_COMPENSATION_ENABLE */ +#if defined(CONFIG_BT_CTLR_PHY) if (lll->phy_rx != PHY_CODED) { +#else + if (1) { +#endif /* CONFIG_BT_CTLR_PHY */ struct lll_df_conn_rx_params *df_rx_params; struct lll_df_conn_rx_cfg *df_rx_cfg; @@ -1011,9 +1015,11 @@ static inline bool create_iq_report(struct lll_conn *lll, uint8_t rssi_ready, ui struct lll_df_conn_rx_params *rx_params; struct lll_df_conn_rx_cfg *rx_cfg; +#if defined(CONFIG_BT_CTLR_PHY) if (lll->phy_rx == PHY_CODED) { return false; } +#endif /* CONFIG_BT_CTLR_PHY */ rx_cfg = &lll->df_rx_cfg; diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_peripheral.c b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_peripheral.c index 761bf1ed8c6..4c89cdf2d24 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_peripheral.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_peripheral.c @@ -218,7 +218,11 @@ static int prepare_cb(struct lll_prepare_param *p) enum radio_end_evt_delay_state end_evt_delay; #endif /* CONFIG_BT_CTLR_DF_PHYEND_OFFSET_COMPENSATION_ENABLE */ +#if defined(CONFIG_BT_CTLR_PHY) if (lll->phy_rx != PHY_CODED) { +#else + if (1) { +#endif /* CONFIG_BT_CTLR_PHY */ df_rx_cfg = &lll->df_rx_cfg; df_rx_params = dbuf_latest_get(&df_rx_cfg->hdr, NULL); From 669bfe79e5e51fccea766ea08f9187156ba9b4f7 Mon Sep 17 00:00:00 2001 From: Andries Kruithof Date: Tue, 25 Jan 2022 16:25:41 +0100 Subject: [PATCH 122/207] [nrf fromtree] Bluetooth: controller: llcp: update lll_scan_aux for new LLCP The lll_scan_aux.c file does not compile when the new LLCP is selected due to missing conditional compiles. Conditional compile and proper tx_times are selected with this commit Signed-off-by: Andries Kruithof (cherry picked from commit b554c9d2a91b4bd090d13239482ef1a94ad97bc8) --- .../bluetooth/controller/ll_sw/nordic/lll/lll_scan_aux.c | 9 +++++++++ 1 file changed, 9 insertions(+) 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 328f4000b8b..bbd7b862499 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 @@ -1420,12 +1420,21 @@ static void isr_rx_connect_rsp(void *param) struct lll_conn *conn_lll = lll->conn; #if defined(CONFIG_BT_CTLR_DATA_LENGTH) +#if defined(CONFIG_BT_LL_SW_LLCP_LEGACY) conn_lll->max_tx_time = MAX(conn_lll->max_tx_time, PDU_DC_MAX_US(PDU_DC_PAYLOAD_SIZE_MIN, lll_aux->phy)); conn_lll->max_rx_time = MAX(conn_lll->max_rx_time, PDU_DC_MAX_US(PDU_DC_PAYLOAD_SIZE_MIN, lll_aux->phy)); +#else + conn_lll->dle.eff.max_tx_time = MAX(conn_lll->dle.eff.max_tx_time, + PDU_DC_MAX_US(PDU_DC_PAYLOAD_SIZE_MIN, + lll_aux->phy)); + conn_lll->dle.eff.max_rx_time = MAX(conn_lll->dle.eff.max_rx_time, + PDU_DC_MAX_US(PDU_DC_PAYLOAD_SIZE_MIN, + lll_aux->phy)); +#endif /* CONFIG_BT_LL_SW_LLCP_LEGACY */ #endif /* CONFIG_BT_CTLR_DATA_LENGTH*/ conn_lll->phy_tx = lll_aux->phy; From e94b77f39fc6f86bd1e738a4ffd376387f5c887a Mon Sep 17 00:00:00 2001 From: Piotr Pryga Date: Thu, 3 Feb 2022 20:15:56 +0100 Subject: [PATCH 123/207] [nrf fromtree] Bluetooth: Controller: llcp: Add missing PDU initialization There was missing a PDU initialization. CP bit in data channel PDU heder was not cleared. Also cte_info byte was not crelader. That lead to malformed control procedures PDUs and issues with connection maintenance. Signed-off-by: Piotr Pryga (cherry picked from commit b15499f74907a21f4e279f8aaaaef58069f9d7aa) --- subsys/bluetooth/controller/ll_sw/ull_llcp.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/subsys/bluetooth/controller/ll_sw/ull_llcp.c b/subsys/bluetooth/controller/ll_sw/ull_llcp.c index 0a39d9b038f..71dbeb6e1ae 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_llcp.c +++ b/subsys/bluetooth/controller/ll_sw/ull_llcp.c @@ -188,10 +188,15 @@ void llcp_tx_alloc_unpeek(struct proc_ctx *ctx) struct node_tx *llcp_tx_alloc(struct ll_conn *conn, struct proc_ctx *ctx) { + struct pdu_data *pdu; struct node_tx *tx; ARG_UNUSED(conn); tx = (struct node_tx *)mem_acquire(&mem_tx.free); + + pdu = (struct pdu_data *)tx->pdu; + ull_pdu_data_init(pdu); + return tx; } #endif /* LLCP_TX_CTRL_BUF_QUEUE_ENABLE */ From fe07cce01f34ad61cd3206bbce285951d1dff910 Mon Sep 17 00:00:00 2001 From: Piotr Pryga Date: Thu, 3 Feb 2022 20:09:13 +0100 Subject: [PATCH 124/207] [nrf fromtree] Bluetooth: Controller: df: CP bit not cleared in DF conn mode RX In direction finding connected mode there is a CP bit that is set data PDU header. The bit was initialized only if CTE transmission was enabled. In case of reception of a CTE the bit was available in PDUs but not initialized. That caused issues in connection maintenance if PDU memory buffers were reused. PDU were malformed and connections were lost. Signed-off-by: Piotr Pryga (cherry picked from commit bef35638c8c812b3f5286c5df6067b2b3df64bec) --- .../controller/ll_sw/nordic/lll/lll_conn.c | 18 ++++++++++++++---- subsys/bluetooth/controller/ll_sw/ull_conn.c | 12 ++++++------ .../controller/ll_sw/ull_conn_internal.h | 2 +- 3 files changed, 21 insertions(+), 11 deletions(-) diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_conn.c b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_conn.c index 3f9e68bdafd..903a4b2e549 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_conn.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_conn.c @@ -727,10 +727,15 @@ void lll_conn_pdu_tx_prep(struct lll_conn *lll, struct pdu_data **pdu_data_tx) if (lll->packet_tx_head_offset) { p->ll_id = PDU_DATA_LLID_DATA_CONTINUE; -#if defined(CONFIG_BT_CTLR_DF_CONN_CTE_TX) +#if defined(CONFIG_BT_CTLR_DF_CONN_CTE_TX) || defined(CONFIG_BT_CTLR_DF_CONN_CTE_RX) + /* BT 5.3 Core Spec does not define handling of CP bit + * for PDUs fragmented by Controller, hence the CP bit + * is set to zero. The CTE should not be transmitted + * with CONTINUE PDUs if fragmentation is performed. + */ p->cp = 0U; p->resv = 0U; -#endif /* CONFIG_BT_CTLR_DF_CONN_CTE_TX */ +#endif /* CONFIG_BT_CTLR_DF_CONN_CTE_TX || CONFIG_BT_CTLR_DF_CONN_CTE_RX */ } p->len = lll->packet_tx_head_len - lll->packet_tx_head_offset; @@ -750,9 +755,9 @@ void lll_conn_pdu_tx_prep(struct lll_conn *lll, struct pdu_data **pdu_data_tx) p->rfu = 0U; #if !defined(CONFIG_BT_CTLR_DATA_LENGTH_CLEAR) -#if !defined(CONFIG_BT_CTLR_DF_CONN_CTE_TX) +#if !defined(CONFIG_BT_CTLR_DF_CONN_CTE_TX) && !defined(CONFIG_BT_CTLR_DF_CONN_CTE_RX) p->resv = 0U; -#endif /* !CONFIG_BT_CTLR_DF_CONN_CTE_TX */ +#endif /* !CONFIG_BT_CTLR_DF_CONN_CTE_TX && !CONFIG_BT_CTLR_DF_CONN_CTE_RX */ #endif /* CONFIG_BT_CTLR_DATA_LENGTH_CLEAR */ } @@ -1007,6 +1012,11 @@ static void empty_tx_init(void) p = (void *)radio_pkt_empty_get(); p->ll_id = PDU_DATA_LLID_DATA_CONTINUE; + + /* cp, rfu, and resv fields in the empty PDU buffer is statically + * zero initialized at power up and these values in this buffer are + * not modified at runtime. + */ } #if defined(CONFIG_BT_CTLR_DF_CONN_CTE_RX) diff --git a/subsys/bluetooth/controller/ll_sw/ull_conn.c b/subsys/bluetooth/controller/ll_sw/ull_conn.c index 1d55dcebc84..75b1858bf34 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_conn.c +++ b/subsys/bluetooth/controller/ll_sw/ull_conn.c @@ -2082,14 +2082,14 @@ uint16_t ull_conn_lll_max_tx_octets_get(struct lll_conn *lll) * Fields that are modified after static initialization are only * re-initialized. * - * @param pdu_tx Pointer to pdu_data object to be initialized + * @param pdu Pointer to pdu_data object to be initialized */ -void ull_pdu_data_init(struct pdu_data *pdu_tx) +void ull_pdu_data_init(struct pdu_data *pdu) { -#if defined(CONFIG_BT_CTLR_DF_CONN_CTE_TX) - pdu_tx->cp = 0U; - pdu_tx->resv = 0U; -#endif /* CONFIG_BT_CTLR_DF_CONN_CTE_TX */ +#if defined(CONFIG_BT_CTLR_DF_CONN_CTE_TX) || defined(CONFIG_BT_CTLR_DF_CONN_CTE_RX) + pdu->cp = 0U; + pdu->resv = 0U; +#endif /* CONFIG_BT_CTLR_DF_CONN_CTE_TX || CONFIG_BT_CTLR_DF_CONN_CTE_RX */ } static int init_reset(void) diff --git a/subsys/bluetooth/controller/ll_sw/ull_conn_internal.h b/subsys/bluetooth/controller/ll_sw/ull_conn_internal.h index 381a8e36768..a2def1b4246 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_conn_internal.h +++ b/subsys/bluetooth/controller/ll_sw/ull_conn_internal.h @@ -37,7 +37,7 @@ void *ull_conn_ack_dequeue(void); void ull_conn_tx_ack(uint16_t handle, memq_link_t *link, struct node_tx *tx); uint8_t ull_conn_llcp_req(void *conn); -void ull_pdu_data_init(struct pdu_data *pdu_tx); +void ull_pdu_data_init(struct pdu_data *pdu); #if !defined(CONFIG_BT_LL_SW_LLCP_LEGACY) From fa12b27ec19de995dbd756f15f75c154e1c62b08 Mon Sep 17 00:00:00 2001 From: Erik Brockhoff Date: Tue, 14 Dec 2021 11:40:51 +0100 Subject: [PATCH 125/207] [nrf fromtree] Bluetooth: controller: completing procedure pause handling Implementing the final parts of procedure pause mechanism This is needed to bar procedures from generating pdus during encryption procedure handling Signed-off-by: Erik Brockhoff wip (cherry picked from commit 015dc31a1b6c42d165445c11a1bdde1664ab6b95) --- .../controller/ll_sw/ull_llcp_chmu.c | 2 +- .../controller/ll_sw/ull_llcp_common.c | 2 +- .../controller/ll_sw/ull_llcp_conn_upd.c | 12 +++++----- .../bluetooth/controller/ll_sw/ull_llcp_enc.c | 20 ++++++++++++++++ .../controller/ll_sw/ull_llcp_internal.h | 4 ++++ .../controller/ll_sw/ull_llcp_local.c | 20 ++++++++++++++++ .../controller/ll_sw/ull_llcp_remote.c | 23 ++++++++++++++++++- 7 files changed, 74 insertions(+), 9 deletions(-) diff --git a/subsys/bluetooth/controller/ll_sw/ull_llcp_chmu.c b/subsys/bluetooth/controller/ll_sw/ull_llcp_chmu.c index f0955b0936b..50800caa980 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_llcp_chmu.c +++ b/subsys/bluetooth/controller/ll_sw/ull_llcp_chmu.c @@ -114,7 +114,7 @@ static void lp_chmu_complete(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t static void lp_chmu_send_channel_map_update_ind(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t evt, void *param) { - if (llcp_rr_get_collision(conn) || !llcp_tx_alloc_peek(conn, ctx)) { + if (ctx->pause || llcp_rr_get_collision(conn) || !llcp_tx_alloc_peek(conn, ctx)) { ctx->state = LP_CHMU_STATE_WAIT_TX_CHAN_MAP_IND; } else { llcp_rr_set_incompat(conn, INCOMPAT_RESOLVABLE); diff --git a/subsys/bluetooth/controller/ll_sw/ull_llcp_common.c b/subsys/bluetooth/controller/ll_sw/ull_llcp_common.c index ea1715e60a2..6a192a6bce7 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_llcp_common.c +++ b/subsys/bluetooth/controller/ll_sw/ull_llcp_common.c @@ -457,7 +457,7 @@ static void lp_comm_send_req(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t } break; case PROC_TERMINATE: - if (ctx->pause || !llcp_tx_alloc_peek(conn, ctx)) { + if (!llcp_tx_alloc_peek(conn, ctx)) { ctx->state = LP_COMMON_STATE_WAIT_TX; } else { lp_comm_tx(conn, ctx); diff --git a/subsys/bluetooth/controller/ll_sw/ull_llcp_conn_upd.c b/subsys/bluetooth/controller/ll_sw/ull_llcp_conn_upd.c index cb194bd92cf..7773d6cd958 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_llcp_conn_upd.c +++ b/subsys/bluetooth/controller/ll_sw/ull_llcp_conn_upd.c @@ -217,7 +217,7 @@ static void lp_cu_complete(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t e static void lp_cu_send_conn_param_req(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t evt, void *param) { - if (llcp_rr_get_collision(conn) || !llcp_tx_alloc_peek(conn, ctx)) { + if (ctx->pause || llcp_rr_get_collision(conn) || !llcp_tx_alloc_peek(conn, ctx)) { ctx->state = LP_CU_STATE_WAIT_TX_CONN_PARAM_REQ; } else { uint16_t event_counter = ull_conn_event_counter(conn); @@ -261,7 +261,7 @@ static void lp_cu_send_conn_param_req(struct ll_conn *conn, struct proc_ctx *ctx static void lp_cu_send_conn_update_ind(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t evt, void *param) { - if (!llcp_tx_alloc_peek(conn, ctx)) { + if (ctx->pause || !llcp_tx_alloc_peek(conn, ctx)) { ctx->state = LP_CU_STATE_WAIT_TX_CONN_UPDATE_IND; } else { ctx->data.cu.win_size = 1U; @@ -626,7 +626,7 @@ static void rp_cu_complete(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t e static void rp_cu_send_conn_update_ind(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t evt, void *param) { - if (!llcp_tx_alloc_peek(conn, ctx)) { + if (ctx->pause || !llcp_tx_alloc_peek(conn, ctx)) { ctx->state = RP_CU_STATE_WAIT_TX_CONN_UPDATE_IND; } else { ctx->data.cu.win_size = 1U; @@ -643,7 +643,7 @@ static void rp_cu_send_conn_update_ind(struct ll_conn *conn, struct proc_ctx *ct static void rp_cu_send_reject_ext_ind(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t evt, void *param) { - if (!llcp_tx_alloc_peek(conn, ctx)) { + if (ctx->pause || !llcp_tx_alloc_peek(conn, ctx)) { ctx->state = RP_CU_STATE_WAIT_TX_REJECT_EXT_IND; } else { rp_cu_tx(conn, ctx, PDU_DATA_LLCTRL_TYPE_REJECT_EXT_IND); @@ -655,7 +655,7 @@ static void rp_cu_send_reject_ext_ind(struct ll_conn *conn, struct proc_ctx *ctx static void rp_cu_send_conn_param_rsp(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t evt, void *param) { - if (!llcp_tx_alloc_peek(conn, ctx)) { + if (ctx->pause || !llcp_tx_alloc_peek(conn, ctx)) { ctx->state = RP_CU_STATE_WAIT_TX_CONN_PARAM_RSP; } else { rp_cu_tx(conn, ctx, PDU_DATA_LLCTRL_TYPE_CONN_PARAM_RSP); @@ -679,7 +679,7 @@ static void rp_cu_send_conn_param_req_ntf(struct ll_conn *conn, struct proc_ctx static void rp_cu_send_unknown_rsp(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t evt, void *param) { - if (!llcp_tx_alloc_peek(conn, ctx)) { + if (ctx->pause || !llcp_tx_alloc_peek(conn, ctx)) { ctx->state = RP_CU_STATE_WAIT_TX_UNKNOWN_RSP; } else { rp_cu_tx(conn, ctx, PDU_DATA_LLCTRL_TYPE_UNKNOWN_RSP); diff --git a/subsys/bluetooth/controller/ll_sw/ull_llcp_enc.c b/subsys/bluetooth/controller/ll_sw/ull_llcp_enc.c index bba4fea04a1..11fb731f218 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_llcp_enc.c +++ b/subsys/bluetooth/controller/ll_sw/ull_llcp_enc.c @@ -250,6 +250,10 @@ static void lp_enc_send_enc_req(struct ll_conn *conn, struct proc_ctx *ctx, uint /* Wait for the LL_ENC_RSP */ ctx->rx_opcode = PDU_DATA_LLCTRL_TYPE_ENC_RSP; ctx->state = LP_ENC_STATE_WAIT_RX_ENC_RSP; + + /* Pause possibly ongoing remote procedure */ + llcp_rr_pause(conn); + } } @@ -410,6 +414,9 @@ static void lp_enc_st_wait_rx_start_enc_req(struct ll_conn *conn, struct proc_ct ctx->data.enc.error = (pdu->llctrl.opcode == PDU_DATA_LLCTRL_TYPE_REJECT_IND) ? pdu->llctrl.reject_ind.error_code : pdu->llctrl.reject_ext_ind.error_code; + /* Resume possibly paused remote procedure */ + llcp_rr_resume(conn); + lp_enc_complete(conn, ctx, evt, param); break; default: @@ -441,6 +448,10 @@ static void lp_enc_st_wait_rx_start_enc_rsp(struct ll_conn *conn, struct proc_ct /* Resume Rx data */ ull_conn_resume_rx_data(conn); ctx->data.enc.error = BT_HCI_ERR_SUCCESS; + + /* Resume possibly paused remote procedure */ + llcp_rr_resume(conn); + lp_enc_complete(conn, ctx, evt, param); break; default: @@ -817,6 +828,8 @@ static void rp_enc_send_reject_ind(struct ll_conn *conn, struct proc_ctx *ctx, u llcp_tx_resume_data(conn); /* Resume Rx data */ ull_conn_resume_rx_data(conn); + /* Resume possibly paused local procedure */ + llcp_lr_resume(conn); } } @@ -835,6 +848,9 @@ static void rp_enc_send_start_enc_rsp(struct ll_conn *conn, struct proc_ctx *ctx /* Resume Rx data */ ull_conn_resume_rx_data(conn); + /* Resume possibly paused local procedure */ + llcp_lr_resume(conn); + /* Tx Encryption enabled */ conn->lll.enc_tx = 1U; } @@ -898,6 +914,10 @@ static void rp_enc_state_wait_rx_enc_req(struct ll_conn *conn, struct proc_ctx * llcp_tx_flush(conn); /* Pause Rx data */ ull_conn_pause_rx_data(conn); + + /* Pause possibly paused local procedure */ + llcp_lr_pause(conn); + rp_enc_store_m(conn, ctx, param); rp_enc_send_enc_rsp(conn, ctx, evt, param); break; diff --git a/subsys/bluetooth/controller/ll_sw/ull_llcp_internal.h b/subsys/bluetooth/controller/ll_sw/ull_llcp_internal.h index 0c1390f395e..cab97dcb05d 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_llcp_internal.h +++ b/subsys/bluetooth/controller/ll_sw/ull_llcp_internal.h @@ -431,6 +431,8 @@ void llcp_pdu_decode_terminate_ind(struct proc_ctx *ctx, struct pdu_data *pdu); * LLCP Local Request */ struct proc_ctx *llcp_lr_peek(struct ll_conn *conn); +void llcp_lr_pause(struct ll_conn *conn); +void llcp_lr_resume(struct ll_conn *conn); void llcp_lr_tx_ack(struct ll_conn *conn, struct proc_ctx *ctx, struct node_tx *tx); void llcp_lr_rx(struct ll_conn *conn, struct proc_ctx *ctx, struct node_rx_pdu *rx); void llcp_lr_enqueue(struct ll_conn *conn, struct proc_ctx *ctx); @@ -449,6 +451,8 @@ bool llcp_rr_get_collision(struct ll_conn *conn); void llcp_rr_set_paused_cmd(struct ll_conn *conn, enum llcp_proc); enum llcp_proc llcp_rr_get_paused_cmd(struct ll_conn *conn); struct proc_ctx *llcp_rr_peek(struct ll_conn *conn); +void llcp_rr_pause(struct ll_conn *conn); +void llcp_rr_resume(struct ll_conn *conn); void llcp_rr_tx_ack(struct ll_conn *conn, struct proc_ctx *ctx, struct node_tx *tx); void llcp_rr_rx(struct ll_conn *conn, struct proc_ctx *ctx, struct node_rx_pdu *rx); void llcp_rr_init(struct ll_conn *conn); diff --git a/subsys/bluetooth/controller/ll_sw/ull_llcp_local.c b/subsys/bluetooth/controller/ll_sw/ull_llcp_local.c index b9323e9ef69..2b0c012b217 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_llcp_local.c +++ b/subsys/bluetooth/controller/ll_sw/ull_llcp_local.c @@ -112,6 +112,26 @@ struct proc_ctx *llcp_lr_peek(struct ll_conn *conn) return ctx; } +void llcp_lr_pause(struct ll_conn *conn) +{ + struct proc_ctx *ctx; + + ctx = (struct proc_ctx *)sys_slist_peek_head(&conn->llcp.local.pend_proc_list); + if (ctx) { + ctx->pause = 1; + } +} + +void llcp_lr_resume(struct ll_conn *conn) +{ + struct proc_ctx *ctx; + + ctx = (struct proc_ctx *)sys_slist_peek_head(&conn->llcp.local.pend_proc_list); + if (ctx) { + ctx->pause = 0; + } +} + void llcp_lr_rx(struct ll_conn *conn, struct proc_ctx *ctx, struct node_rx_pdu *rx) { switch (ctx->proc) { diff --git a/subsys/bluetooth/controller/ll_sw/ull_llcp_remote.c b/subsys/bluetooth/controller/ll_sw/ull_llcp_remote.c index 802c5f19591..c6bbad40a84 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_llcp_remote.c +++ b/subsys/bluetooth/controller/ll_sw/ull_llcp_remote.c @@ -188,6 +188,27 @@ struct proc_ctx *llcp_rr_peek(struct ll_conn *conn) return ctx; } +void llcp_rr_pause(struct ll_conn *conn) +{ + struct proc_ctx *ctx; + + ctx = (struct proc_ctx *)sys_slist_peek_head(&conn->llcp.remote.pend_proc_list); + if (ctx) { + ctx->pause = 1; + } +} + +void llcp_rr_resume(struct ll_conn *conn) +{ + struct proc_ctx *ctx; + + ctx = (struct proc_ctx *)sys_slist_peek_head(&conn->llcp.remote.pend_proc_list); + if (ctx) { + ctx->pause = 0; + } +} + + void llcp_rr_rx(struct ll_conn *conn, struct proc_ctx *ctx, struct node_rx_pdu *rx) { switch (ctx->proc) { @@ -373,7 +394,7 @@ static void rr_act_reject(struct ll_conn *conn) LL_ASSERT(ctx != NULL); - if (!llcp_tx_alloc_peek(conn, ctx)) { + if (ctx->pause || !llcp_tx_alloc_peek(conn, ctx)) { rr_set_state(conn, RR_STATE_REJECT); } else { rr_tx(conn, ctx, PDU_DATA_LLCTRL_TYPE_REJECT_IND); From ab519fd15fd7f6cbb04790b0ef21ae2f1aa6489c Mon Sep 17 00:00:00 2001 From: Erik Brockhoff Date: Tue, 14 Dec 2021 11:42:12 +0100 Subject: [PATCH 126/207] [nrf fromtree] Bluetooth: controller: fixing up struct ll_conn for new LLCP Missing struct member added for non-legacy LLCP Signed-off-by: Erik Brockhoff (cherry picked from commit 14505030a9541e1f5804127b0dab447fff099274) --- subsys/bluetooth/controller/ll_sw/ull_conn_types.h | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/subsys/bluetooth/controller/ll_sw/ull_conn_types.h b/subsys/bluetooth/controller/ll_sw/ull_conn_types.h index fc028e7ebf8..1e7194ea56b 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_conn_types.h +++ b/subsys/bluetooth/controller/ll_sw/ull_conn_types.h @@ -478,8 +478,16 @@ struct ll_conn { * and/or needs to be properly integrated in the control procedures */ union { + struct { +#if defined(CONFIG_BT_CTLR_CONN_META) + uint8_t is_must_expire:1; +#endif /* CONFIG_BT_CTLR_CONN_META */ + } common; #if defined(CONFIG_BT_PERIPHERAL) struct { +#if defined(CONFIG_BT_CTLR_CONN_META) + uint8_t is_must_expire:1; +#endif /* CONFIG_BT_CTLR_CONN_META */ uint8_t latency_cancel:1; uint8_t sca:3; uint32_t force; @@ -489,6 +497,9 @@ struct ll_conn { #if defined(CONFIG_BT_CENTRAL) struct { +#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 08a41107599955e9676c2f2761fa2fce9595c841 Mon Sep 17 00:00:00 2001 From: Erik Brockhoff Date: Wed, 15 Dec 2021 08:33:50 +0100 Subject: [PATCH 127/207] [nrf fromtree] Bluetooth: controller: fixing up possible race in data tx pause/resume Turning the pause flag into a counter, to allow overlapping pause Signed-off-by: Erik Brockhoff (cherry picked from commit 9765e334ded91323d343294c6ead239226605a09) --- subsys/bluetooth/controller/ll_sw/ull_tx_queue.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/subsys/bluetooth/controller/ll_sw/ull_tx_queue.c b/subsys/bluetooth/controller/ll_sw/ull_tx_queue.c index 339771dd650..b0914e4382f 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_tx_queue.c +++ b/subsys/bluetooth/controller/ll_sw/ull_tx_queue.c @@ -15,15 +15,19 @@ void ull_tx_q_init(struct ull_tx_q *queue) void ull_tx_q_pause_data(struct ull_tx_q *queue) { - queue->pause_data = 1U; + queue->pause_data++; } void ull_tx_q_resume_data(struct ull_tx_q *queue) { - queue->pause_data = 0U; + if (queue->pause_data > 0) { + queue->pause_data--; + } - /* move all paused data to the tail of tx list */ - sys_slist_merge_slist(&queue->tx_list, &queue->data_list); + /* move all paused data to the tail of tx list, only if not empty and no longer paused */ + if (!queue->pause_data && !sys_slist_is_empty(&queue->data_list)) { + sys_slist_merge_slist(&queue->tx_list, &queue->data_list); + } } void ull_tx_q_enqueue_data(struct ull_tx_q *queue, struct node_tx *tx) From b00b636866ad50875be5327268f60ba2f54c3c72 Mon Sep 17 00:00:00 2001 From: Erik Brockhoff Date: Wed, 15 Dec 2021 09:30:02 +0100 Subject: [PATCH 128/207] [nrf fromtree] Bluetooth: controller: fixing up problem in collision handling Non-instant based procedures not properly handled, when instant based procedure is ongoing Signed-off-by: Erik Brockhoff (cherry picked from commit ba4920ee7db4d17593d66664ff72304a1873e7d1) --- subsys/bluetooth/controller/ll_sw/ull_llcp_remote.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subsys/bluetooth/controller/ll_sw/ull_llcp_remote.c b/subsys/bluetooth/controller/ll_sw/ull_llcp_remote.c index c6bbad40a84..927607ef9ac 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_llcp_remote.c +++ b/subsys/bluetooth/controller/ll_sw/ull_llcp_remote.c @@ -471,7 +471,7 @@ static void rr_st_idle(struct ll_conn *conn, uint8_t evt, void *param) /* Run remote procedure */ rr_act_run(conn); rr_set_state(conn, RR_STATE_TERMINATE); - } else if (incompat == INCOMPAT_NO_COLLISION) { + } else if (!with_instant || incompat == INCOMPAT_NO_COLLISION) { /* No collision * => Run procedure * From 58d1d9e95fdf9c27ef6b23dae8a8a54cf4d6424c Mon Sep 17 00:00:00 2001 From: Torsten Rasmussen Date: Fri, 7 Jan 2022 10:59:03 +0100 Subject: [PATCH 129/207] [nrf fromtree] cmake: remove base_name for dep file With CMake 3.20 relative path inside DEPFILEs are treated relative to CMAKE_CURRENT_BINARY_DIR and are transformed by CMake in its internal dep file. Therefore Zephyr build system must no longer add `base_name` to the `-MT` argument for the preprocessor. Signed-off-by: Torsten Rasmussen (cherry picked from commit 30d3d154ed5be34abf28eb9601131df45cb6ee13) --- cmake/linker/ld/target.cmake | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/cmake/linker/ld/target.cmake b/cmake/linker/ld/target.cmake index f29d4e6be78..a41e2d1744c 100644 --- a/cmake/linker/ld/target.cmake +++ b/cmake/linker/ld/target.cmake @@ -67,7 +67,6 @@ macro(configure_linker_script linker_script_gen linker_pass_define) endif() zephyr_get_include_directories_for_lang(C current_includes) - get_filename_component(base_name ${CMAKE_CURRENT_BINARY_DIR} NAME) get_property(current_defines GLOBAL PROPERTY PROPERTY_LINKER_SCRIPT_DEFINES) add_custom_command( @@ -81,7 +80,7 @@ macro(configure_linker_script linker_script_gen linker_pass_define) COMMAND ${CMAKE_C_COMPILER} -x assembler-with-cpp ${NOSYSDEF_CFLAG} - -MD -MF ${linker_script_gen}.dep -MT ${base_name}/${linker_script_gen} + -MD -MF ${linker_script_gen}.dep -MT ${linker_script_gen} -D_LINKER -D_ASMLANGUAGE -imacros ${AUTOCONF_H} From 2668dbdc2426dd90851c5ec5e63a420c42517738 Mon Sep 17 00:00:00 2001 From: Rubin Gerritsen Date: Wed, 9 Feb 2022 16:02:52 +0100 Subject: [PATCH 130/207] [nrf fromlist] Bluetooth: Host: Fix setting long advertising data Previously the data was set incorrectly when the data was set in multiple operations. It did not take the previous state into account. Ref: DRGN-16807 Upstream PR: https://github.com/zephyrproject-rtos/zephyr/pull/42639 Signed-off-by: Rubin Gerritsen (cherry picked from commit f21cb42b06a9151f43017faa0cdb217fdc08bef7) --- subsys/bluetooth/host/adv.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/subsys/bluetooth/host/adv.c b/subsys/bluetooth/host/adv.c index 8dcd6e8933a..ecd0de33716 100644 --- a/subsys/bluetooth/host/adv.c +++ b/subsys/bluetooth/host/adv.c @@ -134,7 +134,9 @@ static uint8_t ad_stream_read(struct ad_stream *stream, uint8_t *buf, uint8_t bu stream->current_ltv_offset++; read_len++; } else { - const size_t size_to_copy = MIN(buf_len, current_ltv->data_len); + const size_t remaining_data_len = + current_ltv->data_len - stream->current_ltv_offset + 2; + const size_t size_to_copy = MIN(buf_len - read_len, remaining_data_len); (void)memcpy(&buf[read_len], ¤t_ltv->data[stream->current_ltv_offset - 2], From 8be64241cf45c0529259dbe9b01acff90ac48f0b Mon Sep 17 00:00:00 2001 From: Piotr Golyzniak Date: Fri, 14 Jan 2022 16:36:01 +0100 Subject: [PATCH 131/207] [nrf fromlist] twister: add option to create shorter build paths Add possibility to create shorter build paths when --short-build-path option is enabled. This can help during run Twister on Windows OS and building programs by CMake which has a problem when paths with building files are too long. The solution based on symbolic links which help to connect "traditional" long paths with shorter one like: "twister_links/test_0". Upstream PR: https://github.com/zephyrproject-rtos/zephyr/pull/41930 Signed-off-by: Piotr Golyzniak (cherry picked from commit ee43917f19aadae60845528d541d08561f051dc0) --- scripts/pylib/twister/twisterlib.py | 45 +++++++++++++++++++++++++++++ scripts/twister | 12 ++++++++ 2 files changed, 57 insertions(+) diff --git a/scripts/pylib/twister/twisterlib.py b/scripts/pylib/twister/twisterlib.py index 359d73c1afe..eaef57399b4 100755 --- a/scripts/pylib/twister/twisterlib.py +++ b/scripts/pylib/twister/twisterlib.py @@ -2790,6 +2790,9 @@ def __init__(self, board_root_list=[], testcase_roots=[], outdir=None): # run integration tests only self.integration = False + # used during creating shorter build paths + self.link_dir_counter = 0 + self.pipeline = None self.version = "NA" @@ -3876,6 +3879,48 @@ def verify_platforms_existence(self, platform_names_to_verify, log_info=""): else: logger.error(f"{log_info} - unrecognized platform - {platform}") + def create_build_dir_links(self): + """ + Iterate through all no-skipped instances in suite and create links + for each one build directories. Those links will be passed in the next + steps to the CMake command. + """ + + links_dir_name = "twister_links" # folder for all links + links_dir_path = os.path.join(self.outdir, links_dir_name) + if not os.path.exists(links_dir_path): + os.mkdir(links_dir_path) + + for instance in self.instances.values(): + if instance.status != "skipped": + self._create_build_dir_link(links_dir_path, instance) + + def _create_build_dir_link(self, links_dir_path, instance): + """ + Create build directory with original "long" path. Next take shorter + path and link them with original path - create link. At the end + replace build_dir to created link. This link will be passed to CMake + command. This action helps to limit path length which can be + significant during building by CMake on Windows OS. + """ + + os.makedirs(instance.build_dir) + + link_name = f"test_{self.link_dir_counter}" + link_path = os.path.join(links_dir_path, link_name) + + if os.name == "nt": # if OS is Windows + command = ["mklink", "/J", f"{link_path}", f"{instance.build_dir}"] + subprocess.call(command, shell=True) + else: # for Linux and MAC OS + os.symlink(instance.build_dir, link_path) + + # Here symbolic link is replaced with original build directory. It will + # be passed to CMake command + instance.build_dir = link_path + + self.link_dir_counter += 1 + class CoverageTool: """ Base class for every supported coverage tool diff --git a/scripts/twister b/scripts/twister index d228abcfb7a..fd4808c2930 100755 --- a/scripts/twister +++ b/scripts/twister @@ -684,6 +684,15 @@ structure in the main Zephyr tree: boards///""") help="Execute time-consuming test cases that have been marked " "as 'slow' in testcase.yaml. Normally these are only built.") + parser.add_argument( + "--short-build-path", + action="store_true", + help="Create shorter build directory paths based on symbolic links. " + "The shortened build path will be used by CMake for generating " + "the build system and executing the build. Use this option if " + "you experience build failures related to path length, for " + "example on Windows OS.") + parser.add_argument( "--show-footprint", action="store_true", help="Show footprint statistics and deltas since last release." @@ -1236,6 +1245,9 @@ def main(): logger.info("Completed in %d seconds" % (duration)) return + if options.short_build_path: + suite.create_build_dir_links() + retries = options.retry_failed + 1 completed = 0 From 53c7fdba5a7fd7870c17ca8474ee32b58351e04b Mon Sep 17 00:00:00 2001 From: Krzysztof Chruscinski Date: Fri, 3 Dec 2021 10:47:24 +0100 Subject: [PATCH 132/207] [nrf fromtree] drivers: serial: nrfx_uarte: Add support for read only TX buffers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit UARTE does not support RO TX buffers. Added cache buffer to the driver which is used when provided buffer is not from RAM. Signed-off-by: Krzysztof Chruscinski (cherry picked from commit 2c044c8162ee3e3d9eaae5a0954089d013eb19fd) Signed-off-by: Andrzej Głąbek (cherry picked from commit 36939857cc78f80f7c6431e0e4d1d64cc3dfcc46) --- drivers/serial/Kconfig.nrfx | 10 +++ drivers/serial/uart_nrfx_uarte.c | 120 +++++++++++++++++++++++-------- 2 files changed, 99 insertions(+), 31 deletions(-) diff --git a/drivers/serial/Kconfig.nrfx b/drivers/serial/Kconfig.nrfx index 8b1965afb18..026a3d8541d 100644 --- a/drivers/serial/Kconfig.nrfx +++ b/drivers/serial/Kconfig.nrfx @@ -17,6 +17,16 @@ menuconfig UART_NRFX if UART_NRFX +config UART_ASYNC_TX_CACHE_SIZE + int "TX cache buffer size" + depends on UART_ASYNC_API + depends on NRF_UARTE_PERIPHERAL + default 8 + help + For UARTE, TX cache buffer is used when provided TX buffer is not located + in RAM, because EasyDMA in UARTE peripherals can only transfer data + from RAM. + # Workaround for not being able to have commas in macro arguments DT_COMPAT_NORDIC_NRF_UART := nordic,nrf-uart DT_COMPAT_NORDIC_NRF_UARTE := nordic,nrf-uarte diff --git a/drivers/serial/uart_nrfx_uarte.c b/drivers/serial/uart_nrfx_uarte.c index 1bb8378c4c9..256fd5b016f 100644 --- a/drivers/serial/uart_nrfx_uarte.c +++ b/drivers/serial/uart_nrfx_uarte.c @@ -74,7 +74,11 @@ struct uarte_async_cb { const uint8_t *tx_buf; volatile size_t tx_size; - uint8_t *pend_tx_buf; + const uint8_t *xfer_buf; + size_t xfer_len; + + uint8_t tx_cache[CONFIG_UART_ASYNC_TX_CACHE_SIZE]; + size_t tx_cache_offset; struct k_timer tx_timeout_timer; @@ -100,6 +104,7 @@ struct uarte_async_cb { uint8_t rx_flush_cnt; bool rx_enabled; bool hw_rx_counting; + bool pending_tx; /* Flag to ensure that RX timeout won't be executed during ENDRX ISR */ volatile bool is_in_irq; }; @@ -739,6 +744,44 @@ static int uarte_nrfx_init(const struct device *dev) return 0; } +/* Attempt to start TX (asynchronous transfer). If hardware is not ready, then pending + * flag is set. When current poll_out is completed, pending transfer is started. + * Function must be called with interrupts locked. + */ +static void start_tx_locked(const struct device *dev, struct uarte_nrfx_data *data) +{ + if (!is_tx_ready(dev)) { + /* Active poll out, postpone until it is completed. */ + data->async->pending_tx = true; + } else { + data->async->pending_tx = false; + data->async->tx_amount = -1; + tx_start(dev, data->async->xfer_buf, data->async->xfer_len); + } +} + +/* Setup cache buffer (used for sending data outside of RAM memory). + * During setup data is copied to cache buffer and transfer length is set. + * + * @return True if cache was set, false if no more data to put in cache. + */ +static bool setup_tx_cache(struct uarte_nrfx_data *data) +{ + size_t remaining = data->async->tx_size - data->async->tx_cache_offset; + + if (!remaining) { + return false; + } + + size_t len = MIN(remaining, sizeof(data->async->tx_cache)); + + data->async->xfer_len = len; + data->async->xfer_buf = data->async->tx_cache; + memcpy(data->async->tx_cache, &data->async->tx_buf[data->async->tx_cache_offset], len); + + return true; +} + static int uarte_nrfx_tx(const struct device *dev, const uint8_t *buf, size_t len, int32_t timeout) @@ -746,10 +789,6 @@ static int uarte_nrfx_tx(const struct device *dev, const uint8_t *buf, struct uarte_nrfx_data *data = get_dev_data(dev); NRF_UARTE_Type *uarte = get_uarte_instance(dev); - if (!nrfx_is_in_ram(buf)) { - return -ENOTSUP; - } - int key = irq_lock(); if (data->async->tx_size) { @@ -758,17 +797,19 @@ static int uarte_nrfx_tx(const struct device *dev, const uint8_t *buf, } data->async->tx_size = len; + data->async->tx_buf = buf; nrf_uarte_int_enable(uarte, NRF_UARTE_INT_TXSTOPPED_MASK); - if (!is_tx_ready(dev)) { - /* Active poll out, postpone until it is completed. */ - data->async->pend_tx_buf = (uint8_t *)buf; + if (nrfx_is_in_ram(buf)) { + data->async->xfer_buf = buf; + data->async->xfer_len = len; } else { - data->async->tx_buf = buf; - data->async->tx_amount = -1; - tx_start(dev, buf, len); + data->async->tx_cache_offset = 0; + (void)setup_tx_cache(data); } + start_tx_locked(dev, data); + irq_unlock(key); if (data->uart_config.flow_ctrl == UART_CFG_FLOW_CTRL_RTS_CTS @@ -787,6 +828,8 @@ static int uarte_nrfx_tx_abort(const struct device *dev) if (data->async->tx_buf == NULL) { return -EFAULT; } + + data->async->pending_tx = false; k_timer_stop(&data->async->tx_timeout_timer); nrf_uarte_task_trigger(uarte, NRF_UARTE_TASK_STOPTX); @@ -1317,35 +1360,50 @@ static void txstopped_isr(const struct device *dev) } if (!data->async->tx_buf) { - /* If there is a pending tx request, it means that uart_tx() - * was called when there was ongoing uart_poll_out. Handling - * TXSTOPPED interrupt means that uart_poll_out has completed. - */ - if (data->async->pend_tx_buf) { - key = irq_lock(); - - if (nrf_uarte_event_check(uarte, - NRF_UARTE_EVENT_TXSTOPPED)) { - data->async->tx_buf = data->async->pend_tx_buf; - data->async->pend_tx_buf = NULL; - data->async->tx_amount = -1; - tx_start(dev, data->async->tx_buf, - data->async->tx_size); - } - - irq_unlock(key); - } return; } - k_timer_stop(&data->async->tx_timeout_timer); - key = irq_lock(); size_t amount = (data->async->tx_amount >= 0) ? data->async->tx_amount : nrf_uarte_tx_amount_get(uarte); irq_unlock(key); + /* If there is a pending tx request, it means that uart_tx() + * was called when there was ongoing uart_poll_out. Handling + * TXSTOPPED interrupt means that uart_poll_out has completed. + */ + if (data->async->pending_tx) { + key = irq_lock(); + start_tx_locked(dev, data); + irq_unlock(key); + return; + } + + /* Cache buffer is used because tx_buf wasn't in RAM. */ + if (data->async->tx_buf != data->async->xfer_buf) { + /* In that case setup next chunk. If that was the last chunk + * fall back to reporting TX_DONE. + */ + if (amount == data->async->xfer_len) { + data->async->tx_cache_offset += amount; + if (setup_tx_cache(data)) { + key = irq_lock(); + start_tx_locked(dev, data); + irq_unlock(key); + return; + } + + /* Amount is already included in tx_cache_offset. */ + amount = data->async->tx_cache_offset; + } else { + /* TX was aborted, include tx_cache_offset in amount. */ + amount += data->async->tx_cache_offset; + } + } + + k_timer_stop(&data->async->tx_timeout_timer); + struct uart_event evt = { .data.tx.buf = data->async->tx_buf, .data.tx.len = amount, From f73a6f7e2060380d957a524d1038c62d7d732f48 Mon Sep 17 00:00:00 2001 From: Krzysztof Chruscinski Date: Thu, 2 Dec 2021 13:49:47 +0100 Subject: [PATCH 133/207] [nrf fromtree] tests: drivers: uart: Add test for Nordic UARTE version of the driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add configuration of the uart_async_api test to use uarte peripheral. Signed-off-by: Krzysztof Chruscinski (cherry picked from commit 9b22393b7e0384db9bcf4a4329e5d9f074d453eb) Signed-off-by: Andrzej Głąbek (cherry picked from commit fe8003b6e0d779ce18871f496e90375d339899ea) --- .../uart_async_api/boards/nrf52840dk_nrf52840.overlay | 2 +- .../uart/uart_async_api/boards/nrf9160dk_nrf9160.conf | 2 ++ tests/drivers/uart/uart_async_api/boards/nrf_uart.overlay | 5 +++++ tests/drivers/uart/uart_async_api/testcase.yaml | 8 ++++++++ 4 files changed, 16 insertions(+), 1 deletion(-) create mode 100644 tests/drivers/uart/uart_async_api/boards/nrf_uart.overlay diff --git a/tests/drivers/uart/uart_async_api/boards/nrf52840dk_nrf52840.overlay b/tests/drivers/uart/uart_async_api/boards/nrf52840dk_nrf52840.overlay index 6762dce267a..f9408f65f86 100644 --- a/tests/drivers/uart/uart_async_api/boards/nrf52840dk_nrf52840.overlay +++ b/tests/drivers/uart/uart_async_api/boards/nrf52840dk_nrf52840.overlay @@ -16,7 +16,7 @@ }; &uart0 { - compatible = "nordic,nrf-uart"; + compatible = "nordic,nrf-uarte"; current-speed = <115200>; status = "okay"; tx-pin = <33>; diff --git a/tests/drivers/uart/uart_async_api/boards/nrf9160dk_nrf9160.conf b/tests/drivers/uart/uart_async_api/boards/nrf9160dk_nrf9160.conf index b695c18ab28..3bf0d47364b 100644 --- a/tests/drivers/uart/uart_async_api/boards/nrf9160dk_nrf9160.conf +++ b/tests/drivers/uart/uart_async_api/boards/nrf9160dk_nrf9160.conf @@ -1 +1,3 @@ CONFIG_ARM_MPU=n +CONFIG_UART_1_NRF_HW_ASYNC=y +CONFIG_UART_1_NRF_HW_ASYNC_TIMER=2 diff --git a/tests/drivers/uart/uart_async_api/boards/nrf_uart.overlay b/tests/drivers/uart/uart_async_api/boards/nrf_uart.overlay new file mode 100644 index 00000000000..936a3ea2437 --- /dev/null +++ b/tests/drivers/uart/uart_async_api/boards/nrf_uart.overlay @@ -0,0 +1,5 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +&uart0 { + compatible = "nordic,nrf-uart"; +}; diff --git a/tests/drivers/uart/uart_async_api/testcase.yaml b/tests/drivers/uart/uart_async_api/testcase.yaml index feee2d965f4..d91a8c7086b 100644 --- a/tests/drivers/uart/uart_async_api/testcase.yaml +++ b/tests/drivers/uart/uart_async_api/testcase.yaml @@ -10,6 +10,14 @@ tests: harness: ztest harness_config: fixture: gpio_loopback + drivers.uart.uart_async_api.nrf_uart: + tags: drivers + filter: CONFIG_UART_CONSOLE and CONFIG_SERIAL_SUPPORT_ASYNC + harness: ztest + platform_allow: nrf52840dk_nrf52840 + harness_config: + fixture: gpio_loopback + extra_args: DTC_OVERLAY_FILE="boards/nrf52840dk_nrf52840.overlay;boards/nrf_uart.overlay" drivers.uart.uart_async_api.rtt: tags: drivers filter: CONFIG_UART_CONSOLE and CONFIG_SERIAL_SUPPORT_ASYNC and CONFIG_HAS_SEGGER_RTT From ef38cee06ec60186de0e5cc5d8092f8789c1c281 Mon Sep 17 00:00:00 2001 From: Krzysztof Chruscinski Date: Fri, 3 Dec 2021 10:59:05 +0100 Subject: [PATCH 134/207] [nrf fromtree] tests: drivers: uart: async_api: Test const buffers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Small modifications to use RO buffer in the test. Signed-off-by: Krzysztof Chruscinski (cherry picked from commit bdabf1eee9b35b988e0bfdd891f3c55cc203a102) Signed-off-by: Andrzej Głąbek (cherry picked from commit a062b87b07c3b7b148e627c4f04bed2f1860341a) --- tests/drivers/uart/uart_async_api/src/test_uart_async.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/drivers/uart/uart_async_api/src/test_uart_async.c b/tests/drivers/uart/uart_async_api/src/test_uart_async.c index 8e120370286..ad0564213fa 100644 --- a/tests/drivers/uart/uart_async_api/src/test_uart_async.c +++ b/tests/drivers/uart/uart_async_api/src/test_uart_async.c @@ -68,7 +68,9 @@ void test_single_read_setup(void) void test_single_read(void) { uint8_t rx_buf[10] = {0}; - uint8_t tx_buf[5] = "test"; + + /* Check also if sending from read only memory (e.g. flash) works. */ + static const uint8_t tx_buf[5] = "test"; zassert_not_equal(memcmp(tx_buf, rx_buf, 5), 0, "Initial buffer check failed"); From d8390658ee8b6d1106e0f183b1479f73037a12cf Mon Sep 17 00:00:00 2001 From: Krzysztof Chruscinski Date: Fri, 3 Dec 2021 11:08:41 +0100 Subject: [PATCH 135/207] [nrf fromtree] tests: drivers: uart: mix_poll: Test const buffers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Modifications to use RO buffer in the test. Added configuration which is using RO buffer for uart_tx. Signed-off-by: Krzysztof Chruscinski (cherry picked from commit 875ec0a0cb02d261f758adf2d0f6a01ca566b4df) Signed-off-by: Andrzej Głąbek (cherry picked from commit 2eb7368189f414dacdf8701e7705a67174c8272c) --- .../uart/uart_mix_fifo_poll/src/main.c | 61 ++++++++++++------- .../uart/uart_mix_fifo_poll/testcase.yaml | 14 +++++ 2 files changed, 52 insertions(+), 23 deletions(-) diff --git a/tests/drivers/uart/uart_mix_fifo_poll/src/main.c b/tests/drivers/uart/uart_mix_fifo_poll/src/main.c index 3cad674940f..20224fab244 100644 --- a/tests/drivers/uart/uart_mix_fifo_poll/src/main.c +++ b/tests/drivers/uart/uart_mix_fifo_poll/src/main.c @@ -36,16 +36,29 @@ struct rx_source { uint8_t prev; }; +#define BUF_SIZE 16 + +/* Buffer used for polling. */ +static uint8_t txbuf[3][BUF_SIZE]; + +/* Buffer used for async or interrupt driven apis. + * One of test configurations checks if RO buffer works with the driver. + */ +static IF_ENABLED(TEST_CONST_BUFFER, (const)) uint8_t txbuf3[16] = { + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f +}; + struct test_data { - uint8_t buf[16]; + const uint8_t *buf; volatile int cnt; int max; struct k_sem sem; }; static struct rx_source source[4]; -static struct test_data test_data[4]; -static struct test_data *int_async_data; +static struct test_data test_data[3]; +static struct test_data int_async_data; static const struct device *counter_dev; static const struct device *uart_dev; @@ -152,7 +165,7 @@ static void rx_isr(void) int len; do { - len = uart_fifo_read(uart_dev, buf, sizeof(buf)); + len = uart_fifo_read(uart_dev, buf, BUF_SIZE); for (int i = 0; i < len; i++) { process_byte(buf[i]); } @@ -161,10 +174,10 @@ static void rx_isr(void) static void tx_isr(void) { - uint8_t *buf = &int_async_data->buf[int_async_data->cnt & 0xF]; + const uint8_t *buf = &int_async_data.buf[int_async_data.cnt & 0xF]; int len = uart_fifo_fill(uart_dev, buf, 1); - int_async_data->cnt += len; + int_async_data.cnt += len; k_busy_wait(len ? 4 : 2); uart_irq_tx_disable(uart_dev); @@ -208,7 +221,7 @@ static void bulk_poll_out(struct test_data *data, int wait_base, int wait_range) for (int i = 0; i < data->max; i++) { data->cnt++; - uart_poll_out(uart_dev, data->buf[i % sizeof(data->buf)]); + uart_poll_out(uart_dev, data->buf[i % BUF_SIZE]); if (wait_base) { int r = sys_rand32_get(); @@ -240,15 +253,17 @@ static void int_async_thread_func(void *p_data, void *base, void *range) while (data->cnt < data->max) { if (async) { - uint8_t *buf; int err; err = k_sem_take(&async_tx_sem, K_MSEC(1000)); zassert_true(err >= 0, NULL); - buf = &int_async_data->buf[data->cnt & 0xF]; - data->cnt++; - err = uart_tx(uart_dev, buf, 1, 1000 * USEC_PER_MSEC); + int idx = data->cnt & 0xF; + size_t len = (idx < BUF_SIZE / 2) ? 5 : 1; /* Try various lengths */ + + data->cnt += len; + err = uart_tx(uart_dev, &int_async_data.buf[idx], + len, 1000 * USEC_PER_MSEC); zassert_true(err >= 0, "Unexpected err:%d", err); } else { @@ -267,7 +282,7 @@ static void poll_out_timer_handler(struct k_timer *timer) { struct test_data *data = k_timer_user_data_get(timer); - uart_poll_out(uart_dev, data->buf[data->cnt % sizeof(data->buf)]); + uart_poll_out(uart_dev, data->buf[data->cnt % BUF_SIZE]); data->cnt++; if (data->cnt == data->max) { @@ -288,10 +303,10 @@ static void init_buf(uint8_t *buf, int len, int idx) } } -static void init_test_data(struct test_data *data, int id, int repeat) +static void init_test_data(struct test_data *data, const uint8_t *buf, int repeat) { k_sem_init(&data->sem, 0, 1); - init_buf(data->buf, sizeof(data->buf), id); + data->buf = buf; data->cnt = 0; data->max = repeat; } @@ -303,7 +318,8 @@ static void test_mixed_uart_access(void) int num_of_contexts = ARRAY_SIZE(test_data); for (int i = 0; i < ARRAY_SIZE(test_data); i++) { - init_test_data(&test_data[i], i, repeat); + init_buf(txbuf[i], sizeof(txbuf[i]), i); + init_test_data(&test_data[i], txbuf[i], repeat); } (void)k_thread_create(&high_poll_out_thread, high_poll_out_thread_stack, 1024, @@ -312,15 +328,12 @@ static void test_mixed_uart_access(void) if (async || int_driven) { - int_async_data = &test_data[3]; + init_test_data(&int_async_data, txbuf3, repeat); (void)k_thread_create(&int_async_thread, int_async_thread_stack, 1024, int_async_thread_func, - int_async_data, (void *)300, (void *)400, + &int_async_data, (void *)300, (void *)400, 2, 0, K_NO_WAIT); - } else { - /* async/int driven context not used. */ - num_of_contexts--; } k_timer_user_data_set(&poll_out_timer, &test_data[1]); @@ -333,18 +346,20 @@ static void test_mixed_uart_access(void) for (int i = 0; i < num_of_contexts; i++) { err = k_sem_take(&test_data[i].sem, K_MSEC(10000)); zassert_equal(err, 0, NULL); + } + if (async || int_driven) { + err = k_sem_take(&int_async_data.sem, K_MSEC(10000)); + zassert_equal(err, 0, NULL); } k_msleep(10); - for (int i = 0; i < num_of_contexts; i++) { + for (int i = 0; i < (num_of_contexts + (async || int_driven ? 1 : 0)); i++) { zassert_equal(source[i].cnt, repeat, "%d: Unexpected rx bytes count (%d/%d)", i, source[i].cnt, repeat); - } - } void test_main(void) diff --git a/tests/drivers/uart/uart_mix_fifo_poll/testcase.yaml b/tests/drivers/uart/uart_mix_fifo_poll/testcase.yaml index 3114aaf0726..0ad912c7eda 100644 --- a/tests/drivers/uart/uart_mix_fifo_poll/testcase.yaml +++ b/tests/drivers/uart/uart_mix_fifo_poll/testcase.yaml @@ -31,6 +31,20 @@ tests: - CONFIG_NRFX_TIMER2=y - CONFIG_UART_0_ENHANCED_POLL_OUT=n + drivers.uart.uart_mix_poll_async_api_const: + tags: drivers + platform_allow: nrf52840dk_nrf52840 nrf9160dk_nrf9160 + extra_args: TEST_CONST_BUFFER=1 + extra_configs: + - CONFIG_UART_ASYNC_API=y + - CONFIG_UART_0_INTERRUPT_DRIVEN=n + - CONFIG_UART_0_ASYNC=y + - CONFIG_UART_0_NRF_HW_ASYNC=y + - CONFIG_UART_0_NRF_HW_ASYNC_TIMER=2 + - CONFIG_NRFX_TIMER2=y + - CONFIG_UART_0_ENHANCED_POLL_OUT=n + - CONFIG_UART_ASYNC_TX_CACHE_SIZE=2 + drivers.uart.uart_mix_poll_async_api_low_power: tags: drivers platform_allow: nrf52840dk_nrf52840 nrf9160dk_nrf9160 From 6573d984efb4781091a10b8b048539c71bc594b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20G=C5=82=C4=85bek?= Date: Thu, 3 Feb 2022 15:50:43 +0100 Subject: [PATCH 136/207] [nrf fromtree] drivers: uart_nrfx_uarte: Fix RX auto disabling routine MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is a follow-up to commit 11bbdb030def3b4a4b97ee380b1091913e61d371. When RX is automatically disabled because all provided RX buffers have been filled up, the rx_enabled flag needs to be cleared, otherwise it will be impossible to enable RX again. Signed-off-by: Andrzej Głąbek (cherry picked from commit c80589af5686c503ca9f6c58d883540a7b25b4ab) (cherry picked from commit 0fd07d7b7ffcf66f39117b1ec971b8754126dd09) --- drivers/serial/uart_nrfx_uarte.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/serial/uart_nrfx_uarte.c b/drivers/serial/uart_nrfx_uarte.c index 256fd5b016f..5910bac54b6 100644 --- a/drivers/serial/uart_nrfx_uarte.c +++ b/drivers/serial/uart_nrfx_uarte.c @@ -1333,7 +1333,16 @@ static void rxto_isr(const struct device *dev) notify_rx_buf_release(dev, &data->async->rx_buf, true); notify_rx_buf_release(dev, &data->async->rx_next_buf, true); - if (!data->async->rx_enabled) { + /* If the rx_enabled flag is still set at this point, it means that + * RX is being disabled because all provided RX buffers have been + * filled up. Clear the flag then, so that RX can be enabled again. + * + * If the flag is already cleared, it means that RX was aborted by + * a call to uart_rx_disable() and data from FIFO should be discarded. + */ + if (data->async->rx_enabled) { + data->async->rx_enabled = false; + } else { (void)rx_flush(dev, NULL, 0); } From eee5a549710018effd6287f9c5452c638c74045b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20G=C5=82=C4=85bek?= Date: Thu, 3 Feb 2022 15:51:36 +0100 Subject: [PATCH 137/207] [nrf fromtree] tests: uart_async_api: Add multiple_rx_enable test case MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a test case that ensures that uart_rx_enable() can be successfully called after RX is disabled with uart_rx_disable() and also when it is disabled automatically after the provided RX buffer is filled up. Signed-off-by: Andrzej Głąbek (cherry picked from commit 18fc88da50c9063da5075e40c03a2255df5c0159) (cherry picked from commit cc14952b4ab5bcb91d8eb21027fe4da20c697a8d) --- tests/drivers/uart/uart_async_api/src/main.c | 2 + .../uart/uart_async_api/src/test_uart.h | 2 + .../uart/uart_async_api/src/test_uart_async.c | 98 +++++++++++++++++++ 3 files changed, 102 insertions(+) diff --git a/tests/drivers/uart/uart_async_api/src/main.c b/tests/drivers/uart/uart_async_api/src/main.c index d09b75725f7..b1a4b3c6f62 100644 --- a/tests/drivers/uart/uart_async_api/src/main.c +++ b/tests/drivers/uart/uart_async_api/src/main.c @@ -24,6 +24,8 @@ void test_main(void) ztest_test_suite(uart_async_test, ztest_unit_test(test_single_read_setup), ztest_user_unit_test(test_single_read), + ztest_unit_test(test_multiple_rx_enable_setup), + ztest_user_unit_test(test_multiple_rx_enable), ztest_unit_test(test_chained_read_setup), ztest_user_unit_test(test_chained_read), ztest_unit_test(test_double_buffer_setup), diff --git a/tests/drivers/uart/uart_async_api/src/test_uart.h b/tests/drivers/uart/uart_async_api/src/test_uart.h index 5bb65ff1849..c534c5d5b71 100644 --- a/tests/drivers/uart/uart_async_api/src/test_uart.h +++ b/tests/drivers/uart/uart_async_api/src/test_uart.h @@ -54,6 +54,7 @@ void init_test(void); void test_single_read(void); +void test_multiple_rx_enable(void); void test_chained_read(void); void test_double_buffer(void); void test_read_abort(void); @@ -63,6 +64,7 @@ void test_long_buffers(void); void test_chained_write(void); void test_single_read_setup(void); +void test_multiple_rx_enable_setup(void); void test_chained_read_setup(void); void test_double_buffer_setup(void); void test_read_abort_setup(void); diff --git a/tests/drivers/uart/uart_async_api/src/test_uart_async.c b/tests/drivers/uart/uart_async_api/src/test_uart_async.c index ad0564213fa..7178de985e1 100644 --- a/tests/drivers/uart/uart_async_api/src/test_uart_async.c +++ b/tests/drivers/uart/uart_async_api/src/test_uart_async.c @@ -103,6 +103,104 @@ void test_single_read(void) zassert_equal(tx_aborted_count, 0, "TX aborted triggered"); } +void test_multiple_rx_enable_setup(void) +{ + tx_aborted_count = 0; + + /* Reuse the callback from the single_read test case, as this test case + * does not need anything extra in this regard. + */ + uart_callback_set(uart_dev, + test_single_read_callback, + (void *)&tx_aborted_count); + + k_sem_reset(&rx_rdy); + k_sem_reset(&rx_buf_released); + k_sem_reset(&rx_disabled); + k_sem_reset(&tx_done); +} + +void test_multiple_rx_enable(void) +{ + /* Check also if sending from read only memory (e.g. flash) works. */ + static const uint8_t tx_buf[] = "test"; + uint8_t rx_buf[sizeof(tx_buf)] = {0}; + int ret; + + /* Enable RX without a timeout. */ + ret = uart_rx_enable(uart_dev, rx_buf, sizeof(rx_buf), SYS_FOREVER_US); + zassert_equal(ret, 0, "uart_rx_enable failed"); + zassert_equal(k_sem_take(&rx_rdy, K_MSEC(100)), -EAGAIN, + "RX_RDY not expected at this point"); + zassert_equal(k_sem_take(&rx_disabled, K_MSEC(100)), -EAGAIN, + "RX_DISABLED not expected at this point"); + + /* Disable RX before any data has been received. */ + ret = uart_rx_disable(uart_dev); + zassert_equal(ret, 0, "uart_rx_disable failed"); + zassert_equal(k_sem_take(&rx_rdy, K_MSEC(100)), -EAGAIN, + "RX_RDY not expected at this point"); + zassert_equal(k_sem_take(&rx_buf_released, K_MSEC(100)), 0, + "RX_BUF_RELEASED timeout"); + zassert_equal(k_sem_take(&rx_disabled, K_MSEC(100)), 0, + "RX_DISABLED timeout"); + + k_sem_reset(&rx_buf_released); + k_sem_reset(&rx_disabled); + + /* Check that RX can be reenabled after "manual" disabling. */ + ret = uart_rx_enable(uart_dev, rx_buf, sizeof(rx_buf), + 50 * USEC_PER_MSEC); + zassert_equal(ret, 0, "uart_rx_enable failed"); + zassert_equal(k_sem_take(&rx_rdy, K_MSEC(100)), -EAGAIN, + "RX_RDY not expected at this point"); + + /* Send enough data to completely fill RX buffer, so that RX ends. */ + ret = uart_tx(uart_dev, tx_buf, sizeof(tx_buf), 100 * USEC_PER_MSEC); + zassert_equal(ret, 0, "uart_tx failed"); + zassert_equal(k_sem_take(&tx_done, K_MSEC(100)), 0, "TX_DONE timeout"); + zassert_equal(k_sem_take(&rx_rdy, K_MSEC(100)), 0, "RX_RDY timeout"); + zassert_equal(k_sem_take(&rx_rdy, K_MSEC(100)), -EAGAIN, + "Extra RX_RDY received"); + zassert_equal(k_sem_take(&rx_buf_released, K_MSEC(100)), 0, + "RX_BUF_RELEASED timeout"); + zassert_equal(k_sem_take(&rx_disabled, K_MSEC(100)), 0, + "RX_DISABLED timeout"); + zassert_equal(tx_aborted_count, 0, "Unexpected TX abort"); + + zassert_equal(memcmp(tx_buf, rx_buf, sizeof(tx_buf)), 0, + "Buffers not equal"); + + k_sem_reset(&rx_rdy); + k_sem_reset(&rx_buf_released); + k_sem_reset(&rx_disabled); + k_sem_reset(&tx_done); + memset(rx_buf, 0, sizeof(rx_buf)); + + /* Check that RX can be reenabled after automatic disabling. */ + ret = uart_rx_enable(uart_dev, rx_buf, sizeof(rx_buf), + 50 * USEC_PER_MSEC); + zassert_equal(ret, 0, "uart_rx_enable failed"); + zassert_equal(k_sem_take(&rx_rdy, K_MSEC(100)), -EAGAIN, + "RX_RDY not expected at this point"); + + /* Fill RX buffer again to confirm that RX still works properly. */ + ret = uart_tx(uart_dev, tx_buf, sizeof(tx_buf), 100 * USEC_PER_MSEC); + zassert_equal(ret, 0, "uart_tx failed"); + zassert_equal(k_sem_take(&tx_done, K_MSEC(100)), 0, "TX_DONE timeout"); + zassert_equal(k_sem_take(&rx_rdy, K_MSEC(100)), 0, "RX_RDY timeout"); + zassert_equal(k_sem_take(&rx_rdy, K_MSEC(100)), -EAGAIN, + "Extra RX_RDY received"); + zassert_equal(k_sem_take(&rx_buf_released, K_MSEC(100)), 0, + "RX_BUF_RELEASED timeout"); + zassert_equal(k_sem_take(&rx_disabled, K_MSEC(100)), 0, + "RX_DISABLED timeout"); + zassert_equal(tx_aborted_count, 0, "Unexpected TX abort"); + + zassert_equal(memcmp(tx_buf, rx_buf, sizeof(tx_buf)), 0, + "Buffers not equal"); +} + ZTEST_BMEM uint8_t chained_read_buf0[10]; ZTEST_BMEM uint8_t chained_read_buf1[20]; ZTEST_BMEM uint8_t chained_read_buf2[30]; From 1d69fbb9490dad7aa511387fdfef5fd70d0fade4 Mon Sep 17 00:00:00 2001 From: Jordan Yates Date: Mon, 31 Jan 2022 13:28:52 +1000 Subject: [PATCH 138/207] [nrf fromtree] spi: nrfx_spi*: only run uninit if configured MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Only run the `uninit` function if the SPI instance has previously been configured. This stops an assertion in the HAL drivers from triggering due to running `uninit` without a previous `init`. Fixes #42299. Signed-off-by: Jordan Yates (cherry picked from commit fdc25cd44c2b693aecff96d3dfcd0ee088d48d5b) Signed-off-by: Andrzej Głąbek (cherry picked from commit 99f5a809bd178c7c9bdd98b6bfc27be40619631b) --- drivers/spi/spi_nrfx_spi.c | 6 ++++-- drivers/spi/spi_nrfx_spim.c | 6 ++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/spi/spi_nrfx_spi.c b/drivers/spi/spi_nrfx_spi.c index a11ce60866a..597c1c5dd4f 100644 --- a/drivers/spi/spi_nrfx_spi.c +++ b/drivers/spi/spi_nrfx_spi.c @@ -294,8 +294,10 @@ static int spi_nrfx_pm_action(const struct device *dev, break; case PM_DEVICE_ACTION_SUSPEND: - nrfx_spi_uninit(&config->spi); - data->initialized = false; + if (data->initialized) { + nrfx_spi_uninit(&config->spim); + data->initialized = false; + } break; default: diff --git a/drivers/spi/spi_nrfx_spim.c b/drivers/spi/spi_nrfx_spim.c index e434d68f3eb..6f16515e515 100644 --- a/drivers/spi/spi_nrfx_spim.c +++ b/drivers/spi/spi_nrfx_spim.c @@ -453,8 +453,10 @@ static int spim_nrfx_pm_action(const struct device *dev, break; case PM_DEVICE_ACTION_SUSPEND: - nrfx_spim_uninit(&config->spim); - data->initialized = false; + if (data->initialized) { + nrfx_spim_uninit(&config->spim); + data->initialized = false; + } break; default: From fefd14fe6829a3159416b0807b68bde831980328 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20G=C5=82=C4=85bek?= Date: Tue, 8 Feb 2022 11:52:25 +0100 Subject: [PATCH 139/207] [nrf fromtree] drivers: spi_nrfx_spi: Fix compilation error MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix a copy/paste mistake introduced by commit fdc25cd44c2b693aecff96d3dfcd0ee088d48d5b. Signed-off-by: Andrzej Głąbek (cherry picked from commit 9b9de620469956e40a8dc52ad785a5ec9cd75900) (cherry picked from commit 199d339e98f91cd44f038bf4eb81e41e1d5ccac5) --- drivers/spi/spi_nrfx_spi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/spi/spi_nrfx_spi.c b/drivers/spi/spi_nrfx_spi.c index 597c1c5dd4f..b24456ca6eb 100644 --- a/drivers/spi/spi_nrfx_spi.c +++ b/drivers/spi/spi_nrfx_spi.c @@ -295,7 +295,7 @@ static int spi_nrfx_pm_action(const struct device *dev, case PM_DEVICE_ACTION_SUSPEND: if (data->initialized) { - nrfx_spi_uninit(&config->spim); + nrfx_spi_uninit(&config->spi); data->initialized = false; } break; From 66d6913fb49c9f91c31c23765c869ebb62b28061 Mon Sep 17 00:00:00 2001 From: Morten Priess Date: Wed, 19 May 2021 14:01:57 +0200 Subject: [PATCH 140/207] [nrf fromtree] Bluetooth: controller: Support for separate ISO RX data path Provides interface, data structures and demuxing capability for ISO RX PDU allocation and transport from LLL to HCI. Uses the RXFIFO composite for simplicity and reduced overhead. Signed-off-by: Morten Priess (cherry picked from commit 7c89f1fe9f2ed89b666dd9f7df0b95f94c7849be) (cherry picked from commit 8917a60c297ddfe5f3c1ed79876bbc125f7e0071) --- subsys/bluetooth/controller/Kconfig | 18 ++ subsys/bluetooth/controller/hci/hci_driver.c | 48 +++- subsys/bluetooth/controller/include/ll.h | 1 + subsys/bluetooth/controller/ll_sw/lll.h | 12 +- .../ll_sw/nordic/lll/lll_sync_iso.c | 14 +- subsys/bluetooth/controller/ll_sw/ull.c | 42 ---- subsys/bluetooth/controller/ll_sw/ull_iso.c | 225 ++++++++++++++++++ .../controller/ll_sw/ull_iso_internal.h | 3 + .../bsim_bt/bsim_test_iso/src/main.c | 2 +- 9 files changed, 306 insertions(+), 59 deletions(-) diff --git a/subsys/bluetooth/controller/Kconfig b/subsys/bluetooth/controller/Kconfig index 1c6d947237d..51568a3591f 100644 --- a/subsys/bluetooth/controller/Kconfig +++ b/subsys/bluetooth/controller/Kconfig @@ -199,6 +199,20 @@ config BT_CTLR_RX_BUFFERS connection interval and 2M PHY, maximum 18 packets with L2CAP payload size of 1 byte can be received. +config BT_CTLR_ISO_RX_BUFFERS + int "Number of Isochronous Rx buffers" + depends on BT_CTLR_SYNC_ISO || BT_CTLR_CONN_ISO + default 8 + range 1 30 + help + Set the number of Isochronous Rx PDUs to be buffered in the + controller. Number of required RX buffers would worst-case be + the number of RX nodes prepared in one ISO event for each + active ISO group. This depends on the number of bursts in an + ISO group and number of groups, and may need to be set lower + that the theoretical maximum. Default of 8 is for supporting + two groups of 4 payloads, e.g. 2 CIGs with 2 CISes of BN=2. + config BT_CTLR_ISO_TX_BUFFERS int "Number of Isochronous Tx buffers" depends on BT_CTLR_ADV_ISO || BT_CTLR_CONN_ISO @@ -217,6 +231,10 @@ 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_ISO_VENDOR_DATA_PATH + bool "Enable vendor-specific ISO data path" + depends on BT_CTLR_SYNC_ISO || BT_CTLR_CONN_ISO + choice BT_CTLR_TX_PWR prompt "Tx Power" default BT_CTLR_TX_PWR_0 diff --git a/subsys/bluetooth/controller/hci/hci_driver.c b/subsys/bluetooth/controller/hci/hci_driver.c index 149ba8515af..c252234f9c4 100644 --- a/subsys/bluetooth/controller/hci/hci_driver.c +++ b/subsys/bluetooth/controller/hci/hci_driver.c @@ -49,7 +49,6 @@ #include "ll_sw/lll_sync_iso.h" #include "ll_sw/lll_conn.h" #include "ll_sw/lll_conn_iso.h" - #include "ll_sw/isoal.h" #include "ll_sw/ull_iso_types.h" @@ -229,9 +228,30 @@ static void prio_recv_thread(void *p1, void *p2, void *p3) while (1) { struct node_rx_pdu *node_rx; struct net_buf *buf; + bool iso_received; uint8_t num_cmplt; uint16_t handle; + iso_received = false; + +#if defined(CONFIG_BT_CTLR_ISO) + node_rx = ll_iso_rx_get(); + if (node_rx) { + ll_iso_rx_dequeue(); + + /* Find out and store the class for this node */ + node_rx->hdr.user_meta = hci_get_class(node_rx); + + /* Send the rx node up to Host thread, + * recv_thread() + */ + BT_DBG("ISO RX node enqueue"); + k_fifo_put(&recv_fifo, node_rx); + + iso_received = true; + } +#endif /* CONFIG_BT_CTLR_ISO */ + /* While there are completed rx nodes */ while ((num_cmplt = ll_rx_get((void *)&node_rx, &handle))) { #if defined(CONFIG_BT_CONN) @@ -280,13 +300,14 @@ static void prio_recv_thread(void *p1, void *p2, void *p3) BT_DBG("RX node enqueue"); k_fifo_put(&recv_fifo, node_rx); } + } + if (iso_received || node_rx) { /* There may still be completed nodes, continue * pushing all those up to Host before waiting * for ULL mayfly */ continue; - } BT_DBG("sem take..."); @@ -364,13 +385,24 @@ static inline struct net_buf *encode_node(struct node_rx_pdu *node_rx, isoal_status_t err; stream = ull_sync_iso_stream_get(node_rx->hdr.handle); - isoal_rx.meta = &node_rx->hdr.rx_iso_meta; - isoal_rx.pdu = (void *)node_rx->pdu; - err = isoal_rx_pdu_recombine(stream->dp->sink_hdl, &isoal_rx); - LL_ASSERT(err == ISOAL_STATUS_OK || - err == ISOAL_STATUS_ERR_SDU_ALLOC); + + /* Check validity of the data path sink. FIXME: A channel disconnect race + * may cause ISO data pending with without valid data path. + */ + if (stream && stream->dp && stream->dp->sink_hdl) { + isoal_rx.meta = &node_rx->hdr.rx_iso_meta; + isoal_rx.pdu = (void *)node_rx->pdu; + err = isoal_rx_pdu_recombine(stream->dp->sink_hdl, &isoal_rx); + + LL_ASSERT(err == ISOAL_STATUS_OK || + err == ISOAL_STATUS_ERR_SDU_ALLOC); + } #endif /* CONFIG_BT_CTLR_SYNC_ISO */ - break; + + node_rx->hdr.next = NULL; + ll_iso_rx_mem_release((void **)&node_rx); + + return buf; } #endif /* CONFIG_BT_CTLR_ISO */ diff --git a/subsys/bluetooth/controller/include/ll.h b/subsys/bluetooth/controller/include/ll.h index fa69bf70907..d31e050c200 100644 --- a/subsys/bluetooth/controller/include/ll.h +++ b/subsys/bluetooth/controller/include/ll.h @@ -330,6 +330,7 @@ int ll_tx_mem_enqueue(uint16_t handle, void *node_tx); uint8_t ll_rx_get(void **node_rx, uint16_t *handle); void ll_rx_dequeue(void); void ll_rx_mem_release(void **node_rx); +void ll_iso_rx_mem_release(void **node_rx); /* Downstream - ISO Data */ void *ll_iso_tx_mem_acquire(void); diff --git a/subsys/bluetooth/controller/ll_sw/lll.h b/subsys/bluetooth/controller/ll_sw/lll.h index 77c660664c2..fc50cc4f532 100644 --- a/subsys/bluetooth/controller/ll_sw/lll.h +++ b/subsys/bluetooth/controller/ll_sw/lll.h @@ -498,6 +498,15 @@ static inline void lll_hdr_init(void *lll, void *parent) #endif /* CONFIG_BT_CTLR_JIT_SCHEDULING */ } +/* If ISO vendor data path is not used, queue directly to ll_iso_rx */ +#if defined(CONFIG_BT_CTLR_ISO_VENDOR_DATA_PATH) +#define iso_rx_put(link, rx) ull_iso_rx_put(link, rx) +#define iso_rx_sched() ull_iso_rx_sched() +#else +#define iso_rx_put(link, rx) ll_iso_rx_put(link, rx) +#define iso_rx_sched() ll_rx_sched() +#endif /* CONFIG_BT_CTLR_ISO_VENDOR_DATA_PATH */ + void lll_done_score(void *param, uint8_t result); int lll_init(void); @@ -529,12 +538,13 @@ void *ull_pdu_rx_alloc_peek(uint8_t count); void *ull_pdu_rx_alloc_peek_iter(uint8_t *idx); void *ull_pdu_rx_alloc(void); void *ull_iso_pdu_rx_alloc_peek(uint8_t count); -void *ull_iso_pdu_rx_alloc_peek_iter(uint8_t *idx); void *ull_iso_pdu_rx_alloc(void); void ull_rx_put(memq_link_t *link, void *rx); void ull_rx_put_done(memq_link_t *link, void *done); void ull_rx_sched(void); void ull_rx_sched_done(void); +void ull_iso_rx_put(memq_link_t *link, void *rx); +void ull_iso_rx_sched(void); struct event_done_extra *ull_event_done_extra_get(void); struct event_done_extra *ull_done_extra_type_set(uint8_t type); void *ull_event_done(void *param); 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 8ae4c7fc000..db259789603 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 @@ -263,7 +263,7 @@ static int prepare_cb_common(struct lll_prepare_param *p) radio_crc_configure(PDU_CRC_POLYNOMIAL, sys_get_le24(crc_init)); lll_chan_set(data_chan_use); - node_rx = ull_pdu_rx_alloc_peek(1U); + node_rx = ull_iso_pdu_rx_alloc_peek(1U); LL_ASSERT(node_rx); radio_pkt_rx_set(node_rx->pdu); @@ -437,7 +437,7 @@ static void isr_rx(void *param) lll->ctrl) { lll->cssn_curr = lll->cssn_next; - node_rx = ull_pdu_rx_alloc_peek(1U); + node_rx = ull_iso_pdu_rx_alloc_peek(1U); LL_ASSERT(node_rx); pdu = (void *)node_rx->pdu; @@ -455,7 +455,7 @@ static void isr_rx(void *param) } } } else { - node_rx = ull_pdu_rx_alloc_peek(3U); + node_rx = ull_iso_pdu_rx_alloc_peek(3U); if (!node_rx) { goto isr_rx_done; } @@ -480,7 +480,7 @@ static void isr_rx(void *param) (payload_index < lll->payload_head))) { struct node_rx_iso_meta *iso_meta; - ull_pdu_rx_alloc(); + ull_iso_pdu_rx_alloc(); node_rx->hdr.type = NODE_RX_TYPE_ISO_PDU; node_rx->hdr.handle = lll->stream_handle[bis_idx]; @@ -601,7 +601,7 @@ static void isr_rx(void *param) node_rx = lll->payload[bis_idx][payload_tail]; lll->payload[bis_idx][payload_tail] = NULL; - ull_rx_put(node_rx->hdr.link, node_rx); + iso_rx_put(node_rx->hdr.link, node_rx); } payload_index = payload_tail + 1U; @@ -615,7 +615,7 @@ static void isr_rx(void *param) #if !defined(CONFIG_BT_CTLR_LOW_LAT_ULL) if (node_rx) { - ull_rx_sched(); + iso_rx_sched(); } #endif /* CONFIG_BT_CTLR_LOW_LAT_ULL */ @@ -681,7 +681,7 @@ static void isr_rx(void *param) } lll_chan_set(data_chan_use); - node_rx = ull_pdu_rx_alloc_peek(1U); + node_rx = ull_iso_pdu_rx_alloc_peek(1U); LL_ASSERT(node_rx); radio_pkt_rx_set(node_rx->pdu); diff --git a/subsys/bluetooth/controller/ll_sw/ull.c b/subsys/bluetooth/controller/ll_sw/ull.c index c76a4ab1890..032a9ec8acd 100644 --- a/subsys/bluetooth/controller/ll_sw/ull.c +++ b/subsys/bluetooth/controller/ll_sw/ull.c @@ -1204,10 +1204,6 @@ void ll_rx_dequeue(void) case NODE_RX_TYPE_CIS_ESTABLISHED: #endif /* CONFIG_BT_CTLR_CONN_ISO */ -#if defined(CONFIG_BT_CTLR_ISO) - case NODE_RX_TYPE_ISO_PDU: -#endif - #if defined(CONFIG_BT_CTLR_DF_SCAN_CTE_RX) case NODE_RX_TYPE_SYNC_IQ_SAMPLE_REPORT: #endif /* CONFIG_BT_CTLR_DF_SCAN_CTE_RX */ @@ -2545,44 +2541,6 @@ static inline int rx_demux_rx(memq_link_t *link, struct node_rx_hdr *rx) * CONFIG_BT_CONN */ -#if defined(CONFIG_BT_CTLR_ISO) - case NODE_RX_TYPE_ISO_PDU: - { - /* Remove from receive-queue; ULL has received this now */ - (void)memq_dequeue(memq_ull_rx.tail, &memq_ull_rx.head, NULL); - -#if defined(CONFIG_BT_CTLR_CONN_ISO) - struct node_rx_pdu *rx_pdu = (struct node_rx_pdu *)rx; - struct ll_conn_iso_stream *cis = - ll_conn_iso_stream_get(rx_pdu->hdr.handle); - struct ll_iso_datapath *dp = cis->hdr.datapath_out; - isoal_sink_handle_t sink = dp->sink_hdl; - - if (dp->path_id != BT_HCI_DATAPATH_ID_HCI) { - /* If vendor specific datapath pass to ISO AL here, - * in case of HCI destination it will be passed in - * HCI context. - */ - struct isoal_pdu_rx pckt_meta = { - .meta = &rx_pdu->hdr.rx_iso_meta, - .pdu = (struct pdu_iso *) &rx_pdu->pdu[0] - }; - - /* Pass the ISO PDU through ISO-AL */ - isoal_status_t err = - isoal_rx_pdu_recombine(sink, &pckt_meta); - - LL_ASSERT(err == ISOAL_STATUS_OK); /* TODO handle err */ - } -#endif - - /* Let ISO PDU start its long journey upwards */ - ll_rx_put(link, rx); - ll_rx_sched(); - } - break; -#endif - default: { #if defined(CONFIG_BT_CTLR_USER_EXT) diff --git a/subsys/bluetooth/controller/ll_sw/ull_iso.c b/subsys/bluetooth/controller/ll_sw/ull_iso.c index 1a2aa1bc617..47d7e98585a 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_iso.c +++ b/subsys/bluetooth/controller/ll_sw/ull_iso.c @@ -14,6 +14,7 @@ #include "util/memq.h" #include "util/mem.h" #include "util/mfifo.h" +#include "util/mayfly.h" #include "pdu.h" @@ -60,8 +61,32 @@ static int init_reset(void); #if BT_CTLR_ISO_STREAMS static struct ll_iso_datapath datapath_pool[BT_CTLR_ISO_STREAMS]; #endif + static void *datapath_free; +#if defined(CONFIG_BT_CTLR_SYNC_ISO) || defined(CONFIG_BT_CTLR_CONN_ISO) +#define NODE_RX_HEADER_SIZE (offsetof(struct node_rx_pdu, pdu)) +/* ISO LL conformance tests require a PDU size of maximum 251 bytes + header */ +#define ISO_RX_BUFFER_SIZE (2 + 251) + +/* Declare the ISO rx node RXFIFO. This is a composite pool-backed MFIFO for + * rx_nodes. The declaration constructs the following data structures: + * - mfifo_iso_rx: FIFO with pointers to PDU buffers + * - mem_iso_rx: Backing data pool for PDU buffer elements + * - mem_link_iso_rx: Pool of memq_link_t elements + * + * Two extra links are reserved for use by the ll_iso_rx and ull_iso_rx memq. + */ +static RXFIFO_DEFINE(iso_rx, NODE_RX_HEADER_SIZE + ISO_RX_BUFFER_SIZE, + CONFIG_BT_CTLR_ISO_RX_BUFFERS, 2); + +static MEMQ_DECLARE(ll_iso_rx); +#if defined(CONFIG_BT_CTLR_ISO_VENDOR_DATA_PATH) +static MEMQ_DECLARE(ull_iso_rx); +static void iso_rx_demux(void *param); +#endif /* CONFIG_BT_CTLR_ISO_VENDOR_DATA_PATH */ +#endif /* CONFIG_BT_CTLR_SYNC_ISO) || CONFIG_BT_CTLR_CONN_ISO */ + #if defined(CONFIG_BT_CTLR_ADV_ISO) || defined(CONFIG_BT_CTLR_CONN_ISO) static MFIFO_DEFINE(iso_tx, sizeof(struct lll_tx), CONFIG_BT_CTLR_ISO_TX_BUFFERS); @@ -522,6 +547,182 @@ int ull_iso_reset(void) return 0; } +#if defined(CONFIG_BT_CTLR_SYNC_ISO) || defined(CONFIG_BT_CTLR_CONN_ISO) +void *ull_iso_pdu_rx_alloc_peek(uint8_t count) +{ + if (count > MFIFO_AVAIL_COUNT_GET(iso_rx)) { + return NULL; + } + + return MFIFO_DEQUEUE_PEEK(iso_rx); +} + +void *ull_iso_pdu_rx_alloc(void) +{ + return MFIFO_DEQUEUE(iso_rx); +} + +#if defined(CONFIG_BT_CTLR_ISO_VENDOR_DATA_PATH) +void ull_iso_rx_put(memq_link_t *link, void *rx) +{ + /* Enqueue the Rx object */ + memq_enqueue(link, rx, &memq_ull_iso_rx.tail); +} + +void ull_iso_rx_sched(void) +{ + static memq_link_t link; + static struct mayfly mfy = {0, 0, &link, NULL, iso_rx_demux}; + + /* Kick the ULL (using the mayfly, tailchain it) */ + mayfly_enqueue(TICKER_USER_ID_LLL, TICKER_USER_ID_ULL_HIGH, 1, &mfy); +} + +static void iso_rx_demux(void *param) +{ + struct ll_conn_iso_stream *cis; + struct ll_iso_datapath *dp; + struct node_rx_pdu *rx_pdu; + isoal_sink_handle_t sink; + struct node_rx_hdr *rx; + memq_link_t *link; + + do { + link = memq_peek(memq_ull_iso_rx.head, memq_ull_iso_rx.tail, + (void **)&rx); + if (link) { + /* Demux Rx objects */ + switch (rx->type) { + case NODE_RX_TYPE_RELEASE: + (void)memq_dequeue(memq_ull_iso_rx.tail, + &memq_ull_iso_rx.head, NULL); + ll_iso_rx_put(link, rx); + ll_rx_sched(); + break; + + case NODE_RX_TYPE_ISO_PDU: + /* Remove from receive-queue; ULL has received this now */ + (void)memq_dequeue(memq_ull_iso_rx.tail, &memq_ull_iso_rx.head, + NULL); + +#if defined(CONFIG_BT_CTLR_CONN_ISO) + rx_pdu = (struct node_rx_pdu *)rx; + cis = ll_conn_iso_stream_get(rx_pdu->hdr.handle); + dp = cis->hdr.datapath_out; + sink = dp->sink_hdl; + + if (dp->path_id != BT_HCI_DATAPATH_ID_HCI) { + /* If vendor specific datapath pass to ISO AL here, + * in case of HCI destination it will be passed in + * HCI context. + */ + struct isoal_pdu_rx pckt_meta = { + .meta = &rx_pdu->hdr.rx_iso_meta, + .pdu = (struct pdu_iso *)&rx_pdu->pdu[0] + }; + + /* Pass the ISO PDU through ISO-AL */ + const isoal_status_t err = + isoal_rx_pdu_recombine(sink, &pckt_meta); + + LL_ASSERT(err == ISOAL_STATUS_OK); /* TODO handle err */ + } +#endif /* CONFIG_BT_CTLR_CONN_ISO */ + + /* Let ISO PDU start its long journey upwards */ + ll_iso_rx_put(link, rx); + ll_rx_sched(); + break; + + default: + LL_ASSERT(0); + break; + } + } + } while (link); +} +#endif /* CONFIG_BT_CTLR_ISO_VENDOR_DATA_PATH */ + +void ll_iso_rx_put(memq_link_t *link, void *rx) +{ + /* Enqueue the Rx object */ + memq_enqueue(link, rx, &memq_ll_iso_rx.tail); +} + +void *ll_iso_rx_get(void) +{ + struct node_rx_hdr *rx; + memq_link_t *link; + + link = memq_peek(memq_ll_iso_rx.head, memq_ll_iso_rx.tail, (void **)&rx); + while (link) { + /* Do not send up buffers to Host thread that are + * marked for release + */ + if (rx->type == NODE_RX_TYPE_RELEASE) { + (void)memq_dequeue(memq_ll_iso_rx.tail, + &memq_ll_iso_rx.head, NULL); + mem_release(link, &mem_link_iso_rx.free); + mem_release(rx, &mem_iso_rx.free); + RXFIFO_ALLOC(iso_rx, 1); + + link = memq_peek(memq_ll_iso_rx.head, memq_ll_iso_rx.tail, (void **)&rx); + continue; + } + return rx; + } + + return NULL; +} + +void ll_iso_rx_dequeue(void) +{ + struct node_rx_hdr *rx = NULL; + memq_link_t *link; + + link = memq_dequeue(memq_ll_iso_rx.tail, &memq_ll_iso_rx.head, + (void **)&rx); + LL_ASSERT(link); + + mem_release(link, &mem_link_iso_rx.free); + + /* Handle object specific clean up */ + switch (rx->type) { + case NODE_RX_TYPE_ISO_PDU: + break; + default: + LL_ASSERT(0); + break; + } +} + +void ll_iso_rx_mem_release(void **node_rx) +{ + struct node_rx_hdr *rx; + + rx = *node_rx; + while (rx) { + struct node_rx_hdr *rx_free; + + rx_free = rx; + rx = rx->next; + + switch (rx_free->type) { + case NODE_RX_TYPE_ISO_PDU: + mem_release(rx_free, &mem_iso_rx.free); + break; + default: + LL_ASSERT(0); + break; + } + } + + *node_rx = rx; + + RXFIFO_ALLOC(iso_rx, UINT8_MAX); +} +#endif /* CONFIG_BT_CTLR_SYNC_ISO) || CONFIG_BT_CTLR_CONN_ISO */ + void ull_iso_datapath_release(struct ll_iso_datapath *dp) { mem_release(dp, &datapath_free); @@ -529,6 +730,30 @@ void ull_iso_datapath_release(struct ll_iso_datapath *dp) static int init_reset(void) { +#if defined(CONFIG_BT_CTLR_SYNC_ISO) || defined(CONFIG_BT_CTLR_CONN_ISO) + memq_link_t *link; + + RXFIFO_INIT(iso_rx); + + /* Acquire a link to initialize ull rx memq */ + link = mem_acquire(&mem_link_iso_rx.free); + LL_ASSERT(link); + +#if defined(CONFIG_BT_CTLR_ISO_VENDOR_DATA_PATH) + /* Initialize ull rx memq */ + MEMQ_INIT(ull_iso_rx, link); +#endif /* CONFIG_BT_CTLR_ISO_VENDOR_DATA_PATH */ + + /* Acquire a link to initialize ll_iso_rx memq */ + link = mem_acquire(&mem_link_iso_rx.free); + LL_ASSERT(link); + + /* Initialize ll_iso_rx memq */ + MEMQ_INIT(ll_iso_rx, link); + + RXFIFO_ALLOC(iso_rx, UINT8_MAX); +#endif /* CONFIG_BT_CTLR_SYNC_ISO) || CONFIG_BT_CTLR_CONN_ISO */ + #if defined(CONFIG_BT_CTLR_ADV_ISO) || defined(CONFIG_BT_CTLR_CONN_ISO) /* Initialize tx pool. */ mem_init(mem_iso_tx.pool, CONFIG_BT_CTLR_ISO_TX_BUFFER_SIZE, diff --git a/subsys/bluetooth/controller/ll_sw/ull_iso_internal.h b/subsys/bluetooth/controller/ll_sw/ull_iso_internal.h index 4b5136bd4ce..78e45275ea6 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_iso_internal.h +++ b/subsys/bluetooth/controller/ll_sw/ull_iso_internal.h @@ -7,3 +7,6 @@ int ull_iso_init(void); int ull_iso_reset(void); void ull_iso_datapath_release(struct ll_iso_datapath *dp); +void ll_iso_rx_put(memq_link_t *link, void *rx); +void *ll_iso_rx_get(void); +void ll_iso_rx_dequeue(void); diff --git a/tests/bluetooth/bsim_bt/bsim_test_iso/src/main.c b/tests/bluetooth/bsim_bt/bsim_test_iso/src/main.c index 3114ff6f208..c3814cad71d 100644 --- a/tests/bluetooth/bsim_bt/bsim_test_iso/src/main.c +++ b/tests/bluetooth/bsim_bt/bsim_test_iso/src/main.c @@ -646,7 +646,7 @@ static void test_iso_recv_main(void) uint8_t check_countdown = 3; printk("Waiting for remote BIG terminate by checking for missing " - "%u BIG Info report...", check_countdown); + "%u BIG Info report...\n", check_countdown); do { is_sync_recv = false; is_big_info = false; From 688326832a5657fa354fc648b0848d91826f61d0 Mon Sep 17 00:00:00 2001 From: Morten Priess Date: Thu, 13 Jan 2022 12:41:56 +0100 Subject: [PATCH 141/207] [nrf fromtree] Bluetooth: controller: Fixed BSIM ISO compile error Added missing #includes for access to ULL functions. Signed-off-by: Morten Priess (cherry picked from commit c71dd808345b33b005a9cbba0a1f22edec729daf) (cherry picked from commit f1be4bd5e47175cf9723ee0641fab46b7acf7166) --- subsys/bluetooth/controller/ll_sw/lll_sync_iso.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/subsys/bluetooth/controller/ll_sw/lll_sync_iso.h b/subsys/bluetooth/controller/ll_sw/lll_sync_iso.h index d5fccaf9e9c..356461d665d 100644 --- a/subsys/bluetooth/controller/ll_sw/lll_sync_iso.h +++ b/subsys/bluetooth/controller/ll_sw/lll_sync_iso.h @@ -78,3 +78,5 @@ void lll_sync_iso_create_prepare(void *param); void lll_sync_iso_prepare(void *param); extern uint8_t ull_sync_iso_lll_handle_get(struct lll_sync_iso *lll); +extern void ll_iso_rx_put(memq_link_t *link, void *rx); +extern void ll_rx_sched(void); From 0339246689d5cb6dd4a9a11a8b1b1d363a65f361 Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Wed, 1 Dec 2021 21:01:23 +0530 Subject: [PATCH 142/207] [nrf fromtree] Bluetooth: Controller: Restrict Extended Adv Report to max data length Add implementation to limit Extended Scanned data to a configurable maximum length when generating HCI reports. Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit 8a5f0b50eb076ae0d3862f53052140acbbc73d26) (cherry picked from commit d223bcfea35cf5ac5153924ce8723935915d6e79) --- subsys/bluetooth/controller/Kconfig | 7 ++++ subsys/bluetooth/controller/hci/hci.c | 57 +++++++++++++++++++++++++-- 2 files changed, 61 insertions(+), 3 deletions(-) diff --git a/subsys/bluetooth/controller/Kconfig b/subsys/bluetooth/controller/Kconfig index 51568a3591f..840614cd19e 100644 --- a/subsys/bluetooth/controller/Kconfig +++ b/subsys/bluetooth/controller/Kconfig @@ -509,6 +509,13 @@ config BT_CTLR_ADV_EXT_RX_PDU_LEN_MAX help Maximum Advertising Extensions Receive PDU Length. +config BT_CTLR_SCAN_DATA_LEN_MAX + int "Maximum Extended Scanning Data Length" + depends on BT_OBSERVER + range 31 1650 + help + Maximum Extended Scanning Data Length. + config BT_CTLR_ADV_PERIODIC bool "LE Periodic Advertising in Advertising State" if !BT_LL_SW_SPLIT depends on BT_BROADCASTER && BT_CTLR_ADV_PERIODIC_SUPPORT diff --git a/subsys/bluetooth/controller/hci/hci.c b/subsys/bluetooth/controller/hci/hci.c index 0d6f40fec2b..01bf33af1fb 100644 --- a/subsys/bluetooth/controller/hci/hci.c +++ b/subsys/bluetooth/controller/hci/hci.c @@ -5746,6 +5746,7 @@ static void ext_adv_pdu_frag(uint8_t evt_type, uint8_t phy, uint8_t sec_phy, const uint8_t data_len_frag = MIN(*data_len, data_len_max); do { + /* Prepare a fragment of PDU data in a HCI event */ ext_adv_info_fill(evt_type, phy, sec_phy, adv_addr_type, adv_addr, direct_addr_type, direct_addr, rl_idx, tx_pwr, rssi, interval_le16, adi, @@ -5757,6 +5758,10 @@ static void ext_adv_pdu_frag(uint8_t evt_type, uint8_t phy, uint8_t sec_phy, *evt_buf = bt_buf_get_rx(BT_BUF_EVT, K_FOREVER); net_buf_frag_add(buf, *evt_buf); + + /* Continue to fragment until last partial PDU data fragment, + * remainder PDU data's HCI event will be prepare by caller. + */ } while (*data_len > data_len_max); } @@ -5776,15 +5781,24 @@ static void ext_adv_data_frag(const struct node_rx_pdu *node_rx_data, evt_type |= (BT_HCI_LE_ADV_EVT_TYPE_DATA_STATUS_PARTIAL << 5); do { + /* Fragment the PDU data */ ext_adv_pdu_frag(evt_type, phy, *sec_phy, adv_addr_type, adv_addr, direct_addr_type, direct_addr, rl_idx, tx_pwr, rssi, interval_le16, adi, data_len_max, &data_len_total, data_len, data, buf, evt_buf); + /* Check if more PDUs in the list */ node_rx_data = node_rx_data->hdr.rx_ftr.extra; if (node_rx_data) { - if (*data_len) { + if (*data_len >= data_len_total) { + /* Last fragment restricted to maximum scan + * data length, caller will prepare the last + * HCI fragment event. + */ + break; + } else if (*data_len) { + /* Last fragment of current PDU data */ ext_adv_pdu_frag(evt_type, phy, *sec_phy, adv_addr_type, adv_addr, direct_addr_type, direct_addr, @@ -5794,9 +5808,20 @@ static void ext_adv_data_frag(const struct node_rx_pdu *node_rx_data, data_len, data, buf, evt_buf); } + /* Get next PDU data in list */ *data_len = ext_adv_data_get(node_rx_data, sec_phy, data); + + /* Restrict PDU data to maximum scan data length */ + if (*data_len > data_len_total) { + *data_len = data_len_total; + } } + + /* Continue to fragment if current PDU data length less than + * total data length or current PDU data length greater than + * HCI event max length. + */ } while ((*data_len < data_len_total) || (*data_len > data_len_max)); } @@ -6144,6 +6169,16 @@ static void le_ext_adv_report(struct pdu_data *pdu_data, } } + /* Restrict data length to maximum scan data length */ + if (data_len_total > CONFIG_BT_CTLR_SCAN_DATA_LEN_MAX) { + data_len_total = CONFIG_BT_CTLR_SCAN_DATA_LEN_MAX; + if (data_len > data_len_total) { + data_len = data_len_total; + } + + data_status = BT_HCI_LE_ADV_EVT_TYPE_DATA_STATUS_INCOMPLETE; + } + /* Set directed advertising bit */ if (direct_addr) { evt_type |= BT_HCI_LE_ADV_EVT_TYPE_DIRECT; @@ -6156,6 +6191,9 @@ static void le_ext_adv_report(struct pdu_data *pdu_data, sizeof(struct bt_hci_evt_le_ext_advertising_report) - sizeof(struct bt_hci_evt_le_ext_advertising_info); + /* If PDU data length less than total data length or PDU data length + * greater than maximum HCI event data length, then fragment. + */ if ((data_len < data_len_total) || (data_len > data_len_max)) { ext_adv_data_frag(node_rx_data, evt_type, phy, &sec_phy, adv_addr_type, adv_addr, direct_addr_type, @@ -6168,7 +6206,7 @@ static void le_ext_adv_report(struct pdu_data *pdu_data, /* Set data status bits */ evt_type |= (data_status << 5); - /* Start constructing the adv event */ + /* Start constructing the adv event for remainder of the PDU data */ ext_adv_info_fill(evt_type, phy, sec_phy, adv_addr_type, adv_addr, direct_addr_type, direct_addr, rl_idx, tx_pwr, rssi, interval_le16, adi, data_len, data, evt_buf); @@ -6180,6 +6218,16 @@ static void le_ext_adv_report(struct pdu_data *pdu_data, return; } + /* Restrict scan response data length to maximum scan data length */ + if (scan_data_len_total > CONFIG_BT_CTLR_SCAN_DATA_LEN_MAX) { + scan_data_len_total = CONFIG_BT_CTLR_SCAN_DATA_LEN_MAX; + if (scan_data_len > scan_data_len_total) { + scan_data_len = scan_data_len_total; + } + + scan_data_status = BT_HCI_LE_ADV_EVT_TYPE_DATA_STATUS_INCOMPLETE; + } + /* Set scan response bit */ evt_type |= BT_HCI_LE_ADV_EVT_TYPE_SCAN_RSP; @@ -6192,6 +6240,9 @@ static void le_ext_adv_report(struct pdu_data *pdu_data, evt_buf = bt_buf_get_rx(BT_BUF_EVT, K_FOREVER); net_buf_frag_add(buf, evt_buf); + /* If PDU data length less than total data length or PDU data length + * greater than maximum HCI event data length, then fragment. + */ if ((scan_data_len < scan_data_len_total) || (scan_data_len > data_len_max)) { ext_adv_data_frag(node_rx_scan_data, evt_type, phy, @@ -6205,7 +6256,7 @@ static void le_ext_adv_report(struct pdu_data *pdu_data, /* set scan data status bits */ evt_type |= (scan_data_status << 5); - /* Start constructing the event */ + /* Start constructing the event for remainder of the PDU data */ ext_adv_info_fill(evt_type, phy, sec_phy_scan, adv_addr_type, adv_addr, direct_addr_type, direct_addr, rl_idx, tx_pwr, rssi, interval_le16, adi, scan_data_len, scan_data, From 7536dcf2b09bbd3fa16400e8515dfbd48f443af3 Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Fri, 10 Dec 2021 07:03:24 +0530 Subject: [PATCH 143/207] [nrf fromtree] Bluetooth: Controller: Fix Periodic Sync LLL scheduling flag Fix Periodic Advertising Sync LLL scheduling flag to not be set when chain PDUs use LLL scheduling, only set when primary AUX_SYNC_IND PDU received use LLL scheduling. Without the fix, spurious EVENT_DONE_EXTRA_TYPE_SYNC would be generated when chain PDUs are failed to be received. This can cause Sync Lost message to be generated. Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit 7bc3fdc856bd50853eb03a5e518b9916276c3313) (cherry picked from commit 84fdecb62c99d90519453132176229bae9ed83e6) --- subsys/bluetooth/controller/ll_sw/nordic/lll/lll_sync.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_sync.c b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_sync.c index 0f83aee86a3..f5e8e91e210 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_sync.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_sync.c @@ -634,7 +634,10 @@ static int isr_rx(struct lll_sync *lll, uint8_t node_type, uint8_t crc_ok, uint8 isr_aux_setup, lll); if (ftr->aux_lll_sched) { - lll->is_aux_sched = 1U; + if (node_type != NODE_RX_TYPE_EXT_AUX_REPORT) { + lll->is_aux_sched = 1U; + } + err = -EBUSY; } else { err = 0; From a95d7d7de76d05a126a64d2f13f764b95bb10218 Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Sun, 2 Jan 2022 13:31:21 +0530 Subject: [PATCH 144/207] [nrf fromtree] Bluetooth: Host: Added new LE Feature Support bit masks Added new LE Feature Support bit mask as documented in Bluetooth Spec. v5.3 Vol 6, Part B, Section 4.6 Feature Support. Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit 3c6fa016b17b84e7c77426ea94cf8116c0fe9f8e) (cherry picked from commit 43cea2e2cc09586e9f5930f22a039cc8a492270c) --- include/bluetooth/hci.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/bluetooth/hci.h b/include/bluetooth/hci.h index d324e0c68ac..8ed57b234a0 100644 --- a/include/bluetooth/hci.h +++ b/include/bluetooth/hci.h @@ -166,6 +166,10 @@ struct bt_hci_cmd_hdr { #define BT_LE_FEAT_BIT_PWR_CTRL_REQ 33 #define BT_LE_FEAT_BIT_PWR_CHG_IND 34 #define BT_LE_FEAT_BIT_PATH_LOSS_MONITOR 35 +#define BT_LE_FEAT_BIT_PER_ADV_ADI_SUPP 36 +#define BT_LE_FEAT_BIT_CONN_SUBRATING 37 +#define BT_LE_FEAT_BIT_CONN_SUBRATING_HOST_SUPP 38 +#define BT_LE_FEAT_BIT_CHANNEL_CLASSIFICATION 39 #define BT_LE_FEAT_TEST(feat, n) (feat[(n) >> 3] & \ BIT((n) & 7)) From 5b19914312b69e6149dacc3dc0b3c5bb1baaa468 Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Sun, 2 Jan 2022 13:33:41 +0530 Subject: [PATCH 145/207] [nrf fromtree] Bluetooth: Controller: Fix Periodic Advertising ADI feature bits Fix Periodic Advertising ADI Support feature bits so that it is return back in the Read Local Supported Features. Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit 2d953b6b9e6bf015cbec73f574c7dbd87a66c226) (cherry picked from commit 841b2848ebe86e2740bfbacdf52d0e2985639881) --- subsys/bluetooth/controller/include/ll_feat.h | 22 ++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/subsys/bluetooth/controller/include/ll_feat.h b/subsys/bluetooth/controller/include/ll_feat.h index b80a4574903..32ed99456a2 100644 --- a/subsys/bluetooth/controller/include/ll_feat.h +++ b/subsys/bluetooth/controller/include/ll_feat.h @@ -195,20 +195,31 @@ #define LL_BIS_OCTETS_RX_MAX 0 #endif /* !CONFIG_BT_CTLR_SYNC_ISO */ +#if defined(CONFIG_BT_CTLR_ADV_PERIODIC_ADI_SUPPORT) || \ + defined(CONFIG_BT_CTLR_SYNC_PERIODIC_ADI_SUPPORT) +#define LL_FEAT_BIT_PERIODIC_ADI_SUPPORT BIT64(BT_LE_FEAT_BIT_PER_ADV_ADI_SUPP) +#else /* !CONFIG_BT_CTLR_ADV_PERIODIC_ADI_SUPPORT && + * !CONFIG_BT_CTLR_SYNC_PERIODIC_ADI_SUPPORT + */ +#define LL_FEAT_BIT_PERIODIC_ADI_SUPPORT 0U +#endif /* !CONFIG_BT_CTLR_ADV_PERIODIC_ADI_SUPPORT && + * !CONFIG_BT_CTLR_SYNC_PERIODIC_ADI_SUPPORT + */ + /* All defined feature bits */ -#define LL_FEAT_BIT_MASK 0xFFFFFFFFFULL +#define LL_FEAT_BIT_MASK 0xFFFFFFFFFFULL /* * LL_FEAT_BIT_MASK_VALID is defined as per - * Core Spec V5.2 Volume 6, Part B, chapter 4.6 + * Core Spec V5.3 Volume 6, Part B, chapter 4.6 */ -#define LL_FEAT_BIT_MASK_VALID 0xFF787CF2FULL +#define LL_FEAT_BIT_MASK_VALID 0xEFF787CF2FULL /* Mask to filter away octet 0 for feature exchange */ #define LL_FEAT_FILTER_OCTET0 (LL_FEAT_BIT_MASK & ~0xFFULL) /* Mask for host controlled features */ -#define LL_FEAT_HOST_BIT_MASK 0x100000000ULL +#define LL_FEAT_HOST_BIT_MASK 0x4100000000ULL /* Feature bits of this controller */ #define LL_FEAT (LL_FEAT_BIT_ENC | \ @@ -237,4 +248,5 @@ LL_FEAT_BIT_CIS_CENTRAL | \ LL_FEAT_BIT_CIS_PERIPHERAL | \ LL_FEAT_BIT_ISO_BROADCASTER | \ - LL_FEAT_BIT_SYNC_RECEIVER) + LL_FEAT_BIT_SYNC_RECEIVER | \ + LL_FEAT_BIT_PERIODIC_ADI_SUPPORT) From 6dcd9a465b70d90745f3b5812d7645047ff625d8 Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Mon, 25 Oct 2021 21:34:46 +0530 Subject: [PATCH 146/207] [nrf fromtree] Bluetooth: Controller: Define EVENT_SYNC_B2B_MAFS_US Define EVENT_SYNC_B2B_MAFS_US to use the Kconfig option used to configure the MAFS between Periodic Advertising chain PDUs. Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit e1a3606391fa9c8cd6c1e875a3059ec63c13adc9) (cherry picked from commit b411daa4efe827ef6c6c54c4f96753ac4fddd769) --- .../controller/ll_sw/nordic/lll/lll_adv_sync.c | 16 ++++++---------- subsys/bluetooth/controller/ll_sw/pdu.h | 4 +++- 2 files changed, 9 insertions(+), 11 deletions(-) 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 7734d1b93e2..ebe462ffacb 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 @@ -44,12 +44,6 @@ #include "common/log.h" #include "hal/debug.h" -#if defined(CONFIG_BT_CTLR_ADV_SYNC_PDU_BACK2BACK) -#define ADV_SYNC_PDU_B2B_AFS (CONFIG_BT_CTLR_ADV_SYNC_PDU_BACK2BACK_AFS) -#else -#define ADV_SYNC_PDU_B2B_AFS 0 -#endif - static int init_reset(void); static int prepare_cb(struct lll_prepare_param *p); static void abort_cb(struct lll_prepare_param *prepare_param, void *param); @@ -204,7 +198,7 @@ static int prepare_cb(struct lll_prepare_param *p) lll->last_pdu = pdu; radio_isr_set(isr_tx, lll); - radio_tmr_tifs_set(ADV_SYNC_PDU_B2B_AFS); + radio_tmr_tifs_set(EVENT_SYNC_B2B_MAFS_US); switch_radio_complete_and_b2b_tx(lll, phy_s); } else #endif /* CONFIG_BT_CTLR_ADV_SYNC_PDU_BACK2BACK */ @@ -350,7 +344,7 @@ static void isr_tx(void *param) /* setup tIFS switching */ if (pdu->adv_ext_ind.ext_hdr_len && pdu->adv_ext_ind.ext_hdr.aux_ptr) { - radio_tmr_tifs_set(ADV_SYNC_PDU_B2B_AFS); + radio_tmr_tifs_set(EVENT_SYNC_B2B_MAFS_US); radio_isr_set(isr_tx, lll_sync); switch_radio_complete_and_b2b_tx(lll_sync, lll->phy_s); } else { @@ -381,7 +375,9 @@ static void isr_tx(void *param) } radio_gpio_lna_setup(); - radio_gpio_pa_lna_enable(radio_tmr_tifs_base_get() + ADV_SYNC_PDU_B2B_AFS - 4 + cte_len_us - + radio_gpio_pa_lna_enable(radio_tmr_tifs_base_get() + + EVENT_SYNC_B2B_MAFS_US - + (EVENT_CLOCK_JITTER_US << 1) + cte_len_us - radio_tx_chain_delay_get(lll->phy_s, 0) - HAL_RADIO_GPIO_LNA_OFFSET); #endif /* HAL_RADIO_GPIO_HAVE_LNA_PIN */ @@ -396,7 +392,7 @@ static void pdu_b2b_update(struct lll_adv_sync *lll, struct pdu_adv *pdu, uint32 while (pdu) { /* FIXME: Use implementation defined channel index */ pdu_b2b_aux_ptr_update(pdu, lll->adv->phy_s, lll->adv->phy_flags, 0, - ADV_SYNC_PDU_B2B_AFS, cte_len_us); + EVENT_SYNC_B2B_MAFS_US, cte_len_us); pdu = lll_adv_pdu_linked_next_get(pdu); } } diff --git a/subsys/bluetooth/controller/ll_sw/pdu.h b/subsys/bluetooth/controller/ll_sw/pdu.h index 8f16b26c3ba..63adc9c4e98 100644 --- a/subsys/bluetooth/controller/ll_sw/pdu.h +++ b/subsys/bluetooth/controller/ll_sw/pdu.h @@ -99,8 +99,10 @@ #define EVENT_MAFS_US 300 /* Standard allows 2 us timing uncertainty inside the event */ #define EVENT_MAFS_MAX_US (EVENT_MAFS_US + EVENT_CLOCK_JITTER_US) -/* Controller defined back to back transmit MAFS */ +/* Controller defined back to back transmit MAFS for extended advertising */ #define EVENT_B2B_MAFS_US (CONFIG_BT_CTLR_ADV_PDU_BACK2BACK_AFS) +/* Controller defined back to back transmit MAFS for periodic advertising */ +#define EVENT_SYNC_B2B_MAFS_US (CONFIG_BT_CTLR_ADV_SYNC_PDU_BACK2BACK_AFS) /* Minimum Subevent Space timings */ #define EVENT_MSS_US 150 /* Standard allows 2 us timing uncertainty inside the event */ From 8b529af75a81802a70c5f878de0f8ac8040e0a44 Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Mon, 20 Dec 2021 17:55:42 +0530 Subject: [PATCH 147/207] [nrf fromtree] Bluetooth: Controller: Fix Periodic Advertising to setup Power Amp Fix Periodic Advertising implementation to setup Power Amplifier (PA) GPIO toggle for transmission instead of incorrect Low Noise Amplifier (LNA) setup which is for reception. Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit 4e5290948e45c749b0c47048886582d95fb4d45a) (cherry picked from commit 49f18a1ad7bd34c85a2df09b686051d471588150) --- .../ll_sw/nordic/lll/lll_adv_sync.c | 31 ++++++++++++++++--- 1 file changed, 27 insertions(+), 4 deletions(-) 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 ebe462ffacb..d87410bf0d7 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 @@ -217,6 +217,26 @@ static int prepare_cb(struct lll_prepare_param *p) remainder = p->remainder; start_us = radio_tmr_start(1, ticks_at_start, remainder); +#if defined(CONFIG_BT_CTLR_PROFILE_ISR) || \ + defined(HAL_RADIO_GPIO_HAVE_PA_PIN) + /* capture end of AUX_SYNC_IND/AUX_CHAIN_IND PDU, used for calculating + * next PDU timestamp. + * + * In Periodic Advertising without chaining there is no need for LLL to + * get the end time from radio, hence there is no call to + * radio_tmr_end_capture() to capture the radio end time. + * + * With chaining the sw_switch used PPI/DPPI for back to back Tx, no + * radio end time capture is needed there either. + * + * For PA LNA (and ISR profiling), the radio end time is required to + * setup the GPIOTE using radio_gpio_pa_lna_enable which needs call to + * radio_tmr_tifs_base_get(), both PA/LNA and ISR profiling call + * radio_tmr_end_get(). + */ + radio_tmr_end_capture(); +#endif /* CONFIG_BT_CTLR_PROFILE_ISR */ + #if defined(HAL_RADIO_GPIO_HAVE_PA_PIN) radio_gpio_pa_setup(); @@ -361,12 +381,15 @@ static void isr_tx(void *param) lll_prof_cputime_capture(); } +#if defined(CONFIG_BT_CTLR_PROFILE_ISR) || \ + defined(HAL_RADIO_GPIO_HAVE_PA_PIN) /* capture end of AUX_SYNC_IND/AUX_CHAIN_IND PDU, used for calculating * next PDU timestamp. */ radio_tmr_end_capture(); +#endif /* CONFIG_BT_CTLR_PROFILE_ISR */ -#if defined(HAL_RADIO_GPIO_HAVE_LNA_PIN) +#if defined(HAL_RADIO_GPIO_HAVE_PA_PIN) if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) { /* PA/LNA enable is overwriting packet end used in ISR * profiling, hence back it up for later use. @@ -374,13 +397,13 @@ static void isr_tx(void *param) lll_prof_radio_end_backup(); } - radio_gpio_lna_setup(); + radio_gpio_pa_setup(); radio_gpio_pa_lna_enable(radio_tmr_tifs_base_get() + EVENT_SYNC_B2B_MAFS_US - (EVENT_CLOCK_JITTER_US << 1) + cte_len_us - radio_tx_chain_delay_get(lll->phy_s, 0) - - HAL_RADIO_GPIO_LNA_OFFSET); -#endif /* HAL_RADIO_GPIO_HAVE_LNA_PIN */ + HAL_RADIO_GPIO_PA_OFFSET); +#endif /* HAL_RADIO_GPIO_HAVE_PA_PIN */ if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) { lll_prof_send(); From 7fdd0daada18acb6af9467fdaaf4e9dd92721acd Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Sat, 11 Dec 2021 19:56:59 +0530 Subject: [PATCH 148/207] [nrf fromtree] Bluetooth: Controller: Rename flag to sync_term to is_term Rename the flag sync_term to is_term to be consistent with other flags. Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit 77e810e4b8b60dd28bc572ae81dc9b371374cc19) (cherry picked from commit 94cc9a690f7633851562b22ccfae9191749698c4) --- subsys/bluetooth/controller/ll_sw/ull_sync.c | 4 ++-- subsys/bluetooth/controller/ll_sw/ull_sync_types.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/subsys/bluetooth/controller/ll_sw/ull_sync.c b/subsys/bluetooth/controller/ll_sw/ull_sync.c index b0f34eb85ed..94d456266b7 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_sync.c +++ b/subsys/bluetooth/controller/ll_sw/ull_sync.c @@ -792,7 +792,7 @@ void ull_sync_established_report(memq_link_t *link, struct node_rx_hdr *rx) #if !defined(CONFIG_BT_CTLR_CTEINLINE_SUPPORT) /* Notify done event handler to terminate sync scan if required. */ - ull_sync->sync_term = sync_status == SYNC_STAT_TERM; + ull_sync->is_term = (sync_status == SYNC_STAT_TERM); #endif /* !CONFIG_BT_CTLR_CTEINLINE_SUPPORT */ #else se->status = BT_HCI_ERR_SUCCESS; @@ -846,7 +846,7 @@ void ull_sync_done(struct node_rx_event_done *done) #if defined(CONFIG_BT_CTLR_CTEINLINE_SUPPORT) if (done->extra.sync_term) { #else - if (sync->sync_term) { + if (sync->is_term) { #endif /* CONFIG_BT_CTLR_CTEINLINE_SUPPORT */ /* Stop periodic advertising scan ticker */ sync_ticker_cleanup(sync, NULL); diff --git a/subsys/bluetooth/controller/ll_sw/ull_sync_types.h b/subsys/bluetooth/controller/ll_sw/ull_sync_types.h index cdffc5eb093..2da6b8ecc5d 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_sync_types.h +++ b/subsys/bluetooth/controller/ll_sw/ull_sync_types.h @@ -40,7 +40,7 @@ struct ll_sync_set { /* Member used to notify event done handler to terminate sync scanning. * Used only when no HW support for parsing PDU for CTEInfo. */ - uint8_t sync_term:1; + uint8_t is_term:1; #endif /* CONFIG_BT_CTLR_SYNC_PERIODIC_CTE_TYPE_FILTERING && !CONFIG_BT_CTLR_CTEINLINE_SUPPORT */ uint8_t sync_expire:3; /* countdown of 6 before fail to establish */ From 648787d4f350ab61aebdfdb6bc08937cd95b198b Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Thu, 9 Dec 2021 06:08:30 +0530 Subject: [PATCH 149/207] [nrf fromtree] Bluetooth: Controller: Rename per_scan field to periodic Rename per_scan field in scan context to periodic field to avoid confusing with abbreviation for peripheral. Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit 3c1277b49d2c97786cc6e54a216fc1118c78d7d3) (cherry picked from commit 8c7c4b105ba0981a2872020f2ac16a085267dc40) --- subsys/bluetooth/controller/hci/hci.c | 12 +- subsys/bluetooth/controller/ll_sw/ull.c | 2 +- subsys/bluetooth/controller/ll_sw/ull_scan.c | 4 +- .../bluetooth/controller/ll_sw/ull_scan_aux.c | 8 +- .../controller/ll_sw/ull_scan_types.h | 2 +- subsys/bluetooth/controller/ll_sw/ull_sync.c | 108 +++++++++--------- 6 files changed, 68 insertions(+), 68 deletions(-) diff --git a/subsys/bluetooth/controller/hci/hci.c b/subsys/bluetooth/controller/hci/hci.c index 01bf33af1fb..edcfc8ccc9b 100644 --- a/subsys/bluetooth/controller/hci/hci.c +++ b/subsys/bluetooth/controller/hci/hci.c @@ -6343,17 +6343,17 @@ static void le_per_adv_sync_established(struct pdu_data *pdu_data, scan = node_rx->hdr.rx_ftr.param; - dup_periodic_adv_reset(scan->per_scan.adv_addr_type, - scan->per_scan.adv_addr, - scan->per_scan.sid); + dup_periodic_adv_reset(scan->periodic.adv_addr_type, + scan->periodic.adv_addr, + scan->periodic.sid); sep->handle = sys_cpu_to_le16(node_rx->hdr.handle); /* Resolved address, if private, has been populated in ULL */ - sep->adv_addr.type = scan->per_scan.adv_addr_type; - memcpy(&sep->adv_addr.a.val[0], scan->per_scan.adv_addr, BDADDR_SIZE); + sep->adv_addr.type = scan->periodic.adv_addr_type; + (void)memcpy(sep->adv_addr.a.val, scan->periodic.adv_addr, BDADDR_SIZE); - sep->sid = scan->per_scan.sid; + sep->sid = scan->periodic.sid; sep->phy = find_lsb_set(se->phy); sep->interval = sys_cpu_to_le16(se->interval); sep->clock_accuracy = se->sca; diff --git a/subsys/bluetooth/controller/ll_sw/ull.c b/subsys/bluetooth/controller/ll_sw/ull.c index 032a9ec8acd..dabf60fb8fb 100644 --- a/subsys/bluetooth/controller/ll_sw/ull.c +++ b/subsys/bluetooth/controller/ll_sw/ull.c @@ -1434,7 +1434,7 @@ void ll_rx_mem_release(void **node_rx) /* pick the sync context before scan context * is cleanup of sync context association. */ - sync = scan->per_scan.sync; + sync = scan->periodic.sync; ull_sync_setup_complete(scan); diff --git a/subsys/bluetooth/controller/ll_sw/ull_scan.c b/subsys/bluetooth/controller/ll_sw/ull_scan.c index 93fad1907f6..1b312fecb4d 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_scan.c +++ b/subsys/bluetooth/controller/ll_sw/ull_scan.c @@ -621,7 +621,7 @@ uint32_t ull_scan_is_enabled(uint8_t handle) #if defined(CONFIG_BT_CTLR_SYNC_PERIODIC) scan = ull_scan_set_get(handle); - return scan->per_scan.sync ? ULL_SCAN_IS_SYNC : 0U; + return scan->periodic.sync ? ULL_SCAN_IS_SYNC : 0U; #else return 0U; #endif @@ -632,7 +632,7 @@ uint32_t ull_scan_is_enabled(uint8_t handle) (scan->lll.conn ? ULL_SCAN_IS_INITIATOR : 0U) | #endif #if defined(CONFIG_BT_CTLR_SYNC_PERIODIC) - (scan->per_scan.sync ? ULL_SCAN_IS_SYNC : 0U) | + (scan->periodic.sync ? ULL_SCAN_IS_SYNC : 0U) | #endif 0U); } diff --git a/subsys/bluetooth/controller/ll_sw/ull_scan_aux.c b/subsys/bluetooth/controller/ll_sw/ull_scan_aux.c index fa984ec7b83..fdb1b93c666 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_scan_aux.c +++ b/subsys/bluetooth/controller/ll_sw/ull_scan_aux.c @@ -290,7 +290,7 @@ void ull_scan_aux_setup(memq_link_t *link, struct node_rx_hdr *rx) #if defined(CONFIG_BT_CTLR_SYNC_PERIODIC) /* Check if Periodic Advertising Synchronization to be created */ - if (sync && (scan->per_scan.state != LL_SYNC_STATE_CREATED)) { + if (sync && (scan->periodic.state != LL_SYNC_STATE_CREATED)) { /* Check address and update internal state */ #if defined(CONFIG_BT_CTLR_PRIVACY) ull_sync_setup_addr_check(scan, pdu->tx_addr, ptr, @@ -553,8 +553,8 @@ void ull_scan_aux_setup(memq_link_t *link, struct node_rx_hdr *rx) ull_scan_aux_rx_flush: #if defined(CONFIG_BT_CTLR_SYNC_PERIODIC) - if (sync && (scan->per_scan.state != LL_SYNC_STATE_CREATED)) { - scan->per_scan.state = LL_SYNC_STATE_IDLE; + if (sync && (scan->periodic.state != LL_SYNC_STATE_CREATED)) { + scan->periodic.state = LL_SYNC_STATE_IDLE; } #endif /* CONFIG_BT_CTLR_SYNC_PERIODIC */ @@ -794,7 +794,7 @@ static inline uint8_t aux_handle_get(struct ll_scan_aux_set *aux) static inline struct ll_sync_set *sync_create_get(struct ll_scan_set *scan) { #if defined(CONFIG_BT_CTLR_SYNC_PERIODIC) - return scan->per_scan.sync; + return scan->periodic.sync; #else /* !CONFIG_BT_CTLR_SYNC_PERIODIC */ return NULL; #endif /* !CONFIG_BT_CTLR_SYNC_PERIODIC */ diff --git a/subsys/bluetooth/controller/ll_sw/ull_scan_types.h b/subsys/bluetooth/controller/ll_sw/ull_scan_types.h index 7ee46c86d75..429986e45b9 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_scan_types.h +++ b/subsys/bluetooth/controller/ll_sw/ull_scan_types.h @@ -31,7 +31,7 @@ struct ll_scan_set { * cancelling sync create, hence the volatile keyword. */ struct ll_sync_set *volatile sync; - } per_scan; + } periodic; #endif }; diff --git a/subsys/bluetooth/controller/ll_sw/ull_sync.c b/subsys/bluetooth/controller/ll_sw/ull_sync.c index 94d456266b7..f93f8627c22 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_sync.c +++ b/subsys/bluetooth/controller/ll_sw/ull_sync.c @@ -102,7 +102,7 @@ uint8_t ll_sync_create(uint8_t options, uint8_t sid, uint8_t adv_addr_type, struct ll_sync_set *sync; scan = ull_scan_set_get(SCAN_HANDLE_1M); - if (!scan || scan->per_scan.sync) { + if (!scan || scan->periodic.sync) { return BT_HCI_ERR_CMD_DISALLOWED; } @@ -116,7 +116,7 @@ uint8_t ll_sync_create(uint8_t options, uint8_t sid, uint8_t adv_addr_type, if (IS_ENABLED(CONFIG_BT_CTLR_PHY_CODED)) { scan_coded = ull_scan_set_get(SCAN_HANDLE_PHY_CODED); - if (!scan_coded || scan_coded->per_scan.sync) { + if (!scan_coded || scan_coded->periodic.sync) { return BT_HCI_ERR_CMD_DISALLOWED; } } @@ -152,26 +152,26 @@ uint8_t ll_sync_create(uint8_t options, uint8_t sid, uint8_t adv_addr_type, return BT_HCI_ERR_MEM_CAPACITY_EXCEEDED; } - scan->per_scan.state = LL_SYNC_STATE_IDLE; - scan->per_scan.filter_policy = + scan->periodic.state = LL_SYNC_STATE_IDLE; + scan->periodic.filter_policy = options & BT_HCI_LE_PER_ADV_CREATE_SYNC_FP_USE_LIST; if (IS_ENABLED(CONFIG_BT_CTLR_PHY_CODED)) { - scan_coded->per_scan.state = LL_SYNC_STATE_IDLE; - scan_coded->per_scan.filter_policy = - scan->per_scan.filter_policy; + scan_coded->periodic.state = LL_SYNC_STATE_IDLE; + scan_coded->periodic.filter_policy = + scan->periodic.filter_policy; } - if (!scan->per_scan.filter_policy) { - scan->per_scan.sid = sid; - scan->per_scan.adv_addr_type = adv_addr_type; - memcpy(scan->per_scan.adv_addr, adv_addr, BDADDR_SIZE); + if (!scan->periodic.filter_policy) { + scan->periodic.sid = sid; + scan->periodic.adv_addr_type = adv_addr_type; + (void)memcpy(scan->periodic.adv_addr, adv_addr, BDADDR_SIZE); if (IS_ENABLED(CONFIG_BT_CTLR_PHY_CODED)) { - scan_coded->per_scan.sid = scan->per_scan.sid; - scan_coded->per_scan.adv_addr_type = - scan->per_scan.adv_addr_type; - memcpy(scan_coded->per_scan.adv_addr, - scan->per_scan.adv_addr, BDADDR_SIZE); + scan_coded->periodic.sid = scan->periodic.sid; + scan_coded->periodic.adv_addr_type = + scan->periodic.adv_addr_type; + (void)memcpy(scan_coded->periodic.adv_addr, + scan->periodic.adv_addr, BDADDR_SIZE); } } @@ -230,7 +230,7 @@ uint8_t ll_sync_create(uint8_t options, uint8_t sid, uint8_t adv_addr_type, lll_sync->window_widening_event_us = 0U; #if defined(CONFIG_BT_CTLR_SYNC_PERIODIC_CTE_TYPE_FILTERING) lll_sync->cte_type = sync_cte_type; - lll_sync->filter_policy = scan->per_scan.filter_policy; + lll_sync->filter_policy = scan->periodic.filter_policy; #endif /* CONFIG_BT_CTLR_SYNC_PERIODIC_CTE_TYPE_FILTERING */ #if defined(CONFIG_BT_CTLR_DF_SCAN_CTE_RX) @@ -242,9 +242,9 @@ uint8_t ll_sync_create(uint8_t options, uint8_t sid, uint8_t adv_addr_type, lll_hdr_init(lll_sync, sync); /* Enable scanner to create sync */ - scan->per_scan.sync = sync; + scan->periodic.sync = sync; if (IS_ENABLED(CONFIG_BT_CTLR_PHY_CODED)) { - scan_coded->per_scan.sync = sync; + scan_coded->periodic.sync = sync; } return 0; @@ -261,13 +261,13 @@ uint8_t ll_sync_create_cancel(void **rx) struct node_rx_sync *se; scan = ull_scan_set_get(SCAN_HANDLE_1M); - if (!scan || !scan->per_scan.sync) { + if (!scan || !scan->periodic.sync) { return BT_HCI_ERR_CMD_DISALLOWED; } if (IS_ENABLED(CONFIG_BT_CTLR_PHY_CODED)) { scan_coded = ull_scan_set_get(SCAN_HANDLE_PHY_CODED); - if (!scan_coded || !scan_coded->per_scan.sync) { + if (!scan_coded || !scan_coded->periodic.sync) { return BT_HCI_ERR_CMD_DISALLOWED; } } @@ -275,15 +275,15 @@ uint8_t ll_sync_create_cancel(void **rx) /* Check for race condition where in sync is established when sync * context was set to NULL. * - * Setting `scan->per_scan.sync` to NULL represents cancellation + * Setting `scan->periodic.sync` to NULL represents cancellation * requested in the thread context. Checking `sync->timeout_reload` * confirms if synchronization was established before - * `scan->per_scan.sync` was set to NULL. + * `scan->periodic.sync` was set to NULL. */ - sync = scan->per_scan.sync; - scan->per_scan.sync = NULL; + sync = scan->periodic.sync; + scan->periodic.sync = NULL; if (IS_ENABLED(CONFIG_BT_CTLR_PHY_CODED)) { - scan_coded->per_scan.sync = NULL; + scan_coded->periodic.sync = NULL; } cpu_dmb(); if (!sync || sync->timeout_reload) { @@ -485,59 +485,59 @@ void ull_sync_setup_addr_check(struct ll_scan_set *scan, uint8_t addr_type, { /* Check if Periodic Advertiser list to be used */ if (IS_ENABLED(CONFIG_BT_CTLR_SYNC_PERIODIC_ADV_LIST) && - scan->per_scan.filter_policy) { + scan->periodic.filter_policy) { /* Check in Periodic Advertiser List */ if (ull_filter_ull_pal_addr_match(addr_type, addr)) { /* Remember the address, to check with * SID in Sync Info */ - scan->per_scan.adv_addr_type = addr_type; - (void)memcpy(scan->per_scan.adv_addr, addr, + scan->periodic.adv_addr_type = addr_type; + (void)memcpy(scan->periodic.adv_addr, addr, BDADDR_SIZE); /* Address matched */ - scan->per_scan.state = LL_SYNC_STATE_ADDR_MATCH; + scan->periodic.state = LL_SYNC_STATE_ADDR_MATCH; /* Check in Resolving List */ } else if (IS_ENABLED(CONFIG_BT_CTLR_PRIVACY) && ull_filter_ull_pal_listed(rl_idx, &addr_type, - scan->per_scan.adv_addr)) { + scan->periodic.adv_addr)) { /* Remember the address, to check with the * SID in Sync Info */ - scan->per_scan.adv_addr_type = addr_type; + scan->periodic.adv_addr_type = addr_type; /* Address matched */ - scan->per_scan.state = LL_SYNC_STATE_ADDR_MATCH; + scan->periodic.state = LL_SYNC_STATE_ADDR_MATCH; } /* Check with explicitly supplied address */ - } else if ((addr_type == scan->per_scan.adv_addr_type) && - !memcmp(addr, scan->per_scan.adv_addr, BDADDR_SIZE)) { + } else if ((addr_type == scan->periodic.adv_addr_type) && + !memcmp(addr, scan->periodic.adv_addr, BDADDR_SIZE)) { /* Address matched */ - scan->per_scan.state = LL_SYNC_STATE_ADDR_MATCH; + scan->periodic.state = LL_SYNC_STATE_ADDR_MATCH; /* Check identity address with explicitly supplied address */ } else if (IS_ENABLED(CONFIG_BT_CTLR_PRIVACY) && (rl_idx < ll_rl_size_get())) { ll_rl_id_addr_get(rl_idx, &addr_type, addr); - if ((addr_type == scan->per_scan.adv_addr_type) && - !memcmp(addr, scan->per_scan.adv_addr, BDADDR_SIZE)) { + if ((addr_type == scan->periodic.adv_addr_type) && + !memcmp(addr, scan->periodic.adv_addr, BDADDR_SIZE)) { /* Identity address matched */ - scan->per_scan.state = LL_SYNC_STATE_ADDR_MATCH; + scan->periodic.state = LL_SYNC_STATE_ADDR_MATCH; } } } bool ull_sync_setup_sid_match(struct ll_scan_set *scan, uint8_t sid) { - return (scan->per_scan.state == LL_SYNC_STATE_ADDR_MATCH) && + return (scan->periodic.state == LL_SYNC_STATE_ADDR_MATCH) && ((IS_ENABLED(CONFIG_BT_CTLR_SYNC_PERIODIC_ADV_LIST) && - scan->per_scan.filter_policy && - ull_filter_ull_pal_match(scan->per_scan.adv_addr_type, - scan->per_scan.adv_addr, sid)) || - (!scan->per_scan.filter_policy && - (sid == scan->per_scan.sid))); + scan->periodic.filter_policy && + ull_filter_ull_pal_match(scan->periodic.adv_addr_type, + scan->periodic.adv_addr, sid)) || + (!scan->periodic.filter_policy && + (sid == scan->periodic.sid))); } void ull_sync_setup(struct ll_scan_set *scan, struct ll_scan_aux_set *aux, @@ -562,7 +562,7 @@ void ull_sync_setup(struct ll_scan_set *scan, struct ll_scan_aux_set *aux, uint8_t sca; /* Populate the LLL context */ - sync = scan->per_scan.sync; + sync = scan->periodic.sync; lll = &sync->lll; /* Copy channel map from sca_chm field in sync_info structure, and @@ -588,8 +588,8 @@ void ull_sync_setup(struct ll_scan_set *scan, struct ll_scan_aux_set *aux, /* Remember the peer address. * NOTE: Peer identity address is copied here when privacy is enable. */ - sync->peer_id_addr_type = scan->per_scan.adv_addr_type; - (void)memcpy(sync->peer_id_addr, scan->per_scan.adv_addr, + sync->peer_id_addr_type = scan->periodic.adv_addr_type; + (void)memcpy(sync->peer_id_addr, scan->periodic.adv_addr, sizeof(sync->peer_id_addr)); #endif /* CONFIG_BT_CTLR_CHECK_SAME_PEER_SYNC || * CONFIG_BT_CTLR_SYNC_PERIODIC_ADI_SUPPORT @@ -633,7 +633,7 @@ void ull_sync_setup(struct ll_scan_set *scan, struct ll_scan_aux_set *aux, } /* Set the state to sync create */ - scan->per_scan.state = LL_SYNC_STATE_CREATED; + scan->periodic.state = LL_SYNC_STATE_CREATED; if (IS_ENABLED(CONFIG_BT_CTLR_PHY_CODED)) { struct ll_scan_set *scan_1m; @@ -642,9 +642,9 @@ void ull_sync_setup(struct ll_scan_set *scan, struct ll_scan_aux_set *aux, struct ll_scan_set *scan_coded; scan_coded = ull_scan_set_get(SCAN_HANDLE_PHY_CODED); - scan_coded->per_scan.state = LL_SYNC_STATE_CREATED; + scan_coded->periodic.state = LL_SYNC_STATE_CREATED; } else { - scan_1m->per_scan.state = LL_SYNC_STATE_CREATED; + scan_1m->periodic.state = LL_SYNC_STATE_CREATED; } } @@ -719,7 +719,7 @@ void ull_sync_setup(struct ll_scan_set *scan, struct ll_scan_aux_set *aux, void ull_sync_setup_complete(struct ll_scan_set *scan) { /* Remove the sync context from being associated with scan contexts */ - scan->per_scan.sync = NULL; + scan->periodic.sync = NULL; if (IS_ENABLED(CONFIG_BT_CTLR_PHY_CODED)) { struct ll_scan_set *scan_1m; @@ -728,9 +728,9 @@ void ull_sync_setup_complete(struct ll_scan_set *scan) struct ll_scan_set *scan_coded; scan_coded = ull_scan_set_get(SCAN_HANDLE_PHY_CODED); - scan_coded->per_scan.sync = NULL; + scan_coded->periodic.sync = NULL; } else { - scan_1m->per_scan.sync = NULL; + scan_1m->periodic.sync = NULL; } } } From 7da7588fcd42a427f839fd75f06802ef44290469 Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Thu, 9 Dec 2021 06:27:16 +0530 Subject: [PATCH 150/207] [nrf fromtree] Bluetooth: Controller: Minor refactor for consistent variable names Minor refactor of auxiliary scanning implementation to use consistent variable naming and assignment close to its locality of reference. Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit 1fe80ec62a9d11a2e230982fe3e6805cd6bc6fa6) (cherry picked from commit a448dd9814d0c5a76bf1e8a66917103cf0769961) --- .../bluetooth/controller/ll_sw/ull_scan_aux.c | 31 +++++++++++++------ 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/subsys/bluetooth/controller/ll_sw/ull_scan_aux.c b/subsys/bluetooth/controller/ll_sw/ull_scan_aux.c index fdb1b93c666..2949d92228c 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_scan_aux.c +++ b/subsys/bluetooth/controller/ll_sw/ull_scan_aux.c @@ -117,12 +117,11 @@ void ull_scan_aux_setup(memq_link_t *link, struct node_rx_hdr *rx) is_scan_req = false; ftr = &rx->rx_ftr; - sync_lll = NULL; - switch (rx->type) { case NODE_RX_TYPE_EXT_1M_REPORT: lll_aux = NULL; aux = NULL; + sync_lll = NULL; sync_iso = NULL; lll = ftr->param; scan = HDR_LLL2ULL(lll); @@ -132,6 +131,7 @@ void ull_scan_aux_setup(memq_link_t *link, struct node_rx_hdr *rx) case NODE_RX_TYPE_EXT_CODED_REPORT: lll_aux = NULL; aux = NULL; + sync_lll = NULL; sync_iso = NULL; lll = ftr->param; scan = HDR_LLL2ULL(lll); @@ -141,6 +141,8 @@ void ull_scan_aux_setup(memq_link_t *link, struct node_rx_hdr *rx) case NODE_RX_TYPE_EXT_AUX_REPORT: sync_iso = NULL; if (ull_scan_aux_is_valid_get(HDR_LLL2ULL(ftr->param))) { + sync_lll = NULL; + /* Node has valid aux context so its scan was scheduled * from ULL. */ @@ -149,7 +151,10 @@ void ull_scan_aux_setup(memq_link_t *link, struct node_rx_hdr *rx) /* aux parent will be NULL for periodic sync */ lll = aux->parent; + } else if (ull_scan_is_valid_get(HDR_LLL2ULL(ftr->param))) { + sync_lll = NULL; + /* Node that does not have valid aux context but has * valid scan set was scheduled from LLL. We can * retrieve aux context from lll_scan as it was stored @@ -162,10 +167,12 @@ void ull_scan_aux_setup(memq_link_t *link, struct node_rx_hdr *rx) aux = HDR_LLL2ULL(lll_aux); LL_ASSERT(lll == aux->parent); + } else { + lll = NULL; + /* If none of the above, node is part of sync scanning */ - lll = NULL; sync_lll = ftr->param; lll_aux = sync_lll->lll_aux; @@ -634,23 +641,27 @@ void ull_scan_aux_done(struct node_rx_event_done *done) uint8_t ull_scan_aux_lll_handle_get(struct lll_scan_aux *lll) { - return aux_handle_get((void *)lll->hdr.parent); + struct ll_scan_aux_set *aux; + + aux = HDR_LLL2ULL(lll); + + return aux_handle_get(aux); } void *ull_scan_aux_lll_parent_get(struct lll_scan_aux *lll, uint8_t *is_lll_scan) { - struct ll_scan_aux_set *aux_set; - struct ll_scan_set *scan_set; + struct ll_scan_aux_set *aux; + struct ll_scan_set *scan; - aux_set = HDR_LLL2ULL(lll); - scan_set = HDR_LLL2ULL(aux_set->parent); + aux = HDR_LLL2ULL(lll); + scan = HDR_LLL2ULL(aux->parent); if (is_lll_scan) { - *is_lll_scan = !!ull_scan_is_valid_get(scan_set); + *is_lll_scan = !!ull_scan_is_valid_get(scan); } - return aux_set->parent; + return aux->parent; } struct ll_scan_aux_set *ull_scan_aux_is_valid_get(struct ll_scan_aux_set *aux) From 0b5905417db834201efaecf838d53616783635aa Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Fri, 10 Dec 2021 07:33:16 +0530 Subject: [PATCH 151/207] [nrf fromtree] Bluetooth: Controller: Minor fix isr_done context parameter passed Remove redundant parameter pass of lll_aux to isr_done as the auxiliary context use is always for scan context as the parent. Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit 93d6d1e1142434925d490f80794d2798ee45ed49) (cherry picked from commit 5b987b8d7be7428ea6e7cdcca89a16b69bea7114) --- subsys/bluetooth/controller/ll_sw/nordic/lll/lll_scan_aux.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 bbd7b862499..d14a2b561f2 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 @@ -1477,7 +1477,7 @@ static void isr_rx_connect_rsp(void *param) radio_isr_set(lll_scan_isr_resume, lll); } else { - radio_isr_set(isr_done, lll_aux); + radio_isr_set(isr_done, NULL); } radio_disable(); From d115475906c254603cb4cf22a38720954b1f3920 Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Wed, 1 Dec 2021 21:01:23 +0530 Subject: [PATCH 152/207] [nrf fromtree] Bluetooth: Controller: Fix Periodic Adv Report to scan max data length Fix implementation to limit Periodic Advertising data to a configurable maximum length when generating HCI reports. Bluetooth Test Specification defines Scan_Max_Data value in IXIT. When HCI LE Periodic Advertising Report events are generated by assembling the chain PDUs, the test cases expect that if the data length is no more than Scan_Max_Data, then at least once the IUT shall not truncate the data in the advertising report. Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit faa89c779cbee1b35a4c9323effa82232451ace6) (cherry picked from commit f2a7ac24f35d9a2b0e1ad07fdc13fccf80f9ec82) --- subsys/bluetooth/controller/hci/hci.c | 43 +++++----- subsys/bluetooth/controller/ll_sw/lll.h | 15 ++-- .../bluetooth/controller/ll_sw/ull_scan_aux.c | 84 ++++++++++++++++--- .../controller/ll_sw/ull_scan_types.h | 2 + subsys/bluetooth/controller/ll_sw/ull_sync.c | 3 + .../controller/ll_sw/ull_sync_types.h | 2 + 6 files changed, 113 insertions(+), 36 deletions(-) diff --git a/subsys/bluetooth/controller/hci/hci.c b/subsys/bluetooth/controller/hci/hci.c index edcfc8ccc9b..1f27265623c 100644 --- a/subsys/bluetooth/controller/hci/hci.c +++ b/subsys/bluetooth/controller/hci/hci.c @@ -6371,7 +6371,7 @@ static void le_per_adv_sync_report(struct pdu_data *pdu_data, uint8_t cte_type = BT_HCI_LE_NO_CTE; struct pdu_adv_com_ext_adv *p; struct pdu_adv_ext_hdr *h; - uint8_t data_status = 0U; + uint16_t data_len_total; struct net_buf *evt_buf; uint8_t data_len = 0U; uint8_t acad_len = 0U; @@ -6538,13 +6538,20 @@ static void le_per_adv_sync_report(struct pdu_data *pdu_data, data_len_max = ADV_REPORT_EVT_MAX_LEN - sizeof(struct bt_hci_evt_le_meta_event) - sizeof(struct bt_hci_evt_le_per_advertising_report); + data_len_total = node_rx->hdr.rx_ftr.aux_data_len; evt_buf = buf; - if ((le_event_mask & BT_EVT_MASK_LE_PER_ADVERTISING_REPORT) && accept) { + if ((le_event_mask & BT_EVT_MASK_LE_PER_ADVERTISING_REPORT) && accept && + ((data_len_total - data_len) < CONFIG_BT_CTLR_SCAN_DATA_LEN_MAX)) { + + data_len = MIN(data_len, (CONFIG_BT_CTLR_SCAN_DATA_LEN_MAX + + data_len - data_len_total)); + do { struct bt_hci_evt_le_per_advertising_report *sep; uint8_t data_len_frag; + uint8_t data_status; data_len_frag = MIN(data_len, data_len_max); @@ -6553,17 +6560,30 @@ static void le_per_adv_sync_report(struct pdu_data *pdu_data, BT_HCI_EVT_LE_PER_ADVERTISING_REPORT, sizeof(*sep) + data_len_frag); + sep->handle = sys_cpu_to_le16(node_rx->hdr.handle); + sep->tx_power = tx_pwr; + sep->rssi = rssi; + sep->cte_type = cte_type; + sep->length = data_len_frag; memcpy(&sep->data[0], data, data_len_frag); + data += data_len_frag; data_len -= data_len_frag; if (data_len > 0) { /* Some data left in PDU, mark as partial data. */ data_status = BT_HCI_LE_ADV_EVT_TYPE_DATA_STATUS_PARTIAL; - } else if (!aux_ptr) { + + evt_buf = bt_buf_get_rx(BT_BUF_EVT, K_FOREVER); + net_buf_frag_add(buf, evt_buf); + + tx_pwr = BT_HCI_LE_ADV_TX_POWER_NO_PREF; + } else if (!aux_ptr && + (data_len_total <= CONFIG_BT_CTLR_SCAN_DATA_LEN_MAX)) { /* No data left, no AuxPtr, mark as complete data. */ data_status = BT_HCI_LE_ADV_EVT_TYPE_DATA_STATUS_COMPLETE; - } else if (ftr->aux_w4next) { + } else if (ftr->aux_sched && + (data_len_total < CONFIG_BT_CTLR_SCAN_DATA_LEN_MAX)) { /* No data left, but have AuxPtr and scheduled aux scan, * mark as partial data. */ @@ -6575,22 +6595,7 @@ static void le_per_adv_sync_report(struct pdu_data *pdu_data, data_status = BT_HCI_LE_ADV_EVT_TYPE_DATA_STATUS_INCOMPLETE; } - sep->handle = sys_cpu_to_le16(node_rx->hdr.handle); - /* TODO: use actual TX power only on 1st report, subsequent - * reports can use 0x7F - */ - sep->tx_power = tx_pwr; - sep->rssi = rssi; - sep->cte_type = cte_type; sep->data_status = data_status; - sep->length = data_len_frag; - - if (data_len > 0) { - evt_buf = bt_buf_get_rx(BT_BUF_EVT, K_FOREVER); - net_buf_frag_add(buf, evt_buf); - - tx_pwr = BT_HCI_LE_ADV_TX_POWER_NO_PREF; - } } while (data_len > 0); evt_buf = NULL; diff --git a/subsys/bluetooth/controller/ll_sw/lll.h b/subsys/bluetooth/controller/ll_sw/lll.h index fc50cc4f532..1ff8369552a 100644 --- a/subsys/bluetooth/controller/ll_sw/lll.h +++ b/subsys/bluetooth/controller/ll_sw/lll.h @@ -327,21 +327,24 @@ struct node_rx_ftr { #endif /* CONFIG_BT_CTLR_EXT_SCAN_FP */ #if defined(CONFIG_BT_CTLR_ADV_EXT) && defined(CONFIG_BT_OBSERVER) + uint8_t phy_flags:1; + uint8_t scan_req:1; + uint8_t scan_rsp:1; + #if defined(CONFIG_BT_CTLR_PRIVACY) uint8_t direct_resolved:1; #endif /* CONFIG_BT_CTLR_PRIVACY */ - uint8_t aux_lll_sched:1; - uint8_t aux_w4next:1; - uint8_t aux_failed:1; #if defined(CONFIG_BT_CTLR_SYNC_PERIODIC) uint8_t sync_status:2; uint8_t sync_rx_enabled:1; #endif /* CONFIG_BT_CTLR_SYNC_PERIODIC */ - uint8_t phy_flags:1; - uint8_t scan_req:1; - uint8_t scan_rsp:1; + uint8_t aux_sched:1; + uint8_t aux_lll_sched:1; + uint8_t aux_failed:1; + + uint16_t aux_data_len; #endif /* CONFIG_BT_CTLR_ADV_EXT && CONFIG_BT_OBSERVER */ #if defined(CONFIG_BT_HCI_MESH_EXT) diff --git a/subsys/bluetooth/controller/ll_sw/ull_scan_aux.c b/subsys/bluetooth/controller/ll_sw/ull_scan_aux.c index 2949d92228c..c56d844d708 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_scan_aux.c +++ b/subsys/bluetooth/controller/ll_sw/ull_scan_aux.c @@ -107,9 +107,11 @@ void ull_scan_aux_setup(memq_link_t *link, struct node_rx_hdr *rx) uint32_t ticker_status; struct lll_scan *lll; struct pdu_adv *pdu; + uint8_t hdr_buf_len; uint8_t aux_handle; bool is_scan_req; uint8_t acad_len; + uint8_t data_len; uint8_t hdr_len; uint8_t *ptr; uint8_t phy; @@ -273,11 +275,25 @@ void ull_scan_aux_setup(memq_link_t *link, struct node_rx_hdr *rx) rx->link = link; ftr->extra = NULL; - ftr->aux_w4next = 0; + ftr->aux_sched = 0U; pdu = (void *)((struct node_rx_pdu *)rx)->pdu; p = (void *)&pdu->adv_ext_ind; if (!p->ext_hdr_len) { + data_len = pdu->len - PDU_AC_EXT_HEADER_SIZE_MIN; + if (sync_lll) { + struct ll_sync_set *sync; + + sync = HDR_LLL2ULL(sync_lll); + ftr->aux_data_len = sync->data_len + data_len; + sync->data_len = 0U; + } else if (aux) { + aux->data_len += data_len; + ftr->aux_data_len = aux->data_len; + } else { + ftr->aux_data_len = data_len; + } + goto ull_scan_aux_rx_flush; } @@ -355,14 +371,20 @@ void ull_scan_aux_setup(memq_link_t *link, struct node_rx_hdr *rx) /* Calculate ACAD Len */ hdr_len = ptr - (uint8_t *)p; - if (hdr_len <= (p->ext_hdr_len + offsetof(struct pdu_adv_com_ext_adv, - ext_hdr_adv_data))) { - acad_len = p->ext_hdr_len + - offsetof(struct pdu_adv_com_ext_adv, - ext_hdr_adv_data) - - hdr_len; - } else { + hdr_buf_len = PDU_AC_EXT_HEADER_SIZE_MIN + p->ext_hdr_len; + if (hdr_len > hdr_buf_len) { + /* FIXME: Handle invalid header length */ acad_len = 0U; + } else { + acad_len = hdr_buf_len - hdr_len; + hdr_len += acad_len; + } + + /* calculate total data length */ + if (hdr_len < pdu->len) { + data_len = pdu->len - hdr_len; + } else { + data_len = 0U; } /* Periodic Advertising Channel Map Indication and/or Broadcast ISO @@ -386,6 +408,19 @@ void ull_scan_aux_setup(memq_link_t *link, struct node_rx_hdr *rx) */ if (!aux_ptr || !aux_ptr->offs || is_scan_req || (aux_ptr->phy > EXT_ADV_AUX_PHY_LE_CODED)) { + if (sync_lll) { + struct ll_sync_set *sync; + + sync = HDR_LLL2ULL(sync_lll); + ftr->aux_data_len = sync->data_len + data_len; + sync->data_len = 0U; + } else if (aux) { + aux->data_len += data_len; + ftr->aux_data_len = aux->data_len; + } else { + ftr->aux_data_len = data_len; + } + if (is_scan_req) { LL_ASSERT(aux && aux->rx_last); @@ -401,10 +436,19 @@ void ull_scan_aux_setup(memq_link_t *link, struct node_rx_hdr *rx) if (!aux) { aux = aux_acquire(); if (!aux) { + if (sync_lll) { + struct ll_sync_set *sync; + + sync = HDR_LLL2ULL(sync_lll); + ftr->aux_data_len = sync->data_len + data_len; + sync->data_len = 0U; + } + goto ull_scan_aux_rx_flush; } aux->rx_head = aux->rx_last = NULL; + aux->data_len = data_len; lll_aux = &aux->lll; lll_aux->is_chain_sched = 0U; @@ -412,14 +456,25 @@ void ull_scan_aux_setup(memq_link_t *link, struct node_rx_hdr *rx) lll_hdr_init(lll_aux, aux); aux->parent = lll ? (void *)lll : (void *)sync_lll; + } else { + aux->data_len += data_len; } + /* AUX_ADV_IND/AUX_CHAIN_IND PDU reception is being setup */ + ftr->aux_sched = 1U; + /* In sync context we can dispatch rx immediately, in scan context we * enqueue rx in aux context and will flush them after scan is complete. */ if (0) { #if defined(CONFIG_BT_CTLR_SYNC_PERIODIC) } else if (sync_lll) { + struct ll_sync_set *sync; + + sync = HDR_LLL2ULL(sync_lll); + sync->data_len += data_len; + ftr->aux_data_len = sync->data_len; + ll_rx_put(link, rx); ll_rx_sched(); #endif /* CONFIG_BT_CTLR_SYNC_PERIODIC */ @@ -430,13 +485,15 @@ void ull_scan_aux_setup(memq_link_t *link, struct node_rx_hdr *rx) aux->rx_head = rx; } aux->rx_last = rx; + + ftr->aux_data_len = aux->data_len; } + /* Initialize the channel index and PHY for the Auxiliary PDU reception. + */ lll_aux->chan = aux_ptr->chan_idx; lll_aux->phy = BIT(aux_ptr->phy); - ftr->aux_w4next = 1; - /* See if this was already scheduled from LLL. If so, store aux context * in global scan struct so we can pick it when scanned node is received * with a valid context. @@ -575,6 +632,7 @@ void ull_scan_aux_setup(memq_link_t *link, struct node_rx_hdr *rx) aux->rx_last->rx_ftr.extra = rx; } else { LL_ASSERT(sync_lll); + ll_rx_put(link, rx); ll_rx_sched(); } @@ -698,8 +756,12 @@ void ull_scan_aux_release(memq_link_t *link, struct node_rx_hdr *rx) lll_aux = rx->rx_ftr.param; #if defined(CONFIG_BT_CTLR_SYNC_PERIODIC) } else if (ull_sync_is_valid_get(param_ull)) { + struct ll_sync_set *sync; struct lll_sync *lll; + sync = param_ull; + sync->data_len = 0U; + lll = rx->rx_ftr.param; lll_aux = lll->lll_aux; @@ -707,7 +769,7 @@ void ull_scan_aux_release(memq_link_t *link, struct node_rx_hdr *rx) * data properly. */ rx->type = NODE_RX_TYPE_SYNC_REPORT; - rx->handle = ull_sync_handle_get(param_ull); + rx->handle = ull_sync_handle_get(sync); /* Dequeue will try releasing list of node rx, set the extra * pointer to NULL. diff --git a/subsys/bluetooth/controller/ll_sw/ull_scan_types.h b/subsys/bluetooth/controller/ll_sw/ull_scan_types.h index 429986e45b9..15eaa998a05 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_scan_types.h +++ b/subsys/bluetooth/controller/ll_sw/ull_scan_types.h @@ -44,4 +44,6 @@ struct ll_scan_aux_set { struct node_rx_hdr *rx_head; struct node_rx_hdr *rx_last; + + uint16_t data_len; }; diff --git a/subsys/bluetooth/controller/ll_sw/ull_sync.c b/subsys/bluetooth/controller/ll_sw/ull_sync.c index f93f8627c22..39d41ba18b7 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_sync.c +++ b/subsys/bluetooth/controller/ll_sw/ull_sync.c @@ -477,6 +477,9 @@ void ull_sync_release(struct ll_sync_set *sync) /* Mark sync context not sync established */ sync->timeout_reload = 0U; + /* reset accumulated data len */ + sync->data_len = 0U; + mem_release(sync, &sync_free); } diff --git a/subsys/bluetooth/controller/ll_sw/ull_sync_types.h b/subsys/bluetooth/controller/ll_sw/ull_sync_types.h index 2da6b8ecc5d..8c812403d9a 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_sync_types.h +++ b/subsys/bluetooth/controller/ll_sw/ull_sync_types.h @@ -74,6 +74,8 @@ struct ll_sync_set { struct ll_sync_iso_set *volatile sync_iso; } iso; #endif /* CONFIG_BT_CTLR_SYNC_ISO */ + + uint16_t data_len; }; struct node_rx_sync { From af4c5694780bbadea55fddb931385dd9938a405b Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Fri, 10 Dec 2021 06:34:55 +0530 Subject: [PATCH 153/207] [nrf fromtree] Bluetooth: Controller: Fix parsing empty ADV_EXT_IND and ADV_SYNC_IND Fix implementation to check for empty ADV_EXT_IND and ADV_SYNC_IND PDUs, and not parse them incorrectly. Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit 3f37210cd6c709158c6ce5609eb398c906baa729) (cherry picked from commit b83d15b3a1b2dbf39068f7e3ea5642a4c8f00c04) --- .../bluetooth/controller/ll_sw/nordic/lll/lll_scan_aux.c | 5 +++++ subsys/bluetooth/controller/ll_sw/ull_scan_aux.c | 9 +++++++-- 2 files changed, 12 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 d14a2b561f2..4c315b9f893 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 @@ -135,6 +135,11 @@ uint8_t lll_scan_aux_setup(struct pdu_adv *pdu, uint8_t pdu_phy, /* Get reference to extended header */ pri_com_hdr = (void *)&pdu->adv_ext_ind; + if (!pdu->len || !pri_com_hdr->ext_hdr_len) { + return 0U; + } + + /* Get reference to flags and contents */ pri_hdr = (void *)pri_com_hdr->ext_hdr_adv_data; pri_dptr = pri_hdr->data; diff --git a/subsys/bluetooth/controller/ll_sw/ull_scan_aux.c b/subsys/bluetooth/controller/ll_sw/ull_scan_aux.c index c56d844d708..e74c8a0a9bb 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_scan_aux.c +++ b/subsys/bluetooth/controller/ll_sw/ull_scan_aux.c @@ -279,8 +279,13 @@ void ull_scan_aux_setup(memq_link_t *link, struct node_rx_hdr *rx) pdu = (void *)((struct node_rx_pdu *)rx)->pdu; p = (void *)&pdu->adv_ext_ind; - if (!p->ext_hdr_len) { - data_len = pdu->len - PDU_AC_EXT_HEADER_SIZE_MIN; + if (!pdu->len || !p->ext_hdr_len) { + if (pdu->len) { + data_len = pdu->len - PDU_AC_EXT_HEADER_SIZE_MIN; + } else { + data_len = 0U; + } + if (sync_lll) { struct ll_sync_set *sync; From efa3261f340de464ab7a290619ab5654dd0f99b5 Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Tue, 25 Jan 2022 11:20:59 +0530 Subject: [PATCH 154/207] [nrf fromtree] Bluetooth: Controller: Fix missing ISO data packet receive Fix missing ISO Data packet received by Synchronized Receiver due to incorrect check on sink handle that did not permit handle value of 0. Fixed function to get ISO stream context to check for valid ISO sync context, i.e. not being terminated. Regression introduced in commit 7c89f1fe9f2e ("Bluetooth: controller: Support for separate ISO RX data path"). Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit b5ab2f13534a680489c5ffff1f9d489ce56a4134) (cherry picked from commit 6a6fac9c4ea714f567be340696d6428ae54e7797) --- subsys/bluetooth/controller/hci/hci_driver.c | 4 ++-- subsys/bluetooth/controller/ll_sw/ull_iso.c | 6 +++++- subsys/bluetooth/controller/ll_sw/ull_sync_iso.c | 7 ++++++- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/subsys/bluetooth/controller/hci/hci_driver.c b/subsys/bluetooth/controller/hci/hci_driver.c index c252234f9c4..495030b69ba 100644 --- a/subsys/bluetooth/controller/hci/hci_driver.c +++ b/subsys/bluetooth/controller/hci/hci_driver.c @@ -387,9 +387,9 @@ static inline struct net_buf *encode_node(struct node_rx_pdu *node_rx, stream = ull_sync_iso_stream_get(node_rx->hdr.handle); /* Check validity of the data path sink. FIXME: A channel disconnect race - * may cause ISO data pending with without valid data path. + * may cause ISO data pending without valid data path. */ - if (stream && stream->dp && stream->dp->sink_hdl) { + if (stream && stream->dp) { isoal_rx.meta = &node_rx->hdr.rx_iso_meta; isoal_rx.pdu = (void *)node_rx->pdu; err = isoal_rx_pdu_recombine(stream->dp->sink_hdl, &isoal_rx); diff --git a/subsys/bluetooth/controller/ll_sw/ull_iso.c b/subsys/bluetooth/controller/ll_sw/ull_iso.c index 47d7e98585a..ea27fd2aabb 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_iso.c +++ b/subsys/bluetooth/controller/ll_sw/ull_iso.c @@ -238,7 +238,7 @@ uint8_t ll_setup_iso_path(uint16_t handle, uint8_t path_dir, uint8_t path_id, stream_handle = handle - BT_CTLR_SYNC_ISO_STREAM_HANDLE_BASE; stream = ull_sync_iso_stream_get(stream_handle); - if (stream->dp) { + if (!stream || stream->dp) { return BT_HCI_ERR_CMD_DISALLOWED; } #endif /* CONFIG_BT_CTLR_CONN_ISO */ @@ -406,6 +406,10 @@ uint8_t ll_remove_iso_path(uint16_t handle, uint8_t path_dir) stream_handle = handle - BT_CTLR_SYNC_ISO_STREAM_HANDLE_BASE; stream = ull_sync_iso_stream_get(stream_handle); + if (!stream) { + return BT_HCI_ERR_CMD_DISALLOWED; + } + dp = stream->dp; if (dp) { stream->dp = NULL; diff --git a/subsys/bluetooth/controller/ll_sw/ull_sync_iso.c b/subsys/bluetooth/controller/ll_sw/ull_sync_iso.c index 6b85b567d1d..93584dd8b22 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_sync_iso.c +++ b/subsys/bluetooth/controller/ll_sw/ull_sync_iso.c @@ -268,7 +268,11 @@ struct ll_sync_iso_set *ull_sync_iso_by_stream_get(uint16_t handle) struct lll_sync_iso_stream *ull_sync_iso_stream_get(uint16_t handle) { - if (handle >= CONFIG_BT_CTLR_SYNC_ISO_STREAM_COUNT) { + struct ll_sync_iso_set *sync_iso; + + /* Get the BIG Sync context and check for not being terminated */ + sync_iso = ull_sync_iso_by_stream_get(handle); + if (!sync_iso || !sync_iso->sync) { return NULL; } @@ -287,6 +291,7 @@ void ull_sync_iso_stream_release(struct ll_sync_iso_set *sync_iso) handle = lll->stream_handle[lll->stream_count]; stream = ull_sync_iso_stream_get(handle); + LL_ASSERT(stream); dp = stream->dp; if (dp) { From 9e2ea80dc0739bac4eada72de4aab56d60eae3db Mon Sep 17 00:00:00 2001 From: Piotr Pryga Date: Fri, 28 Jan 2022 20:16:18 +0100 Subject: [PATCH 155/207] [nrf fromtree] Bluetooth: Controller: df: Add missing CTE request is_enabled set There were missing set of is_enabled member of CTE request. That allowed host to run HCI_LE_Connection_CTE_Request_Enable command with enable parameter set to true sequently. That violates BT 5.3 Core specification Vol 4 Part B section 7.8.8.85. Signed-off-by: Piotr Pryga (cherry picked from commit 1856c6b23e8e5be262b322c74b79dff25b7fcc0e) (cherry picked from commit a88837500d8b5f5f881b3a8d986c27323fc55942) --- subsys/bluetooth/controller/ll_sw/ull_df.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subsys/bluetooth/controller/ll_sw/ull_df.c b/subsys/bluetooth/controller/ll_sw/ull_df.c index 21b3a2f7f79..37320c3ffa6 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_df.c +++ b/subsys/bluetooth/controller/ll_sw/ull_df.c @@ -1218,7 +1218,7 @@ uint8_t ll_df_set_conn_cte_req_enable(uint16_t handle, uint8_t enable, return BT_HCI_ERR_UNSUPP_REMOTE_FEATURE; } - conn->llcp.cte_req.is_enabled = 0U; + conn->llcp.cte_req.is_enabled = 1U; conn->llcp.cte_req.req_interval = cte_request_interval; conn->llcp.cte_req.cte_type = requested_cte_type; conn->llcp.cte_req.min_cte_len = requested_cte_length; From 395990d0aa7f697252dc0dee5670d546a0a78ad5 Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Wed, 8 Dec 2021 22:31:24 +0530 Subject: [PATCH 156/207] [nrf fromtree] Bluetooth: Controller: Fix to defer Periodic Report after ULL schedule Fix Periodic Advertising Report data status when ULL scheduling to receive auxiliary PDU fails. Defer the dispatch of Periodic Advertising Report until ULL scheduling status is comfirmed and assign the correct value to aux_sched flag. Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit 1b3671005f40e1d107b3c352e9a86300d6d69263) (cherry picked from commit a6b962609c22d1fabcd2a37636d66cc2f6d77a1c) --- .../controller/ll_sw/nordic/lll/lll_sync.c | 12 +- .../bluetooth/controller/ll_sw/ull_scan_aux.c | 184 ++++++++++++++++-- .../controller/ll_sw/ull_scan_types.h | 4 + 3 files changed, 184 insertions(+), 16 deletions(-) diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_sync.c b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_sync.c index f5e8e91e210..e4fc8476a81 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_sync.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_sync.c @@ -606,7 +606,13 @@ static int isr_rx(struct lll_sync *lll, uint8_t node_type, uint8_t crc_ok, uint8 if (crc_ok) { struct node_rx_pdu *node_rx; - node_rx = ull_pdu_rx_alloc_peek(3); + /* Verify if there are free RX buffers for: + * - reporting just received PDU + * - allocating an extra node_rx for periodic report incomplete + * - a buffer for receiving data in a connection + * - a buffer for receiving empty PDU + */ + node_rx = ull_pdu_rx_alloc_peek(4); if (node_rx) { struct node_rx_ftr *ftr; struct pdu_adv *pdu; @@ -627,6 +633,10 @@ static int isr_rx(struct lll_sync *lll, uint8_t node_type, uint8_t crc_ok, uint8 ftr->sync_status = status; ftr->sync_rx_enabled = lll->is_rx_enabled; + if (node_type != NODE_RX_TYPE_EXT_AUX_REPORT) { + ftr->extra = ull_pdu_rx_alloc(); + } + pdu = (void *)node_rx->pdu; ftr->aux_lll_sched = lll_scan_aux_setup(pdu, lll->phy, diff --git a/subsys/bluetooth/controller/ll_sw/ull_scan_aux.c b/subsys/bluetooth/controller/ll_sw/ull_scan_aux.c index e74c8a0a9bb..d90c2ebd53a 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_scan_aux.c +++ b/subsys/bluetooth/controller/ll_sw/ull_scan_aux.c @@ -53,11 +53,21 @@ static inline struct ll_sync_iso_set * static void last_disabled_cb(void *param); static void done_disabled_cb(void *param); static void flush(void *param); + +#if defined(CONFIG_BT_CTLR_SYNC_PERIODIC) +static void rx_release_put(struct node_rx_hdr *rx); +#endif /* CONFIG_BT_CTLR_SYNC_PERIODIC */ + static void ticker_cb(uint32_t ticks_at_expire, uint32_t ticks_drift, uint32_t remainder, uint16_t lazy, uint8_t force, void *param); static void ticker_op_cb(uint32_t status, void *param); +/* Auxiliary context pool used for reception of PDUs at aux offsets, common for + * both Extended Advertising and Periodic Advertising. + * Increasing the count allows simultaneous reception of interleaved chain PDUs + * from multiple advertisers. + */ static struct ll_scan_aux_set ll_scan_aux_pool[CONFIG_BT_CTLR_SCAN_AUX_SET]; static void *scan_aux_free; @@ -87,6 +97,7 @@ int ull_scan_aux_reset(void) void ull_scan_aux_setup(memq_link_t *link, struct node_rx_hdr *rx) { + struct node_rx_hdr *rx_incomplete; struct ll_sync_iso_set *sync_iso; struct pdu_adv_aux_ptr *aux_ptr; struct pdu_adv_com_ext_adv *p; @@ -125,6 +136,7 @@ void ull_scan_aux_setup(memq_link_t *link, struct node_rx_hdr *rx) aux = NULL; sync_lll = NULL; sync_iso = NULL; + rx_incomplete = NULL; lll = ftr->param; scan = HDR_LLL2ULL(lll); sync = sync_create_get(scan); @@ -135,6 +147,7 @@ void ull_scan_aux_setup(memq_link_t *link, struct node_rx_hdr *rx) aux = NULL; sync_lll = NULL; sync_iso = NULL; + rx_incomplete = NULL; lll = ftr->param; scan = HDR_LLL2ULL(lll); sync = sync_create_get(scan); @@ -142,6 +155,7 @@ void ull_scan_aux_setup(memq_link_t *link, struct node_rx_hdr *rx) break; case NODE_RX_TYPE_EXT_AUX_REPORT: sync_iso = NULL; + rx_incomplete = NULL; if (ull_scan_aux_is_valid_get(HDR_LLL2ULL(ftr->param))) { sync_lll = NULL; @@ -263,6 +277,11 @@ void ull_scan_aux_setup(memq_link_t *link, struct node_rx_hdr *rx) scan = NULL; sync = NULL; phy = sync_lll->phy; + + /* backup extra node_rx supplied for generating + * incomplete report + */ + rx_incomplete = ftr->extra; #endif /* CONFIG_BT_CTLR_SYNC_PERIODIC */ } @@ -447,6 +466,7 @@ void ull_scan_aux_setup(memq_link_t *link, struct node_rx_hdr *rx) sync = HDR_LLL2ULL(sync_lll); ftr->aux_data_len = sync->data_len + data_len; sync->data_len = 0U; + } goto ull_scan_aux_rx_flush; @@ -461,13 +481,16 @@ void ull_scan_aux_setup(memq_link_t *link, struct node_rx_hdr *rx) lll_hdr_init(lll_aux, aux); aux->parent = lll ? (void *)lll : (void *)sync_lll; + +#if defined(CONFIG_BT_CTLR_SYNC_PERIODIC) + aux->rx_incomplete = rx_incomplete; + rx_incomplete = NULL; +#endif /* CONFIG_BT_CTLR_SYNC_PERIODIC */ + } else { aux->data_len += data_len; } - /* AUX_ADV_IND/AUX_CHAIN_IND PDU reception is being setup */ - ftr->aux_sched = 1U; - /* In sync context we can dispatch rx immediately, in scan context we * enqueue rx in aux context and will flush them after scan is complete. */ @@ -480,8 +503,6 @@ void ull_scan_aux_setup(memq_link_t *link, struct node_rx_hdr *rx) sync->data_len += data_len; ftr->aux_data_len = sync->data_len; - ll_rx_put(link, rx); - ll_rx_sched(); #endif /* CONFIG_BT_CTLR_SYNC_PERIODIC */ } else { if (aux->rx_last) { @@ -504,10 +525,18 @@ void ull_scan_aux_setup(memq_link_t *link, struct node_rx_hdr *rx) * with a valid context. */ if (ftr->aux_lll_sched) { + /* AUX_ADV_IND/AUX_CHAIN_IND PDU reception is being setup */ + ftr->aux_sched = 1U; + if (0) { #if defined(CONFIG_BT_CTLR_SYNC_PERIODIC) } else if (sync_lll) { sync_lll->lll_aux = lll_aux; + + /* In sync context, dispatch immediately */ + ll_rx_put(link, rx); + ll_rx_sched(); + #endif /* CONFIG_BT_CTLR_SYNC_PERIODIC */ } else { lll->lll_aux = lll_aux; @@ -528,6 +557,8 @@ void ull_scan_aux_setup(memq_link_t *link, struct node_rx_hdr *rx) LL_ASSERT(sync_lll && (!sync_lll->lll_aux || sync_lll->lll_aux == lll_aux)); sync_lll->lll_aux = lll_aux; + + aux->rx_head = rx; } /* Determine the window size */ @@ -666,6 +697,13 @@ void ull_scan_aux_setup(memq_link_t *link, struct node_rx_hdr *rx) } ll_rx_put(link, rx); + +#if defined(CONFIG_BT_CTLR_SYNC_PERIODIC) + if (rx_incomplete) { + rx_release_put(rx_incomplete); + } +#endif /* CONFIG_BT_CTLR_SYNC_PERIODIC */ + ll_rx_sched(); } @@ -765,6 +803,8 @@ void ull_scan_aux_release(memq_link_t *link, struct node_rx_hdr *rx) struct lll_sync *lll; sync = param_ull; + + /* reset data len total */ sync->data_len = 0U; lll = rx->rx_ftr.param; @@ -917,29 +957,110 @@ static void done_disabled_cb(void *param) static void flush(void *param) { struct ll_scan_aux_set *aux; + struct ll_scan_set *scan; struct node_rx_hdr *rx; + struct lll_scan *lll; + bool sched = false; - /* Nodes are enqueued only in scan context so need to send them now */ aux = param; rx = aux->rx_head; if (rx) { - struct lll_scan *lll; + ll_rx_put(rx->link, rx); + sched = true; + } - lll = aux->parent; - lll->lll_aux = NULL; +#if defined(CONFIG_BT_CTLR_SYNC_PERIODIC) + if (aux->rx_incomplete) { + rx_release_put(aux->rx_incomplete); + sched = true; + } +#endif /* CONFIG_BT_CTLR_SYNC_PERIODIC */ - ll_rx_put(rx->link, rx); + if (sched) { ll_rx_sched(); + } + + lll = aux->parent; + scan = HDR_LLL2ULL(lll); + scan = ull_scan_is_valid_get(scan); + if (scan) { + lll->lll_aux = NULL; } else { + struct lll_sync *sync_lll; + + sync_lll = aux->parent; + + LL_ASSERT(sync_lll->lll_aux); + sync_lll->lll_aux = NULL; + } + + aux_release(aux); +} + +#if defined(CONFIG_BT_CTLR_SYNC_PERIODIC) +static void rx_release_put(struct node_rx_hdr *rx) +{ + rx->type = NODE_RX_TYPE_RELEASE; + + ll_rx_put(rx->link, rx); +} + +static void aux_sync_partial(void *param) +{ + struct ll_scan_aux_set *aux; + struct node_rx_hdr *rx; + + aux = param; + rx = aux->rx_head; + aux->rx_head = NULL; + + rx->rx_ftr.aux_sched = 1U; + + ll_rx_put(rx->link, rx); + ll_rx_sched(); +} + +static void aux_sync_incomplete(void *param) +{ + struct ll_scan_aux_set *aux; + + aux = param; + if (!aux->rx_head) { + struct ll_sync_set *sync; + struct node_rx_hdr *rx; struct lll_sync *lll; + /* get reference to sync context */ lll = aux->parent; - LL_ASSERT(lll->lll_aux); - lll->lll_aux = NULL; + sync = HDR_LLL2ULL(lll); + + /* reset data len total */ + sync->data_len = 0U; + + /* pick extra node rx stored in aux context */ + rx = aux->rx_incomplete; + LL_ASSERT(rx); + aux->rx_incomplete = NULL; + + /* prepare sync report with failure */ + rx->type = NODE_RX_TYPE_SYNC_REPORT; + rx->handle = ull_sync_handle_get(sync); + + /* flag chain reception failure */ + rx->rx_ftr.aux_failed = 1U; + + /* Dequeue will try releasing list of node rx, + * set the extra pointer to NULL. + */ + rx->rx_ftr.extra = NULL; + + /* add to rx list, will be flushed */ + aux->rx_head = rx; } - aux_release(aux); + flush(aux); } +#endif /* CONFIG_BT_CTLR_SYNC_PERIODIC */ static void ticker_cb(uint32_t ticks_at_expire, uint32_t ticks_drift, uint32_t remainder, uint16_t lazy, uint8_t force, @@ -977,11 +1098,44 @@ static void ticker_cb(uint32_t ticks_at_expire, uint32_t ticks_drift, static void ticker_op_cb(uint32_t status, void *param) { static memq_link_t link; - static struct mayfly mfy = {0, 0, &link, NULL, flush}; + static struct mayfly mfy = {0, 0, &link, NULL, NULL}; + struct ll_sync_set *sync; uint32_t ret; + if (IS_ENABLED(CONFIG_BT_CTLR_SYNC_PERIODIC)) { + struct ll_scan_aux_set *aux; + struct lll_sync *sync_lll; + + aux = param; + sync_lll = aux->parent; + sync = HDR_LLL2ULL(sync_lll); + sync = ull_sync_is_valid_get(sync); + } else { + sync = NULL; + } + if (status == TICKER_STATUS_SUCCESS) { - return; + if (0) { + +#if defined(CONFIG_BT_CTLR_SYNC_PERIODIC) + } else if (sync) { + mfy.fp = aux_sync_partial; +#endif /* CONFIG_BT_CTLR_SYNC_PERIODIC */ + + } else { + return; + } + } else { + if (0) { + +#if defined(CONFIG_BT_CTLR_SYNC_PERIODIC) + } else if (sync) { + mfy.fp = aux_sync_incomplete; +#endif /* CONFIG_BT_CTLR_SYNC_PERIODIC */ + + } else { + mfy.fp = flush; + } } mfy.param = param; diff --git a/subsys/bluetooth/controller/ll_sw/ull_scan_types.h b/subsys/bluetooth/controller/ll_sw/ull_scan_types.h index 15eaa998a05..8a7c7c94fc5 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_scan_types.h +++ b/subsys/bluetooth/controller/ll_sw/ull_scan_types.h @@ -46,4 +46,8 @@ struct ll_scan_aux_set { struct node_rx_hdr *rx_last; uint16_t data_len; + +#if defined(CONFIG_BT_CTLR_SYNC_PERIODIC) + struct node_rx_hdr *rx_incomplete; +#endif }; From e2738521592c92388a7b9c3174a1441dcfb955bd Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Thu, 9 Dec 2021 06:18:07 +0530 Subject: [PATCH 157/207] [nrf fromtree] Bluetooth: Controller: Refactor Periodic Advertising cond. compilation Refactor Periodic Advertising conditional compilation to use IS_ENABLED define. Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit ee8994ee42d35dd499e4e09cfdad0befe22ec6f6) (cherry picked from commit bbb0088ed5a23faf3998edfb1468a10f7ef597a3) --- .../ll_sw/nordic/lll/lll_scan_aux.c | 6 +- .../bluetooth/controller/ll_sw/ull_scan_aux.c | 79 ++++++------------- 2 files changed, 26 insertions(+), 59 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 4c315b9f893..733eec698b6 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 @@ -429,16 +429,14 @@ static int prepare_cb(struct lll_prepare_param *p) lll_aux = p->param; lll = ull_scan_aux_lll_parent_get(lll_aux, &is_lll_scan); -#if defined(CONFIG_BT_CTLR_SYNC_PERIODIC) /* Check if this aux scan is for periodic advertising train */ - if (!is_lll_scan) { + if (IS_ENABLED(CONFIG_BT_CTLR_SYNC_PERIODIC) && !is_lll_scan) { lll_sync_aux_prepare_cb((void *)lll, lll_aux); lll = NULL; goto sync_aux_prepare_done; } -#endif /* CONFIG_BT_CTLR_SYNC_PERIODIC */ #if defined(CONFIG_BT_CENTRAL) /* Check if stopped (on connection establishment race between @@ -519,9 +517,7 @@ static int prepare_cb(struct lll_prepare_param *p) (uint8_t *)fal->bdaddr); } -#if defined(CONFIG_BT_CTLR_SYNC_PERIODIC) sync_aux_prepare_done: -#endif /* Calculate event timings, coarse and fine */ ticks_at_event = p->ticks_at_expire; ull = HDR_LLL2ULL(lll_aux); diff --git a/subsys/bluetooth/controller/ll_sw/ull_scan_aux.c b/subsys/bluetooth/controller/ll_sw/ull_scan_aux.c index d90c2ebd53a..96e3154c232 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_scan_aux.c +++ b/subsys/bluetooth/controller/ll_sw/ull_scan_aux.c @@ -50,7 +50,6 @@ static inline uint8_t aux_handle_get(struct ll_scan_aux_set *aux); static inline struct ll_sync_set *sync_create_get(struct ll_scan_set *scan); static inline struct ll_sync_iso_set * sync_iso_create_get(struct ll_sync_set *sync); -static void last_disabled_cb(void *param); static void done_disabled_cb(void *param); static void flush(void *param); @@ -168,7 +167,8 @@ void ull_scan_aux_setup(memq_link_t *link, struct node_rx_hdr *rx) /* aux parent will be NULL for periodic sync */ lll = aux->parent; - } else if (ull_scan_is_valid_get(HDR_LLL2ULL(ftr->param))) { + } else if (!IS_ENABLED(CONFIG_BT_CTLR_SYNC_PERIODIC) || + ull_scan_is_valid_get(HDR_LLL2ULL(ftr->param))) { sync_lll = NULL; /* Node that does not have valid aux context but has @@ -195,7 +195,7 @@ void ull_scan_aux_setup(memq_link_t *link, struct node_rx_hdr *rx) aux = HDR_LLL2ULL(lll_aux); } - if (lll) { + if (!IS_ENABLED(CONFIG_BT_CTLR_SYNC_PERIODIC) || lll) { scan = HDR_LLL2ULL(lll); sync = (void *)scan; scan = ull_scan_is_valid_get(scan); @@ -208,7 +208,7 @@ void ull_scan_aux_setup(memq_link_t *link, struct node_rx_hdr *rx) } phy = lll_aux->phy; - if (scan) { + if (!IS_ENABLED(CONFIG_BT_CTLR_SYNC_PERIODIC) || scan) { /* Here we are scanner context */ sync = sync_create_get(scan); @@ -305,7 +305,7 @@ void ull_scan_aux_setup(memq_link_t *link, struct node_rx_hdr *rx) data_len = 0U; } - if (sync_lll) { + if (IS_ENABLED(CONFIG_BT_CTLR_SYNC_PERIODIC) && sync_lll) { struct ll_sync_set *sync; sync = HDR_LLL2ULL(sync_lll); @@ -378,15 +378,14 @@ void ull_scan_aux_setup(memq_link_t *link, struct node_rx_hdr *rx) si = (void *)ptr; ptr += sizeof(*si); -#if defined(CONFIG_BT_CTLR_SYNC_PERIODIC) /* Check if Periodic Advertising Synchronization to be created. * Setup synchronization if address and SID match in the * Periodic Advertiser List or with the explicitly supplied. */ - if (sync && adi && ull_sync_setup_sid_match(scan, adi->sid)) { + if (IS_ENABLED(CONFIG_BT_CTLR_SYNC_PERIODIC) && sync && adi && + ull_sync_setup_sid_match(scan, adi->sid)) { ull_sync_setup(scan, aux, rx, si); } -#endif /* CONFIG_BT_CTLR_SYNC_PERIODIC */ } if (h->tx_pwr) { @@ -432,7 +431,7 @@ void ull_scan_aux_setup(memq_link_t *link, struct node_rx_hdr *rx) */ if (!aux_ptr || !aux_ptr->offs || is_scan_req || (aux_ptr->phy > EXT_ADV_AUX_PHY_LE_CODED)) { - if (sync_lll) { + if (IS_ENABLED(CONFIG_BT_CTLR_SYNC_PERIODIC) && sync_lll) { struct ll_sync_set *sync; sync = HDR_LLL2ULL(sync_lll); @@ -460,7 +459,8 @@ void ull_scan_aux_setup(memq_link_t *link, struct node_rx_hdr *rx) if (!aux) { aux = aux_acquire(); if (!aux) { - if (sync_lll) { + if (IS_ENABLED(CONFIG_BT_CTLR_SYNC_PERIODIC) && + sync_lll) { struct ll_sync_set *sync; sync = HDR_LLL2ULL(sync_lll); @@ -494,16 +494,12 @@ void ull_scan_aux_setup(memq_link_t *link, struct node_rx_hdr *rx) /* In sync context we can dispatch rx immediately, in scan context we * enqueue rx in aux context and will flush them after scan is complete. */ - if (0) { -#if defined(CONFIG_BT_CTLR_SYNC_PERIODIC) - } else if (sync_lll) { + if (IS_ENABLED(CONFIG_BT_CTLR_SYNC_PERIODIC) && sync_lll) { struct ll_sync_set *sync; sync = HDR_LLL2ULL(sync_lll); sync->data_len += data_len; ftr->aux_data_len = sync->data_len; - -#endif /* CONFIG_BT_CTLR_SYNC_PERIODIC */ } else { if (aux->rx_last) { aux->rx_last->rx_ftr.extra = rx; @@ -528,16 +524,12 @@ void ull_scan_aux_setup(memq_link_t *link, struct node_rx_hdr *rx) /* AUX_ADV_IND/AUX_CHAIN_IND PDU reception is being setup */ ftr->aux_sched = 1U; - if (0) { -#if defined(CONFIG_BT_CTLR_SYNC_PERIODIC) - } else if (sync_lll) { + if (IS_ENABLED(CONFIG_BT_CTLR_SYNC_PERIODIC) && sync_lll) { sync_lll->lll_aux = lll_aux; /* In sync context, dispatch immediately */ ll_rx_put(link, rx); ll_rx_sched(); - -#endif /* CONFIG_BT_CTLR_SYNC_PERIODIC */ } else { lll->lll_aux = lll_aux; } @@ -551,7 +543,7 @@ void ull_scan_aux_setup(memq_link_t *link, struct node_rx_hdr *rx) } /* Switching to ULL scheduling to receive auxiliary PDUs */ - if (lll) { + if (!IS_ENABLED(CONFIG_BT_CTLR_SYNC_PERIODIC) || lll) { lll->lll_aux = NULL; } else { LL_ASSERT(sync_lll && @@ -664,7 +656,7 @@ void ull_scan_aux_setup(memq_link_t *link, struct node_rx_hdr *rx) /* Enqueue last rx in aux context if possible, otherwise send * immediately since we are in sync context. */ - if (aux->rx_last) { + if (!IS_ENABLED(CONFIG_BT_CTLR_SYNC_PERIODIC) || aux->rx_last) { aux->rx_last->rx_ftr.extra = rx; } else { LL_ASSERT(sync_lll); @@ -690,7 +682,7 @@ void ull_scan_aux_setup(memq_link_t *link, struct node_rx_hdr *rx) LL_ASSERT(!hdr->disabled_cb); hdr->disabled_param = aux; - hdr->disabled_cb = last_disabled_cb; + hdr->disabled_cb = done_disabled_cb; } return; @@ -715,9 +707,8 @@ void ull_scan_aux_done(struct node_rx_event_done *done) /* Get reference to ULL context */ aux = CONTAINER_OF(done->param, struct ll_scan_aux_set, ull); - if (0) { -#if defined(CONFIG_BT_CTLR_SYNC_PERIODIC) - } else if (!ull_scan_aux_is_valid_get(aux)) { + if (IS_ENABLED(CONFIG_BT_CTLR_SYNC_PERIODIC) && + !ull_scan_aux_is_valid_get(aux)) { struct ll_sync_set *sync; sync = CONTAINER_OF(done->param, struct ll_sync_set, ull); @@ -729,7 +720,6 @@ void ull_scan_aux_done(struct node_rx_event_done *done) } aux = HDR_LLL2ULL(sync->lll.lll_aux); -#endif /* CONFIG_BT_CTLR_SYNC_PERIODIC */ } else { /* Setup the disabled callback to flush the auxiliary PDUs */ hdr = &aux->ull; @@ -792,12 +782,14 @@ void ull_scan_aux_release(memq_link_t *link, struct node_rx_hdr *rx) lll = rx->rx_ftr.param; lll_aux = lll->lll_aux; - } else if (ull_scan_aux_is_valid_get(param_ull)) { + + } else if (!IS_ENABLED(CONFIG_BT_CTLR_SYNC_PERIODIC) || + ull_scan_aux_is_valid_get(param_ull)) { /* Mark for buffer for release */ rx->type = NODE_RX_TYPE_RELEASE; lll_aux = rx->rx_ftr.param; -#if defined(CONFIG_BT_CTLR_SYNC_PERIODIC) + } else if (ull_sync_is_valid_get(param_ull)) { struct ll_sync_set *sync; struct lll_sync *lll; @@ -820,7 +812,7 @@ void ull_scan_aux_release(memq_link_t *link, struct node_rx_hdr *rx) * pointer to NULL. */ rx->rx_ftr.extra = NULL; -#endif /* CONFIG_BT_CTLR_SYNC_PERIODIC */ + } else { LL_ASSERT(0); lll_aux = NULL; @@ -842,7 +834,7 @@ void ull_scan_aux_release(memq_link_t *link, struct node_rx_hdr *rx) LL_ASSERT(!hdr->disabled_cb); hdr->disabled_param = aux; - hdr->disabled_cb = last_disabled_cb; + hdr->disabled_cb = done_disabled_cb; } } @@ -928,30 +920,9 @@ static inline struct ll_sync_iso_set * #endif /* !CONFIG_BT_CTLR_SYNC_ISO */ } -static void last_disabled_cb(void *param) -{ - flush(param); -} - static void done_disabled_cb(void *param) { - struct ll_scan_aux_set *aux; - - aux = param; - LL_ASSERT(ull_scan_aux_is_valid_get(aux)); - - aux = ull_scan_aux_is_valid_get(aux); -#if defined(CONFIG_BT_CTLR_SYNC_PERIODIC) - if (!aux) { - struct lll_sync *sync_lll; - - sync_lll = param; - LL_ASSERT(sync_lll->lll_aux); - aux = HDR_LLL2ULL(sync_lll->lll_aux); - } -#endif /* CONFIG_BT_CTLR_SYNC_PERIODIC */ - - flush(aux); + flush(param); } static void flush(void *param) @@ -983,7 +954,7 @@ static void flush(void *param) lll = aux->parent; scan = HDR_LLL2ULL(lll); scan = ull_scan_is_valid_get(scan); - if (scan) { + if (!IS_ENABLED(CONFIG_BT_CTLR_SYNC_PERIODIC) || scan) { lll->lll_aux = NULL; } else { struct lll_sync *sync_lll; From 5ddd2c992793d184cb5c3273089842dd6913310d Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Thu, 9 Dec 2021 06:21:44 +0530 Subject: [PATCH 158/207] [nrf fromtree] Bluetooth: Controller: Fix Periodic Sync Aux context leak on -ENOMEM Fix Controller implementation to release auxiliary context when there is no node rx buffer available to receive Periodic Advertising Sync AUX_CHAIN_IND PDUs. Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit d43435a727286fb4406640857944b95c08c9daa3) (cherry picked from commit 57951589452023cdd2912698433ec2945b5c42d2) --- subsys/bluetooth/controller/ll_sw/nordic/lll/lll_sync.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_sync.c b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_sync.c index e4fc8476a81..457e6f319b5 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_sync.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_sync.c @@ -656,6 +656,8 @@ static int isr_rx(struct lll_sync *lll, uint8_t node_type, uint8_t crc_ok, uint8 ull_rx_put(node_rx->hdr.link, node_rx); sched = true; + } else if (node_type == NODE_RX_TYPE_EXT_AUX_REPORT) { + err = -ENOMEM; } else { err = 0; } @@ -834,6 +836,7 @@ static void isr_rx_aux_chain(void *param) lll_isr_status_reset(); crc_ok = 0U; + err = 0; goto isr_rx_aux_chain_done; } @@ -854,6 +857,9 @@ static void isr_rx_aux_chain(void *param) if (!trx_done) { /* TODO: Combine the early exit with above if-then-else block */ + + err = 0; + goto isr_rx_aux_chain_done; } @@ -869,7 +875,7 @@ static void isr_rx_aux_chain(void *param) } isr_rx_aux_chain_done: - if (!crc_ok) { + if (!crc_ok || err) { struct node_rx_pdu *node_rx; node_rx = ull_pdu_rx_alloc(); From 6bd88cdad744254e2d78855f2c787495e520c000 Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Sun, 12 Dec 2021 05:37:42 +0530 Subject: [PATCH 159/207] [nrf fromtree] Bluetooth: Controller: Fix missing Periodic LLL sched incomplete report Fix missing Periodic Advertising Report with incomplete data status when LLL scheduled chain reception is aborted. Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit 03f74c7ec23a9660a0679508139094824b3f4ed8) (cherry picked from commit d4f6364417e3427c96e6fd3e5200dd9b5548b12d) --- .../controller/ll_sw/nordic/lll/lll_sync.c | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_sync.c b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_sync.c index 457e6f319b5..8b8896d17c1 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_sync.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_sync.c @@ -878,6 +878,9 @@ static void isr_rx_aux_chain(void *param) if (!crc_ok || err) { struct node_rx_pdu *node_rx; + /* Generate message to release aux context and flag the report + * generated thereafter by HCI as incomplete. + */ node_rx = ull_pdu_rx_alloc(); LL_ASSERT(node_rx); @@ -930,7 +933,33 @@ static void isr_rx_done_cleanup(struct lll_sync *lll, uint8_t crc_ok, bool sync_ static void isr_done(void *param) { + struct lll_sync *lll; + lll_isr_status_reset(); + + lll = param; + + /* LLL scheduling used for chain PDU reception is aborted/preempted */ + if (lll->is_aux_sched) { + struct node_rx_pdu *node_rx; + + lll->is_aux_sched = 0U; + + /* Generate message to release aux context and flag the report + * generated thereafter by HCI as incomplete. + */ + node_rx = ull_pdu_rx_alloc(); + LL_ASSERT(node_rx); + + node_rx->hdr.type = NODE_RX_TYPE_EXT_AUX_RELEASE; + + node_rx->hdr.rx_ftr.param = lll; + node_rx->hdr.rx_ftr.aux_failed = 1U; + + ull_rx_put(node_rx->hdr.link, node_rx); + ull_rx_sched(); + } + isr_rx_done_cleanup(param, ((trx_cnt) ? 1U : 0U), false); } From 2f98bb3e886fcff1af2cbeed47a6466fb5693f77 Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Sun, 12 Dec 2021 05:37:42 +0530 Subject: [PATCH 160/207] [nrf fromtree] Bluetooth: Controller: Fix missing Periodic ULL sched incomplete report Fix missing Periodic Advertising Report with incomplete data status when ULL scheduled chain reception is aborted. Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit 5f4d6e34bcec11c36c77b38f79ec4d6f13bb2241) (cherry picked from commit 64aea361c7aef3ed55b2044d05356de7ec7dd27d) --- .../ll_sw/nordic/lll/lll_scan_aux.c | 31 +++++++++++++++++-- 1 file changed, 29 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 733eec698b6..78a1548706c 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 @@ -622,11 +622,38 @@ static void abort_cb(struct lll_prepare_param *prepare_param, void *param) static void isr_done(void *param) { - struct event_done_extra *e; + struct lll_sync *lll; + uint8_t is_lll_scan; lll_isr_status_reset(); - if (!trx_cnt) { + if (param) { + lll = ull_scan_aux_lll_parent_get(param, &is_lll_scan); + } else { + lll = NULL; + } + + /* Check if this aux scan is for periodic advertising train */ + if (IS_ENABLED(CONFIG_BT_CTLR_SYNC_PERIODIC) && lll && !is_lll_scan) { + struct node_rx_pdu *node_rx; + + /* Generate message to release aux context and flag the report + * generated thereafter by HCI as incomplete. + */ + node_rx = ull_pdu_rx_alloc(); + LL_ASSERT(node_rx); + + node_rx->hdr.type = NODE_RX_TYPE_EXT_AUX_RELEASE; + + node_rx->hdr.rx_ftr.param = lll; + node_rx->hdr.rx_ftr.aux_failed = 1U; + + ull_rx_put(node_rx->hdr.link, node_rx); + ull_rx_sched(); + + } else if (!trx_cnt) { + struct event_done_extra *e; + e = ull_done_extra_type_set(EVENT_DONE_EXTRA_TYPE_SCAN_AUX); LL_ASSERT(e); } From 72565bd921f6c9e46348804783bf683e881cf6ad Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Mon, 13 Dec 2021 21:30:08 +0530 Subject: [PATCH 161/207] [nrf fromtree] Bluetooth: Controller: Fix extended scan rx flush for continous scan Fix missing progression of the rx_last pointer when appending rx buffers before flushing them towards Host. Under continuous scanning, as the disabled_cb would only be called when reference count reaches zero, the rx_last pointer needs to progress when appending the rx buffers. Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit 79e3be3c6330c1b2e7448fc1f8ad3aa6ec891b06) (cherry picked from commit 7ccb425cfbfc53ef878acb5dea8f6623ca2950a9) --- subsys/bluetooth/controller/ll_sw/ull_scan_aux.c | 1 + 1 file changed, 1 insertion(+) diff --git a/subsys/bluetooth/controller/ll_sw/ull_scan_aux.c b/subsys/bluetooth/controller/ll_sw/ull_scan_aux.c index 96e3154c232..7e69a9f90cd 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_scan_aux.c +++ b/subsys/bluetooth/controller/ll_sw/ull_scan_aux.c @@ -658,6 +658,7 @@ void ull_scan_aux_setup(memq_link_t *link, struct node_rx_hdr *rx) */ if (!IS_ENABLED(CONFIG_BT_CTLR_SYNC_PERIODIC) || aux->rx_last) { aux->rx_last->rx_ftr.extra = rx; + aux->rx_last = rx; } else { LL_ASSERT(sync_lll); From 8a758f284d307ffd41287bec56fd85f2dfdf4830 Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Wed, 15 Dec 2021 21:07:57 +0530 Subject: [PATCH 162/207] [nrf fromtree] Bluetooth: Controller: Fix Periodic Sync memq link leak Fix memq link buffer leak on Periodic Sync failed to be established. Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit c474e374a77ac8e45c437b7fb3a524f5d101f180) (cherry picked from commit 8afba95c765e51e9cbea39838682d0a4a466f876) --- subsys/bluetooth/controller/ll_sw/ull.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/subsys/bluetooth/controller/ll_sw/ull.c b/subsys/bluetooth/controller/ll_sw/ull.c index dabf60fb8fb..574525138c2 100644 --- a/subsys/bluetooth/controller/ll_sw/ull.c +++ b/subsys/bluetooth/controller/ll_sw/ull.c @@ -1439,6 +1439,12 @@ void ll_rx_mem_release(void **node_rx) ull_sync_setup_complete(scan); if (status != BT_HCI_ERR_SUCCESS) { + memq_link_t *link_sync_lost; + + link_sync_lost = + sync->node_rx_lost.hdr.link; + ll_rx_link_release(link_sync_lost); + ull_sync_release(sync); } From cc36c16697ce669f79c27a642d824d840bd62bc5 Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Wed, 15 Dec 2021 21:05:20 +0530 Subject: [PATCH 163/207] [nrf fromtree] Bluetooth: Controller: Fix same peer periodic sync check Move the same peer periodic sync check to after check for existing periodic sync create on both 1M and Coded PHY. Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit f5a2b05b0d2c2d210c62ee68bae7018cb6664e7d) (cherry picked from commit 4a178c759c82b517d5b1a49c64f242e279437ab2) --- subsys/bluetooth/controller/ll_sw/ull_sync.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/subsys/bluetooth/controller/ll_sw/ull_sync.c b/subsys/bluetooth/controller/ll_sw/ull_sync.c index 39d41ba18b7..ffd414fc450 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_sync.c +++ b/subsys/bluetooth/controller/ll_sw/ull_sync.c @@ -106,14 +106,6 @@ uint8_t ll_sync_create(uint8_t options, uint8_t sid, uint8_t adv_addr_type, return BT_HCI_ERR_CMD_DISALLOWED; } -#if defined(CONFIG_BT_CTLR_CHECK_SAME_PEER_SYNC) - /* Do not sync twice to the same peer and same SID */ - if (((options & BT_HCI_LE_PER_ADV_CREATE_SYNC_FP_USE_LIST) == 0U) && - peer_sid_sync_exists(adv_addr_type, adv_addr, sid)) { - return BT_HCI_ERR_CONN_ALREADY_EXISTS; - } -#endif /* CONFIG_BT_CTLR_CHECK_SAME_PEER_SYNC */ - if (IS_ENABLED(CONFIG_BT_CTLR_PHY_CODED)) { scan_coded = ull_scan_set_get(SCAN_HANDLE_PHY_CODED); if (!scan_coded || scan_coded->periodic.sync) { @@ -121,7 +113,13 @@ uint8_t ll_sync_create(uint8_t options, uint8_t sid, uint8_t adv_addr_type, } } - /* FIXME: Check for already synchronized to same peer */ +#if defined(CONFIG_BT_CTLR_CHECK_SAME_PEER_SYNC) + /* Do not sync twice to the same peer and same SID */ + if (((options & BT_HCI_LE_PER_ADV_CREATE_SYNC_FP_USE_LIST) == 0U) && + peer_sid_sync_exists(adv_addr_type, adv_addr, sid)) { + return BT_HCI_ERR_CONN_ALREADY_EXISTS; + } +#endif /* CONFIG_BT_CTLR_CHECK_SAME_PEER_SYNC */ link_sync_estab = ll_rx_link_alloc(); if (!link_sync_estab) { From ee230998767b5ae1ff214f5f3d3f26e168a5253e Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Thu, 23 Dec 2021 11:46:36 +0530 Subject: [PATCH 164/207] [nrf fromtree] Bluetooth: Controller: Fix duplicate release of auxiliary context Fix duplicate release of auxiliary context when scanning uses LLL scheduling for reception of auxiliary PDU but the reception fails. Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit 0cfcc56d9df06469c3c8d395070878073a61d4a3) (cherry picked from commit c1f6aeeb021a459fb7cb6dd323d7a60f42c7faa6) --- subsys/bluetooth/controller/ll_sw/nordic/lll/lll_scan_aux.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 78a1548706c..f18bdfb7373 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 @@ -796,7 +796,7 @@ static void isr_rx(struct lll_scan *lll, struct lll_scan_aux *lll_aux, radio_isr_set(isr_done, NULL); } else { /* Send message to flush Auxiliary PDU list */ - if (err != -ECANCELED) { + if (lll->is_aux_sched && err != -ECANCELED) { struct node_rx_pdu *node_rx; node_rx = ull_pdu_rx_alloc(); From eff414f3c0ea79a02258a7fa2a1c6181281d0a59 Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Wed, 22 Dec 2021 22:55:30 +0530 Subject: [PATCH 165/207] [nrf fromtree] Bluetooth: Controller: Fix race condition in sync create cancel Fix race condition in sync create cancel that assigned NULL scan context's associated periodic sync context which caused ULL to dereference NULL pointer. Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit a7d0b5e9807eeab3eaf042895bd02449e7a79ca4) (cherry picked from commit fcec07c1e7312e7cdbde36bc910cf07607bd16e7) --- .../bluetooth/controller/ll_sw/ull_scan_aux.c | 2 +- .../controller/ll_sw/ull_scan_types.h | 1 + subsys/bluetooth/controller/ll_sw/ull_sync.c | 27 +++++++++++++------ 3 files changed, 21 insertions(+), 9 deletions(-) diff --git a/subsys/bluetooth/controller/ll_sw/ull_scan_aux.c b/subsys/bluetooth/controller/ll_sw/ull_scan_aux.c index 7e69a9f90cd..a0983dfdb1a 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_scan_aux.c +++ b/subsys/bluetooth/controller/ll_sw/ull_scan_aux.c @@ -905,7 +905,7 @@ static inline uint8_t aux_handle_get(struct ll_scan_aux_set *aux) static inline struct ll_sync_set *sync_create_get(struct ll_scan_set *scan) { #if defined(CONFIG_BT_CTLR_SYNC_PERIODIC) - return scan->periodic.sync; + return (!scan->periodic.cancelled) ? scan->periodic.sync : NULL; #else /* !CONFIG_BT_CTLR_SYNC_PERIODIC */ return NULL; #endif /* !CONFIG_BT_CTLR_SYNC_PERIODIC */ diff --git a/subsys/bluetooth/controller/ll_sw/ull_scan_types.h b/subsys/bluetooth/controller/ll_sw/ull_scan_types.h index 8a7c7c94fc5..0b2aa0f58b1 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_scan_types.h +++ b/subsys/bluetooth/controller/ll_sw/ull_scan_types.h @@ -22,6 +22,7 @@ struct ll_scan_set { uint8_t adv_addr_type:1; uint8_t filter_policy:1; + uint8_t cancelled:1; uint8_t state:2; uint8_t adv_addr[BDADDR_SIZE]; diff --git a/subsys/bluetooth/controller/ll_sw/ull_sync.c b/subsys/bluetooth/controller/ll_sw/ull_sync.c index ffd414fc450..d7e3e377739 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_sync.c +++ b/subsys/bluetooth/controller/ll_sw/ull_sync.c @@ -150,10 +150,12 @@ uint8_t ll_sync_create(uint8_t options, uint8_t sid, uint8_t adv_addr_type, return BT_HCI_ERR_MEM_CAPACITY_EXCEEDED; } + scan->periodic.cancelled = 0U; scan->periodic.state = LL_SYNC_STATE_IDLE; scan->periodic.filter_policy = options & BT_HCI_LE_PER_ADV_CREATE_SYNC_FP_USE_LIST; if (IS_ENABLED(CONFIG_BT_CTLR_PHY_CODED)) { + scan_coded->periodic.cancelled = 0U; scan_coded->periodic.state = LL_SYNC_STATE_IDLE; scan_coded->periodic.filter_policy = scan->periodic.filter_policy; @@ -271,23 +273,32 @@ uint8_t ll_sync_create_cancel(void **rx) } /* Check for race condition where in sync is established when sync - * context was set to NULL. + * create cancel is invoked. * - * Setting `scan->periodic.sync` to NULL represents cancellation - * requested in the thread context. Checking `sync->timeout_reload` - * confirms if synchronization was established before - * `scan->periodic.sync` was set to NULL. + * Setting `scan->periodic.cancelled` to represent cancellation + * requested in the thread context. Checking `scan->periodic.sync` for + * NULL confirms if synchronization was established before + * `scan->periodic.cancelled` was set to 1U. */ - sync = scan->periodic.sync; - scan->periodic.sync = NULL; + scan->periodic.cancelled = 1U; if (IS_ENABLED(CONFIG_BT_CTLR_PHY_CODED)) { - scan_coded->periodic.sync = NULL; + scan_coded->periodic.cancelled = 1U; } cpu_dmb(); + sync = scan->periodic.sync; if (!sync || sync->timeout_reload) { + /* FIXME: sync establishment in progress looking for first + * AUX_SYNC_IND. Cleanup by stopping ticker and disabling + * LLL events. + */ return BT_HCI_ERR_CMD_DISALLOWED; } + /* It is safe to remove association with scanner as cancelled flag is + * set and sync has not been established. + */ + scan->periodic.sync = NULL; + /* Mark the sync context as sync create cancelled */ if (IS_ENABLED(CONFIG_BT_CTLR_CHECK_SAME_PEER_SYNC)) { sync->timeout = 0U; From 2018d31c81cbcf2dfe4fb4f2789f87a8513f7221 Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Thu, 30 Dec 2021 07:39:53 +0530 Subject: [PATCH 166/207] [nrf fromtree] Bluetooth: Controller: Fix duplicate incomplete data status Fix duplicate incomplete data status generated for Periodic Advertising Report when LLL scheduling is used but auxiliary context failed to be allocated in ULL. Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit fc348614e623b27b2002c9dcc6b6b14222217279) (cherry picked from commit fd0557ccc27977fbd259785736a5bfbd4a27e05d) --- subsys/bluetooth/controller/ll_sw/ull_scan_aux.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/subsys/bluetooth/controller/ll_sw/ull_scan_aux.c b/subsys/bluetooth/controller/ll_sw/ull_scan_aux.c index a0983dfdb1a..f53aed0bd56 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_scan_aux.c +++ b/subsys/bluetooth/controller/ll_sw/ull_scan_aux.c @@ -459,6 +459,17 @@ void ull_scan_aux_setup(memq_link_t *link, struct node_rx_hdr *rx) if (!aux) { aux = aux_acquire(); if (!aux) { + /* As LLL scheduling has been used and will fail due to + * non-allocation of aux context, a sync report with + * aux_failed flag set will be generated. Let the + * current sync report be set as partial, and the + * sync report corresponding to ull_scan_aux_release + * have the incomplete data status. + */ + if (ftr->aux_lll_sched) { + ftr->aux_sched = 1U; + } + if (IS_ENABLED(CONFIG_BT_CTLR_SYNC_PERIODIC) && sync_lll) { struct ll_sync_set *sync; From 439f7a5604a254d50193aba9d83de4eadcac6ed1 Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Tue, 28 Dec 2021 06:38:32 +0530 Subject: [PATCH 167/207] [nrf fromtree] Bluetooth: Controller: Avoid reporting IQ samples after terminate Avoid reporting IQ samples after terminate. Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit 7570af6c941f52360bd8505822cc2e2ebfea6467) (cherry picked from commit d92600e32a9c7a10325362def83fcf12277a26fc) --- subsys/bluetooth/controller/hci/hci.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/subsys/bluetooth/controller/hci/hci.c b/subsys/bluetooth/controller/hci/hci.c index 1f27265623c..c5e6f0624e4 100644 --- a/subsys/bluetooth/controller/hci/hci.c +++ b/subsys/bluetooth/controller/hci/hci.c @@ -2794,19 +2794,21 @@ static void le_df_connectionless_iq_report(struct pdu_data *pdu_rx, } lll = iq_report->hdr.rx_ftr.param; + sync = HDR_LLL2ULL(lll); /* TX LL thread has higher priority than RX thread. It may happen that - * host succefully disables CTE sampling in the meantime. - * It should be verified here, to avoid reporint IQ samples after - * the functionality was disabled. + * host successfully disables CTE sampling in the meantime. + * It should be verified here, to avoid reporting IQ samples after + * the functionality was disabled or if sync was lost. */ - if (ull_df_sync_cfg_is_not_enabled(&lll->df_cfg)) { - /* Dropp further processing of the event. */ + if (ull_df_sync_cfg_is_not_enabled(&lll->df_cfg) || + !sync->timeout_reload) { + /* Drop further processing of the event. */ return; } /* If there are no IQ samples due to insufficient resources - * HCI event should inform about it by store single octet with + * HCI event should inform about it by storing single octet with * special I_sample and Q_sample data. */ samples_cnt = (!iq_report->sample_count ? 1 : iq_report->sample_count); @@ -2820,8 +2822,6 @@ static void le_df_connectionless_iq_report(struct pdu_data *pdu_rx, /* Get the sync handle corresponding to the LLL context passed in the * node rx footer field. */ - sync = HDR_LLL2ULL(lll); - sep->sync_handle = sys_cpu_to_le16(ull_sync_handle_get(sync)); sep->rssi = sys_cpu_to_le16(rssi); sep->rssi_ant_id = iq_report->rssi_ant_id; From afb06a2d01327f5e49dcbfcf2f099fed8095ffa2 Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Tue, 1 Feb 2022 09:04:50 +0530 Subject: [PATCH 168/207] [nrf fromtree] Bluetooth: Controller: Fix missing offset adjust field assignment Fix missing offset adjust field assignment in the Periodic Advertising's sync_info struct that is present in the Extended Advertising PDU. When the sync offset is equal or over 2.4576 seconds from the Extended Advertising PDU, then the sync offset has to be reduced by 2.4576 seconds and the offs_adjust flag be set in the sync_info field. This fixes a bug where Periodic Synchronization could not be established for Periodic Advertisings with intervals greater than 2.4576 seconds as the sync offset was incorrect due to rollover in the 13-bit offset field. Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit 8f444e490c319b922436e03a05dd95348b409dfa) (cherry picked from commit e704945a96ac9cf7f17353037e75424506e877b5) --- subsys/bluetooth/controller/ll_sw/pdu.h | 2 +- subsys/bluetooth/controller/ll_sw/ull_adv_sync.c | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/subsys/bluetooth/controller/ll_sw/pdu.h b/subsys/bluetooth/controller/ll_sw/pdu.h index 63adc9c4e98..afc124f5027 100644 --- a/subsys/bluetooth/controller/ll_sw/pdu.h +++ b/subsys/bluetooth/controller/ll_sw/pdu.h @@ -126,7 +126,7 @@ #define OFFS_UNIT_VALUE_30_US 0 #define OFFS_UNIT_VALUE_300_US 1 /* Value specified in BT Spec. Vol 6, Part B, section 2.3.4.6 */ -#define OFFS_ADJUST_US 245760 +#define OFFS_ADJUST_US 2457600UL /* Advertiser's Sleep Clock Accuracy Value */ #define SCA_500_PPM 500 /* 51 ppm to 500 ppm */ diff --git a/subsys/bluetooth/controller/ll_sw/ull_adv_sync.c b/subsys/bluetooth/controller/ll_sw/ull_adv_sync.c index 1e51e514706..1860e05e9a5 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_adv_sync.c +++ b/subsys/bluetooth/controller/ll_sw/ull_adv_sync.c @@ -1734,6 +1734,12 @@ static inline void sync_info_offset_fill(struct pdu_adv_sync_info *si, uint32_t offs; offs = HAL_TICKER_TICKS_TO_US(ticks_offset) - start_us; + + if (offs >= OFFS_ADJUST_US) { + offs -= OFFS_ADJUST_US; + si->offs_adjust = 1U; + } + offs = offs / OFFS_UNIT_30_US; if (!!(offs >> OFFS_UNIT_BITS)) { si->offs = sys_cpu_to_le16(offs / (OFFS_UNIT_300_US / From 8e712b9db48332eae1386a36c1105276507022b8 Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Sat, 11 Dec 2021 19:51:38 +0530 Subject: [PATCH 169/207] [nrf fromtree] Bluetooth: Controller: Fix Periodic Sync Terminate race condition Fix Periodic Sync Terminate implementation for race conditions with ULL scheduling by using a flag to stop any new ULL scheduling to receive chain PDUs. Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit 32e812c94454015a494d6c821d27a98692bb77de) (cherry picked from commit 9062ae2564b1d33f1f6717c0893a8368d1c05ce3) --- subsys/bluetooth/controller/ll_sw/lll_sync.h | 2 +- .../controller/ll_sw/nordic/lll/lll_sync.c | 3 + .../bluetooth/controller/ll_sw/ull_scan_aux.c | 125 +++++++++++++----- subsys/bluetooth/controller/ll_sw/ull_sync.c | 28 +++- .../controller/ll_sw/ull_sync_types.h | 1 + 5 files changed, 120 insertions(+), 39 deletions(-) diff --git a/subsys/bluetooth/controller/ll_sw/lll_sync.h b/subsys/bluetooth/controller/ll_sw/lll_sync.h index e77d32247d2..a1a4c86836f 100644 --- a/subsys/bluetooth/controller/ll_sw/lll_sync.h +++ b/subsys/bluetooth/controller/ll_sw/lll_sync.h @@ -51,7 +51,7 @@ struct lll_sync { uint32_t window_size_event_us; /* used to store lll_aux when chain is being scanned */ - struct lll_scan_aux *lll_aux; + struct lll_scan_aux *volatile lll_aux; #if defined(CONFIG_BT_CTLR_DF_SCAN_CTE_RX) struct lll_df_sync df_cfg; diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_sync.c b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_sync.c index 8b8896d17c1..c2e1c8caa53 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_sync.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_sync.c @@ -937,6 +937,9 @@ static void isr_done(void *param) lll_isr_status_reset(); + /* Generate incomplete data status and release aux context when + * sync event is using LLL scheduling. + */ lll = param; /* LLL scheduling used for chain PDU reception is aborted/preempted */ diff --git a/subsys/bluetooth/controller/ll_sw/ull_scan_aux.c b/subsys/bluetooth/controller/ll_sw/ull_scan_aux.c index f53aed0bd56..c95f8eed5d8 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_scan_aux.c +++ b/subsys/bluetooth/controller/ll_sw/ull_scan_aux.c @@ -52,11 +52,8 @@ static inline struct ll_sync_iso_set * sync_iso_create_get(struct ll_sync_set *sync); static void done_disabled_cb(void *param); static void flush(void *param); - -#if defined(CONFIG_BT_CTLR_SYNC_PERIODIC) static void rx_release_put(struct node_rx_hdr *rx); -#endif /* CONFIG_BT_CTLR_SYNC_PERIODIC */ - +static void aux_sync_incomplete(void *param); static void ticker_cb(uint32_t ticks_at_expire, uint32_t ticks_drift, uint32_t remainder, uint16_t lazy, uint8_t force, void *param); @@ -557,10 +554,23 @@ void ull_scan_aux_setup(memq_link_t *link, struct node_rx_hdr *rx) if (!IS_ENABLED(CONFIG_BT_CTLR_SYNC_PERIODIC) || lll) { lll->lll_aux = NULL; } else { + struct ll_sync_set *sync; + LL_ASSERT(sync_lll && (!sync_lll->lll_aux || sync_lll->lll_aux == lll_aux)); + + /* Do not ULL schedule if sync terminate requested */ + sync = HDR_LLL2ULL(sync_lll); + if (unlikely(sync->is_stop)) { + goto ull_scan_aux_rx_flush; + } + + /* Associate the auxiliary context with sync context */ sync_lll->lll_aux = lll_aux; + /* Backup the node rx to be dispatch on successfully ULL + * scheduling setup. + */ aux->rx_head = rx; } @@ -663,6 +673,7 @@ void ull_scan_aux_setup(memq_link_t *link, struct node_rx_hdr *rx) if (aux) { struct ull_hdr *hdr; + uint8_t ref; /* Enqueue last rx in aux context if possible, otherwise send * immediately since we are in sync context. @@ -687,12 +698,17 @@ void ull_scan_aux_setup(memq_link_t *link, struct node_rx_hdr *rx) * ull_hdr before done event was processed. */ hdr = &aux->ull; - LL_ASSERT(ull_ref_get(hdr) < 2); - if (ull_ref_get(hdr) == 0) { + ref = ull_ref_get(hdr); + if (ref == 0) { flush(aux); } else { - LL_ASSERT(!hdr->disabled_cb); + /* A specific single shot scheduled aux context cannot + * overlap, i.e. ULL reference count shall be less than + * 2. + */ + LL_ASSERT(ref < 2); + LL_ASSERT(!hdr->disabled_cb); hdr->disabled_param = aux; hdr->disabled_cb = done_disabled_cb; } @@ -702,11 +718,9 @@ void ull_scan_aux_setup(memq_link_t *link, struct node_rx_hdr *rx) ll_rx_put(link, rx); -#if defined(CONFIG_BT_CTLR_SYNC_PERIODIC) - if (rx_incomplete) { + if (IS_ENABLED(CONFIG_BT_CTLR_SYNC_PERIODIC) && rx_incomplete) { rx_release_put(rx_incomplete); } -#endif /* CONFIG_BT_CTLR_SYNC_PERIODIC */ ll_rx_sched(); } @@ -727,7 +741,7 @@ void ull_scan_aux_done(struct node_rx_event_done *done) LL_ASSERT(ull_sync_is_valid_get(sync)); hdr = &sync->ull; - if (!sync->lll.lll_aux) { + if (unlikely(sync->is_stop) || !sync->lll.lll_aux) { return; } @@ -832,21 +846,61 @@ void ull_scan_aux_release(memq_link_t *link, struct node_rx_hdr *rx) if (lll_aux) { struct ll_scan_aux_set *aux; + struct ll_scan_set *scan; + struct lll_scan *lll; struct ull_hdr *hdr; + uint8_t is_stop; aux = HDR_LLL2ULL(lll_aux); - hdr = &aux->ull; + lll = aux->parent; + scan = HDR_LLL2ULL(lll); + scan = ull_scan_is_valid_get(scan); + if (scan) { + is_stop = 0U; + } else { + struct lll_sync *sync_lll; + struct ll_sync_set *sync; - LL_ASSERT(ull_ref_get(hdr) < 2); + sync_lll = (void *)lll; + sync = HDR_LLL2ULL(sync_lll); + is_stop = sync->is_stop; + } - /* Flush from here of from done event, if one is pending */ - if (ull_ref_get(hdr) == 0) { - flush(aux); + if (!is_stop) { + uint8_t ref; + + /* Flush from here or from done event, if one is + * pending. + */ + hdr = &aux->ull; + ref = ull_ref_get(hdr); + if (ref == 0) { + flush(aux); + } else { + /* A specific single shot scheduled aux context + * cannot overlap, i.e. ULL reference count + * shall be less than 2. + */ + LL_ASSERT(ref < 2); + + LL_ASSERT(!hdr->disabled_cb); + hdr->disabled_param = aux; + hdr->disabled_cb = done_disabled_cb; + } } else { - LL_ASSERT(!hdr->disabled_cb); + /* Sync terminate requested, enqueue node rx that will + * be flushed by the disabled_cb setup by the + * terminate. + */ + rx->link = link; + if (aux->rx_last) { + aux->rx_last->rx_ftr.extra = rx; + } else { + aux->rx_head = rx; + } + aux->rx_last = rx; - hdr->disabled_param = aux; - hdr->disabled_cb = done_disabled_cb; + return; } } @@ -857,7 +911,7 @@ void ull_scan_aux_release(memq_link_t *link, struct node_rx_hdr *rx) int ull_scan_aux_stop(struct ll_scan_aux_set *aux) { static memq_link_t link; - static struct mayfly mfy = {0, 0, &link, NULL, flush}; + static struct mayfly mfy = {0, 0, &link, NULL, NULL}; uint8_t aux_handle; uint32_t ret; int err; @@ -876,6 +930,11 @@ int ull_scan_aux_stop(struct ll_scan_aux_set *aux) if (ret) { return -EBUSY; } + + mfy.fp = flush; + } else { + /* ULL scheduling stopped before prepare */ + mfy.fp = aux_sync_incomplete; } /* Release auxiliary context in ULL execution context */ @@ -970,17 +1029,18 @@ static void flush(void *param) lll->lll_aux = NULL; } else { struct lll_sync *sync_lll; + struct ll_sync_set *sync; sync_lll = aux->parent; + sync = HDR_LLL2ULL(sync_lll); - LL_ASSERT(sync_lll->lll_aux); + LL_ASSERT(sync->is_stop || sync_lll->lll_aux); sync_lll->lll_aux = NULL; } aux_release(aux); } -#if defined(CONFIG_BT_CTLR_SYNC_PERIODIC) static void rx_release_put(struct node_rx_hdr *rx) { rx->type = NODE_RX_TYPE_RELEASE; @@ -1005,9 +1065,14 @@ static void aux_sync_partial(void *param) static void aux_sync_incomplete(void *param) { +#if defined(CONFIG_BT_CTLR_SYNC_PERIODIC) struct ll_scan_aux_set *aux; aux = param; + + /* ULL scheduling succeeded hence no backup node rx present, use the + * extra node rx reserved for incomplete data status generation. + */ if (!aux->rx_head) { struct ll_sync_set *sync; struct node_rx_hdr *rx; @@ -1042,8 +1107,8 @@ static void aux_sync_incomplete(void *param) } flush(aux); -} #endif /* CONFIG_BT_CTLR_SYNC_PERIODIC */ +} static void ticker_cb(uint32_t ticks_at_expire, uint32_t ticks_drift, uint32_t remainder, uint16_t lazy, uint8_t force, @@ -1098,24 +1163,14 @@ static void ticker_op_cb(uint32_t status, void *param) } if (status == TICKER_STATUS_SUCCESS) { - if (0) { - -#if defined(CONFIG_BT_CTLR_SYNC_PERIODIC) - } else if (sync) { + if (IS_ENABLED(CONFIG_BT_CTLR_SYNC_PERIODIC) && sync) { mfy.fp = aux_sync_partial; -#endif /* CONFIG_BT_CTLR_SYNC_PERIODIC */ - } else { return; } } else { - if (0) { - -#if defined(CONFIG_BT_CTLR_SYNC_PERIODIC) - } else if (sync) { + if (IS_ENABLED(CONFIG_BT_CTLR_SYNC_PERIODIC) && sync) { mfy.fp = aux_sync_incomplete; -#endif /* CONFIG_BT_CTLR_SYNC_PERIODIC */ - } else { mfy.fp = flush; } diff --git a/subsys/bluetooth/controller/ll_sw/ull_sync.c b/subsys/bluetooth/controller/ll_sw/ull_sync.c index d7e3e377739..bd46260daf5 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_sync.c +++ b/subsys/bluetooth/controller/ll_sw/ull_sync.c @@ -190,6 +190,7 @@ uint8_t ll_sync_create(uint8_t options, uint8_t sid, uint8_t adv_addr_type, 1U : 0U; #endif sync->skip = skip; + sync->is_stop = 0U; /* NOTE: Use timeout not zero to represent sync context used for sync * create. @@ -223,6 +224,7 @@ uint8_t ll_sync_create(uint8_t options, uint8_t sid, uint8_t adv_addr_type, /* Initialize sync LLL context */ lll_sync = &sync->lll; + lll_sync->lll_aux = NULL; lll_sync->is_rx_enabled = sync->rx_enable; lll_sync->skip_prepare = 0U; lll_sync->skip_event = 0U; @@ -344,6 +346,11 @@ uint8_t ll_sync_terminate(uint16_t handle) return BT_HCI_ERR_UNKNOWN_ADV_IDENTIFIER; } + /* Request terminate, no new ULL scheduling to be setup */ + sync->is_stop = 1U; + cpu_dmb(); + + /* Stop periodic sync ticker timeouts */ err = ull_ticker_stop_with_mark(TICKER_ID_SCAN_SYNC_BASE + handle, sync, &sync->lll); LL_ASSERT(err == 0 || err == -EALREADY); @@ -351,6 +358,7 @@ uint8_t ll_sync_terminate(uint16_t handle) return BT_HCI_ERR_CMD_DISALLOWED; } + /* Check and stop any auxiliary PDU receptions */ lll_aux = sync->lll.lll_aux; if (lll_aux) { struct ll_scan_aux_set *aux; @@ -845,14 +853,17 @@ void ull_sync_done(struct node_rx_event_done *done) uint32_t ticks_drift_plus; struct ll_sync_set *sync; uint16_t elapsed_event; - struct lll_sync *lll; uint16_t skip_event; uint16_t lazy; uint8_t force; /* Get reference to ULL context */ sync = CONTAINER_OF(done->param, struct ll_sync_set, ull); - lll = &sync->lll; + + /* Do nothing if local terminate requested */ + if (unlikely(sync->is_stop)) { + return; + } #if defined(CONFIG_BT_CTLR_SYNC_PERIODIC_CTE_TYPE_FILTERING) #if defined(CONFIG_BT_CTLR_CTEINLINE_SUPPORT) @@ -865,6 +876,10 @@ void ull_sync_done(struct node_rx_event_done *done) } else #endif /* CONFIG_BT_CTLR_SYNC_PERIODIC_CTE_TYPE_FILTERING */ { + struct lll_sync *lll; + + lll = &sync->lll; + /* Events elapsed used in timeout checks below */ skip_event = lll->skip_event; elapsed_event = skip_event + 1; @@ -1202,7 +1217,14 @@ static void ticker_stop_sync_lost_op_cb(uint32_t status, void *param) static memq_link_t link; static struct mayfly mfy = {0, 0, &link, NULL, sync_lost}; - LL_ASSERT(status == TICKER_STATUS_SUCCESS); + /* When in race between terminate requested in thread context and + * sync lost scenario, do not generate the sync lost node rx from here + */ + if (status != TICKER_STATUS_SUCCESS) { + LL_ASSERT(param == ull_disable_mark_get()); + + return; + } mfy.param = param; diff --git a/subsys/bluetooth/controller/ll_sw/ull_sync_types.h b/subsys/bluetooth/controller/ll_sw/ull_sync_types.h index 8c812403d9a..7df41cf1d05 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_sync_types.h +++ b/subsys/bluetooth/controller/ll_sw/ull_sync_types.h @@ -43,6 +43,7 @@ struct ll_sync_set { uint8_t is_term:1; #endif /* CONFIG_BT_CTLR_SYNC_PERIODIC_CTE_TYPE_FILTERING && !CONFIG_BT_CTLR_CTEINLINE_SUPPORT */ + uint8_t is_stop:1; /* sync terminate requested */ uint8_t sync_expire:3; /* countdown of 6 before fail to establish */ #if defined(CONFIG_BT_CTLR_CHECK_SAME_PEER_SYNC) From a595cdf7aedb60babf176261af0a8c4db61524f5 Mon Sep 17 00:00:00 2001 From: Piotr Pryga Date: Fri, 4 Feb 2022 15:11:36 +0100 Subject: [PATCH 170/207] [nrf fromtree] Bluetooth: Controller: df: Fix IQ sample data saturation info drop Nordic Semiconductor Radio peripheral provides IQ samples as 12 bits signed integer with sign extended to 16 bits. Where out of range IQ samples (saturated) have value -32768. Due to conversion of IQ samples to 8 bit signed integer, required by BT 5.3 Core Vol 4, Part E sections 7.7.65.21 and 7.7.65.22 the saturation information was lost. The PR fixes that issue by use of value -128 to mark saturated IQ samples. Note that BT 5.3 Core does not give any particular value of IQ sample a special meaning. This is a vendor specific solution and does not affect other implementations of lower link layer. Signed-off-by: Piotr Pryga (cherry picked from commit d04456f4d92760e4716bf36249fcdf1a2d2febb2) (cherry picked from commit dcbbf6682f815e190d298f6e23eedc70082de622) --- subsys/bluetooth/controller/hci/hci.c | 8 ++++---- .../controller/ll_sw/nordic/lll/lll_df_types.h | 16 +++++++++++++++- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/subsys/bluetooth/controller/hci/hci.c b/subsys/bluetooth/controller/hci/hci.c index c5e6f0624e4..f8dc0024679 100644 --- a/subsys/bluetooth/controller/hci/hci.c +++ b/subsys/bluetooth/controller/hci/hci.c @@ -2846,8 +2846,8 @@ static void le_df_connectionless_iq_report(struct pdu_data *pdu_rx, sep->sample_count = 0U; } else { for (uint8_t idx = 0U; idx < samples_cnt; ++idx) { - sep->sample[idx].i = IQ_SHIFT_12_TO_8_BIT(iq_report->sample[idx].i); - sep->sample[idx].q = IQ_SHIFT_12_TO_8_BIT(iq_report->sample[idx].q); + sep->sample[idx].i = IQ_CONVERT_12_TO_8_BIT(iq_report->sample[idx].i); + sep->sample[idx].q = IQ_CONVERT_12_TO_8_BIT(iq_report->sample[idx].q); } sep->sample_count = samples_cnt; @@ -2969,8 +2969,8 @@ static void le_df_connection_iq_report(struct node_rx_pdu *node_rx, struct net_b sep->sample_count = 0U; } else { for (uint8_t idx = 0U; idx < samples_cnt; ++idx) { - sep->sample[idx].i = IQ_SHIFT_12_TO_8_BIT(iq_report->sample[idx].i); - sep->sample[idx].q = IQ_SHIFT_12_TO_8_BIT(iq_report->sample[idx].q); + sep->sample[idx].i = IQ_CONVERT_12_TO_8_BIT(iq_report->sample[idx].i); + sep->sample[idx].q = IQ_CONVERT_12_TO_8_BIT(iq_report->sample[idx].q); } sep->sample_count = samples_cnt; } diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_df_types.h b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_df_types.h index 2916709d51b..e58d4450eff 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_df_types.h +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_df_types.h @@ -66,8 +66,22 @@ struct lll_df_adv_cfg { #define IQ_SAMPLE_CNT (PDU_DC_LL_HEADER_SIZE + LL_LENGTH_OCTETS_RX_MAX) #define RSSI_DBM_TO_DECI_DBM(x) (-(x) * 10) -#define IQ_SHIFT_12_TO_8_BIT(x) ((int8_t)((x) >> 4)) +/* Macro that represents out of range IQ sample (saturated). Value provided by Radio specifications. + * It is not defined by Bluetooth Core specification. This is the vendor specific value. + * + * Nordic Semiconductor Radio peripheral provides 16 bit wide IQ samples. + * BT 5.3 Core specification Vol 4, Part E sectons 7.7.65.21 and 7.7.65.22 limit size of + * IQ samples to 8 bits. + * To mitigate the limited accuratcy and losing information about saturated IQ samples a 0x80 value + * is selected to serve the purpose. + */ +#define IQ_SAMPLE_STATURATED_16_BIT 0x8000 +#define IQ_SAMPLE_STATURATED_8_BIT 0x80 +#define IQ_SHIFT_12_TO_8_BIT(x) ((int8_t)((x) >> 4)) +#define IQ_CONVERT_12_TO_8_BIT(x) \ + (((x) == IQ_SAMPLE_STATURATED_16_BIT) ? IQ_SAMPLE_STATURATED_8_BIT : \ + IQ_SHIFT_12_TO_8_BIT((x))) /* Structure to store an single IQ sample */ struct iq_sample { int16_t i; From a28eb6db915e3ad45b6ea5b228b2fa5cbd9da5f6 Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Sat, 1 Jan 2022 07:41:13 +0530 Subject: [PATCH 171/207] [nrf fromtree] Bluetooth: Controller: Fix advertising pdu latest get Fix advertising pdu latest get to defer release of stale PDU chain buffers. Returning NULL after some buffers where released causes LLL to assert when chained PDUs are switched. Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit 179fe06a808398b4899492f3e70a1549c79ba07d) (cherry picked from commit f68eeba78dc72a07f3a22ed0014319480bff8084) --- .../bluetooth/controller/ll_sw/nordic/lll/lll_adv.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_adv.c b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_adv.c index 32e98d44abc..ae93d280ae4 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_adv.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_adv.c @@ -472,8 +472,7 @@ struct pdu_adv *lll_adv_pdu_latest_get(struct lll_adv_pdu *pdu, * switch attempt (on next event). */ if (!MFIFO_ENQUEUE_IDX_GET(pdu_free, &free_idx)) { - pdu->pdu[pdu_idx] = p; - return NULL; + break; } #if defined(CONFIG_BT_CTLR_ADV_PDU_LINK) @@ -488,16 +487,19 @@ struct pdu_adv *lll_adv_pdu_latest_get(struct lll_adv_pdu *pdu, p = next; } while (p); - pdu->pdu[pdu_idx] = NULL; + /* If not all PDUs where released into mfifo, keep the list in + * current data index, to be released on the next switch + * attempt. + */ + pdu->pdu[pdu_idx] = p; + /* Progress to next data index */ first += 1U; if (first == DOUBLE_BUFFER_SIZE) { first = 0U; } pdu->first = first; *is_modified = 1U; - - pdu->pdu[pdu_idx] = NULL; } return (void *)pdu->pdu[first]; From d45f59cbb3d340348cd2c708b7f967bfc1796803 Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Mon, 13 Dec 2021 06:57:57 +0530 Subject: [PATCH 172/207] [nrf fromtree] Bluetooth: Controller: Update ull_disable with -EALREADY return Update ull_disable implementation to return -EALREADY if LLL event is already disabled. Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit ffeee6ce1ffa5e362b58d8adb39cb6367f90cf52) (cherry picked from commit 681d6c1821562ce9599ed3bbb5814154ab625b6c) --- subsys/bluetooth/controller/ll_sw/ull.c | 16 +++++++++------- subsys/bluetooth/controller/ll_sw/ull_adv.c | 12 ++++++------ subsys/bluetooth/controller/ll_sw/ull_adv_aux.c | 4 ++-- .../controller/ll_sw/ull_adv_internal.h | 2 +- 4 files changed, 18 insertions(+), 16 deletions(-) diff --git a/subsys/bluetooth/controller/ll_sw/ull.c b/subsys/bluetooth/controller/ll_sw/ull.c index 574525138c2..a61b6ef5191 100644 --- a/subsys/bluetooth/controller/ll_sw/ull.c +++ b/subsys/bluetooth/controller/ll_sw/ull.c @@ -1702,6 +1702,7 @@ int ull_ticker_stop_with_mark(uint8_t ticker_handle, void *param, uint32_t volatile ret_cb; uint32_t ret; void *mark; + int err; mark = ull_disable_mark(param); if (mark != param) { @@ -1722,16 +1723,17 @@ int ull_ticker_stop_with_mark(uint8_t ticker_handle, void *param, return -EALREADY; } - ret = ull_disable(lll_disable); - if (ret) { - return -EBUSY; - } + err = ull_disable(lll_disable); mark = ull_disable_unmark(param); if (mark != param) { return -ENOLCK; } + if (err && (err != -EALREADY)) { + return err; + } + return 0; } @@ -1761,8 +1763,8 @@ int ull_disable(void *lll) uint32_t ret; hdr = HDR_LLL2ULL(lll); - if (!hdr || !ull_ref_get(hdr)) { - return 0; + if (!ull_ref_get(hdr)) { + return -EALREADY; } k_sem_init(&sem, 0, 1); @@ -1780,7 +1782,7 @@ int ull_disable(void *lll) * care. */ if (!ull_ref_get(hdr)) { - return 0; + return -EALREADY; } mfy.param = lll; diff --git a/subsys/bluetooth/controller/ll_sw/ull_adv.c b/subsys/bluetooth/controller/ll_sw/ull_adv.c index 5a7f0fb9644..875f54b6e55 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_adv.c +++ b/subsys/bluetooth/controller/ll_sw/ull_adv.c @@ -2523,8 +2523,9 @@ static inline uint8_t disable(uint8_t handle) { uint32_t volatile ret_cb; struct ll_adv_set *adv; - void *mark; uint32_t ret; + void *mark; + int err; adv = ull_adv_is_enabled_get(handle); if (!adv) { @@ -2585,8 +2586,8 @@ static inline uint8_t disable(uint8_t handle) return BT_HCI_ERR_CMD_DISALLOWED; } - ret = ull_disable(&adv->lll); - LL_ASSERT(!ret); + err = ull_disable(&adv->lll); + LL_ASSERT(!err || (err == -EALREADY)); mark = ull_disable_unmark(adv); LL_ASSERT(mark == adv); @@ -2596,13 +2597,12 @@ static inline uint8_t disable(uint8_t handle) if (lll_aux) { struct ll_adv_aux_set *aux; - uint8_t err; aux = HDR_LLL2ULL(lll_aux); err = ull_adv_aux_stop(aux); - if (err) { - return err; + if (err && (err != -EALREADY)) { + return BT_HCI_ERR_CMD_DISALLOWED; } } #endif /* CONFIG_BT_CTLR_ADV_EXT && (CONFIG_BT_CTLR_ADV_AUX_SET > 0) */ diff --git a/subsys/bluetooth/controller/ll_sw/ull_adv_aux.c b/subsys/bluetooth/controller/ll_sw/ull_adv_aux.c index f159ed0926b..81da55191d8 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_adv_aux.c +++ b/subsys/bluetooth/controller/ll_sw/ull_adv_aux.c @@ -1073,7 +1073,7 @@ uint32_t ull_adv_aux_start(struct ll_adv_aux_set *aux, uint32_t ticks_anchor, return ret; } -uint8_t ull_adv_aux_stop(struct ll_adv_aux_set *aux) +int ull_adv_aux_stop(struct ll_adv_aux_set *aux) { uint8_t aux_handle; int err; @@ -1084,7 +1084,7 @@ uint8_t ull_adv_aux_stop(struct ll_adv_aux_set *aux) aux, &aux->lll); LL_ASSERT(err == 0 || err == -EALREADY); if (err) { - return BT_HCI_ERR_CMD_DISALLOWED; + return err; } aux->is_started = 0U; diff --git a/subsys/bluetooth/controller/ll_sw/ull_adv_internal.h b/subsys/bluetooth/controller/ll_sw/ull_adv_internal.h index f1b7982b564..93b567139c7 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_adv_internal.h +++ b/subsys/bluetooth/controller/ll_sw/ull_adv_internal.h @@ -83,7 +83,7 @@ uint32_t ull_adv_aux_start(struct ll_adv_aux_set *aux, uint32_t ticks_anchor, uint32_t ticks_slot_overhead); /* helper function to stop auxiliary advertising */ -uint8_t ull_adv_aux_stop(struct ll_adv_aux_set *aux); +int ull_adv_aux_stop(struct ll_adv_aux_set *aux); /* helper function to acquire and initialize auxiliary advertising instance */ struct ll_adv_aux_set *ull_adv_aux_acquire(struct lll_adv *lll); From 4ef1ff2d31610eaa8627a9b5faff7c0c9e6309e0 Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Mon, 13 Dec 2021 07:04:53 +0530 Subject: [PATCH 173/207] [nrf fromtree] Bluetooth: Controller: Fix to stop Extended Auxiliary Scan context Fix any stray Extended Auxiliary PDU from being scanned when disabling Extended Scanning. Updated Extended Scan disable implementation to find any active auxiliary scan context and stop them. Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit a5fb4347051ab4c307ca6378951697e78c3d3516) (cherry picked from commit 943bab07b108caf54771cce2d1b5d766e26a66e0) --- subsys/bluetooth/controller/ll_sw/ull_scan.c | 39 ++++++++- .../bluetooth/controller/ll_sw/ull_scan_aux.c | 81 ++++++++++++++++--- .../controller/ll_sw/ull_scan_internal.h | 3 + .../controller/ll_sw/ull_scan_types.h | 2 + 4 files changed, 115 insertions(+), 10 deletions(-) diff --git a/subsys/bluetooth/controller/ll_sw/ull_scan.c b/subsys/bluetooth/controller/ll_sw/ull_scan.c index 1b312fecb4d..f3779f7e0c3 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_scan.c +++ b/subsys/bluetooth/controller/ll_sw/ull_scan.c @@ -355,13 +355,20 @@ void ull_scan_params_set(struct lll_scan *lll, uint8_t type, uint16_t interval, uint8_t ull_scan_enable(struct ll_scan_set *scan) { - struct lll_scan *lll = &scan->lll; uint32_t ticks_slot_overhead; uint32_t volatile ret_cb; uint32_t ticks_interval; uint32_t ticks_anchor; + struct lll_scan *lll; uint32_t ret; +#if defined(CONFIG_BT_CTLR_ADV_EXT) + /* Initialize extend scan stop request */ + scan->is_stop = 0U; +#endif /* CONFIG_BT_CTLR_ADV_EXT */ + + /* Initialize LLL scan context */ + lll = &scan->lll; lll->init_addr_type = scan->own_addr_type; (void)ll_addr_read(lll->init_addr_type, lll->init_addr); lll->chan = 0U; @@ -462,6 +469,12 @@ uint8_t ull_scan_disable(uint8_t handle, struct ll_scan_set *scan) { int err; +#if defined(CONFIG_BT_CTLR_ADV_EXT) + /* Request Extended Scan stop */ + scan->is_stop = 1U; + cpu_dmb(); +#endif /* CONFIG_BT_CTLR_ADV_EXT */ + err = ull_ticker_stop_with_mark(TICKER_ID_SCAN_BASE + handle, scan, &scan->lll); LL_ASSERT(err == 0 || err == -EALREADY); @@ -469,6 +482,30 @@ uint8_t ull_scan_disable(uint8_t handle, struct ll_scan_set *scan) return BT_HCI_ERR_CMD_DISALLOWED; } +#if defined(CONFIG_BT_CTLR_ADV_EXT) + /* Find and stop associated auxiliary scan contexts */ + for (uint8_t aux_handle = 0; aux_handle < CONFIG_BT_CTLR_SCAN_AUX_SET; + aux_handle++) { + struct lll_scan_aux *aux_scan_lll; + struct ll_scan_set *aux_scan; + struct ll_scan_aux_set *aux; + + aux = ull_scan_aux_set_get(aux_handle); + aux_scan_lll = aux->parent; + if (!aux_scan_lll) { + continue; + } + + aux_scan = HDR_LLL2ULL(aux_scan_lll); + if (aux_scan == scan) { + err = ull_scan_aux_stop(aux); + if (err && (err != -EALREADY)) { + return BT_HCI_ERR_CMD_DISALLOWED; + } + } + } +#endif /* CONFIG_BT_CTLR_ADV_EXT */ + return 0; } diff --git a/subsys/bluetooth/controller/ll_sw/ull_scan_aux.c b/subsys/bluetooth/controller/ll_sw/ull_scan_aux.c index c95f8eed5d8..a360edde51f 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_scan_aux.c +++ b/subsys/bluetooth/controller/ll_sw/ull_scan_aux.c @@ -552,6 +552,14 @@ void ull_scan_aux_setup(memq_link_t *link, struct node_rx_hdr *rx) /* Switching to ULL scheduling to receive auxiliary PDUs */ if (!IS_ENABLED(CONFIG_BT_CTLR_SYNC_PERIODIC) || lll) { + /* Do not ULL schedule if scan disable requested */ + if (unlikely(scan->is_stop)) { + goto ull_scan_aux_rx_flush; + } + + /* Remove auxiliary context association with scan context so + * that LLL can differentiate it to being ULL scheduling. + */ lll->lll_aux = NULL; } else { struct ll_sync_set *sync; @@ -747,13 +755,36 @@ void ull_scan_aux_done(struct node_rx_event_done *done) aux = HDR_LLL2ULL(sync->lll.lll_aux); } else { + struct ll_scan_set *scan; + + scan = HDR_LLL2ULL(aux->parent); + LL_ASSERT(ull_scan_is_valid_get(scan)); + + /* Auxiliary context will be flushed by ull_scan_aux_stop() */ + if (unlikely(scan->is_stop)) { + return; + } + /* Setup the disabled callback to flush the auxiliary PDUs */ hdr = &aux->ull; } - LL_ASSERT(!hdr->disabled_cb); - hdr->disabled_param = aux; - hdr->disabled_cb = done_disabled_cb; + if (ull_ref_get(hdr) == 0U) { + flush(aux); + } else { + LL_ASSERT(!hdr->disabled_cb); + hdr->disabled_param = aux; + hdr->disabled_cb = done_disabled_cb; + } +} + +struct ll_scan_aux_set *ull_scan_aux_set_get(uint8_t handle) +{ + if (handle >= CONFIG_BT_CTLR_SCAN_AUX_SET) { + return NULL; + } + + return &ll_scan_aux_pool[handle]; } uint8_t ull_scan_aux_lll_handle_get(struct lll_scan_aux *lll) @@ -856,7 +887,7 @@ void ull_scan_aux_release(memq_link_t *link, struct node_rx_hdr *rx) scan = HDR_LLL2ULL(lll); scan = ull_scan_is_valid_get(scan); if (scan) { - is_stop = 0U; + is_stop = scan->is_stop; } else { struct lll_sync *sync_lll; struct ll_sync_set *sync; @@ -926,15 +957,37 @@ int ull_scan_aux_stop(struct ll_scan_aux_set *aux) /* Abort LLL event if ULL scheduling not used or already in prepare */ if (err == -EALREADY) { - ret = ull_disable(&aux->lll); - if (ret) { - return -EBUSY; + err = ull_disable(&aux->lll); + if (err) { + return err; } mfy.fp = flush; + + } else if (!IS_ENABLED(CONFIG_BT_CTLR_SYNC_PERIODIC)) { + /* ULL scan auxiliary PDU reception scheduling stopped + * before prepare. + */ + mfy.fp = flush; + } else { - /* ULL scheduling stopped before prepare */ - mfy.fp = aux_sync_incomplete; + struct ll_scan_set *scan; + struct lll_scan *lll; + + lll = aux->parent; + scan = HDR_LLL2ULL(lll); + scan = ull_scan_is_valid_get(scan); + if (scan) { + /* ULL scan auxiliary PDU reception scheduling stopped + * before prepare. + */ + mfy.fp = flush; + } else { + /* ULL sync chain reception scheduling stopped before + * prepare. + */ + mfy.fp = aux_sync_incomplete; + } } /* Release auxiliary context in ULL execution context */ @@ -963,6 +1016,16 @@ static inline struct ll_scan_aux_set *aux_acquire(void) static inline void aux_release(struct ll_scan_aux_set *aux) { + /* Debug check that parent was assigned when allocated for reception of + * auxiliary channel PDUs. + */ + LL_ASSERT(aux->parent); + + /* Clear the parent so that when scan is being disabled then this + * auxiliary context shall not associate itself from being disable. + */ + aux->parent = NULL; + mem_release(aux, &scan_aux_free); } diff --git a/subsys/bluetooth/controller/ll_sw/ull_scan_internal.h b/subsys/bluetooth/controller/ll_sw/ull_scan_internal.h index e664ae13781..a90aac5527e 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_scan_internal.h +++ b/subsys/bluetooth/controller/ll_sw/ull_scan_internal.h @@ -80,6 +80,9 @@ void ull_scan_aux_setup(memq_link_t *link, struct node_rx_hdr *rx); /* Helper to clean up auxiliary channel scanning */ void ull_scan_aux_done(struct node_rx_event_done *done); +/* Return the scan aux set instance given the handle */ +struct ll_scan_aux_set *ull_scan_aux_set_get(uint8_t handle); + /* Helper function to check and return if a valid aux scan context */ struct ll_scan_aux_set *ull_scan_aux_is_valid_get(struct ll_scan_aux_set *aux); diff --git a/subsys/bluetooth/controller/ll_sw/ull_scan_types.h b/subsys/bluetooth/controller/ll_sw/ull_scan_types.h index 0b2aa0f58b1..969f6fa9106 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_scan_types.h +++ b/subsys/bluetooth/controller/ll_sw/ull_scan_types.h @@ -11,6 +11,8 @@ struct ll_scan_set { #if defined(CONFIG_BT_CTLR_ADV_EXT) uint16_t duration_lazy; struct node_rx_hdr *node_rx_scan_term; + + uint8_t is_stop:1; #endif /* CONFIG_BT_CTLR_ADV_EXT */ uint8_t is_enabled:1; From 96ee9149303205254cb3e73871b47164b514371a Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Tue, 14 Dec 2021 21:58:17 +0530 Subject: [PATCH 174/207] [nrf fromtree] Bluetooth: Controller: Fix Sync Failed to be Established on no memory Update implementation to generate Periodic Sync Failed to be Established when Sync Established message could not be generate due to lack of free node rx buffers and when there is sync lost before sync established message could be generated. Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit bebc7a0df8d01987d36189571a5805035c589b00) (cherry picked from commit cff0919c367e905d102d35c2651e73e14c7a9981) --- subsys/bluetooth/controller/ll_sw/ull_sync.c | 42 +++++++++++-------- .../controller/ll_sw/ull_sync_types.h | 2 + 2 files changed, 26 insertions(+), 18 deletions(-) diff --git a/subsys/bluetooth/controller/ll_sw/ull_sync.c b/subsys/bluetooth/controller/ll_sw/ull_sync.c index bd46260daf5..9a99cdd60a1 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_sync.c +++ b/subsys/bluetooth/controller/ll_sw/ull_sync.c @@ -86,9 +86,6 @@ static void *sync_free; static struct k_sem sem_ticker_cb; #endif /* CONFIG_BT_CTLR_DF_SCAN_CTE_RX */ -static memq_link_t link_lll_prepare; -static struct mayfly mfy_lll_prepare = { 0, 0, &link_lll_prepare, NULL, lll_sync_prepare }; - uint8_t ll_sync_create(uint8_t options, uint8_t sid, uint8_t adv_addr_type, uint8_t *adv_addr, uint16_t skip, uint16_t sync_timeout, uint8_t sync_cte_type) @@ -720,7 +717,7 @@ void ull_sync_setup(struct ll_scan_set *scan, struct ll_scan_aux_set *aux, } ticks_slot_offset += HAL_TICKER_US_TO_TICKS(EVENT_OVERHEAD_START_US); - mfy_lll_prepare.fp = lll_sync_create_prepare; + sync->lll_sync_prepare = lll_sync_create_prepare; ret = ticker_start(TICKER_INSTANCE_ID_CTLR, TICKER_USER_ID_ULL_HIGH, (TICKER_ID_SCAN_SYNC_BASE + sync_handle), @@ -758,12 +755,14 @@ void ull_sync_setup_complete(struct ll_scan_set *scan) void ull_sync_established_report(memq_link_t *link, struct node_rx_hdr *rx) { struct node_rx_pdu *rx_establ; - struct ll_sync_set *ull_sync; + struct ll_sync_set *sync; struct node_rx_ftr *ftr; struct node_rx_sync *se; struct lll_sync *lll; ftr = &rx->rx_ftr; + lll = ftr->param; + sync = HDR_LLL2ULL(lll); #if defined(CONFIG_BT_CTLR_SYNC_PERIODIC_CTE_TYPE_FILTERING) enum sync_status sync_status; @@ -773,8 +772,6 @@ void ull_sync_established_report(memq_link_t *link, struct node_rx_hdr *rx) #else struct pdu_cte_info *rx_cte_info; - lll = ftr->param; - rx_cte_info = pdu_cte_info_get((struct pdu_adv *)((struct node_rx_pdu *)rx)->pdu); if (rx_cte_info != NULL) { sync_status = lll_sync_cte_is_allowed(lll->cte_type, lll->filter_policy, @@ -794,15 +791,10 @@ void ull_sync_established_report(memq_link_t *link, struct node_rx_hdr *rx) if (1) { #endif /* !CONFIG_BT_CTLR_SYNC_PERIODIC_CTE_TYPE_FILTERING */ - /* Set the sync handle corresponding to the LLL context passed in the node rx - * footer field. - */ - lll = ftr->param; - ull_sync = HDR_LLL2ULL(lll); - /* Prepare and dispatch sync notification */ - rx_establ = (void *)ull_sync->node_rx_sync_estab; + rx_establ = (void *)sync->node_rx_sync_estab; rx_establ->hdr.type = NODE_RX_TYPE_SYNC; + rx_establ->hdr.handle = ull_sync_handle_get(sync); se = (void *)rx_establ->pdu; #if defined(CONFIG_BT_CTLR_SYNC_PERIODIC_CTE_TYPE_FILTERING) @@ -812,7 +804,7 @@ void ull_sync_established_report(memq_link_t *link, struct node_rx_hdr *rx) #if !defined(CONFIG_BT_CTLR_CTEINLINE_SUPPORT) /* Notify done event handler to terminate sync scan if required. */ - ull_sync->is_term = (sync_status == SYNC_STAT_TERM); + sync->is_term = (sync_status == SYNC_STAT_TERM); #endif /* !CONFIG_BT_CTLR_CTEINLINE_SUPPORT */ #else se->status = BT_HCI_ERR_SUCCESS; @@ -836,8 +828,9 @@ void ull_sync_established_report(memq_link_t *link, struct node_rx_hdr *rx) if (1) { #endif /* !CONFIG_BT_CTLR_SYNC_PERIODIC_CTE_TYPE_FILTERING */ + /* Switch sync event prepare function to one reposnsible for regular PDUs receive */ - mfy_lll_prepare.fp = lll_sync_prepare; + sync->lll_sync_prepare = lll_sync_prepare; /* Change node type to appropriately handle periodic * advertising PDU report. @@ -1128,6 +1121,9 @@ static void ticker_cb(uint32_t ticks_at_expire, uint32_t ticks_drift, uint32_t remainder, uint16_t lazy, uint8_t force, void *param) { + static memq_link_t link_lll_prepare; + static struct mayfly mfy_lll_prepare = { + 0, 0, &link_lll_prepare, NULL, NULL}; static struct lll_prepare_param p; struct ll_sync_set *sync = param; struct lll_sync *lll; @@ -1152,9 +1148,11 @@ static void ticker_cb(uint32_t ticks_at_expire, uint32_t ticks_drift, p.force = force; p.param = lll; mfy_lll_prepare.param = &p; + mfy_lll_prepare.fp = sync->lll_sync_prepare; /* Kick LLL prepare */ - ret = mayfly_enqueue(TICKER_USER_ID_ULL_HIGH, TICKER_USER_ID_LLL, 0, &mfy_lll_prepare); + ret = mayfly_enqueue(TICKER_USER_ID_ULL_HIGH, TICKER_USER_ID_LLL, 0, + &mfy_lll_prepare); LL_ASSERT(!ret); DEBUG_RADIO_PREPARE_O(1); @@ -1235,9 +1233,17 @@ static void ticker_stop_sync_lost_op_cb(uint32_t status, void *param) static void sync_lost(void *param) { - struct ll_sync_set *sync = param; + struct ll_sync_set *sync; struct node_rx_pdu *rx; + /* sync established was not generated yet, no free node rx */ + sync = param; + if (sync->lll_sync_prepare != lll_sync_prepare) { + sync_expire(param); + + return; + } + /* Generate Periodic advertising sync lost */ rx = (void *)&sync->node_rx_lost; rx->hdr.handle = ull_sync_handle_get(sync); diff --git a/subsys/bluetooth/controller/ll_sw/ull_sync_types.h b/subsys/bluetooth/controller/ll_sw/ull_sync_types.h index 7df41cf1d05..03b4d1cb45b 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_sync_types.h +++ b/subsys/bluetooth/controller/ll_sw/ull_sync_types.h @@ -21,6 +21,8 @@ struct ll_sync_set { uint16_t volatile timeout_reload; /* Non-zero when sync established */ uint16_t timeout_expire; + void (*lll_sync_prepare)(void *param); + #if defined(CONFIG_BT_CTLR_CHECK_SAME_PEER_SYNC) || \ defined(CONFIG_BT_CTLR_SYNC_PERIODIC_ADI_SUPPORT) uint8_t peer_id_addr[BDADDR_SIZE]; From 73ccb5df5ed800282fe2094c866c10aab6ba9dda Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Tue, 8 Feb 2022 18:13:07 +0530 Subject: [PATCH 175/207] [nrf fromtree] Bluetooth: Controller: Add sync established code comment Add code comment related to sync context field used to indicate the sync established event being generated towards HCI Layer. Co-authored-by: Piotr Pryga Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit fc9f976485c571bdc174c7dc5a498d93f010ab87) (cherry picked from commit 015aed146382c7ba05ce53030220fe66a7a72cc9) --- subsys/bluetooth/controller/ll_sw/ull_sync_types.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/subsys/bluetooth/controller/ll_sw/ull_sync_types.h b/subsys/bluetooth/controller/ll_sw/ull_sync_types.h index 03b4d1cb45b..8b2288c45b8 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_sync_types.h +++ b/subsys/bluetooth/controller/ll_sw/ull_sync_types.h @@ -21,6 +21,10 @@ struct ll_sync_set { uint16_t volatile timeout_reload; /* Non-zero when sync established */ uint16_t timeout_expire; + /* Member to store periodic advertising sync prepare. + * Also serves as a flag to inform if sync established was + * already generated. + */ void (*lll_sync_prepare)(void *param); #if defined(CONFIG_BT_CTLR_CHECK_SAME_PEER_SYNC) || \ From 58601e218e49d295d261b4380a14fdc9748c86ba Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Thu, 23 Dec 2021 11:51:25 +0530 Subject: [PATCH 176/207] [nrf fromtree] Bluetooth: Controller: Fix Periodic Sync lost implementation Fix Periodic Advertising Synchronization lost implementation to avoid processing done event twice in cases of overlapping events or race between sync terminate being requested. Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit 31c6a9cf184aa99933d6c60418e1cc94ee132bb4) (cherry picked from commit 50962c879dcc90e794df8673e1d1ed3d10439a5f) --- subsys/bluetooth/controller/ll_sw/ull_sync.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/subsys/bluetooth/controller/ll_sw/ull_sync.c b/subsys/bluetooth/controller/ll_sw/ull_sync.c index 9a99cdd60a1..20af75c0418 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_sync.c +++ b/subsys/bluetooth/controller/ll_sw/ull_sync.c @@ -370,6 +370,9 @@ uint8_t ll_sync_terminate(uint16_t handle) link_sync_lost = sync->node_rx_lost.hdr.link; ll_rx_link_release(link_sync_lost); + /* Mark sync context not sync established */ + sync->timeout_reload = 0U; + ull_sync_release(sync); return 0; @@ -488,9 +491,6 @@ void ull_sync_release(struct ll_sync_set *sync) sync->timeout = 0U; } - /* Mark sync context not sync established */ - sync->timeout_reload = 0U; - /* reset accumulated data len */ sync->data_len = 0U; @@ -853,8 +853,8 @@ void ull_sync_done(struct node_rx_event_done *done) /* Get reference to ULL context */ sync = CONTAINER_OF(done->param, struct ll_sync_set, ull); - /* Do nothing if local terminate requested */ - if (unlikely(sync->is_stop)) { + /* Do nothing if local terminate requested or sync lost */ + if (unlikely(sync->is_stop || !sync->timeout_reload)) { return; } @@ -1115,6 +1115,9 @@ static void sync_ticker_cleanup(struct ll_sync_set *sync, ticker_op_func stop_op TICKER_ID_SCAN_SYNC_BASE + sync_handle, stop_op_cb, (void *)sync); LL_ASSERT((ret == TICKER_STATUS_SUCCESS) || (ret == TICKER_STATUS_BUSY)); + + /* Mark sync context not sync established */ + sync->timeout_reload = 0U; } static void ticker_cb(uint32_t ticks_at_expire, uint32_t ticks_drift, From a8cad88d6f5c732755f7cd6edbe777fa76cbc4e2 Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Tue, 28 Dec 2021 06:41:39 +0530 Subject: [PATCH 177/207] [nrf fromtree] Bluetooth: Controller: Add assert to check IQ sample allocation Add assert to check IQ sample allocation. Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit ebe64beb2a49b42e746a9fba350802cceaa34390) (cherry picked from commit 6fedc1e27f64925e98e2cf3cb28d951e7f0d682d) --- subsys/bluetooth/controller/ll_sw/nordic/lll/lll_sync.c | 1 + 1 file changed, 1 insertion(+) diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_sync.c b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_sync.c index c2e1c8caa53..3f1b919b9a0 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_sync.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_sync.c @@ -990,6 +990,7 @@ static inline int create_iq_report(struct lll_sync *lll, uint8_t rssi_ready, cte_info = radio_df_cte_status_get(); ant = radio_df_pdu_antenna_switch_pattern_get(); iq_report = ull_df_iq_report_alloc(); + LL_ASSERT(iq_report); iq_report->hdr.type = NODE_RX_TYPE_SYNC_IQ_SAMPLE_REPORT; iq_report->sample_count = sample_cnt; From b0bc986b22495812d7b193474843cf09efd80714 Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Thu, 23 Dec 2021 11:43:58 +0530 Subject: [PATCH 178/207] [nrf fromtree] Bluetooth: Controller: Add development assert to check auxiliary parent Add development assert to check the validity of auxiliary context's parent. This is to ensure a released auxiliary context is not reused without allocation. Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit 18ca682357edeb746877ddd31109ba2017f92771) (cherry picked from commit 542bc9d02e4060d0eb052cb762a40d3f52c9ff78) --- .../bluetooth/controller/ll_sw/ull_scan_aux.c | 37 +++++++++++++++---- 1 file changed, 29 insertions(+), 8 deletions(-) diff --git a/subsys/bluetooth/controller/ll_sw/ull_scan_aux.c b/subsys/bluetooth/controller/ll_sw/ull_scan_aux.c index a360edde51f..db12ddea071 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_scan_aux.c +++ b/subsys/bluetooth/controller/ll_sw/ull_scan_aux.c @@ -163,6 +163,7 @@ void ull_scan_aux_setup(memq_link_t *link, struct node_rx_hdr *rx) /* aux parent will be NULL for periodic sync */ lll = aux->parent; + LL_ASSERT(lll); } else if (!IS_ENABLED(CONFIG_BT_CTLR_SYNC_PERIODIC) || ull_scan_is_valid_get(HDR_LLL2ULL(ftr->param))) { @@ -190,6 +191,7 @@ void ull_scan_aux_setup(memq_link_t *link, struct node_rx_hdr *rx) lll_aux = sync_lll->lll_aux; aux = HDR_LLL2ULL(lll_aux); + LL_ASSERT(sync_lll == aux->parent); } if (!IS_ENABLED(CONFIG_BT_CTLR_SYNC_PERIODIC) || lll) { @@ -756,8 +758,12 @@ void ull_scan_aux_done(struct node_rx_event_done *done) aux = HDR_LLL2ULL(sync->lll.lll_aux); } else { struct ll_scan_set *scan; + struct lll_scan *lll; + + lll = aux->parent; + LL_ASSERT(lll); - scan = HDR_LLL2ULL(aux->parent); + scan = HDR_LLL2ULL(lll); LL_ASSERT(ull_scan_is_valid_get(scan)); /* Auxiliary context will be flushed by ull_scan_aux_stop() */ @@ -800,12 +806,17 @@ void *ull_scan_aux_lll_parent_get(struct lll_scan_aux *lll, uint8_t *is_lll_scan) { struct ll_scan_aux_set *aux; - struct ll_scan_set *scan; aux = HDR_LLL2ULL(lll); - scan = HDR_LLL2ULL(aux->parent); if (is_lll_scan) { + struct ll_scan_set *scan; + struct lll_scan *lll; + + lll = aux->parent; + LL_ASSERT(lll); + + scan = HDR_LLL2ULL(lll); *is_lll_scan = !!ull_scan_is_valid_get(scan); } @@ -884,6 +895,8 @@ void ull_scan_aux_release(memq_link_t *link, struct node_rx_hdr *rx) aux = HDR_LLL2ULL(lll_aux); lll = aux->parent; + LL_ASSERT(lll); + scan = HDR_LLL2ULL(lll); scan = ull_scan_is_valid_get(scan); if (scan) { @@ -975,6 +988,8 @@ int ull_scan_aux_stop(struct ll_scan_aux_set *aux) struct lll_scan *lll; lll = aux->parent; + LL_ASSERT(lll); + scan = HDR_LLL2ULL(lll); scan = ull_scan_is_valid_get(scan); if (scan) { @@ -1016,14 +1031,10 @@ static inline struct ll_scan_aux_set *aux_acquire(void) static inline void aux_release(struct ll_scan_aux_set *aux) { - /* Debug check that parent was assigned when allocated for reception of - * auxiliary channel PDUs. - */ - LL_ASSERT(aux->parent); - /* Clear the parent so that when scan is being disabled then this * auxiliary context shall not associate itself from being disable. */ + LL_ASSERT(aux->parent); aux->parent = NULL; mem_release(aux, &scan_aux_free); @@ -1067,7 +1078,12 @@ static void flush(void *param) struct lll_scan *lll; bool sched = false; + /* Debug check that parent was assigned when allocated for reception of + * auxiliary channel PDUs. + */ aux = param; + LL_ASSERT(aux->parent); + rx = aux->rx_head; if (rx) { ll_rx_put(rx->link, rx); @@ -1143,6 +1159,7 @@ static void aux_sync_incomplete(void *param) /* get reference to sync context */ lll = aux->parent; + LL_ASSERT(lll); sync = HDR_LLL2ULL(lll); /* reset data len total */ @@ -1169,6 +1186,8 @@ static void aux_sync_incomplete(void *param) aux->rx_head = rx; } + LL_ASSERT(!ull_ref_get(&aux->ull)); + flush(aux); #endif /* CONFIG_BT_CTLR_SYNC_PERIODIC */ } @@ -1219,6 +1238,8 @@ static void ticker_op_cb(uint32_t status, void *param) aux = param; sync_lll = aux->parent; + LL_ASSERT(sync_lll); + sync = HDR_LLL2ULL(sync_lll); sync = ull_sync_is_valid_get(sync); } else { From 485d69a65fef29c2d8b9b7e6e709f9905f4cfcc1 Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Thu, 23 Dec 2021 11:43:58 +0530 Subject: [PATCH 179/207] [nrf fromtree] Bluetooth: Controller: Add development assert to check aux context Add development assert to check the validity of auxiliary context allocation. This is to ensure that primary PDU reception does not have an auxiliary context allocated until ULL has processed the node rx. Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit e5e0470ed3833af9386037309fee8b06b223abd9) (cherry picked from commit 1e604b4edd806ff25aa717acac0f57b5a1ec757d) --- subsys/bluetooth/controller/ll_sw/ull_scan_aux.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/subsys/bluetooth/controller/ll_sw/ull_scan_aux.c b/subsys/bluetooth/controller/ll_sw/ull_scan_aux.c index db12ddea071..60455c2752a 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_scan_aux.c +++ b/subsys/bluetooth/controller/ll_sw/ull_scan_aux.c @@ -133,7 +133,10 @@ void ull_scan_aux_setup(memq_link_t *link, struct node_rx_hdr *rx) sync_lll = NULL; sync_iso = NULL; rx_incomplete = NULL; + lll = ftr->param; + LL_ASSERT(!lll->lll_aux); + scan = HDR_LLL2ULL(lll); sync = sync_create_get(scan); phy = BT_HCI_LE_EXT_SCAN_PHY_1M; @@ -144,7 +147,10 @@ void ull_scan_aux_setup(memq_link_t *link, struct node_rx_hdr *rx) sync_lll = NULL; sync_iso = NULL; rx_incomplete = NULL; + lll = ftr->param; + LL_ASSERT(!lll->lll_aux); + scan = HDR_LLL2ULL(lll); sync = sync_create_get(scan); phy = BT_HCI_LE_EXT_SCAN_PHY_CODED; @@ -190,6 +196,8 @@ void ull_scan_aux_setup(memq_link_t *link, struct node_rx_hdr *rx) sync_lll = ftr->param; lll_aux = sync_lll->lll_aux; + LL_ASSERT(lll_aux); + aux = HDR_LLL2ULL(lll_aux); LL_ASSERT(sync_lll == aux->parent); } From b8c298501ba1b6eddb5dc2a6f42b5ea191c15451 Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Thu, 30 Dec 2021 12:04:22 +0530 Subject: [PATCH 180/207] [nrf fromtree] Bluetooth: Controller: Add assert check to detect sync aux context leak Add assertion check to detect sync aux context leak. Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit 0a290bd51d8f65db992d7aa051acfb40ecc0217d) (cherry picked from commit 5859068a5ed6e4daa64a8361226a012b9bd3eaf4) --- subsys/bluetooth/controller/ll_sw/ull_scan_aux.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/subsys/bluetooth/controller/ll_sw/ull_scan_aux.c b/subsys/bluetooth/controller/ll_sw/ull_scan_aux.c index 60455c2752a..3c882c0fd23 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_scan_aux.c +++ b/subsys/bluetooth/controller/ll_sw/ull_scan_aux.c @@ -268,6 +268,8 @@ void ull_scan_aux_setup(memq_link_t *link, struct node_rx_hdr *rx) * passed in the node rx footer field. */ sync_lll = ftr->param; + LL_ASSERT(!sync_lll->lll_aux); + ull_sync = HDR_LLL2ULL(sync_lll); rx->handle = ull_sync_handle_get(ull_sync); From 08de84f3054688b285ea860402a497373a19cdb1 Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Sun, 2 Jan 2022 12:21:10 +0530 Subject: [PATCH 181/207] [nrf fromtree] Bluetooth: Controller: Remove minor redundant assignment Minor change to remove redundant assignment statement. Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit 481a334d2b1f89d65b20ca7e669379161befc897) (cherry picked from commit 955eda61306d35c96afd9c8f59a50e0548990ec8) --- subsys/bluetooth/controller/ll_sw/ull_scan_aux.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/subsys/bluetooth/controller/ll_sw/ull_scan_aux.c b/subsys/bluetooth/controller/ll_sw/ull_scan_aux.c index 3c882c0fd23..565f0566203 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_scan_aux.c +++ b/subsys/bluetooth/controller/ll_sw/ull_scan_aux.c @@ -247,8 +247,6 @@ void ull_scan_aux_setup(memq_link_t *link, struct node_rx_hdr *rx) rx->type = NODE_RX_TYPE_SYNC_REPORT; rx->handle = ull_sync_handle_get(sync); - sync_lll = &sync->lll; - /* Check if we need to create BIG sync */ sync_iso = sync_iso_create_get(sync); From 4f01ca4ef81753f06a40008d83498431cc368398 Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Sun, 19 Dec 2021 06:34:21 +0530 Subject: [PATCH 182/207] [nrf fromtree] Bluetooth: Controller: Periodic Sync Chain reception continuation Implementation to continue Periodic Sync Chain reception when overlapping with scan events. Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit bd4086b847205694a182a9ccaeb1a0828a241442) (cherry picked from commit 0cbf6beb9caf4e347c3cc97b77685b782cf565d3) --- subsys/bluetooth/controller/ll_sw/lll_scan.h | 1 + .../controller/ll_sw/nordic/lll/lll_sync.c | 31 +++++++++++++++++-- subsys/bluetooth/controller/ll_sw/ull_scan.c | 13 ++++++++ 3 files changed, 43 insertions(+), 2 deletions(-) diff --git a/subsys/bluetooth/controller/ll_sw/lll_scan.h b/subsys/bluetooth/controller/ll_sw/lll_scan.h index 04894e5a7a8..5646d36773c 100644 --- a/subsys/bluetooth/controller/ll_sw/lll_scan.h +++ b/subsys/bluetooth/controller/ll_sw/lll_scan.h @@ -86,3 +86,4 @@ int lll_scan_reset(void); void lll_scan_prepare(void *param); extern uint8_t ull_scan_lll_handle_get(struct lll_scan *lll); +extern struct lll_scan *ull_scan_lll_is_valid_get(struct lll_scan *lll); diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_sync.c b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_sync.c index 3f1b919b9a0..4ccd61a4013 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_sync.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_sync.c @@ -49,6 +49,7 @@ static void prepare(void *param); static int create_prepare_cb(struct lll_prepare_param *p); static int prepare_cb(struct lll_prepare_param *p); static int prepare_cb_common(struct lll_prepare_param *p, uint8_t chan_idx); +static int is_abort_cb(void *next, void *curr, lll_prepare_cb_t *resume_cb); static void abort_cb(struct lll_prepare_param *prepare_param, void *param); static int isr_rx(struct lll_sync *lll, uint8_t node_type, uint8_t crc_ok, uint8_t rssi_ready, enum sync_status status); @@ -98,7 +99,7 @@ void lll_sync_create_prepare(void *param) prepare(param); /* Invoke common pipeline handling of prepare */ - err = lll_prepare(lll_is_abort_cb, abort_cb, create_prepare_cb, 0, param); + err = lll_prepare(is_abort_cb, abort_cb, create_prepare_cb, 0, param); LL_ASSERT(!err || err == -EINPROGRESS); } @@ -109,7 +110,7 @@ void lll_sync_prepare(void *param) prepare(param); /* Invoke common pipeline handling of prepare */ - err = lll_prepare(lll_is_abort_cb, abort_cb, prepare_cb, 0, param); + err = lll_prepare(is_abort_cb, abort_cb, prepare_cb, 0, param); LL_ASSERT(!err || err == -EINPROGRESS); } @@ -455,6 +456,32 @@ static int prepare_cb_common(struct lll_prepare_param *p, uint8_t chan_idx) return 0; } +static int is_abort_cb(void *next, void *curr, lll_prepare_cb_t *resume_cb) +{ + /* Sync context shall not resume when being preempted, i.e. they + * shall not use -EAGAIN as return value. + */ + ARG_UNUSED(resume_cb); + + /* Different radio event overlap */ + if (next != curr) { + struct lll_scan *lll; + + lll = ull_scan_lll_is_valid_get(next); + if (!lll) { + /* Abort current event as next event is not a scan + * event. + */ + return -ECANCELED; + } + } + + /* Do not abort if current periodic sync event overlaps next interval + * or next event is a scan event. + */ + return 0; +} + static void abort_cb(struct lll_prepare_param *prepare_param, void *param) { struct lll_sync *lll; diff --git a/subsys/bluetooth/controller/ll_sw/ull_scan.c b/subsys/bluetooth/controller/ll_sw/ull_scan.c index f3779f7e0c3..62ce791de4d 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_scan.c +++ b/subsys/bluetooth/controller/ll_sw/ull_scan.c @@ -625,6 +625,19 @@ struct ll_scan_set *ull_scan_is_valid_get(struct ll_scan_set *scan) return scan; } +struct lll_scan *ull_scan_lll_is_valid_get(struct lll_scan *lll) +{ + struct ll_scan_set *scan; + + scan = HDR_LLL2ULL(lll); + scan = ull_scan_is_valid_get(scan); + if (scan) { + return &scan->lll; + } + + return NULL; +} + struct ll_scan_set *ull_scan_is_enabled_get(uint8_t handle) { struct ll_scan_set *scan; From 3aa82d2145c18f0ebbdee0dcb5d20a6e51379c42 Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Sun, 19 Dec 2021 06:34:21 +0530 Subject: [PATCH 183/207] [nrf fromtree] Bluetooth: Controller: Auxiliary PDU reception continuation Implementation to continue Auxiliary PDU reception when overlapping with scan events. Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit 4d87a7ff1545c122e22caa16e5b02a22d9361716) (cherry picked from commit 62916a7df91235fa4dd1058f08ec3a409b409c0d) --- .../ll_sw/nordic/lll/lll_scan_aux.c | 29 ++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) 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 f18bdfb7373..c0009faf335 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 @@ -53,6 +53,7 @@ static int init_reset(void); static int prepare_cb(struct lll_prepare_param *p); +static int is_abort_cb(void *next, void *curr, lll_prepare_cb_t *resume_cb); static void abort_cb(struct lll_prepare_param *prepare_param, void *param); static void isr_done(void *param); static void isr_rx_ull_schedule(void *param); @@ -110,7 +111,7 @@ void lll_scan_aux_prepare(void *param) err = lll_hfclock_on(); LL_ASSERT(err >= 0); - err = lll_prepare(lll_is_abort_cb, abort_cb, prepare_cb, 0, param); + err = lll_prepare(is_abort_cb, abort_cb, prepare_cb, 0, param); LL_ASSERT(!err || err == -EINPROGRESS); } @@ -596,6 +597,32 @@ static int prepare_cb(struct lll_prepare_param *p) return 0; } +static int is_abort_cb(void *next, void *curr, lll_prepare_cb_t *resume_cb) +{ + struct lll_scan *lll; + + /* Auxiliary context shall not resume when being preempted, i.e. they + * shall not use -EAGAIN as return value. + */ + ARG_UNUSED(resume_cb); + + /* Auxiliary event shall not overlap as they are not periodically + * scheduled. + */ + LL_ASSERT(next != curr); + + lll = ull_scan_lll_is_valid_get(next); + if (lll) { + /* Next event is scan context, let the current auxiliary scan + * continue. + */ + return 0; + } + + /* Yield current auxiliary event to other than scan events */ + return -ECANCELED; +} + static void abort_cb(struct lll_prepare_param *prepare_param, void *param) { int err; From 93f832604a1c380bf5b90c8bb0ea029e77f39199 Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Thu, 23 Dec 2021 11:46:36 +0530 Subject: [PATCH 184/207] [nrf fromtree] Bluetooth: Controller: Fix reset of is_aux_sched flag Fix reset of is_aux_sched flag when closing the primary and auxiliary PDU reception. Without this fix when scan window is closed there would be duplicate auxiliary release message generated causing memory corruption. Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit 0748474831d1128310c5e596c9b6fc9ef4b374df) (cherry picked from commit 0b8acca330a1985ae56e994fbbd15417316dd417) --- .../controller/ll_sw/nordic/lll/lll_scan.c | 2 ++ .../ll_sw/nordic/lll/lll_scan_aux.c | 21 ++++++++++--------- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_scan.c b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_scan.c index ecebaf9a65e..fb3c0304e1d 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_scan.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_scan.c @@ -1015,6 +1015,8 @@ static void isr_done_cleanup(void *param) if (lll->is_aux_sched) { struct node_rx_pdu *node_rx; + lll->is_aux_sched = 0U; + node_rx = ull_pdu_rx_alloc(); LL_ASSERT(node_rx); 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 c0009faf335..55e6abe3105 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 @@ -850,6 +850,8 @@ static void isr_rx(struct lll_scan *lll, struct lll_scan_aux *lll_aux, * context or auxiliary PDU reception by aux context */ if (lll->is_aux_sched) { + lll->is_aux_sched = 0U; + /* Go back to resuming primary channel scanning */ radio_isr_set(lll_scan_isr_resume, lll); } else { @@ -1214,11 +1216,6 @@ static int isr_rx_pdu(struct lll_scan *lll, struct lll_scan_aux *lll_aux, ftr->param = lll; ftr->scan_rsp = lll->lll_aux->state; - /* Auxiliary PDU received by LLL scheduling by scan - * context. - */ - lll->is_aux_sched = 1U; - /* Further auxiliary PDU reception will be chain PDUs */ lll->lll_aux->is_chain_sched = 1U; } else { @@ -1266,18 +1263,22 @@ static int isr_rx_pdu(struct lll_scan *lll, struct lll_scan_aux *lll_aux, ull_rx_sched(); - /* Increase trx count so as to not generate done extra event - * as a valid Auxiliary PDU node rx is being reported to ULL. - */ - trx_cnt++; - /* Next aux scan is scheduled from LLL, we already handled radio * disable so prevent caller from doing it again. */ if (ftr->aux_lll_sched) { + if (!lll_aux) { + lll->is_aux_sched = 1U; + } + return 0; } + /* Increase trx count so as to not generate done extra event + * as a valid Auxiliary PDU node rx is being reported to ULL. + */ + trx_cnt++; + return -ECANCELED; } From 922bab6f9eb606057737a2e62c636f6dbd98d46c Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Sun, 2 Jan 2022 06:00:30 +0530 Subject: [PATCH 185/207] [nrf fromtree] Bluetooth: Controller: Fix auxiliary context release on scan done Fix auxiliary context release on scan done, do not wait for reference count to reduce when Periodic Sync events overlap. Regression introduced in commit 624e0030646a ("Bluetooth: controller: Fix auxiliary scan context release"). Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit 4591c0173fc54cf9413d69254b66c7eee64ca3ca) (cherry picked from commit 8e80aed06377ed38bac531eb2e1ab9842ab9e0e4) --- subsys/bluetooth/controller/ll_sw/ull_scan_aux.c | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/subsys/bluetooth/controller/ll_sw/ull_scan_aux.c b/subsys/bluetooth/controller/ll_sw/ull_scan_aux.c index 565f0566203..720a7d0cd80 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_scan_aux.c +++ b/subsys/bluetooth/controller/ll_sw/ull_scan_aux.c @@ -746,7 +746,6 @@ void ull_scan_aux_setup(memq_link_t *link, struct node_rx_hdr *rx) void ull_scan_aux_done(struct node_rx_event_done *done) { struct ll_scan_aux_set *aux; - struct ull_hdr *hdr; /* Get reference to ULL context */ aux = CONTAINER_OF(done->param, struct ll_scan_aux_set, ull); @@ -757,8 +756,8 @@ void ull_scan_aux_done(struct node_rx_event_done *done) sync = CONTAINER_OF(done->param, struct ll_sync_set, ull); LL_ASSERT(ull_sync_is_valid_get(sync)); - hdr = &sync->ull; + /* Auxiliary context will be flushed by ull_scan_aux_stop() */ if (unlikely(sync->is_stop) || !sync->lll.lll_aux) { return; } @@ -778,18 +777,9 @@ void ull_scan_aux_done(struct node_rx_event_done *done) if (unlikely(scan->is_stop)) { return; } - - /* Setup the disabled callback to flush the auxiliary PDUs */ - hdr = &aux->ull; } - if (ull_ref_get(hdr) == 0U) { - flush(aux); - } else { - LL_ASSERT(!hdr->disabled_cb); - hdr->disabled_param = aux; - hdr->disabled_cb = done_disabled_cb; - } + flush(aux); } struct ll_scan_aux_set *ull_scan_aux_set_get(uint8_t handle) From efb9ccc8e1746825d6c4631ae185af111afa0d9d Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Mon, 3 Jan 2022 07:04:57 +0530 Subject: [PATCH 186/207] [nrf fromtree] Bluetooth: Controller: Fix missing auxiliary context done event Fix missing use of auxiliary context to generate done event which caused leak in release of auxiliary context being not release when reference count that should decrease to zero. Regression in 'commit 665a8d2c6ea6 ("Bluetooth: Controller: Fix repeated per sync drift compensations"). Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit c2dda0950d839cd6b362f950b7d24cf303898489) (cherry picked from commit 7a53a6d6a7d42c14b36d6a13bd83473e677a5c01) --- subsys/bluetooth/controller/ll_sw/nordic/lll/lll_sync.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_sync.c b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_sync.c index 4ccd61a4013..b18726192f5 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_sync.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_sync.c @@ -925,7 +925,7 @@ static void isr_rx_aux_chain(void *param) isr_rx_done_cleanup(lll, 1U, false); } else { - lll_isr_cleanup(lll); + lll_isr_cleanup(lll_aux); } } From f7d4cfaff20d9cfc6d83c6f5743ed096627da25b Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Wed, 5 Jan 2022 12:45:35 +0530 Subject: [PATCH 187/207] [nrf fromtree] Bluetooth: Controller: Fix missing aux release on abort of LLL sched Fix missing auxiliary context release message on abort of LLL scheduling scheduling used by scan context. Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit 7f24d3bc6bf96a44b352bc3bbeeb6751a674f46b) (cherry picked from commit 343972f60434061292ec6bcd4cbb41f7400f00b2) --- .../controller/ll_sw/nordic/lll/lll_scan.c | 43 +++++++++++++------ 1 file changed, 29 insertions(+), 14 deletions(-) diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_scan.c b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_scan.c index fb3c0304e1d..593eea4f024 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_scan.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_scan.c @@ -1012,6 +1012,19 @@ static void isr_done_cleanup(void *param) #if defined(CONFIG_BT_CTLR_ADV_EXT) struct event_done_extra *extra; + /* Generate Scan done events so that duration and max expiry is + * detected in ULL. + */ + extra = ull_done_extra_type_set(EVENT_DONE_EXTRA_TYPE_SCAN); + LL_ASSERT(extra); + + /* Prevent scan events in pipeline from being scheduled if duration has + * expired. + */ + if (unlikely(lll->duration_reload && !lll->duration_expire)) { + lll->is_stop = 1U; + } + if (lll->is_aux_sched) { struct node_rx_pdu *node_rx; @@ -1027,19 +1040,6 @@ static void isr_done_cleanup(void *param) ull_rx_put(node_rx->hdr.link, node_rx); ull_rx_sched(); } - - /* Generate Scan done events so that duration and max expiry is - * detected in ULL. - */ - extra = ull_done_extra_type_set(EVENT_DONE_EXTRA_TYPE_SCAN); - LL_ASSERT(extra); - - /* Prevent scan events in pipeline from being scheduled if duration has - * expired. - */ - if (unlikely(lll->duration_reload && !lll->duration_expire)) { - lll->is_stop = 1U; - } #endif /* CONFIG_BT_CTLR_ADV_EXT */ lll_isr_cleanup(param); @@ -1095,9 +1095,24 @@ static void isr_cleanup(void *param) #if defined(CONFIG_BT_CTLR_ADV_EXT) struct lll_scan *lll = param; - lll->is_aux_sched = 0U; + if (lll->is_aux_sched) { + struct node_rx_pdu *node_rx; + + lll->is_aux_sched = 0U; + + node_rx = ull_pdu_rx_alloc(); + LL_ASSERT(node_rx); + + node_rx->hdr.type = NODE_RX_TYPE_EXT_AUX_RELEASE; + + node_rx->hdr.rx_ftr.param = lll; + + ull_rx_put(node_rx->hdr.link, node_rx); + ull_rx_sched(); + } #endif /* CONFIG_BT_CTLR_ADV_EXT */ + lll_isr_cleanup(param); } From 7d45497fec0310421aae064d7aa616b80b065bc9 Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Thu, 6 Jan 2022 17:39:38 +0530 Subject: [PATCH 188/207] [nrf fromtree] Bluetooth: Controller: Fix scanner window close by using lll_disable Fix race condition in setting up ISR callback and parameter caused between ULL_HIGH and LLL context. As LLL IRQ is not disabled the parameter and ISR callback would get out of sync causing incorrect parameter supplied to callback and hence leading to development assert in ull_scan_done(). Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit d367447d6460125b91dbce077bef06e6c968522b) (cherry picked from commit 073483a6dc10019756c8072b5b75e5bfa72c4f6c) --- .../controller/ll_sw/nordic/lll/lll.c | 13 +- .../ll_sw/nordic/lll/lll_internal.h | 2 +- .../controller/ll_sw/nordic/lll/lll_scan.c | 124 +++++++----------- 3 files changed, 57 insertions(+), 82 deletions(-) diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll.c b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll.c index e0cc6de53a3..c206ab810c7 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll.c @@ -375,9 +375,14 @@ void lll_done_ull_inc(void) } #endif /* CONFIG_BT_CTLR_LOW_LAT_ULL_DONE */ -bool lll_is_done(void *param) +bool lll_is_done(void *param, bool *is_resume) { - /* FIXME: use param to check */ + /* NOTE: Current radio event when preempted could put itself in resume + * into the prepare pipeline in which case event.curr.param would + * be set to NULL. + */ + *is_resume = (param != event.curr.param); + return !event.curr.abort_cb; } @@ -731,6 +736,10 @@ static struct lll_event *resume_enqueue(lll_prepare_cb_t resume_cb) { struct lll_prepare_param prepare_param = {0}; + /* Enqueue into prepare pipeline as resume radio event, and remove + * parameter assignment from currently active radio event so that + * done event is not generated. + */ prepare_param.param = event.curr.param; event.curr.param = NULL; diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_internal.h b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_internal.h index 6fdf3b74c74..032ca508148 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_internal.h +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_internal.h @@ -6,7 +6,7 @@ int lll_prepare_done(void *param); int lll_done(void *param); -bool lll_is_done(void *param); +bool lll_is_done(void *param, bool *is_resume); int lll_is_abort_cb(void *next, void *curr, lll_prepare_cb_t *resume_cb); void lll_abort_cb(struct lll_prepare_param *prepare_param, void *param); diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_scan.c b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_scan.c index 593eea4f024..4f8308455e5 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_scan.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_scan.c @@ -79,7 +79,6 @@ static void isr_abort(void *param); * (EVENT_OVERHEAD_PREEMPT_US <= EVENT_OVERHEAD_PREEMPT_MIN_US) */ static void isr_done_cleanup(void *param); -static void isr_cleanup(void *param); static inline int isr_rx_pdu(struct lll_scan *lll, struct pdu_adv *pdu_adv_rx, uint8_t devmatch_ok, uint8_t devmatch_id, @@ -620,11 +619,8 @@ static void abort_cb(struct lll_prepare_param *prepare_param, void *param) cpu_sleep(); } #endif /* CONFIG_BT_CENTRAL */ - } else if (IS_ENABLED(CONFIG_BT_CTLR_LOW_LAT)) { - radio_isr_set(isr_done_cleanup, param); - radio_disable(); } else { - radio_isr_set(isr_cleanup, param); + radio_isr_set(isr_done_cleanup, param); radio_disable(); } return; @@ -640,10 +636,17 @@ static void abort_cb(struct lll_prepare_param *prepare_param, void *param) } static void ticker_stop_cb(uint32_t ticks_at_expire, uint32_t ticks_drift, - uint32_t remainder, uint16_t lazy, uint8_t force, void *param) + uint32_t remainder, uint16_t lazy, uint8_t force, + void *param) { - radio_isr_set(isr_done_cleanup, param); - radio_disable(); + static memq_link_t link; + static struct mayfly mfy = {0, 0, &link, NULL, lll_disable}; + uint32_t ret; + + mfy.param = param; + ret = mayfly_enqueue(TICKER_USER_ID_ULL_HIGH, TICKER_USER_ID_LLL, 0, + &mfy); + LL_ASSERT(!ret); } static void ticker_op_start_cb(uint32_t status, void *param) @@ -982,6 +985,7 @@ static void isr_abort(void *param) static void isr_done_cleanup(void *param) { struct lll_scan *lll; + bool is_resume; /* Clear radio status and events */ lll_isr_status_reset(); @@ -989,7 +993,7 @@ static void isr_done_cleanup(void *param) /* Under race between duration expire, is_stop is set in this function, * and event preemption, prevent generating duplicate scan done events. */ - if (lll_is_done(param)) { + if (lll_is_done(param, &is_resume)) { return; } @@ -1009,67 +1013,26 @@ static void isr_done_cleanup(void *param) ticker_stop(TICKER_INSTANCE_ID_CTLR, TICKER_USER_ID_LLL, TICKER_ID_SCAN_STOP, NULL, NULL); -#if defined(CONFIG_BT_CTLR_ADV_EXT) - struct event_done_extra *extra; - - /* Generate Scan done events so that duration and max expiry is - * detected in ULL. - */ - extra = ull_done_extra_type_set(EVENT_DONE_EXTRA_TYPE_SCAN); - LL_ASSERT(extra); +#if defined(CONFIG_BT_CTLR_SCAN_INDICATION) + struct node_rx_hdr *node_rx; - /* Prevent scan events in pipeline from being scheduled if duration has - * expired. + /* Check if there are enough free node rx available: + * 1. For generating this scan indication + * 2. Keep one available free for reception of ACL connection Rx data + * 3. Keep one available free for reception on ACL connection to NACK + * the PDU */ - if (unlikely(lll->duration_reload && !lll->duration_expire)) { - lll->is_stop = 1U; - } - - if (lll->is_aux_sched) { - struct node_rx_pdu *node_rx; - - lll->is_aux_sched = 0U; - - node_rx = ull_pdu_rx_alloc(); - LL_ASSERT(node_rx); - - node_rx->hdr.type = NODE_RX_TYPE_EXT_AUX_RELEASE; + node_rx = ull_pdu_rx_alloc_peek(3); + if (node_rx) { + ull_pdu_rx_alloc(); - node_rx->hdr.rx_ftr.param = lll; + /* TODO: add other info by defining a payload struct */ + node_rx->type = NODE_RX_TYPE_SCAN_INDICATION; - ull_rx_put(node_rx->hdr.link, node_rx); + ull_rx_put(node_rx->link, node_rx); ull_rx_sched(); } -#endif /* CONFIG_BT_CTLR_ADV_EXT */ - - lll_isr_cleanup(param); -} - -static void isr_cleanup(void *param) -{ - /* Clear radio status and events */ - lll_isr_status_reset(); - - /* Do not generate done event for connection initiation, ULL will - * disable the event when establishing/setting up the connection. - * Also, do not generate done event when duration expire, as ULL - * will disable the event. - * As it was transmission of CONNECT_IND, there is not filters to - * disable either. - */ - if (lll_is_done(param)) { - return; - } - - /* Disable Rx filters, if cleanup after being in Rx state */ - radio_filter_disable(); - - /* Scanner stop can expire while here in this ISR. - * Deferred attempt to stop can fail as it would have - * expired, hence ignore failure. - */ - ticker_stop(TICKER_INSTANCE_ID_CTLR, TICKER_USER_ID_LLL, - TICKER_ID_SCAN_STOP, NULL, NULL); +#endif /* CONFIG_BT_CTLR_SCAN_INDICATION */ #if defined(CONFIG_BT_HCI_MESH_EXT) if (_radio.advertiser.is_enabled && _radio.advertiser.is_mesh && @@ -1078,22 +1041,26 @@ static void isr_cleanup(void *param) } #endif /* CONFIG_BT_HCI_MESH_EXT */ -#if defined(CONFIG_BT_CTLR_SCAN_INDICATION) - struct node_rx_hdr *node_rx = ull_pdu_rx_alloc_peek(3); - - if (node_rx) { - ull_pdu_rx_alloc(); - - /* TODO: add other info by defining a payload struct */ - node_rx->type = NODE_RX_TYPE_SCAN_INDICATION; +#if defined(CONFIG_BT_CTLR_ADV_EXT) + /* If continuous scan then do not generate scan done when radio event + * has been placed into prepare pipeline as a resume radio event. + */ + if (!is_resume) { + struct event_done_extra *extra; - ull_rx_put(node_rx->link, node_rx); - ull_rx_sched(); + /* Generate Scan done events so that duration and max expiry is + * detected in ULL. + */ + extra = ull_done_extra_type_set(EVENT_DONE_EXTRA_TYPE_SCAN); + LL_ASSERT(extra); } -#endif /* CONFIG_BT_CTLR_SCAN_INDICATION */ -#if defined(CONFIG_BT_CTLR_ADV_EXT) - struct lll_scan *lll = param; + /* Prevent scan events in pipeline from being scheduled if duration has + * expired. + */ + if (unlikely(lll->duration_reload && !lll->duration_expire)) { + lll->is_stop = 1U; + } if (lll->is_aux_sched) { struct node_rx_pdu *node_rx; @@ -1112,7 +1079,6 @@ static void isr_cleanup(void *param) } #endif /* CONFIG_BT_CTLR_ADV_EXT */ - lll_isr_cleanup(param); } @@ -1206,7 +1172,7 @@ static inline int isr_rx_pdu(struct lll_scan *lll, struct pdu_adv *pdu_adv_rx, lll_prof_cputime_capture(); } - radio_isr_set(isr_cleanup, lll); + radio_isr_set(isr_done_cleanup, lll); #if defined(HAL_RADIO_GPIO_HAVE_PA_PIN) if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) { From 54af281ce60274617f8803b91bdaf3ce294535a9 Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Thu, 10 Feb 2022 09:14:26 +0530 Subject: [PATCH 189/207] [nrf fromtree] Bluetooth: Controller: Fix to use non-discardable buffer Fix to use non-discardable Rx buffer for handling Extended and Periodic Advertising Report. Regression introduced in commit 18171bc77445 ("Bluetooth: Host: Non-discardable event buffer size is 255 for ext adv"). The default discardable Rx buffer size was reduced causing increased fragmentation and deadlock trying to get more free discardable Rx buffers to generate HCI Extended and Periodic Advertising reports. Signed-off-by: Vinayak Kariappa Chettimada (cherry picked from commit 230f4f1c1b6211ce5204ff9956a15ac9f9e272cc) (cherry picked from commit 901604f9c22db2cbe7976297639c3b2be1283089) --- subsys/bluetooth/controller/hci/hci.c | 31 +++++++++++---------------- 1 file changed, 13 insertions(+), 18 deletions(-) diff --git a/subsys/bluetooth/controller/hci/hci.c b/subsys/bluetooth/controller/hci/hci.c index f8dc0024679..d9a39760d90 100644 --- a/subsys/bluetooth/controller/hci/hci.c +++ b/subsys/bluetooth/controller/hci/hci.c @@ -190,12 +190,6 @@ static uint32_t conn_count; static uint32_t cis_pending_count; #endif -#if !defined(CONFIG_BT_HCI_RAW) && defined(CONFIG_BT_BUF_EVT_DISCARDABLE_COUNT) -#define ADV_REPORT_EVT_MAX_LEN CONFIG_BT_BUF_EVT_DISCARDABLE_SIZE -#else -#define ADV_REPORT_EVT_MAX_LEN CONFIG_BT_BUF_EVT_RX_SIZE -#endif - /* In HCI event PHY indices start at 1 compare to 0 indexed in aux_ptr field in * the Common Extended Payload Format in the PDUs. */ @@ -6186,7 +6180,7 @@ static void le_ext_adv_report(struct pdu_data *pdu_data, /* HCI fragment */ evt_buf = buf; - data_len_max = ADV_REPORT_EVT_MAX_LEN - + data_len_max = CONFIG_BT_BUF_EVT_RX_SIZE - sizeof(struct bt_hci_evt_le_meta_event) - sizeof(struct bt_hci_evt_le_ext_advertising_report) - sizeof(struct bt_hci_evt_le_ext_advertising_info); @@ -6535,7 +6529,7 @@ static void le_per_adv_sync_report(struct pdu_data *pdu_data, accept = ftr->sync_rx_enabled; } - data_len_max = ADV_REPORT_EVT_MAX_LEN - + data_len_max = CONFIG_BT_BUF_EVT_RX_SIZE - sizeof(struct bt_hci_evt_le_meta_event) - sizeof(struct bt_hci_evt_le_per_advertising_report); data_len_total = node_rx->hdr.rx_ftr.aux_data_len; @@ -7668,13 +7662,6 @@ uint8_t hci_get_class(struct node_rx_pdu *node_rx) defined(CONFIG_BT_CTLR_PROFILE_ISR) #if defined(CONFIG_BT_OBSERVER) case NODE_RX_TYPE_REPORT: - -#if defined(CONFIG_BT_CTLR_ADV_EXT) - __fallthrough; - case NODE_RX_TYPE_EXT_1M_REPORT: - case NODE_RX_TYPE_EXT_2M_REPORT: - case NODE_RX_TYPE_EXT_CODED_REPORT: -#endif /* CONFIG_BT_CTLR_ADV_EXT */ #endif /* CONFIG_BT_OBSERVER */ #if defined(CONFIG_BT_CTLR_SCAN_REQ_NOTIFY) @@ -7703,6 +7690,7 @@ uint8_t hci_get_class(struct node_rx_pdu *node_rx) #if defined(CONFIG_BT_CTLR_ADV_EXT) #if defined(CONFIG_BT_BROADCASTER) case NODE_RX_TYPE_EXT_ADV_TERMINATE: + #if defined(CONFIG_BT_CTLR_ADV_ISO) case NODE_RX_TYPE_BIG_COMPLETE: case NODE_RX_TYPE_BIG_TERMINATE: @@ -7710,11 +7698,12 @@ uint8_t hci_get_class(struct node_rx_pdu *node_rx) #endif /* CONFIG_BT_BROADCASTER */ #if defined(CONFIG_BT_OBSERVER) - __fallthrough; + case NODE_RX_TYPE_EXT_1M_REPORT: + case NODE_RX_TYPE_EXT_2M_REPORT: + case NODE_RX_TYPE_EXT_CODED_REPORT: case NODE_RX_TYPE_EXT_SCAN_TERMINATE: #if defined(CONFIG_BT_CTLR_SYNC_PERIODIC) - __fallthrough; case NODE_RX_TYPE_SYNC: case NODE_RX_TYPE_SYNC_REPORT: case NODE_RX_TYPE_SYNC_LOST: @@ -7724,7 +7713,6 @@ uint8_t hci_get_class(struct node_rx_pdu *node_rx) #endif /* CONFIG_BT_CTLR_DF_SCAN_CTE_RX */ #if defined(CONFIG_BT_CTLR_SYNC_ISO) - __fallthrough; case NODE_RX_TYPE_SYNC_ISO: case NODE_RX_TYPE_SYNC_ISO_LOST: #endif /* CONFIG_BT_CTLR_SYNC_ISO */ @@ -7744,9 +7732,11 @@ uint8_t hci_get_class(struct node_rx_pdu *node_rx) #if defined(CONFIG_BT_CTLR_CONN_ISO) case NODE_RX_TYPE_CIS_ESTABLISHED: #endif /* CONFIG_BT_CTLR_CONN_ISO */ + #if defined(CONFIG_BT_CTLR_DF_CONN_CTE_RX) case NODE_RX_TYPE_CONN_IQ_SAMPLE_REPORT: #endif /* CONFIG_BT_CTLR_DF_CONN_CTE_RX */ + return HCI_CLASS_EVT_REQUIRED; case NODE_RX_TYPE_TERMINATE: @@ -7759,17 +7749,22 @@ uint8_t hci_get_class(struct node_rx_pdu *node_rx) #if defined(CONFIG_BT_CTLR_CONN_RSSI_EVENT) case NODE_RX_TYPE_RSSI: #endif /* CONFIG_BT_CTLR_CONN_RSSI_EVENT */ + #if defined(CONFIG_BT_CTLR_LE_PING) case NODE_RX_TYPE_APTO: #endif /* CONFIG_BT_CTLR_LE_PING */ + #if defined(CONFIG_BT_CTLR_CHAN_SEL_2) case NODE_RX_TYPE_CHAN_SEL_ALGO: #endif /* CONFIG_BT_CTLR_CHAN_SEL_2 */ + #if defined(CONFIG_BT_CTLR_PHY) case NODE_RX_TYPE_PHY_UPDATE: #endif /* CONFIG_BT_CTLR_PHY */ + return HCI_CLASS_EVT_CONNECTION; #endif /* CONFIG_BT_CONN */ + #if defined(CONFIG_BT_CTLR_SYNC_ISO) || defined(CONFIG_BT_CTLR_CONN_ISO) case NODE_RX_TYPE_ISO_PDU: return HCI_CLASS_ISO_DATA; From 76b7916a9732b24ed2253b4127a193962c758a36 Mon Sep 17 00:00:00 2001 From: Marek Pieta Date: Thu, 10 Feb 2022 15:09:55 +0100 Subject: [PATCH 190/207] [nrf fromtree] Revert "Bluetooth: host: Remove CCC update from GATT connected callback" This reverts commit 0a1f553dc23ca9c2b42092dbba44ab0b3204990b. Signed-off-by: Marek Pieta (cherry picked from commit 5c3fc2782e90f01b1520261bcf7396f267ff2b31) --- subsys/bluetooth/host/gatt.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/subsys/bluetooth/host/gatt.c b/subsys/bluetooth/host/gatt.c index b997a4b7421..dae58bc6f16 100644 --- a/subsys/bluetooth/host/gatt.c +++ b/subsys/bluetooth/host/gatt.c @@ -4908,6 +4908,8 @@ void bt_gatt_connected(struct bt_conn *conn) settings_load_subtree_direct(key, ccc_set_direct, (void *)key); } + bt_gatt_foreach_attr(0x0001, 0xffff, update_ccc, &data); + /* BLUETOOTH CORE SPECIFICATION Version 5.1 | Vol 3, Part C page 2192: * * 10.3.1.1 Handling of GATT indications and notifications From d391784eaa7ffc2337b59db77fa60ab46962a262 Mon Sep 17 00:00:00 2001 From: Piotr Pryga Date: Fri, 11 Feb 2022 13:23:02 +0100 Subject: [PATCH 191/207] [nrf fromtree] Bluetooth: Host: Fix wrong length of antenna identifiers for CTE RX There were used an uninitialized variable to set antenna identifiers length. The value should be set with use of params argument, not by cp pointer that is not yet initialized. Signed-off-by: Piotr Pryga (cherry picked from commit c889e34413faba52c73731cfe42e6623c2452ef6) --- subsys/bluetooth/host/direction.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/subsys/bluetooth/host/direction.c b/subsys/bluetooth/host/direction.c index 8bfcba36d29..4a6c01b7e52 100644 --- a/subsys/bluetooth/host/direction.c +++ b/subsys/bluetooth/host/direction.c @@ -282,7 +282,7 @@ prepare_cl_cte_rx_enable_cmd_params(struct net_buf **buf, struct bt_le_per_adv_s uint8_t switch_pattern_len; if (params->cte_types & BT_DF_CTE_TYPE_AOA) { - switch_pattern_len = cp->switch_pattern_len; + switch_pattern_len = params->num_ant_ids; } else { switch_pattern_len = ARRAY_SIZE(df_dummy_switch_pattern); } @@ -522,7 +522,7 @@ static int prepare_conn_cte_rx_enable_cmd_params(struct net_buf **buf, struct bt uint8_t switch_pattern_len; if (params->cte_types & BT_DF_CTE_TYPE_AOA) { - switch_pattern_len = cp->switch_pattern_len; + switch_pattern_len = params->num_ant_ids; } else { switch_pattern_len = ARRAY_SIZE(df_dummy_switch_pattern); } From a4edab554f67590a89703067af703c7996604562 Mon Sep 17 00:00:00 2001 From: Piotr Golyzniak Date: Fri, 11 Feb 2022 12:00:41 +0100 Subject: [PATCH 192/207] [nrf fromlist] twister: short build paths - fix squash! [nrf fromlist] twister: add option to create shorter build paths This changes was introduced to this open Upstream PR: https://github.com/zephyrproject-rtos/zephyr/pull/41930 Signed-off-by: Piotr Golyzniak --- scripts/pylib/twister/twisterlib.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/pylib/twister/twisterlib.py b/scripts/pylib/twister/twisterlib.py index eaef57399b4..af6a5a035f0 100755 --- a/scripts/pylib/twister/twisterlib.py +++ b/scripts/pylib/twister/twisterlib.py @@ -3904,7 +3904,7 @@ def _create_build_dir_link(self, links_dir_path, instance): significant during building by CMake on Windows OS. """ - os.makedirs(instance.build_dir) + os.makedirs(instance.build_dir, exist_ok=True) link_name = f"test_{self.link_dir_counter}" link_path = os.path.join(links_dir_path, link_name) From a3154206a1fb53fda540f40962344a8675b8eaa0 Mon Sep 17 00:00:00 2001 From: Jarno Lamsa Date: Fri, 4 Feb 2022 08:44:34 +0200 Subject: [PATCH 193/207] [nrf fromtree] net: lib: lwm2m: Correct path for update result The path was erroneously pointing to update state resource instead of update result causing a wrong resource value to be updated. Signed-off-by: Jarno Lamsa --- subsys/net/lib/lwm2m/lwm2m_obj_firmware.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/subsys/net/lib/lwm2m/lwm2m_obj_firmware.c b/subsys/net/lib/lwm2m/lwm2m_obj_firmware.c index 0f689c02cd0..5e5ec01d7e0 100644 --- a/subsys/net/lib/lwm2m/lwm2m_obj_firmware.c +++ b/subsys/net/lib/lwm2m/lwm2m_obj_firmware.c @@ -97,7 +97,7 @@ uint8_t lwm2m_firmware_get_update_state(void) void lwm2m_firmware_set_update_state_inst(uint16_t obj_inst_id, uint8_t state) { bool error = false; - char path[sizeof("5/65535/5")]; + char path[sizeof("5/65535/3")]; /* Check LWM2M SPEC appendix E.6.1 */ switch (state) { @@ -211,7 +211,7 @@ void lwm2m_firmware_set_update_result_inst(uint16_t obj_inst_id, uint8_t result) result, state); } - snprintf(path, sizeof(path), "5/%" PRIu16 "/3", obj_inst_id); + snprintf(path, sizeof(path), "5/%" PRIu16 "/5", obj_inst_id); lwm2m_engine_set_u8(path, result); From 22e3f8090e8439b71b70c4b308cec98bb201776c Mon Sep 17 00:00:00 2001 From: Jarno Lamsa Date: Fri, 4 Feb 2022 09:21:12 +0200 Subject: [PATCH 194/207] [nrf fromtree] net: lib: lwm2m: Use snprintk instead of snprintf Use kernel print function to reduce the memory impact. Signed-off-by: Jarno Lamsa --- subsys/net/lib/lwm2m/lwm2m_obj_firmware.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/subsys/net/lib/lwm2m/lwm2m_obj_firmware.c b/subsys/net/lib/lwm2m/lwm2m_obj_firmware.c index 5e5ec01d7e0..7f3c26a4ea7 100644 --- a/subsys/net/lib/lwm2m/lwm2m_obj_firmware.c +++ b/subsys/net/lib/lwm2m/lwm2m_obj_firmware.c @@ -129,7 +129,7 @@ void lwm2m_firmware_set_update_state_inst(uint16_t obj_inst_id, uint8_t state) update_state[obj_inst_id], state); } - snprintf(path, sizeof(path), "5/%" PRIu16 "/3", obj_inst_id); + snprintk(path, sizeof(path), "5/%" PRIu16 "/3", obj_inst_id); lwm2m_engine_set_u8(path, state); @@ -211,7 +211,7 @@ void lwm2m_firmware_set_update_result_inst(uint16_t obj_inst_id, uint8_t result) result, state); } - snprintf(path, sizeof(path), "5/%" PRIu16 "/5", obj_inst_id); + snprintk(path, sizeof(path), "5/%" PRIu16 "/5", obj_inst_id); lwm2m_engine_set_u8(path, result); From 590a3ae38214db019489a9dccaa9b6b7121e086c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=AD=20Bol=C3=ADvar?= Date: Thu, 10 Feb 2022 10:15:44 -0800 Subject: [PATCH 195/207] [nrf noup] ci: fix regex MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit squash! [nrf noup] ci: NCS-specific CI tweaks A shortlog that looks like "[nrf noup]: foo: bar" has shown up in real life and should fail this compliance test, but it doesn't. Fix that by checking for an explicit space after the closing "]" in a sauce tag. Signed-off-by: Martí Bolívar --- .github/workflows/compliance.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/compliance.yml b/.github/workflows/compliance.yml index 184fb057417..d794e13b264 100644 --- a/.github/workflows/compliance.yml +++ b/.github/workflows/compliance.yml @@ -58,7 +58,7 @@ jobs: git config --global user.name "Your Name" git remote -v # Sauce tag checks before rebasing - git log --oneline --first-parent origin/${BASE_REF}..HEAD | grep -E -v "\[nrf (mergeup|fromtree|fromlist|noup)\]" && { echo 'Sauce tag missing'; exit 1; } + git log --oneline --first-parent origin/${BASE_REF}..HEAD | grep -E -v "\[nrf (mergeup|fromtree|fromlist|noup)\][ ]" && { echo 'Sauce tag missing or invalid, format is "[nrf ] "'; exit 1; } git rebase origin/${BASE_REF} # debug git log --pretty=oneline | head -n 10 From 3e6e2c5a9e5264c9f27edc130032cd6e429a2b66 Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Thu, 17 Feb 2022 10:52:47 +0100 Subject: [PATCH 196/207] [nrf fromtree] Bluetooth: L2CAP: Fix checking if LTK is present This fix a typo where incorrect member of bt_keys was used for checking if LTK is present. This was resulting in bogus results depending on connection role and current identity used. This was affecting L2CAP/LE/CFC/BV-25-C qualification test case. Fixes: #42862 Signed-off-by: Szymon Janc Signed-off-by: Ilhan Ates (cherry-pick of 4fce6fb9377f000e7b3a17f50b633bafb8ecd42f) --- subsys/bluetooth/host/l2cap.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/subsys/bluetooth/host/l2cap.c b/subsys/bluetooth/host/l2cap.c index 5aa608ccf7e..54bdf674e5f 100644 --- a/subsys/bluetooth/host/l2cap.c +++ b/subsys/bluetooth/host/l2cap.c @@ -1053,9 +1053,9 @@ static uint16_t l2cap_check_security(struct bt_conn *conn, if (keys) { if (conn->role == BT_HCI_ROLE_CENTRAL) { - ltk_present = keys->id & (BT_KEYS_LTK_P256 | BT_KEYS_PERIPH_LTK); + ltk_present = keys->keys & (BT_KEYS_LTK_P256 | BT_KEYS_PERIPH_LTK); } else { - ltk_present = keys->id & (BT_KEYS_LTK_P256 | BT_KEYS_LTK); + ltk_present = keys->keys & (BT_KEYS_LTK_P256 | BT_KEYS_LTK); } } else { ltk_present = false; From 1ab6be252335ceec5a966b36fbc79883ebd1c4d1 Mon Sep 17 00:00:00 2001 From: Eduardo Montoya Date: Tue, 22 Feb 2022 11:03:11 +0100 Subject: [PATCH 197/207] [nrf fromtree] net: openthread: fix received frame flags Uninitialized memory would report wrong value for `mAckedWithSecEnhAck` flag in the received frame, making the OpenThread stack to update the frame counter for the neighbor wrongly. Signed-off-by: Eduardo Montoya (cherry picked from commit 19ac4d818fe6f43b27864f1564e4894b0a23f1bd) --- subsys/net/lib/openthread/platform/radio.c | 1 + 1 file changed, 1 insertion(+) diff --git a/subsys/net/lib/openthread/platform/radio.c b/subsys/net/lib/openthread/platform/radio.c index 07421c3a7eb..9a53f355224 100644 --- a/subsys/net/lib/openthread/platform/radio.c +++ b/subsys/net/lib/openthread/platform/radio.c @@ -356,6 +356,7 @@ static void openthread_handle_received_frame(otInstance *instance, struct net_pkt *pkt) { otRadioFrame recv_frame; + memset(&recv_frame, 0, sizeof(otRadioFrame)); recv_frame.mPsdu = net_buf_frag_last(pkt->buffer)->data; /* Length inc. CRC. */ From 4b001927aebd783a3d8506e2814b9868368ecfdf Mon Sep 17 00:00:00 2001 From: Eduardo Montoya Date: Tue, 22 Feb 2022 13:48:45 +0100 Subject: [PATCH 198/207] [nrf fromtree] net: openthread: fix handling tx done to report all kind of errors Fix bug in radio implementation that reported any transmit error as `OT_ERROR_NO_ACK` to OpenThread. Signed-off-by: Eduardo Montoya (cherry picked from commit a0093eeda08ec1a79417d0fd3c94ad036c96da16) --- subsys/net/lib/openthread/platform/radio.c | 14 ++---------- tests/subsys/openthread/radio_test.c | 25 +++------------------- 2 files changed, 5 insertions(+), 34 deletions(-) diff --git a/subsys/net/lib/openthread/platform/radio.c b/subsys/net/lib/openthread/platform/radio.c index 9a53f355224..2fef0f2648f 100644 --- a/subsys/net/lib/openthread/platform/radio.c +++ b/subsys/net/lib/openthread/platform/radio.c @@ -336,18 +336,8 @@ static inline void handle_tx_done(otInstance *aInstance) if (IS_ENABLED(CONFIG_OPENTHREAD_DIAG) && otPlatDiagModeGet()) { otPlatDiagRadioTransmitDone(aInstance, &sTransmitFrame, tx_result); } else { - if (sTransmitFrame.mPsdu[0] & IEEE802154_AR_FLAG_SET) { - if (ack_frame.mLength == 0) { - LOG_DBG("No ACK received."); - otPlatRadioTxDone(aInstance, &sTransmitFrame, - NULL, OT_ERROR_NO_ACK); - } else { - otPlatRadioTxDone(aInstance, &sTransmitFrame, - &ack_frame, tx_result); - } - } else { - otPlatRadioTxDone(aInstance, &sTransmitFrame, NULL, tx_result); - } + otPlatRadioTxDone(aInstance, &sTransmitFrame, ack_frame.mLength ? &ack_frame : NULL, + tx_result); ack_frame.mLength = 0; } } diff --git a/tests/subsys/openthread/radio_test.c b/tests/subsys/openthread/radio_test.c index 38e8a3f7e25..aea465d9576 100644 --- a/tests/subsys/openthread/radio_test.c +++ b/tests/subsys/openthread/radio_test.c @@ -430,8 +430,7 @@ static void test_tx_test(void) ztest_expect_value(set_channel_mock, channel, chan); ztest_expect_value(set_txpower_mock, dbm, power); ztest_expect_value(start_mock, dev, &radio); - zassert_equal(otPlatRadioReceive(ot, chan), OT_ERROR_NONE, - "Failed to receive."); + zassert_equal(otPlatRadioReceive(ot, chan), OT_ERROR_NONE, "Failed to receive."); /* ACKed frame */ frm->mChannel = chan2; @@ -442,8 +441,7 @@ static void test_tx_test(void) ztest_expect_value(cca_mock, dev, &radio); ztest_expect_value(tx_mock, frag->data, frm->mPsdu); ztest_expect_value(set_txpower_mock, dbm, power); - zassert_equal(otPlatRadioTransmit(ot, frm), OT_ERROR_NONE, - "Transmit failed."); + zassert_equal(otPlatRadioTransmit(ot, frm), OT_ERROR_NONE, "Transmit failed."); create_ack_frame(); make_sure_sem_set(Z_TIMEOUT_MS(100)); @@ -460,27 +458,10 @@ static void test_tx_test(void) ztest_expect_value(set_channel_mock, channel, chan2); ztest_expect_value(tx_mock, frag->data, frm->mPsdu); ztest_expect_value(set_txpower_mock, dbm, power); - zassert_equal(otPlatRadioTransmit(ot, frm), OT_ERROR_NONE, - "Transmit failed."); + zassert_equal(otPlatRadioTransmit(ot, frm), OT_ERROR_NONE, "Transmit failed."); make_sure_sem_set(Z_TIMEOUT_MS(100)); ztest_expect_value(otPlatRadioTxDone, aError, OT_ERROR_NONE); platformRadioProcess(ot); - - /* ACKed frame, no ACK */ - frm->mChannel = --chan2; - frm->mInfo.mTxInfo.mCsmaCaEnabled = false; - frm->mPsdu[0] = IEEE802154_AR_FLAG_SET; - - ztest_returns_value(set_channel_mock, 0); - ztest_expect_value(set_channel_mock, channel, chan2); - ztest_expect_value(tx_mock, frag->data, frm->mPsdu); - ztest_expect_value(set_txpower_mock, dbm, power); - zassert_equal(otPlatRadioTransmit(ot, frm), OT_ERROR_NONE, - "Transmit failed."); - make_sure_sem_set(Z_TIMEOUT_MS(100)); - - ztest_expect_value(otPlatRadioTxDone, aError, OT_ERROR_NO_ACK); - platformRadioProcess(ot); } /** From a49c0691993ce87d0a8216bd7a6cd8df9cd39941 Mon Sep 17 00:00:00 2001 From: Lukasz Maciejonczyk Date: Tue, 22 Feb 2022 16:41:22 +0100 Subject: [PATCH 199/207] [nrf fromtree] net: openthread: filter ipv6 fragments If OPENTHREAD_IP6_FRAGM is enabled the IPv6 fragments are handled in OpenThread stack but also forwarder unconditionally to the Zephyr uplayers. It causes additional packets processing and leads to errors like unrecognized next header type or duplicate ping reply. What more these errors generate additional traffic which jam channel and decrease latency for packets required fragmentation. This commit add filtering IPv6 fragments when data fragmentation and reassembling is enabled in OpenThread. Signed-off-by: Lukasz Maciejonczyk (cherry picked from commit c9effd0ff953e668b515ea8bf82678ce205d9ff7) --- subsys/net/l2/openthread/openthread.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/subsys/net/l2/openthread/openthread.c b/subsys/net/l2/openthread/openthread.c index 04aa8c51437..12765193075 100644 --- a/subsys/net/l2/openthread/openthread.c +++ b/subsys/net/l2/openthread/openthread.c @@ -297,8 +297,20 @@ static void openthread_process(struct k_work *work) openthread_api_mutex_unlock(ot_context); } -static enum net_verdict openthread_recv(struct net_if *iface, - struct net_pkt *pkt) +static bool is_ipv6_frag(struct net_pkt *pkt) +{ + NET_PKT_DATA_ACCESS_CONTIGUOUS_DEFINE(ipv6_access, struct net_ipv6_hdr); + struct net_ipv6_hdr *hdr; + + hdr = (struct net_ipv6_hdr *)net_pkt_get_data(pkt, &ipv6_access); + if (!hdr) { + return false; + } + + return hdr->nexthdr == NET_IPV6_NEXTHDR_FRAG ? true : false; +} + +static enum net_verdict openthread_recv(struct net_if *iface, struct net_pkt *pkt) { struct openthread_context *ot_context = net_if_l2_data(iface); @@ -310,6 +322,10 @@ static enum net_verdict openthread_recv(struct net_if *iface, net_pkt_hexdump(pkt, "Injected IPv6 packet"); } + if (IS_ENABLED(CONFIG_OPENTHREAD_IP6_FRAGM) && is_ipv6_frag(pkt)) { + return NET_DROP; + } + return NET_CONTINUE; } From 1f20e8cb2dbbe2a7ba08490bedcca84f10990c2e Mon Sep 17 00:00:00 2001 From: Gerard Marull-Paretas Date: Mon, 14 Feb 2022 09:30:59 +0100 Subject: [PATCH 200/207] [nrf fromtree] doc: requirements: disallow breathe 4.33.0 Sphinx 4.33.0 introduces Graphviz support, but the Graphviz configuration value names clash with the Sphinx built-in Graphviz extension. Issue: https://github.com/michaeljones/breathe/issues/803 Signed-off-by: Gerard Marull-Paretas (cherry picked from commit 8889114e3ca907fcd928d7addd0bdde92fa18f51) --- scripts/requirements-doc.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/requirements-doc.txt b/scripts/requirements-doc.txt index 650f55527ce..3ce1be874d5 100644 --- a/scripts/requirements-doc.txt +++ b/scripts/requirements-doc.txt @@ -1,6 +1,6 @@ # DOC: used to generate docs -breathe>=4.30 +breathe>=4.30,!=4.33 sphinx~=4.0 sphinx_rtd_theme~=1.0 sphinx-tabs From 8d85e222974cef658a35e1d024b7cec26d446062 Mon Sep 17 00:00:00 2001 From: Gerard Marull-Paretas Date: Tue, 15 Feb 2022 10:39:00 +0100 Subject: [PATCH 201/207] [nrf fromtree] doc: requirements: stick to breathe < 4.33 Looks like the 4.33 release has some more issues, so let's wait until everything gets fixed before allowing future versions. Ref. https://github.com/michaeljones/breathe/issues/805 Signed-off-by: Gerard Marull-Paretas (cherry picked from commit 10da718fd7f2dbcd5f11a1d38bb3be7eb1fd05bd) --- scripts/requirements-doc.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/requirements-doc.txt b/scripts/requirements-doc.txt index 3ce1be874d5..8a518a69dd3 100644 --- a/scripts/requirements-doc.txt +++ b/scripts/requirements-doc.txt @@ -1,6 +1,6 @@ # DOC: used to generate docs -breathe>=4.30,!=4.33 +breathe>=4.30,<4.33 # 4.33: disabled due to #803 and #805 issues sphinx~=4.0 sphinx_rtd_theme~=1.0 sphinx-tabs From bb1055820462a7ceadf2f38ffbc195c7007c5227 Mon Sep 17 00:00:00 2001 From: Emil Gydesen Date: Wed, 22 Dec 2021 17:28:10 +0100 Subject: [PATCH 202/207] [nrf fromtree] Bluetooth: ISO: Fix bad chan pointer for disconnect If a central disconnects an ISO, then the `chan` pointer will become NULL before attempting to call the disconnect callback. Signed-off-by: Emil Gydesen --- subsys/bluetooth/host/iso.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/subsys/bluetooth/host/iso.c b/subsys/bluetooth/host/iso.c index fe42c6a37bf..fa9771798c6 100644 --- a/subsys/bluetooth/host/iso.c +++ b/subsys/bluetooth/host/iso.c @@ -442,15 +442,16 @@ static void bt_iso_chan_disconnected(struct bt_iso_chan *chan, uint8_t reason) #if defined(CONFIG_BT_ISO_UNICAST) bool is_chan_connected; struct bt_iso_cig *cig; + struct bt_iso_chan *cis_chan; /* Update CIG state */ cig = get_cig(chan); __ASSERT(cig != NULL, "CIG was NULL"); is_chan_connected = false; - SYS_SLIST_FOR_EACH_CONTAINER(&cig->cis_channels, chan, node) { - if (chan->state == BT_ISO_CONNECTED || - chan->state == BT_ISO_CONNECT) { + SYS_SLIST_FOR_EACH_CONTAINER(&cig->cis_channels, cis_chan, node) { + if (cis_chan->state == BT_ISO_CONNECTED || + cis_chan->state == BT_ISO_CONNECT) { is_chan_connected = true; break; } From 1cd83395b12d5755cea65539cb7e7ae0079316d5 Mon Sep 17 00:00:00 2001 From: Aleksander Wasaznik Date: Wed, 26 Jan 2022 12:26:58 +0100 Subject: [PATCH 203/207] [nrf fromtree] Bluetooth: ATT: Fix conn parameter to req cb in att_reset The conn pointer is still valid / not reused at this time and can be used further up the stack as an identifer. This simplifies the API of ATT, and fixes callbacks in GATT that pass on this value directly since their API does not allow conn to be NULL. Fixes #41794 Signed-off-by: Aleksander Wasaznik --- doc/releases/release-notes-3.0.rst | 8 +++++++- subsys/bluetooth/host/att.c | 8 +++++--- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/doc/releases/release-notes-3.0.rst b/doc/releases/release-notes-3.0.rst index 2406c39a698..9e22c25d666 100644 --- a/doc/releases/release-notes-3.0.rst +++ b/doc/releases/release-notes-3.0.rst @@ -44,7 +44,13 @@ Changes in this release Changes in this release ======================= -Removed APIs in this release: +* GATT callbacks ``bt_gatt_..._func_t`` would previously be called with argument + ``conn = NULL`` in the event of a disconnect. This was not documented as part + of the API. This behavior is changed so the ``conn`` argument is provided as + normal when a disconnect occurs. + +Removed APIs in this release +============================ * The following Kconfig options related to radio front-end modules (FEMs) were removed: diff --git a/subsys/bluetooth/host/att.c b/subsys/bluetooth/host/att.c index 5cbbd44fc10..532257429ac 100644 --- a/subsys/bluetooth/host/att.c +++ b/subsys/bluetooth/host/att.c @@ -2622,8 +2622,6 @@ static void att_reset(struct bt_att *att) net_buf_unref(buf); } - att->conn = NULL; - /* Notify pending requests */ while (!sys_slist_is_empty(&att->reqs)) { struct bt_att_req *req; @@ -2632,13 +2630,17 @@ static void att_reset(struct bt_att *att) node = sys_slist_get_not_empty(&att->reqs); req = CONTAINER_OF(node, struct bt_att_req, node); if (req->func) { - req->func(NULL, BT_ATT_ERR_UNLIKELY, NULL, 0, + req->func(att->conn, BT_ATT_ERR_UNLIKELY, NULL, 0, req->user_data); } bt_att_req_free(req); } + /* FIXME: `att->conn` is not reference counted. Consider using `bt_conn_ref` + * and `bt_conn_unref` to follow convention. + */ + att->conn = NULL; k_mem_slab_free(&att_slab, (void **)&att); } From 2736f9951373962536cbd0271d0539722dfae330 Mon Sep 17 00:00:00 2001 From: Torsten Rasmussen Date: Fri, 25 Feb 2022 14:03:08 +0100 Subject: [PATCH 204/207] [nrf noup] kconfig: Define NRF_SECURITY and NORDIC_SECURITY_BACKEND Define NRF_SECURITY and NORDIC_SECURITY_BACKEND so that check-compliance can pass fixup! [nrf noup] mbedtls: Disable configurations in Kconfig.tls-generic Signed-off-by: Torsten Rasmussen --- modules/mbedtls/Kconfig.tls-generic | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/modules/mbedtls/Kconfig.tls-generic b/modules/mbedtls/Kconfig.tls-generic index 20bbe735885..a4af8966aed 100644 --- a/modules/mbedtls/Kconfig.tls-generic +++ b/modules/mbedtls/Kconfig.tls-generic @@ -9,6 +9,12 @@ menu "TLS configuration" menu "Supported TLS version" +config NRF_SECURITY + bool + +config NORDIC_SECURITY_BACKEND + bool + if !(NRF_SECURITY || NORDIC_SECURITY_BACKEND) config MBEDTLS_TLS_VERSION_1_0 From 81bd4a171735ecbf168bf674c26d649dd6c1fcf0 Mon Sep 17 00:00:00 2001 From: Torsten Rasmussen Date: Fri, 25 Feb 2022 14:03:34 +0100 Subject: [PATCH 205/207] [nrf noup] kconfig: Define PSA_PROMPTLESS Define PSA_PROMPTLESS so that check-compliance can pass. fixup! [nrf noup] Adding PSA configurations to mbed TLS Signed-off-by: Torsten Rasmussen --- modules/mbedtls/Kconfig.psa | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/modules/mbedtls/Kconfig.psa b/modules/mbedtls/Kconfig.psa index 7da962f17e9..80e6701e17f 100644 --- a/modules/mbedtls/Kconfig.psa +++ b/modules/mbedtls/Kconfig.psa @@ -5,6 +5,12 @@ # menu "PSA RNG support" +config PSA_PROMPTLESS + bool + +config PSA_DEFAULT_OFF + bool + config PSA_WANT_ALG_CTR_DRBG bool prompt "PSA RNG using CTR_DRBG" From 17f1d00bccaa8e8c9c613620916d1dc350a355fa Mon Sep 17 00:00:00 2001 From: Torsten Rasmussen Date: Fri, 25 Feb 2022 14:04:02 +0100 Subject: [PATCH 206/207] [nrf noup] kconfig: Define IS_SPM Define IS_SPM so that check-compliance can pass. fixup! [nrf noup] kconfig: Disallow FPU for SPM Signed-off-by: Torsten Rasmussen --- arch/Kconfig | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/Kconfig b/arch/Kconfig index 9ae26228720..ccb2eb20303 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -843,6 +843,9 @@ config SRAM_REGION_PERMISSIONS menu "Floating Point Options" +config IS_SPM + bool + config FPU bool "Enable floating point unit (FPU)" depends on CPU_HAS_FPU From 01881891176f4b8a89e6ff7f1a354b518ff84e2d Mon Sep 17 00:00:00 2001 From: Maciej Perkowski Date: Fri, 25 Feb 2022 15:26:44 +0100 Subject: [PATCH 207/207] [nrf noup] ci: Fix complinace check squash! [nrf noup] ci: NCS-specific CI tweaks In nrf we changed Kconfig check to KconfigBasic but the workflow was not changed to scan for the KconfigBasic.txt file which is generated in place of Kconfig.txt . compliance debug Signed-off-by: Maciej Perkowski --- .github/workflows/compliance.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/compliance.yml b/.github/workflows/compliance.yml index d794e13b264..84e7d20f064 100644 --- a/.github/workflows/compliance.yml +++ b/.github/workflows/compliance.yml @@ -92,7 +92,7 @@ jobs: exit 1; fi - for file in Nits.txt checkpatch.txt Identity.txt Gitlint.txt pylint.txt Devicetree.txt Kconfig.txt Codeowners.txt; do + for file in Nits.txt checkpatch.txt Identity.txt Gitlint.txt pylint.txt Devicetree.txt KconfigBasic.txt Codeowners.txt; do if [[ -s $file ]]; then errors=$(cat $file) errors="${errors//'%'/'%25'}"